package valueobjects // AIResponse is the outcome of an AI call. A success carries Content, // Usage and the provider's decoded answer in Raw; a failure carries Error, // PHP's message for the caller, and sometimes Raw (the provider's error // body, or {"raw": body} when the answer was not JSON). Err is the Go // error behind a failure, for logs and tests; it is never shown to a user // and may be nil. type AIResponse struct { Success bool Content string Error string Usage map[string]any Raw map[string]any Err error } // Success builds a successful response. func Success(content string, usage, raw map[string]any) AIResponse { if usage == nil { usage = map[string]any{} } if raw == nil { raw = map[string]any{} } return AIResponse{Success: true, Content: content, Usage: usage, Raw: raw} } // Failure builds a failed response. func Failure(message string, raw map[string]any) AIResponse { if raw == nil { raw = map[string]any{} } return AIResponse{Error: message, Usage: map[string]any{}, Raw: raw} } // TotalTokens is usage.total_tokens, 0 when absent. func (r AIResponse) TotalTokens() int { return usageInt(r.Usage, "total_tokens") } // PromptTokens is usage.prompt_tokens, 0 when absent. func (r AIResponse) PromptTokens() int { return usageInt(r.Usage, "prompt_tokens") } // CompletionTokens is usage.completion_tokens, 0 when absent. func (r AIResponse) CompletionTokens() int { return usageInt(r.Usage, "completion_tokens") } func usageInt(m map[string]any, k string) int { switch n := m[k].(type) { case int: return n case int64: return int(n) case float64: return int(n) } return 0 }