package proxy import ( "encoding/json" "openteam/server/internal/proxy/claude" "openteam/server/internal/proxy/openai" "openteam/server/internal/proxy/responses" ) // parseUsageForProtocol extracts token usage from a non-stream response body. func parseUsageForProtocol(proto Protocol, body []byte) *tokenUsage { switch proto { case ProtocolAnthropic: var mr claude.MessageResponse if err := json.Unmarshal(body, &mr); err != nil || mr.Usage == nil { return nil } return &tokenUsage{ input: mr.Usage.InputTokens, output: mr.Usage.OutputTokens, cacheRead: mr.Usage.CacheReadInputTokens, cacheCreation: mr.Usage.CacheCreationInputTokens, } case ProtocolOpenAIResponses: var r responses.Response if err := json.Unmarshal(body, &r); err != nil || r.Usage == nil { return nil } return &tokenUsage{ input: r.Usage.InputTokens, output: r.Usage.OutputTokens, cacheRead: r.Usage.InputTokensDetails.CachedTokens, } default: var cc openai.ChatCompletion if err := json.Unmarshal(body, &cc); err != nil || cc.Usage == nil { return nil } return &tokenUsage{input: cc.Usage.PromptTokens, output: cc.Usage.CompletionTokens} } } // estimateTokensFromText is a coarse fallback used when the upstream omits usage. func estimateTokensFromText(s string) int64 { // ~4 chars per token, per OpenAI's common heuristic. return int64(len(s)/4 + 1) }