🎭 CHORUS now contains full BZZZ functionality adapted for containers Core systems ported: - P2P networking (libp2p with DHT and PubSub) - Task coordination (COOEE protocol) - HMMM collaborative reasoning - SHHH encryption and security - SLURP admin election system - UCXL content addressing - UCXI server integration - Hypercore logging system - Health monitoring and graceful shutdown - License validation with KACHING Container adaptations: - Environment variable configuration (no YAML files) - Container-optimized logging to stdout/stderr - Auto-generated agent IDs for container deployments - Docker-first architecture All proven BZZZ P2P protocols, AI integration, and collaboration features are now available in containerized form. Next: Build and test container deployment. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
333 lines
11 KiB
Go
333 lines
11 KiB
Go
package ucxl
|
|
|
|
import (
|
|
"time"
|
|
)
|
|
|
|
// UCXLCode represents a standardized UCXL response/error code
|
|
type UCXLCode string
|
|
|
|
// Standard UCXL response codes
|
|
const (
|
|
// Success codes (2xx range)
|
|
CodeSuccess UCXLCode = "UCXL-200-SUCCESS"
|
|
CodeCreated UCXLCode = "UCXL-201-CREATED"
|
|
CodeAccepted UCXLCode = "UCXL-202-ACCEPTED"
|
|
CodeNoContent UCXLCode = "UCXL-204-NO_CONTENT"
|
|
|
|
// Client error codes (4xx range)
|
|
CodeBadRequest UCXLCode = "UCXL-400-BAD_REQUEST"
|
|
CodeInvalidAddress UCXLCode = "UCXL-400-INVALID_ADDRESS"
|
|
CodeInvalidPayload UCXLCode = "UCXL-400-INVALID_PAYLOAD"
|
|
CodeUnauthorized UCXLCode = "UCXL-401-UNAUTHORIZED"
|
|
CodeForbidden UCXLCode = "UCXL-403-FORBIDDEN"
|
|
CodeNotFound UCXLCode = "UCXL-404-NOT_FOUND"
|
|
CodeMethodNotAllowed UCXLCode = "UCXL-405-METHOD_NOT_ALLOWED"
|
|
CodeConflict UCXLCode = "UCXL-409-CONFLICT"
|
|
CodeUnprocessable UCXLCode = "UCXL-422-UNPROCESSABLE"
|
|
CodeTooManyRequests UCXLCode = "UCXL-429-TOO_MANY_REQUESTS"
|
|
|
|
// Server error codes (5xx range)
|
|
CodeInternalError UCXLCode = "UCXL-500-INTERNAL_ERROR"
|
|
CodeNotImplemented UCXLCode = "UCXL-501-NOT_IMPLEMENTED"
|
|
CodeBadGateway UCXLCode = "UCXL-502-BAD_GATEWAY"
|
|
CodeServiceUnavailable UCXLCode = "UCXL-503-SERVICE_UNAVAILABLE"
|
|
CodeGatewayTimeout UCXLCode = "UCXL-504-GATEWAY_TIMEOUT"
|
|
|
|
// UCXI-specific codes
|
|
CodeResolutionFailed UCXLCode = "UCXL-404-RESOLUTION_FAILED"
|
|
CodeStorageFailed UCXLCode = "UCXL-500-STORAGE_FAILED"
|
|
CodeAnnounceFailed UCXLCode = "UCXL-500-ANNOUNCE_FAILED"
|
|
CodeNavigationFailed UCXLCode = "UCXL-422-NAVIGATION_FAILED"
|
|
CodeTemporalInvalid UCXLCode = "UCXL-400-TEMPORAL_INVALID"
|
|
|
|
// Role-based collaboration codes
|
|
CodeCollaborationFailed UCXLCode = "UCXL-500-COLLABORATION_FAILED"
|
|
CodeInvalidRole UCXLCode = "UCXL-400-INVALID_ROLE"
|
|
CodeExpertiseNotAvailable UCXLCode = "UCXL-404-EXPERTISE_NOT_AVAILABLE"
|
|
CodeMentorshipUnavailable UCXLCode = "UCXL-404-MENTORSHIP_UNAVAILABLE"
|
|
CodeProjectNotFound UCXLCode = "UCXL-404-PROJECT_NOT_FOUND"
|
|
CodeCollaborationTimeout UCXLCode = "UCXL-408-COLLABORATION_TIMEOUT"
|
|
)
|
|
|
|
// UCXLResponse represents a standardized UCXL success response
|
|
type UCXLResponse struct {
|
|
Response UCXLResponseData `json:"response"`
|
|
}
|
|
|
|
// UCXLResponseData contains the actual response data
|
|
type UCXLResponseData struct {
|
|
Code UCXLCode `json:"code"`
|
|
Message string `json:"message"`
|
|
Data interface{} `json:"data,omitempty"`
|
|
Details interface{} `json:"details,omitempty"`
|
|
RequestID string `json:"request_id"`
|
|
Timestamp time.Time `json:"timestamp"`
|
|
}
|
|
|
|
// UCXLError represents a standardized UCXL error response
|
|
type UCXLError struct {
|
|
Error UCXLErrorData `json:"error"`
|
|
}
|
|
|
|
// UCXLErrorData contains the actual error data
|
|
type UCXLErrorData struct {
|
|
Code UCXLCode `json:"code"`
|
|
Message string `json:"message"`
|
|
Details interface{} `json:"details,omitempty"`
|
|
Source string `json:"source"`
|
|
Path string `json:"path"`
|
|
RequestID string `json:"request_id"`
|
|
Timestamp time.Time `json:"timestamp"`
|
|
Cause *UCXLError `json:"cause,omitempty"`
|
|
}
|
|
|
|
// ResponseBuilder helps build standardized UCXL responses
|
|
type ResponseBuilder struct {
|
|
requestID string
|
|
source string
|
|
}
|
|
|
|
// NewResponseBuilder creates a new response builder
|
|
func NewResponseBuilder(requestID string, source string) *ResponseBuilder {
|
|
if requestID == "" {
|
|
requestID = generateRequestID()
|
|
}
|
|
if source == "" {
|
|
source = "ucxi-server"
|
|
}
|
|
return &ResponseBuilder{
|
|
requestID: requestID,
|
|
source: source,
|
|
}
|
|
}
|
|
|
|
// Success creates a standardized success response
|
|
func (rb *ResponseBuilder) Success(code UCXLCode, message string, data interface{}) *UCXLResponse {
|
|
return &UCXLResponse{
|
|
Response: UCXLResponseData{
|
|
Code: code,
|
|
Message: message,
|
|
Data: data,
|
|
RequestID: rb.requestID,
|
|
Timestamp: time.Now().UTC(),
|
|
},
|
|
}
|
|
}
|
|
|
|
// SuccessWithDetails creates a success response with additional details
|
|
func (rb *ResponseBuilder) SuccessWithDetails(code UCXLCode, message string, data interface{}, details interface{}) *UCXLResponse {
|
|
return &UCXLResponse{
|
|
Response: UCXLResponseData{
|
|
Code: code,
|
|
Message: message,
|
|
Data: data,
|
|
Details: details,
|
|
RequestID: rb.requestID,
|
|
Timestamp: time.Now().UTC(),
|
|
},
|
|
}
|
|
}
|
|
|
|
// Error creates a standardized error response
|
|
func (rb *ResponseBuilder) Error(code UCXLCode, message string, path string) *UCXLError {
|
|
return &UCXLError{
|
|
Error: UCXLErrorData{
|
|
Code: code,
|
|
Message: message,
|
|
Source: rb.source,
|
|
Path: path,
|
|
RequestID: rb.requestID,
|
|
Timestamp: time.Now().UTC(),
|
|
},
|
|
}
|
|
}
|
|
|
|
// ErrorWithDetails creates an error response with additional details
|
|
func (rb *ResponseBuilder) ErrorWithDetails(code UCXLCode, message string, path string, details interface{}) *UCXLError {
|
|
return &UCXLError{
|
|
Error: UCXLErrorData{
|
|
Code: code,
|
|
Message: message,
|
|
Details: details,
|
|
Source: rb.source,
|
|
Path: path,
|
|
RequestID: rb.requestID,
|
|
Timestamp: time.Now().UTC(),
|
|
},
|
|
}
|
|
}
|
|
|
|
// ErrorWithCause creates an error response with a causal chain
|
|
func (rb *ResponseBuilder) ErrorWithCause(code UCXLCode, message string, path string, cause *UCXLError) *UCXLError {
|
|
return &UCXLError{
|
|
Error: UCXLErrorData{
|
|
Code: code,
|
|
Message: message,
|
|
Source: rb.source,
|
|
Path: path,
|
|
RequestID: rb.requestID,
|
|
Timestamp: time.Now().UTC(),
|
|
Cause: cause,
|
|
},
|
|
}
|
|
}
|
|
|
|
// Convenience methods for common responses
|
|
|
|
// OK creates a standard 200 OK response
|
|
func (rb *ResponseBuilder) OK(data interface{}) *UCXLResponse {
|
|
return rb.Success(CodeSuccess, "Request completed successfully", data)
|
|
}
|
|
|
|
// Created creates a standard 201 Created response
|
|
func (rb *ResponseBuilder) Created(data interface{}) *UCXLResponse {
|
|
return rb.Success(CodeCreated, "Resource created successfully", data)
|
|
}
|
|
|
|
// NoContent creates a standard 204 No Content response
|
|
func (rb *ResponseBuilder) NoContent() *UCXLResponse {
|
|
return rb.Success(CodeNoContent, "Request completed with no content", nil)
|
|
}
|
|
|
|
// BadRequest creates a standard 400 Bad Request error
|
|
func (rb *ResponseBuilder) BadRequest(message string, path string) *UCXLError {
|
|
return rb.Error(CodeBadRequest, message, path)
|
|
}
|
|
|
|
// InvalidAddress creates a UCXL-specific invalid address error
|
|
func (rb *ResponseBuilder) InvalidAddress(message string, path string, addressDetails interface{}) *UCXLError {
|
|
return rb.ErrorWithDetails(CodeInvalidAddress, message, path, map[string]interface{}{
|
|
"field": "address",
|
|
"address": addressDetails,
|
|
})
|
|
}
|
|
|
|
// NotFound creates a standard 404 Not Found error
|
|
func (rb *ResponseBuilder) NotFound(message string, path string) *UCXLError {
|
|
return rb.Error(CodeNotFound, message, path)
|
|
}
|
|
|
|
// Unprocessable creates a standard 422 Unprocessable Entity error
|
|
func (rb *ResponseBuilder) Unprocessable(message string, path string, validationErrors interface{}) *UCXLError {
|
|
return rb.ErrorWithDetails(CodeUnprocessable, message, path, map[string]interface{}{
|
|
"validation_errors": validationErrors,
|
|
})
|
|
}
|
|
|
|
// InternalError creates a standard 500 Internal Server Error
|
|
func (rb *ResponseBuilder) InternalError(message string, path string) *UCXLError {
|
|
return rb.Error(CodeInternalError, message, path)
|
|
}
|
|
|
|
// MethodNotAllowed creates a standard 405 Method Not Allowed error
|
|
func (rb *ResponseBuilder) MethodNotAllowed(allowedMethods []string, path string) *UCXLError {
|
|
return rb.ErrorWithDetails(CodeMethodNotAllowed, "Method not allowed", path, map[string]interface{}{
|
|
"allowed_methods": allowedMethods,
|
|
})
|
|
}
|
|
|
|
// Collaboration-specific error builders
|
|
|
|
// InvalidRole creates a UCXL-specific invalid role error
|
|
func (rb *ResponseBuilder) InvalidRole(message string, path string, roleDetails interface{}) *UCXLError {
|
|
return rb.ErrorWithDetails(CodeInvalidRole, message, path, map[string]interface{}{
|
|
"field": "role",
|
|
"role_details": roleDetails,
|
|
})
|
|
}
|
|
|
|
// ExpertiseNotAvailable creates a UCXL-specific expertise not available error
|
|
func (rb *ResponseBuilder) ExpertiseNotAvailable(message string, path string, expertiseDetails interface{}) *UCXLError {
|
|
return rb.ErrorWithDetails(CodeExpertiseNotAvailable, message, path, map[string]interface{}{
|
|
"requested_expertise": expertiseDetails,
|
|
"suggestion": "Try requesting more general expertise or check available experts",
|
|
})
|
|
}
|
|
|
|
// ProjectNotFound creates a UCXL-specific project not found error
|
|
func (rb *ResponseBuilder) ProjectNotFound(message string, path string, projectID string) *UCXLError {
|
|
return rb.ErrorWithDetails(CodeProjectNotFound, message, path, map[string]interface{}{
|
|
"field": "project_id",
|
|
"project_id": projectID,
|
|
"suggestion": "Verify the project ID is correct and accessible",
|
|
})
|
|
}
|
|
|
|
// CollaborationTimeout creates a UCXL-specific collaboration timeout error
|
|
func (rb *ResponseBuilder) CollaborationTimeout(message string, path string, timeoutDetails interface{}) *UCXLError {
|
|
return rb.ErrorWithDetails(CodeCollaborationTimeout, message, path, map[string]interface{}{
|
|
"timeout_reason": timeoutDetails,
|
|
"suggestion": "Retry the collaboration request or check system load",
|
|
})
|
|
}
|
|
|
|
// CollaborationFailed creates a UCXL-specific collaboration failure error
|
|
func (rb *ResponseBuilder) CollaborationFailed(message string, path string, failureDetails interface{}) *UCXLError {
|
|
return rb.ErrorWithDetails(CodeCollaborationFailed, message, path, map[string]interface{}{
|
|
"failure_details": failureDetails,
|
|
"suggestion": "Check system status and pubsub connectivity",
|
|
})
|
|
}
|
|
|
|
// Helper functions
|
|
|
|
// GetHTTPStatus maps UCXL codes to HTTP status codes
|
|
func GetHTTPStatus(code UCXLCode) int {
|
|
switch code {
|
|
case CodeSuccess:
|
|
return 200
|
|
case CodeCreated:
|
|
return 201
|
|
case CodeAccepted:
|
|
return 202
|
|
case CodeNoContent:
|
|
return 204
|
|
case CodeBadRequest, CodeInvalidAddress, CodeInvalidPayload, CodeTemporalInvalid, CodeInvalidRole:
|
|
return 400
|
|
case CodeUnauthorized:
|
|
return 401
|
|
case CodeForbidden:
|
|
return 403
|
|
case CodeNotFound, CodeResolutionFailed, CodeExpertiseNotAvailable, CodeMentorshipUnavailable, CodeProjectNotFound:
|
|
return 404
|
|
case CodeCollaborationTimeout:
|
|
return 408
|
|
case CodeMethodNotAllowed:
|
|
return 405
|
|
case CodeConflict:
|
|
return 409
|
|
case CodeUnprocessable, CodeNavigationFailed:
|
|
return 422
|
|
case CodeTooManyRequests:
|
|
return 429
|
|
case CodeInternalError, CodeStorageFailed, CodeAnnounceFailed, CodeCollaborationFailed:
|
|
return 500
|
|
case CodeNotImplemented:
|
|
return 501
|
|
case CodeBadGateway:
|
|
return 502
|
|
case CodeServiceUnavailable:
|
|
return 503
|
|
case CodeGatewayTimeout:
|
|
return 504
|
|
default:
|
|
return 500
|
|
}
|
|
}
|
|
|
|
// generateRequestID creates a unique request ID
|
|
func generateRequestID() string {
|
|
// Simple UUID-like generator for request IDs
|
|
return time.Now().Format("20060102-150405") + "-" + randomString(8)
|
|
}
|
|
|
|
// randomString generates a random string of the specified length
|
|
func randomString(length int) string {
|
|
const charset = "abcdefghijklmnopqrstuvwxyz0123456789"
|
|
result := make([]byte, length)
|
|
for i := range result {
|
|
result[i] = charset[time.Now().UnixNano()%(int64(len(charset)))]
|
|
}
|
|
return string(result)
|
|
} |