package main import "encoding/json" // --- Claude API Structs (Anthropic Format) --- // ClaudeRequest represents the incoming request structure from the client type ClaudeRequest struct { Model string `json:"model"` Messages []ClaudeMessage `json:"messages"` System json.RawMessage `json:"system,omitempty"` MaxTokens *int `json:"max_tokens,omitempty"` StopSequences []string `json:"stop_sequences,omitempty"` Stream bool `json:"stream,omitempty"` Temperature *float64 `json:"temperature,omitempty"` TopP *float64 `json:"top_p,omitempty"` TopK *int `json:"top_k,omitempty"` } // ClaudeMessage represents a message in the Claude request type ClaudeMessage struct { Role string `json:"role"` // "user" or "assistant" Name string `json:"name,omitempty"` // **THÊM MỚI:** Dùng để nhận diện các khối đặc biệt như "character_card", "authors_note" Content json.RawMessage `json:"content"` // Can be string or list of blocks } // ClaudeContentBlock represents a block within the content array type ClaudeContentBlock struct { Type string `json:"type"` Text string `json:"text,omitempty"` } // ... Các struct còn lại giữ nguyên ... // ClaudeResponse represents the non-streaming response structure sent to the client type ClaudeResponse struct { ID string `json:"id"` Type string `json:"type"` // e.g., "message" Role string `json:"role"` // e.g., "assistant" Content []ClaudeContentBlock `json:"content"` Model string `json:"model"` StopReason string `json:"stop_reason"` // e.g., "end_turn", "max_tokens" StopSequence *string `json:"stop_sequence"` // Usually null Usage ClaudeUsage `json:"usage"` } // ClaudeUsage represents the token usage information type ClaudeUsage struct { InputTokens int `json:"input_tokens"` OutputTokens int `json:"output_tokens"` } // ClaudeErrorResponse represents the error structure sent to the client type ClaudeErrorResponse struct { Type string `json:"type"` // Always "error" Error ClaudeError `json:"error"` } // ClaudeError represents the detailed error information type ClaudeError struct { Type string `json:"type"` // e.g., "invalid_request_error", "api_error" Message string `json:"message"` } // --- OpenAI API Structs --- // OpenAIRequest represents the request structure sent to the upstream OpenAI API type OpenAIRequest struct { Model string `json:"model"` Messages []OpenAIMessage `json:"messages"` MaxTokens *int `json:"max_tokens,omitempty"` Temperature *float64 `json:"temperature,omitempty"` TopP *float64 `json:"top_p,omitempty"` TopK *int `json:"top_k,omitempty"` Stop []string `json:"stop,omitempty"` Stream bool `json:"stream,omitempty"` } // OpenAIMessage represents a message in the OpenAI request type OpenAIMessage struct { Role string `json:"role"` // "system", "user", or "assistant" Content string `json:"content"` } // OpenAIResponse represents the non-streaming response from the upstream OpenAI API type OpenAIResponse struct { ID string `json:"id"` Object string `json:"object"` // e.g., "chat.completion" Created int64 `json:"created"` Model string `json:"model"` Choices []OpenAIChoice `json:"choices"` Usage *OpenAIUsage `json:"usage,omitempty"` } // OpenAIChoice represents a choice in the OpenAI response type OpenAIChoice struct { Index int `json:"index"` Message OpenAIMessage `json:"message"` FinishReason *string `json:"finish_reason"` } // OpenAIUsage represents the token usage information from OpenAI type OpenAIUsage struct { PromptTokens int `json:"prompt_tokens"` CompletionTokens int `json:"completion_tokens"` TotalTokens int `json:"total_tokens"` } // OpenAIStreamChoice represents a choice within an OpenAI SSE chunk type OpenAIStreamChoice struct { Index int `json:"index"` Delta OpenAIStreamDelta `json:"delta"` FinishReason *string `json:"finish_reason"` } // OpenAIStreamDelta represents the delta content within an OpenAI SSE chunk type OpenAIStreamDelta struct { Role *string `json:"role,omitempty"` Content *string `json:"content,omitempty"` } // OpenAIStreamChunk represents the structure of a data chunk in the OpenAI SSE stream type OpenAIStreamChunk struct { ID string `json:"id"` Object string `json:"object"` // e.g., "chat.completion.chunk" Created int64 `json:"created"` Model string `json:"model"` Choices []OpenAIStreamChoice `json:"choices"` Usage *OpenAIUsage `json:"usage,omitempty"` } // --- Claude SSE Structs (for sending back to client) --- // ClaudeSSEEvent represents a generic Claude SSE event structure for easy marshaling type ClaudeSSEEvent struct { Type string `json:"type"` Index *int `json:"index,omitempty"` Message *ClaudeSSEMessage `json:"message,omitempty"` ContentBlock *ClaudeSSEContentBlock `json:"content_block,omitempty"` Delta *ClaudeSSEDelta `json:"delta,omitempty"` Usage *ClaudeSSEUsage `json:"usage,omitempty"` Error *ClaudeError `json:"error,omitempty"` } // ClaudeSSEMessage is nested within message_start type ClaudeSSEMessage struct { ID string `json:"id"` Type string `json:"type"` // "message" Role string `json:"role"` // "assistant" Content []ClaudeContentBlock `json:"content"` // Initially empty Model string `json:"model"` StopReason *string `json:"stop_reason"` // Initially null StopSequence *string `json:"stop_sequence"` // Initially null Usage ClaudeUsage `json:"usage"` // Initial usage (input tokens) } // ClaudeSSEContentBlock is nested within content_block_start type ClaudeSSEContentBlock struct { Type string `json:"type"` // "text" Text string `json:"text"` // Initially empty } // ClaudeSSEDelta is nested within content_block_delta and message_delta type ClaudeSSEDelta struct { Type string `json:"type,omitempty"` // "text_delta" in content_block_delta Text *string `json:"text,omitempty"` // Pointer for content_block_delta StopReason *string `json:"stop_reason,omitempty"` // Pointer for message_delta StopSequence *string `json:"stop_sequence,omitempty"` // Pointer for message_delta (usually null) } // ClaudeSSEUsage is nested within message_delta (HACK) and message_stop type ClaudeSSEUsage struct { InputTokens *int `json:"input_tokens,omitempty"` // Only in message_stop OutputTokens int `json:"output_tokens"` }