package schema import ( "context" "encoding/json" ) // AnthropicSystemParam accepts system as string or array of content blocks (SDK sends array). type AnthropicSystemParam string // UnmarshalJSON accepts string or array of blocks with "text" field. func (s *AnthropicSystemParam) UnmarshalJSON(data []byte) error { var raw interface{} if err := json.Unmarshal(data, &raw); err != nil { return err } switch v := raw.(type) { case string: *s = AnthropicSystemParam(v) return nil case []interface{}: var out string for _, block := range v { if m, ok := block.(map[string]interface{}); ok && m["type"] == "text" { if t, ok := m["text"].(string); ok { out += t } } } *s = AnthropicSystemParam(out) return nil } return nil } // AnthropicRequest represents a request to the Anthropic Messages API // https://docs.anthropic.com/claude/reference/messages_post type AnthropicRequest struct { Model string `json:"model"` Messages []AnthropicMessage `json:"messages"` MaxTokens int `json:"max_tokens"` Metadata map[string]string `json:"metadata,omitempty"` StopSequences []string `json:"stop_sequences,omitempty"` Stream bool `json:"stream,omitempty"` System AnthropicSystemParam `json:"system,omitempty"` Temperature *float64 `json:"temperature,omitempty"` TopK *int `json:"top_k,omitempty"` TopP *float64 `json:"top_p,omitempty"` Tools []AnthropicTool `json:"tools,omitempty"` ToolChoice interface{} `json:"tool_choice,omitempty"` // Internal fields for request handling Context context.Context `json:"-"` Cancel context.CancelFunc `json:"-"` } // ModelName implements the LocalAIRequest interface func (ar *AnthropicRequest) ModelName(s *string) string { if s != nil { ar.Model = *s } return ar.Model } // AnthropicTool represents a tool definition in the Anthropic format type AnthropicTool struct { Name string `json:"name"` Description string `json:"description,omitempty"` InputSchema map[string]interface{} `json:"input_schema"` } // AnthropicMessage represents a message in the Anthropic format type AnthropicMessage struct { Role string `json:"role"` Content interface{} `json:"content"` } // AnthropicContentBlock represents a content block in an Anthropic message type AnthropicContentBlock struct { Type string `json:"type"` Text string `json:"text,omitempty"` Source *AnthropicImageSource `json:"source,omitempty"` ID string `json:"id,omitempty"` Name string `json:"name,omitempty"` Input map[string]interface{} `json:"input,omitempty"` ToolUseID string `json:"tool_use_id,omitempty"` Content interface{} `json:"content,omitempty"` IsError *bool `json:"is_error,omitempty"` } // AnthropicImageSource represents an image source in Anthropic format type AnthropicImageSource struct { Type string `json:"type"` MediaType string `json:"media_type"` Data string `json:"data"` } // AnthropicResponse represents a response from the Anthropic Messages API type AnthropicResponse struct { ID string `json:"id"` Type string `json:"type"` Role string `json:"role"` Content []AnthropicContentBlock `json:"content"` Model string `json:"model"` StopReason *string `json:"stop_reason"` StopSequence *string `json:"stop_sequence,omitempty"` Usage AnthropicUsage `json:"usage"` } // AnthropicUsage represents token usage in Anthropic format type AnthropicUsage struct { InputTokens int `json:"input_tokens"` OutputTokens int `json:"output_tokens"` } // AnthropicStreamEvent represents a streaming event from the Anthropic API type AnthropicStreamEvent struct { Type string `json:"type"` Index int `json:"index,omitempty"` ContentBlock *AnthropicContentBlock `json:"content_block,omitempty"` Delta *AnthropicStreamDelta `json:"delta,omitempty"` Message *AnthropicStreamMessage `json:"message,omitempty"` Usage *AnthropicUsage `json:"usage,omitempty"` } // AnthropicStreamDelta represents the delta in a streaming response type AnthropicStreamDelta struct { Type string `json:"type,omitempty"` Text string `json:"text,omitempty"` PartialJSON string `json:"partial_json,omitempty"` StopReason *string `json:"stop_reason,omitempty"` StopSequence *string `json:"stop_sequence,omitempty"` } // AnthropicStreamMessage represents the message object in streaming events type AnthropicStreamMessage struct { ID string `json:"id"` Type string `json:"type"` Role string `json:"role"` Content []AnthropicContentBlock `json:"content"` Model string `json:"model"` StopReason *string `json:"stop_reason"` StopSequence *string `json:"stop_sequence,omitempty"` Usage AnthropicUsage `json:"usage"` } // AnthropicErrorResponse represents an error response from the Anthropic API type AnthropicErrorResponse struct { Type string `json:"type"` Error AnthropicError `json:"error"` } // AnthropicError represents an error in the Anthropic format type AnthropicError struct { Type string `json:"type"` Message string `json:"message"` } // GetStringContent extracts the string content from an AnthropicMessage // Content can be either a string or an array of content blocks func (m *AnthropicMessage) GetStringContent() string { switch content := m.Content.(type) { case string: return content case []interface{}: var result string for _, block := range content { if blockMap, ok := block.(map[string]interface{}); ok { if blockMap["type"] == "text" { if text, ok := blockMap["text"].(string); ok { result += text } } } } return result } return "" } // GetContentBlocks extracts content blocks from an AnthropicMessage func (m *AnthropicMessage) GetContentBlocks() []AnthropicContentBlock { switch content := m.Content.(type) { case string: return []AnthropicContentBlock{{Type: "text", Text: content}} case []interface{}: var blocks []AnthropicContentBlock for _, block := range content { if blockMap, ok := block.(map[string]interface{}); ok { cb := AnthropicContentBlock{} data, err := json.Marshal(blockMap) if err != nil { continue } if err := json.Unmarshal(data, &cb); err != nil { continue } blocks = append(blocks, cb) } } return blocks } return nil }