==================== 管理 API ====================
(w http.ResponseWriter, r *http.Request)
| 2145 | "delta": map[string]interface{}{}, |
| 2146 | "finish_reason": finishReason, |
| 2147 | }}, |
| 2148 | "usage": map[string]int{ |
| 2149 | "prompt_tokens": inputTokens, |
| 2150 | "completion_tokens": outputTokens, |
| 2151 | "total_tokens": inputTokens + outputTokens, |
| 2152 | }, |
| 2153 | } |
| 2154 | data, _ := json.Marshal(chunk) |
| 2155 | fmt.Fprintf(w, "data: %s\n\n", string(data)) |
| 2156 | fmt.Fprintf(w, "data: [DONE]\n\n") |
| 2157 | flusher.Flush() |
| 2158 | return |
| 2159 | } |
| 2160 | |
| 2161 | if lastErr == nil { |
| 2162 | h.sendOpenAIError(w, 503, "server_error", "No available accounts") |
| 2163 | return |
| 2164 | } |
| 2165 | |
| 2166 | h.recordFailureWithDetails("openai", model, "", lastErr) |
| 2167 | h.sendOpenAIError(w, 500, "server_error", lastErr.Error()) |
| 2168 | } |
| 2169 | |
| 2170 | // handleOpenAINonStream OpenAI 非流式响应 |
| 2171 | func (h *Handler) handleOpenAINonStream(ctx context.Context, w http.ResponseWriter, payload *KiroPayload, model string, thinking bool, estimatedInputTokens int, apiKeyID string) { |
| 2172 | excluded := make(map[string]bool) |
| 2173 | var lastErr error |
| 2174 | reqStart := time.Now() |
| 2175 | |
| 2176 | for attempt := 0; attempt < maxAccountRetryAttempts; attempt++ { |
| 2177 | account := h.pool.GetNextForModelExcluding(model, excluded) |
| 2178 | if account == nil { |
| 2179 | break |
| 2180 | } |
| 2181 | if err := h.ensureValidToken(account); err != nil { |
| 2182 | lastErr = err |
| 2183 | excluded[account.ID] = true |
| 2184 | h.handleAccountFailure(account, err) |
| 2185 | continue |
| 2186 | } |
| 2187 | |
| 2188 | var content string |
| 2189 | var reasoningContent string |
| 2190 | var toolUses []KiroToolUse |
| 2191 | var inputTokens, outputTokens int |
| 2192 | var credits float64 |
| 2193 | var realInputTokens int |
| 2194 | var upstreamStopReason string |
| 2195 | |
| 2196 | callback := &KiroStreamCallback{ |
| 2197 | OnText: func(text string, isThinking bool) { |
| 2198 | if isThinking { |
| 2199 | reasoningContent += text |
| 2200 | } else { |
| 2201 | content += text |
| 2202 | } |
| 2203 | }, |
| 2204 | OnToolUse: func(tu KiroToolUse) { toolUses = append(toolUses, tu) }, |
no test coverage detected