Files
synapse/pkg/types/content.go
2026-06-28 03:24:26 +08:00

390 lines
13 KiB
Go

package types
// =============================================================================
// Transport Mode Definitions
// =============================================================================
// TransportMode defines the transport mode for task communication
type TransportMode string
const (
TransportModeCallback TransportMode = "callback" // Async callback (webhook)
TransportModePolling TransportMode = "polling" // Async polling
TransportModeSync TransportMode = "sync" // Synchronous
TransportModeHybrid TransportMode = "hybrid" // Callback + Polling fallback
)
// TransportPreferences defines transport preferences for a task
type TransportPreferences struct {
Preferred TransportMode `json:"preferred"`
Fallback TransportMode `json:"fallback,omitempty"`
CallbackEndpoint string `json:"callback_endpoint,omitempty"`
PollingInterval int `json:"polling_interval,omitempty"` // seconds
ProgressUpdates bool `json:"progress_updates"`
ProgressInterval int `json:"progress_interval,omitempty"` // seconds
}
// DefaultTransportPreferences returns default transport preferences
func DefaultTransportPreferences() *TransportPreferences {
return &TransportPreferences{
Preferred: TransportModeCallback,
Fallback: TransportModePolling,
PollingInterval: 5,
ProgressUpdates: true,
ProgressInterval: 10,
}
}
// =============================================================================
// Content Type Definitions
// =============================================================================
// MIME type constants
const (
MIMEJSON = "application/json"
MIMETextPlain = "text/plain"
MIMETextMarkdown = "text/markdown"
MIMETextHTML = "text/html"
MIMETextCSV = "text/csv"
MIMEImageJPEG = "image/jpeg"
MIMEImagePNG = "image/png"
MIMEImageWebP = "image/webp"
MIMEImageGIF = "image/gif"
MIMEImageSVG = "image/svg+xml"
MIMEVideoMP4 = "video/mp4"
MIMEVideoWebM = "video/webm"
MIMEAudioMP3 = "audio/mpeg"
MIMEAudioWAV = "audio/wav"
MIMEAudioAAC = "audio/aac"
MIMEPDF = "application/pdf"
MIMEOctetStream = "application/octet-stream"
MIMEMultipartForm = "multipart/form-data"
)
// ContentEncoding defines content encoding methods
type ContentEncoding string
const (
EncodingNone ContentEncoding = "none"
EncodingBase64 ContentEncoding = "base64"
EncodingGzip ContentEncoding = "gzip"
EncodingDeflate ContentEncoding = "deflate"
)
// TransferMode defines how content is transferred
type TransferMode string
const (
TransferInline TransferMode = "inline" // Embedded in message (base64)
TransferURL TransferMode = "url" // Via URL reference
TransferStreaming TransferMode = "streaming" // Via streaming protocol
TransferMultipart TransferMode = "multipart" // Via multipart form
)
// =============================================================================
// Content Objects
// =============================================================================
// ContentBase is the base struct for all content types
type ContentBase struct {
MIMEType string `json:"mime_type"`
Encoding ContentEncoding `json:"encoding,omitempty"`
Size int64 `json:"size,omitempty"`
Checksum string `json:"checksum,omitempty"` // format: "sha256:xxx"
TransferMode TransferMode `json:"transfer_mode"`
}
// TextContent represents textual content
type TextContent struct {
ContentBase
Charset string `json:"charset"`
Language string `json:"language,omitempty"`
Data string `json:"data"`
}
// JSONContent represents JSON structured content
type JSONContent struct {
ContentBase
Schema string `json:"schema,omitempty"` // Schema identifier
SchemaURL string `json:"schema_url,omitempty"` // URL to schema definition
Data any `json:"data"`
}
// CodeContent represents source code content
type CodeContent struct {
ContentBase
Language string `json:"language"`
Version string `json:"version,omitempty"`
Dependencies []string `json:"dependencies,omitempty"`
Data string `json:"data"`
}
// FileContent represents a file (image, video, document, etc.)
type FileContent struct {
ContentBase
Name string `json:"name"`
Role string `json:"role,omitempty"` // e.g., "reference", "result", "attachment"
Description string `json:"description,omitempty"`
// For inline transfer
Data string `json:"data,omitempty"` // base64 encoded if binary
// For URL transfer
URL string `json:"url,omitempty"`
URLExpiresAt *Timestamp `json:"url_expires_at,omitempty"`
DownloadMethod string `json:"download_method,omitempty"` // GET, POST, signed_url
RangeSupported bool `json:"range_supported,omitempty"`
// Metadata
Width int `json:"width,omitempty"` // images/videos
Height int `json:"height,omitempty"` // images/videos
Duration float64 `json:"duration,omitempty"` // audio/video (seconds)
Resolution string `json:"resolution,omitempty"` // videos
ThumbnailURL string `json:"thumbnail_url,omitempty"`
}
// =============================================================================
// Content Bundles (multiple files)
// =============================================================================
// ContentBundle represents a collection of content items
type ContentBundle struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Items []ContentBundleItem `json:"items"`
TotalSize int64 `json:"total_size,omitempty"`
CreatedAt Timestamp `json:"created_at"`
}
// ContentBundleItem is an item in a content bundle
type ContentBundleItem struct {
ID string `json:"id"`
Role string `json:"role"` // main, reference, attachment, thumbnail, etc.
Content any `json:"content"` // TextContent | FileContent | JSONContent | CodeContent
}
// =============================================================================
// File Transfer Helper Functions
// =============================================================================
// IsSmallFile checks if a file should be transferred inline
func IsSmallFile(size int64, threshold int64) bool {
if threshold <= 0 {
threshold = 1024 * 1024 // 1MB default
}
return size <= threshold
}
// InferMimeType infers MIME type from filename
func InferMimeType(filename string) string {
extMap := map[string]string{
".json": MIMEJSON,
".txt": MIMETextPlain,
".md": MIMETextMarkdown,
".html": MIMETextHTML,
".htm": MIMETextHTML,
".csv": MIMETextCSV,
".jpg": MIMEImageJPEG,
".jpeg": MIMEImageJPEG,
".png": MIMEImagePNG,
".webp": MIMEImageWebP,
".gif": MIMEImageGIF,
".svg": MIMEImageSVG,
".mp4": MIMEVideoMP4,
".webm": MIMEVideoWebM,
".mp3": MIMEAudioMP3,
".wav": MIMEAudioWAV,
".aac": MIMEAudioAAC,
".pdf": MIMEPDF,
".bin": MIMEOctetStream,
}
// Simple extension matching (lowercase would be better)
for ext, mime := range extMap {
if len(filename) > len(ext) && filename[len(filename)-len(ext):] == ext {
return mime
}
// Also check uppercase
upperExt := toUpper(ext)
if len(filename) > len(upperExt) && filename[len(filename)-len(upperExt):] == upperExt {
return mime
}
}
return MIMEOctetStream
}
func toUpper(s string) string {
result := make([]byte, len(s))
for i := 0; i < len(s); i++ {
c := s[i]
if c >= 'a' && c <= 'z' {
c = c - 'a' + 'A'
}
result[i] = c
}
return string(result)
}
// NewInlineFileContent creates an inline file content (for small files)
func NewInlineFileContent(name, mimeType string, data []byte, role string) *FileContent {
// base64 encode would happen here in real implementation
return &FileContent{
ContentBase: ContentBase{
MIMEType: mimeType,
Encoding: EncodingBase64,
Size: int64(len(data)),
TransferMode: TransferInline,
},
Name: name,
Role: role,
Data: "", // base64.RawStdEncoding.EncodeToString(data)
}
}
// NewURLFileContent creates a URL-referenced file content (for large files)
func NewURLFileContent(name, mimeType string, size int64, url string, expiresAt *Timestamp, role string) *FileContent {
return &FileContent{
ContentBase: ContentBase{
MIMEType: mimeType,
Size: size,
TransferMode: TransferURL,
},
Name: name,
Role: role,
URL: url,
URLExpiresAt: expiresAt,
DownloadMethod: "GET",
RangeSupported: true,
}
}
// =============================================================================
// Polling API Types
// =============================================================================
// TaskStatusResponse is the response for task status polling
type TaskStatusResponse struct {
Success bool `json:"success"`
Task *TaskInfo `json:"task,omitempty"`
Error *SynapseError `json:"error,omitempty"`
}
// TaskInfo represents task status information
type TaskInfo struct {
ID string `json:"id"`
Type string `json:"type"`
Status string `json:"status"`
Progress int `json:"progress"`
Message string `json:"message,omitempty"`
CreatedAt Timestamp `json:"created_at"`
UpdatedAt Timestamp `json:"updated_at"`
ETA *Timestamp `json:"eta,omitempty"`
Result any `json:"result,omitempty"`
Error *SynapseError `json:"error,omitempty"`
ETag string `json:"etag,omitempty"`
}
// TaskListResponse is the response for listing tasks
type TaskListResponse struct {
Success bool `json:"success"`
Tasks []TaskInfo `json:"tasks"`
Total int `json:"total"`
Limit int `json:"limit"`
Offset int `json:"offset"`
HasMore bool `json:"has_more"`
}
// TaskEvent represents a task event
type TaskEvent struct {
ID string `json:"id"`
Type string `json:"type"` // status_update, progress, log, error, complete
Timestamp Timestamp `json:"timestamp"`
Data any `json:"data"`
}
// TaskEventsResponse is the response for task events
type TaskEventsResponse struct {
Success bool `json:"success"`
Since string `json:"since"`
Events []TaskEvent `json:"events"`
HasMore bool `json:"has_more"`
Next string `json:"next_cursor,omitempty"`
}
// =============================================================================
// Streaming Types
// =============================================================================
// StreamChunk represents a chunk of streaming data
type StreamChunk struct {
TaskID string `json:"task_id"`
Sequence int64 `json:"sequence"`
ChunkType string `json:"chunk_type"` // text, binary, audio, video
Data string `json:"data"` // base64 for binary
Final bool `json:"final"`
Timestamp Timestamp `json:"timestamp"`
}
// StreamComplete is sent when streaming is complete
type StreamComplete struct {
TaskID string `json:"task_id"`
TotalChunks int64 `json:"total_chunks"`
FullContentChecksum string `json:"full_content_checksum"`
Result any `json:"result,omitempty"`
}
// =============================================================================
// Capabilities Query (Synchronous)
// =============================================================================
// CapabilitiesResponse is the response for capability query
type CapabilitiesResponse struct {
Success bool `json:"success"`
Data *AgentCapabilities `json:"data,omitempty"`
Error *SynapseError `json:"error,omitempty"`
}
// AgentCapabilities describes an agent's capabilities
type AgentCapabilities struct {
AgentID string `json:"agent_id"`
AgentName string `json:"agent_name"`
SystemID string `json:"system_id"`
ProtocolVersion string `json:"protocol_version"`
SupportedTaskTypes []SupportedTaskType `json:"supported_task_types"`
SupportedContentTypes []string `json:"supported_content_types"`
SupportedTransportModes []TransportMode `json:"supported_transport_modes"`
// Limits
MaxFileSize int64 `json:"max_file_size"`
MaxConcurrentTasks int `json:"max_concurrent_tasks"`
MaxTaskDuration int `json:"max_task_duration_seconds"`
// Features
SupportProgressUpdates bool `json:"support_progress_updates"`
SupportStreaming bool `json:"support_streaming"`
SupportHiL bool `json:"support_hil"`
SupportGroups bool `json:"support_groups"`
}
// SupportedTaskType describes a supported task type
type SupportedTaskType struct {
Type string `json:"type"`
Name string `json:"name"`
Description string `json:"description"`
EstimatedTime string `json:"estimated_time"` // e.g., "30s-2min"
InputSchema string `json:"input_schema,omitempty"`
OutputSchema string `json:"output_schema,omitempty"`
Capabilities []string `json:"capabilities,omitempty"`
}
// NewCapabilitiesResponse creates a capabilities response
func NewCapabilitiesResponse(caps *AgentCapabilities) *CapabilitiesResponse {
return &CapabilitiesResponse{
Success: true,
Data: caps,
}
}