| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| package models |
|
|
| import ( |
| "encoding/json" |
| "time" |
| ) |
|
|
| |
| type ChatCompletionRequest struct { |
| Model string `json:"model" binding:"required"` |
| Messages []Message `json:"messages" binding:"required"` |
| Stream bool `json:"stream,omitempty"` |
| Temperature *float64 `json:"temperature,omitempty"` |
| MaxTokens *int `json:"max_tokens,omitempty"` |
| TopP *float64 `json:"top_p,omitempty"` |
| Stop []string `json:"stop,omitempty"` |
| User string `json:"user,omitempty"` |
| Tools []Tool `json:"tools,omitempty"` |
| ToolChoice json.RawMessage `json:"tool_choice,omitempty"` |
| } |
|
|
| |
| type Message struct { |
| Role string `json:"role" binding:"required"` |
| Content interface{} `json:"content"` |
| ToolCalls []ToolCall `json:"tool_calls,omitempty"` |
| ToolCallID string `json:"tool_call_id,omitempty"` |
| Name string `json:"name,omitempty"` |
| } |
|
|
| |
| type ContentPart struct { |
| Type string `json:"type"` |
| Text string `json:"text,omitempty"` |
| URL string `json:"url,omitempty"` |
| } |
|
|
| |
| type Tool struct { |
| Type string `json:"type"` |
| Function FunctionDefinition `json:"function"` |
| } |
|
|
| |
| type FunctionDefinition struct { |
| Name string `json:"name"` |
| Description string `json:"description,omitempty"` |
| Parameters map[string]interface{} `json:"parameters,omitempty"` |
| } |
|
|
| |
| type ToolCall struct { |
| ID string `json:"id"` |
| Type string `json:"type"` |
| Function FunctionCall `json:"function"` |
| } |
|
|
| |
| type FunctionCall struct { |
| Name string `json:"name"` |
| Arguments string `json:"arguments"` |
| } |
|
|
| |
| type ToolChoiceObject struct { |
| Type string `json:"type"` |
| Function *ToolChoiceFunction `json:"function,omitempty"` |
| } |
|
|
| |
| type ToolChoiceFunction struct { |
| Name string `json:"name"` |
| } |
|
|
| |
| type ChatCompletionResponse struct { |
| ID string `json:"id"` |
| Object string `json:"object"` |
| Created int64 `json:"created"` |
| Model string `json:"model"` |
| Choices []Choice `json:"choices"` |
| Usage Usage `json:"usage"` |
| } |
|
|
| |
| type ChatCompletionStreamResponse struct { |
| ID string `json:"id"` |
| Object string `json:"object"` |
| Created int64 `json:"created"` |
| Model string `json:"model"` |
| Choices []StreamChoice `json:"choices"` |
| } |
|
|
| |
| type Choice struct { |
| Index int `json:"index"` |
| Message Message `json:"message"` |
| FinishReason string `json:"finish_reason"` |
| } |
|
|
| |
| type StreamChoice struct { |
| Index int `json:"index"` |
| Delta StreamDelta `json:"delta"` |
| FinishReason *string `json:"finish_reason"` |
| } |
|
|
| |
| type StreamDelta struct { |
| Role string `json:"role,omitempty"` |
| Content string `json:"content,omitempty"` |
| ToolCalls []ToolCallDelta `json:"tool_calls,omitempty"` |
| } |
|
|
| |
| type ToolCallDelta struct { |
| Index int `json:"index"` |
| ID string `json:"id,omitempty"` |
| Type string `json:"type,omitempty"` |
| Function *FunctionCallDelta `json:"function,omitempty"` |
| } |
|
|
| |
| type FunctionCallDelta struct { |
| Name string `json:"name,omitempty"` |
| Arguments string `json:"arguments,omitempty"` |
| } |
|
|
| |
| type Usage struct { |
| PromptTokens int `json:"prompt_tokens"` |
| CompletionTokens int `json:"completion_tokens"` |
| TotalTokens int `json:"total_tokens"` |
| } |
|
|
| |
| type Model struct { |
| ID string `json:"id"` |
| Object string `json:"object"` |
| Created int64 `json:"created"` |
| OwnedBy string `json:"owned_by"` |
| MaxTokens int `json:"max_tokens,omitempty"` |
| ContextWindow int `json:"context_window,omitempty"` |
| } |
|
|
| |
| type ModelsResponse struct { |
| Object string `json:"object"` |
| Data []Model `json:"data"` |
| } |
|
|
| |
| type ErrorResponse struct { |
| Error ErrorDetail `json:"error"` |
| } |
|
|
| |
| type ErrorDetail struct { |
| Message string `json:"message"` |
| Type string `json:"type"` |
| Code string `json:"code,omitempty"` |
| } |
|
|
| |
| type CursorMessage struct { |
| Role string `json:"role"` |
| Parts []CursorPart `json:"parts"` |
| } |
|
|
| |
| type CursorPart struct { |
| Type string `json:"type"` |
| Text string `json:"text"` |
| } |
|
|
| |
| type CursorRequest struct { |
| Context []interface{} `json:"context"` |
| Model string `json:"model"` |
| ID string `json:"id"` |
| Messages []CursorMessage `json:"messages"` |
| Trigger string `json:"trigger"` |
| } |
|
|
| |
| type CursorEventData struct { |
| Type string `json:"type"` |
| Delta string `json:"delta,omitempty"` |
| ErrorText string `json:"errorText,omitempty"` |
| MessageMetadata *CursorMessageMetadata `json:"messageMetadata,omitempty"` |
| } |
|
|
| |
| type CursorMessageMetadata struct { |
| Usage *CursorUsage `json:"usage,omitempty"` |
| } |
|
|
| |
| type CursorUsage struct { |
| InputTokens int `json:"inputTokens"` |
| OutputTokens int `json:"outputTokens"` |
| TotalTokens int `json:"totalTokens"` |
| } |
|
|
| |
| type SSEEvent struct { |
| Data string `json:"data"` |
| Event string `json:"event,omitempty"` |
| ID string `json:"id,omitempty"` |
| } |
|
|
| |
| type CursorParseConfig struct { |
| TriggerSignal string |
| ThinkingEnabled bool |
| } |
|
|
| |
| type AssistantEventKind string |
|
|
| const ( |
| AssistantEventText AssistantEventKind = "text" |
| AssistantEventThinking AssistantEventKind = "thinking" |
| AssistantEventToolCall AssistantEventKind = "tool_call" |
| ) |
|
|
| |
| type AssistantEvent struct { |
| Kind AssistantEventKind |
| Text string |
| Thinking string |
| ToolCall *ToolCall |
| } |
|
|
| |
| func (m *Message) GetStringContent() string { |
| if m.Content == nil { |
| return "" |
| } |
|
|
| switch content := m.Content.(type) { |
| case string: |
| return content |
| case []ContentPart: |
| var text string |
| for _, part := range content { |
| if part.Type == "text" { |
| text += part.Text |
| } |
| } |
| return text |
| case []interface{}: |
| var text string |
| for _, item := range content { |
| if part, ok := item.(map[string]interface{}); ok { |
| if partType, exists := part["type"].(string); exists && partType == "text" { |
| if textContent, exists := part["text"].(string); exists { |
| text += textContent |
| } |
| } |
| } |
| } |
| return text |
| default: |
| if data, err := json.Marshal(content); err == nil { |
| return string(data) |
| } |
| return "" |
| } |
| } |
|
|
| |
| func ToCursorMessages(messages []Message, systemPromptInject string) []CursorMessage { |
| var result []CursorMessage |
|
|
| if systemPromptInject != "" { |
| if len(messages) > 0 && messages[0].Role == "system" { |
| content := messages[0].GetStringContent() |
| content += "\n" + systemPromptInject |
| result = append(result, CursorMessage{ |
| Role: "system", |
| Parts: []CursorPart{ |
| {Type: "text", Text: content}, |
| }, |
| }) |
| messages = messages[1:] |
| } else { |
| result = append(result, CursorMessage{ |
| Role: "system", |
| Parts: []CursorPart{ |
| {Type: "text", Text: systemPromptInject}, |
| }, |
| }) |
| } |
| } else if len(messages) > 0 && messages[0].Role == "system" { |
| result = append(result, CursorMessage{ |
| Role: "system", |
| Parts: []CursorPart{ |
| {Type: "text", Text: messages[0].GetStringContent()}, |
| }, |
| }) |
| messages = messages[1:] |
| } |
|
|
| for _, msg := range messages { |
| if msg.Role == "" { |
| continue |
| } |
|
|
| result = append(result, CursorMessage{ |
| Role: msg.Role, |
| Parts: []CursorPart{ |
| { |
| Type: "text", |
| Text: msg.GetStringContent(), |
| }, |
| }, |
| }) |
| } |
|
|
| return result |
| } |
|
|
| |
| func NewChatCompletionResponse(id, model string, message Message, finishReason string, usage Usage) *ChatCompletionResponse { |
| return &ChatCompletionResponse{ |
| ID: id, |
| Object: "chat.completion", |
| Created: time.Now().Unix(), |
| Model: model, |
| Choices: []Choice{ |
| { |
| Index: 0, |
| Message: message, |
| FinishReason: finishReason, |
| }, |
| }, |
| Usage: usage, |
| } |
| } |
|
|
| |
| func NewChatCompletionStreamResponse(id, model string, delta StreamDelta, finishReason *string) *ChatCompletionStreamResponse { |
| return &ChatCompletionStreamResponse{ |
| ID: id, |
| Object: "chat.completion.chunk", |
| Created: time.Now().Unix(), |
| Model: model, |
| Choices: []StreamChoice{ |
| { |
| Index: 0, |
| Delta: delta, |
| FinishReason: finishReason, |
| }, |
| }, |
| } |
| } |
|
|
| |
| func NewErrorResponse(message, errorType, code string) *ErrorResponse { |
| return &ErrorResponse{ |
| Error: ErrorDetail{ |
| Message: message, |
| Type: errorType, |
| Code: code, |
| }, |
| } |
| } |
|
|