| package services |
|
|
| import ( |
| "bytes" |
| "github.com/libaxuan/cursor2api-go/models" |
| "github.com/libaxuan/cursor2api-go/utils" |
| "encoding/json" |
| "time" |
| ) |
|
|
| |
| func BuildResponseUsage(usage models.Usage) *models.ResponseUsage { |
| if usage.PromptTokens == 0 && usage.CompletionTokens == 0 && usage.TotalTokens == 0 { |
| return nil |
| } |
|
|
| return &models.ResponseUsage{ |
| InputTokens: usage.PromptTokens, |
| OutputTokens: usage.CompletionTokens, |
| TotalTokens: usage.TotalTokens, |
| OutputTokensDetails: &models.ResponseOutputTokensDetails{ |
| ReasoningTokens: 0, |
| }, |
| } |
| } |
|
|
| |
| func NewResponseFromRequest(req *models.ResponseRequest, id string, createdAt int64, status string, output []interface{}, outputText string, usage *models.ResponseUsage, completedAt *int64) models.Response { |
| if output == nil { |
| output = []interface{}{} |
| } |
|
|
| resp := models.Response{ |
| ID: id, |
| Object: "response", |
| CreatedAt: createdAt, |
| Status: status, |
| CompletedAt: completedAt, |
| Background: req.Background, |
| Instructions: decodeRaw(req.Instructions), |
| MaxOutputTokens: req.MaxOutputTokens, |
| MaxToolCalls: req.MaxToolCalls, |
| Model: req.Model, |
| Output: output, |
| OutputText: outputText, |
| ParallelToolCalls: resolveParallelToolCalls(req.ParallelToolCalls), |
| PreviousResponseID: req.PreviousResponseID, |
| Reasoning: decodeReasoning(req.Reasoning), |
| Store: req.Store, |
| Temperature: req.Temperature, |
| Text: decodeRaw(req.Text), |
| ToolChoice: decodeRaw(req.ToolChoice), |
| Tools: req.Tools, |
| TopP: req.TopP, |
| Truncation: req.Truncation, |
| Usage: usage, |
| User: req.User, |
| Metadata: req.Metadata, |
| } |
|
|
| return resp |
| } |
|
|
| |
| func BuildCompletedResponse(req *models.ResponseRequest, output []interface{}, outputText string, usage *models.ResponseUsage) models.Response { |
| now := time.Now().Unix() |
| complete := now |
| return NewResponseFromRequest(req, utils.GenerateResponseID(), now, "completed", output, outputText, usage, &complete) |
| } |
|
|
| func resolveParallelToolCalls(raw *bool) bool { |
| if raw == nil { |
| return false |
| } |
| return *raw |
| } |
|
|
| func decodeRaw(raw json.RawMessage) interface{} { |
| trimmed := bytes.TrimSpace(raw) |
| if len(trimmed) == 0 || string(trimmed) == "null" { |
| return nil |
| } |
| var val interface{} |
| if err := json.Unmarshal(trimmed, &val); err != nil { |
| return nil |
| } |
| return val |
| } |
|
|
| func decodeReasoning(raw json.RawMessage) *models.ResponseReasoning { |
| trimmed := bytes.TrimSpace(raw) |
| if len(trimmed) == 0 || string(trimmed) == "null" { |
| return nil |
| } |
| var val map[string]interface{} |
| if err := json.Unmarshal(trimmed, &val); err != nil { |
| return nil |
| } |
| reasoning := &models.ResponseReasoning{} |
| if effort, ok := val["effort"].(string); ok { |
| reasoning.Effort = &effort |
| } |
| if summary, ok := val["summary"]; ok { |
| reasoning.Summary = summary |
| } |
| return reasoning |
| } |
|
|