Files
RUSTLE/ucxl_codes.py
anthonyrawlins 235ca68ee5 Initial RUSTLE implementation with UCXL Browser and standardized codes
- Complete UCXL protocol implementation with DHT storage layer
- BZZZ Gateway for peer-to-peer networking and content distribution
- Temporal navigation engine with version control and timeline browsing
- Standardized UCXL error/response codes for Rust, Go, and Python
- React-based UI with multi-tab interface and professional styling
- libp2p integration for distributed hash table operations
- Self-healing network mechanisms and peer management
- Comprehensive IPC commands for Tauri desktop integration

Major Components:
- ucxl-core: Core UCXL protocol and DHT implementation
- BZZZ Gateway: Local subnet peer discovery and content replication
- Temporal Engine: Version control and state reconstruction
- Cross-language standards: Unified error handling across implementations
- Modern UI: Professional React interface with DHT and network monitoring

Standards Compliance:
- UCXL-ERROR-CODES.md and UCXL-RESPONSE-CODES.md v1.0
- Machine-readable error codes with structured payloads
- Client guidance for retry logic and error handling
- Cross-language compatibility with identical APIs

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-09 13:17:33 +10:00

458 lines
15 KiB
Python

"""
UCXL Standard Response and Error Codes Library
This module provides standardized UCXL error and response codes for consistent
cross-service communication and client handling.
Based on UCXL-ERROR-CODES.md and UCXL-RESPONSE-CODES.md v1.0
"""
import json
import uuid
from datetime import datetime, timezone
from enum import Enum
from typing import Any, Dict, Optional
from dataclasses import dataclass, field, asdict
class UCXLErrorCode(Enum):
"""Standard UCXL Error Codes following format: UCXL-<HTTP-class>-<SHORT_NAME>"""
# 400 - Client Errors
INVALID_ADDRESS = "UCXL-400-INVALID_ADDRESS"
MISSING_FIELD = "UCXL-400-MISSING_FIELD"
INVALID_FORMAT = "UCXL-400-INVALID_FORMAT"
# 401 - Authentication
UNAUTHORIZED = "UCXL-401-UNAUTHORIZED"
# 403 - Authorization
FORBIDDEN = "UCXL-403-FORBIDDEN"
# 404 - Not Found
NOT_FOUND = "UCXL-404-NOT_FOUND"
# 409 - Conflict
CONFLICT = "UCXL-409-CONFLICT"
# 422 - Unprocessable Entity
UNPROCESSABLE_ENTITY = "UCXL-422-UNPROCESSABLE_ENTITY"
# 429 - Rate Limiting
RATE_LIMIT = "UCXL-429-RATE_LIMIT"
# 500 - Server Errors
INTERNAL_ERROR = "UCXL-500-INTERNAL_ERROR"
# 503 - Service Unavailable
SERVICE_UNAVAILABLE = "UCXL-503-SERVICE_UNAVAILABLE"
# 504 - Gateway Timeout
GATEWAY_TIMEOUT = "UCXL-504-GATEWAY_TIMEOUT"
def http_status(self) -> int:
"""Get the HTTP status code for this error code"""
mapping = {
self.INVALID_ADDRESS: 400,
self.MISSING_FIELD: 400,
self.INVALID_FORMAT: 400,
self.UNAUTHORIZED: 401,
self.FORBIDDEN: 403,
self.NOT_FOUND: 404,
self.CONFLICT: 409,
self.UNPROCESSABLE_ENTITY: 422,
self.RATE_LIMIT: 429,
self.INTERNAL_ERROR: 500,
self.SERVICE_UNAVAILABLE: 503,
self.GATEWAY_TIMEOUT: 504,
}
return mapping.get(self, 500)
def default_message(self) -> str:
"""Get the default error message for this code"""
messages = {
self.INVALID_ADDRESS: "Invalid UCXL address format",
self.MISSING_FIELD: "Required field is missing",
self.INVALID_FORMAT: "Input does not match the expected format",
self.UNAUTHORIZED: "Authentication credentials missing or invalid",
self.FORBIDDEN: "Insufficient permissions for the action",
self.NOT_FOUND: "Requested resource not found",
self.CONFLICT: "Conflict with current state",
self.UNPROCESSABLE_ENTITY: "Semantic validation failed",
self.RATE_LIMIT: "Too many requests; rate limiting in effect",
self.INTERNAL_ERROR: "Internal server error",
self.SERVICE_UNAVAILABLE: "Service is currently unavailable",
self.GATEWAY_TIMEOUT: "Downstream gateway timed out",
}
return messages.get(self, "Unknown error")
def is_client_error(self) -> bool:
"""Check if this is a client error (4xx)"""
return 400 <= self.http_status() < 500
def is_server_error(self) -> bool:
"""Check if this is a server error (5xx)"""
return 500 <= self.http_status() < 600
def should_retry(self) -> bool:
"""Check if this error should trigger a retry"""
return self in {
self.RATE_LIMIT,
self.INTERNAL_ERROR,
self.SERVICE_UNAVAILABLE,
self.GATEWAY_TIMEOUT,
}
class UCXLResponseCode(Enum):
"""Standard UCXL Response Codes following format: UCXL-<HTTP-class>-<SHORT_NAME>"""
# 200 - Success
OK = "UCXL-200-OK"
# 201 - Created
CREATED = "UCXL-201-CREATED"
# 202 - Accepted (Async)
ACCEPTED = "UCXL-202-ACCEPTED"
# 204 - No Content
NO_CONTENT = "UCXL-204-NO_CONTENT"
# 206 - Partial Content
PARTIAL_CONTENT = "UCXL-206-PARTIAL_CONTENT"
# 304 - Not Modified (Caching)
NOT_MODIFIED = "UCXL-304-NOT_MODIFIED"
def http_status(self) -> int:
"""Get the HTTP status code for this response code"""
mapping = {
self.OK: 200,
self.CREATED: 201,
self.ACCEPTED: 202,
self.NO_CONTENT: 204,
self.PARTIAL_CONTENT: 206,
self.NOT_MODIFIED: 304,
}
return mapping.get(self, 200)
def default_message(self) -> str:
"""Get the default success message for this code"""
messages = {
self.OK: "Request completed successfully",
self.CREATED: "Resource created successfully",
self.ACCEPTED: "Request accepted for processing",
self.NO_CONTENT: "Request completed with no content to return",
self.PARTIAL_CONTENT: "Partial results returned",
self.NOT_MODIFIED: "Resource not modified since last fetch",
}
return messages.get(self, "Success")
def is_async(self) -> bool:
"""Check if this indicates an asynchronous operation"""
return self == self.ACCEPTED
def is_partial(self) -> bool:
"""Check if this indicates partial/incomplete results"""
return self in {self.PARTIAL_CONTENT, self.ACCEPTED}
@dataclass
class UCXLError:
"""UCXL Error Details"""
code: UCXLErrorCode
message: str
source: str
path: str
request_id: str
timestamp: datetime
details: Optional[Dict[str, Any]] = None
cause: Optional[str] = None
def __post_init__(self):
if isinstance(self.code, str):
self.code = UCXLErrorCode(self.code)
@dataclass
class UCXLErrorResponse:
"""UCXL Standard Error Response Payload"""
error: UCXLError
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary"""
result = asdict(self)
result['error']['code'] = self.error.code.value
result['error']['timestamp'] = self.error.timestamp.isoformat()
return result
def to_json(self) -> str:
"""Convert to JSON string"""
return json.dumps(self.to_dict())
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> 'UCXLErrorResponse':
"""Create from dictionary"""
error_data = data['error']
error_data['timestamp'] = datetime.fromisoformat(error_data['timestamp'].replace('Z', '+00:00'))
return cls(error=UCXLError(**error_data))
@classmethod
def from_json(cls, json_str: str) -> 'UCXLErrorResponse':
"""Create from JSON string"""
return cls.from_dict(json.loads(json_str))
@dataclass
class UCXLResponse:
"""UCXL Response Details"""
code: UCXLResponseCode
message: str
request_id: str
timestamp: datetime
data: Optional[Any] = None
details: Optional[Dict[str, Any]] = None
def __post_init__(self):
if isinstance(self.code, str):
self.code = UCXLResponseCode(self.code)
@dataclass
class UCXLSuccessResponse:
"""UCXL Standard Success Response Payload"""
response: UCXLResponse
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary"""
result = asdict(self)
result['response']['code'] = self.response.code.value
result['response']['timestamp'] = self.response.timestamp.isoformat()
return result
def to_json(self) -> str:
"""Convert to JSON string"""
return json.dumps(self.to_dict())
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> 'UCXLSuccessResponse':
"""Create from dictionary"""
response_data = data['response']
response_data['timestamp'] = datetime.fromisoformat(response_data['timestamp'].replace('Z', '+00:00'))
return cls(response=UCXLResponse(**response_data))
@classmethod
def from_json(cls, json_str: str) -> 'UCXLSuccessResponse':
"""Create from JSON string"""
return cls.from_dict(json.loads(json_str))
class UCXLErrorBuilder:
"""Builder for creating UCXL Error responses"""
def __init__(self, code: UCXLErrorCode):
self.code = code
self.message = None
self.details = {}
self.source = "ucxl-api/v1"
self.path = "/"
self.request_id = f"req-{str(uuid.uuid4())[:8]}"
self.cause = None
def message(self, message: str) -> 'UCXLErrorBuilder':
"""Set a custom error message"""
self.message = message
return self
def field(self, field: str, provided: Any) -> 'UCXLErrorBuilder':
"""Add details about the field that failed"""
self.details["field"] = field
self.details["provided"] = provided
return self
def expected_format(self, format_str: str) -> 'UCXLErrorBuilder':
"""Add expected format information"""
self.details["expected_format"] = format_str
return self
def detail(self, key: str, value: Any) -> 'UCXLErrorBuilder':
"""Add a detail field"""
self.details[key] = value
return self
def source(self, source: str) -> 'UCXLErrorBuilder':
"""Set the source service"""
self.source = source
return self
def path(self, path: str) -> 'UCXLErrorBuilder':
"""Set the request path"""
self.path = path
return self
def request_id(self, request_id: str) -> 'UCXLErrorBuilder':
"""Set the request ID"""
self.request_id = request_id
return self
def cause(self, cause: str) -> 'UCXLErrorBuilder':
"""Set the error cause"""
self.cause = cause
return self
def build(self) -> UCXLErrorResponse:
"""Build the error response"""
message = self.message or self.code.default_message()
details = self.details if self.details else None
error = UCXLError(
code=self.code,
message=message,
details=details,
source=self.source,
path=self.path,
request_id=self.request_id,
timestamp=datetime.now(timezone.utc),
cause=self.cause,
)
return UCXLErrorResponse(error=error)
class UCXLResponseBuilder:
"""Builder for creating UCXL Success responses"""
def __init__(self, code: UCXLResponseCode):
self.code = code
self.message = None
self.data = None
self.details = {}
self.request_id = f"req-{str(uuid.uuid4())[:8]}"
def message(self, message: str) -> 'UCXLResponseBuilder':
"""Set a custom success message"""
self.message = message
return self
def data(self, data: Any) -> 'UCXLResponseBuilder':
"""Set the response data"""
self.data = data
return self
def detail(self, key: str, value: Any) -> 'UCXLResponseBuilder':
"""Add a detail field"""
self.details[key] = value
return self
def request_id(self, request_id: str) -> 'UCXLResponseBuilder':
"""Set the request ID"""
self.request_id = request_id
return self
def build(self) -> UCXLSuccessResponse:
"""Build the success response"""
message = self.message or self.code.default_message()
details = self.details if self.details else None
response = UCXLResponse(
code=self.code,
message=message,
data=self.data,
details=details,
request_id=self.request_id,
timestamp=datetime.now(timezone.utc),
)
return UCXLSuccessResponse(response=response)
# Convenience functions for common error patterns
def create_invalid_address_error(address: str, path: str = "/", request_id: Optional[str] = None) -> UCXLErrorResponse:
"""Create a standardized invalid address error"""
builder = UCXLErrorBuilder(UCXLErrorCode.INVALID_ADDRESS)
builder.field("address", address)
builder.expected_format("ucxl://<agent>:<role>@<project>:<task>[/<temporal>/<path>]")
builder.path(path)
builder.cause("parse_error")
if request_id:
builder.request_id(request_id)
return builder.build()
def create_not_found_error(resource_id: str, path: str = "/", request_id: Optional[str] = None) -> UCXLErrorResponse:
"""Create a standardized not found error"""
builder = UCXLErrorBuilder(UCXLErrorCode.NOT_FOUND)
builder.field("resource_id", resource_id)
builder.path(path)
if request_id:
builder.request_id(request_id)
return builder.build()
def create_missing_field_error(field: str, path: str = "/", request_id: Optional[str] = None) -> UCXLErrorResponse:
"""Create a standardized missing field error"""
builder = UCXLErrorBuilder(UCXLErrorCode.MISSING_FIELD)
builder.message(f"Required field '{field}' is missing")
builder.field(field, None)
builder.path(path)
builder.cause("validation_error")
if request_id:
builder.request_id(request_id)
return builder.build()
def create_success_response(data: Any = None, path: str = "/", request_id: Optional[str] = None) -> UCXLSuccessResponse:
"""Create a standardized success response"""
builder = UCXLResponseBuilder(UCXLResponseCode.OK)
if data is not None:
builder.data(data)
if request_id:
builder.request_id(request_id)
return builder.build()
def create_created_response(resource_id: str, location: str, path: str = "/", request_id: Optional[str] = None) -> UCXLSuccessResponse:
"""Create a standardized resource created response"""
builder = UCXLResponseBuilder(UCXLResponseCode.CREATED)
builder.data({"id": resource_id, "url": location})
builder.detail("location", location)
if request_id:
builder.request_id(request_id)
return builder.build()
# Example usage and testing
if __name__ == "__main__":
# Example error response
error = UCXLErrorBuilder(UCXLErrorCode.INVALID_ADDRESS) \
.message("Test error message") \
.field("address", "ucxl://invalid") \
.expected_format("ucxl://<agent>:<role>@<project>:<task>") \
.source("test-service") \
.path("/test") \
.cause("parse_error") \
.build()
print("Error Response JSON:")
print(error.to_json())
print()
# Example success response
success = UCXLResponseBuilder(UCXLResponseCode.OK) \
.message("Test success") \
.data({"test": "value"}) \
.detail("info", "additional info") \
.build()
print("Success Response JSON:")
print(success.to_json())
print()
# Test serialization round-trip
error_json = error.to_json()
error_restored = UCXLErrorResponse.from_json(error_json)
print("Error serialization test:", error.error.code == error_restored.error.code)
success_json = success.to_json()
success_restored = UCXLSuccessResponse.from_json(success_json)
print("Success serialization test:", success.response.code == success_restored.response.code)