diff --git a/src/api/providers/gemini.ts b/src/api/providers/gemini.ts index 45be6977d9f..cb247abd478 100644 --- a/src/api/providers/gemini.ts +++ b/src/api/providers/gemini.ts @@ -199,13 +199,17 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl let lastUsageMetadata: GenerateContentResponseUsageMetadata | undefined let pendingGroundingMetadata: GroundingMetadata | undefined let finalResponse: { responseId?: string } | undefined + let finishReason: string | undefined let toolCallCounter = 0 + let hasContent = false + let hasReasoning = false for await (const chunk of result) { // Track the final structured response (per SDK pattern: candidate.finishReason) if (chunk.candidates && chunk.candidates[0]?.finishReason) { finalResponse = chunk as { responseId?: string } + finishReason = chunk.candidates[0].finishReason } // Process candidates and their parts to separate thoughts from content if (chunk.candidates && chunk.candidates.length > 0) { @@ -233,9 +237,11 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl if (part.thought) { // This is a thinking/reasoning part if (part.text) { + hasReasoning = true yield { type: "reasoning", text: part.text } } } else if (part.functionCall) { + hasContent = true // Gemini sends complete function calls in a single chunk // Emit as partial chunks for consistent handling with NativeToolCallParser const callId = `${part.functionCall.name}-${toolCallCounter}` @@ -263,6 +269,7 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl } else { // This is regular content if (part.text) { + hasContent = true yield { type: "text", text: part.text } } } @@ -272,6 +279,7 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl // Fallback to the original text property if no candidates structure else if (chunk.text) { + hasContent = true yield { type: "text", text: chunk.text } } @@ -280,6 +288,21 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl } } + // If we had reasoning but no content, emit a placeholder text to prevent "Empty assistant response" errors. + // This typically happens when the model hits max output tokens while reasoning. + if (hasReasoning && !hasContent) { + let message = t("common:errors.gemini.thinking_complete_no_output") + if (finishReason === "MAX_TOKENS") { + message = t("common:errors.gemini.thinking_complete_truncated") + } else if (finishReason === "SAFETY") { + message = t("common:errors.gemini.thinking_complete_safety") + } else if (finishReason === "RECITATION") { + message = t("common:errors.gemini.thinking_complete_recitation") + } + + yield { type: "text", text: message } + } + if (finalResponse?.responseId) { // Capture responseId so Task.addToApiConversationHistory can store it // alongside the assistant message in api_history.json. diff --git a/src/api/transform/gemini-format.ts b/src/api/transform/gemini-format.ts index f9d855dda93..bc4dc4aa54a 100644 --- a/src/api/transform/gemini-format.ts +++ b/src/api/transform/gemini-format.ts @@ -14,6 +14,11 @@ type ReasoningContentBlock = { type ExtendedContentBlockParam = Anthropic.ContentBlockParam | ThoughtSignatureContentBlock | ReasoningContentBlock type ExtendedAnthropicContent = string | ExtendedContentBlockParam[] +// Extension type to safely add thoughtSignature to Part +type PartWithThoughtSignature = Part & { + thoughtSignature?: string +} + function isThoughtSignatureContentBlock(block: ExtendedContentBlockParam): block is ThoughtSignatureContentBlock { return block.type === "thoughtSignature" } @@ -47,16 +52,11 @@ export function convertAnthropicContentToGemini( return [{ text: content }] } - return content.flatMap((block): Part | Part[] => { + const parts = content.flatMap((block): Part | Part[] => { // Handle thoughtSignature blocks first if (isThoughtSignatureContentBlock(block)) { - if (includeThoughtSignatures && typeof block.thoughtSignature === "string") { - // The Google GenAI SDK currently exposes thoughtSignature as an - // extension field on Part; model it structurally without widening - // the upstream type. - return { thoughtSignature: block.thoughtSignature } as Part - } - // Explicitly omit thoughtSignature when not including it. + // We process thought signatures globally and attach them to the relevant parts + // or create a placeholder part if no other content exists. return [] } @@ -135,6 +135,25 @@ export function convertAnthropicContentToGemini( return [] } }) + + // Post-processing: Ensure thought signature is attached if required + if (includeThoughtSignatures && activeThoughtSignature) { + const hasSignature = parts.some((p) => "thoughtSignature" in p) + + if (!hasSignature) { + if (parts.length > 0) { + // Attach to the first part (usually text) + // We use the intersection type to allow adding the property safely + ;(parts[0] as PartWithThoughtSignature).thoughtSignature = activeThoughtSignature + } else { + // Create a placeholder part if no other content exists + const placeholder: PartWithThoughtSignature = { text: "", thoughtSignature: activeThoughtSignature } + parts.push(placeholder) + } + } + } + + return parts } export function convertAnthropicMessageToGemini( diff --git a/src/i18n/locales/ca/common.json b/src/i18n/locales/ca/common.json index c71cf130ac7..2395cfd83ae 100644 --- a/src/i18n/locales/ca/common.json +++ b/src/i18n/locales/ca/common.json @@ -109,7 +109,11 @@ "gemini": { "generate_stream": "Error del flux de context de generació de Gemini: {{error}}", "generate_complete_prompt": "Error de finalització de Gemini: {{error}}", - "sources": "Fonts:" + "sources": "Fonts:", + "thinking_complete_no_output": "(Pensament completat, però no s'ha generat cap sortida.)", + "thinking_complete_truncated": "(Pensament completat, però la sortida s'ha truncat a causa del límit de fitxes.)", + "thinking_complete_safety": "(Pensament completat, però la sortida s'ha bloquejat a causa de la configuració de seguretat.)", + "thinking_complete_recitation": "(Pensament completat, però la sortida s'ha bloquejat a causa de la comprovació de recitació.)" }, "cerebras": { "authenticationFailed": "Ha fallat l'autenticació de l'API de Cerebras. Comproveu que la vostra clau d'API sigui vàlida i no hagi caducat.", diff --git a/src/i18n/locales/de/common.json b/src/i18n/locales/de/common.json index 6ec9be0f5f6..bce64888b45 100644 --- a/src/i18n/locales/de/common.json +++ b/src/i18n/locales/de/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Fehler beim Generieren des Kontext-Streams von Gemini: {{error}}", "generate_complete_prompt": "Fehler bei der Vervollständigung durch Gemini: {{error}}", - "sources": "Quellen:" + "sources": "Quellen:", + "thinking_complete_no_output": "(Denken abgeschlossen, aber es wurde keine Ausgabe generiert.)", + "thinking_complete_truncated": "(Denken abgeschlossen, aber die Ausgabe wurde aufgrund des Token-Limits gekürzt.)", + "thinking_complete_safety": "(Denken abgeschlossen, aber die Ausgabe wurde aufgrund von Sicherheitseinstellungen blockiert.)", + "thinking_complete_recitation": "(Denken abgeschlossen, aber die Ausgabe wurde aufgrund der Rezitationsprüfung blockiert.)" }, "cerebras": { "authenticationFailed": "Cerebras API-Authentifizierung fehlgeschlagen. Bitte überprüfe, ob dein API-Schlüssel gültig und nicht abgelaufen ist.", diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index 784540e06f7..ae2e20a292b 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Gemini generate context stream error: {{error}}", "generate_complete_prompt": "Gemini completion error: {{error}}", - "sources": "Sources:" + "sources": "Sources:", + "thinking_complete_no_output": "(Thinking complete, but no output was generated.)", + "thinking_complete_truncated": "(Thinking complete, but output was truncated due to token limit.)", + "thinking_complete_safety": "(Thinking complete, but output was blocked due to safety settings.)", + "thinking_complete_recitation": "(Thinking complete, but output was blocked due to recitation check.)" }, "cerebras": { "authenticationFailed": "Cerebras API authentication failed. Please check your API key is valid and not expired.", diff --git a/src/i18n/locales/es/common.json b/src/i18n/locales/es/common.json index ade6aa9c460..308505e9b03 100644 --- a/src/i18n/locales/es/common.json +++ b/src/i18n/locales/es/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Error del stream de contexto de generación de Gemini: {{error}}", "generate_complete_prompt": "Error de finalización de Gemini: {{error}}", - "sources": "Fuentes:" + "sources": "Fuentes:", + "thinking_complete_no_output": "(Pensamiento completado, pero no se generó salida.)", + "thinking_complete_truncated": "(Pensamiento completado, pero la salida fue truncada debido al límite de tokens.)", + "thinking_complete_safety": "(Pensamiento completado, pero la salida fue bloqueada debido a la configuración de seguridad.)", + "thinking_complete_recitation": "(Pensamiento completado, pero la salida fue bloqueada debido a la comprobación de recitación.)" }, "cerebras": { "authenticationFailed": "Falló la autenticación de la API de Cerebras. Verifica que tu clave de API sea válida y no haya expirado.", diff --git a/src/i18n/locales/fr/common.json b/src/i18n/locales/fr/common.json index dc06e0ca7a5..d1d71a9a2cf 100644 --- a/src/i18n/locales/fr/common.json +++ b/src/i18n/locales/fr/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Erreur du flux de contexte de génération Gemini : {{error}}", "generate_complete_prompt": "Erreur d'achèvement de Gemini : {{error}}", - "sources": "Sources :" + "sources": "Sources :", + "thinking_complete_no_output": "(Réflexion terminée, mais aucune sortie générée.)", + "thinking_complete_truncated": "(Réflexion terminée, mais la sortie a été tronquée en raison de la limite de jetons.)", + "thinking_complete_safety": "(Réflexion terminée, mais la sortie a été bloquée en raison des paramètres de sécurité.)", + "thinking_complete_recitation": "(Réflexion terminée, mais la sortie a été bloquée en raison de la vérification de récitation.)" }, "cerebras": { "authenticationFailed": "Échec de l'authentification de l'API Cerebras. Vérifiez que votre clé API est valide et n'a pas expiré.", diff --git a/src/i18n/locales/hi/common.json b/src/i18n/locales/hi/common.json index 14da25805b1..38ed41b7e21 100644 --- a/src/i18n/locales/hi/common.json +++ b/src/i18n/locales/hi/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "जेमिनी जनरेट कॉन्टेक्स्ट स्ट्रीम त्रुटि: {{error}}", "generate_complete_prompt": "जेमिनी समापन त्रुटि: {{error}}", - "sources": "स्रोत:" + "sources": "स्रोत:", + "thinking_complete_no_output": "(सोचना पूरा हुआ, लेकिन कोई आउटपुट नहीं बना।)", + "thinking_complete_truncated": "(सोचना पूरा हुआ, लेकिन टोकन सीमा के कारण आउटपुट काट दिया गया।)", + "thinking_complete_safety": "(सोचना पूरा हुआ, लेकिन सुरक्षा सेटिंग्स के कारण आउटपुट अवरुद्ध कर दिया गया।)", + "thinking_complete_recitation": "(सोचना पूरा हुआ, लेकिन पाठ जाँच के कारण आउटपुट अवरुद्ध कर दिया गया।)" }, "cerebras": { "authenticationFailed": "Cerebras API प्रमाणीकरण विफल हुआ। कृपया जांचें कि आपकी API कुंजी वैध है और समाप्त नहीं हुई है।", diff --git a/src/i18n/locales/id/common.json b/src/i18n/locales/id/common.json index 5622d722159..aa57fd1a934 100644 --- a/src/i18n/locales/id/common.json +++ b/src/i18n/locales/id/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Kesalahan aliran konteks pembuatan Gemini: {{error}}", "generate_complete_prompt": "Kesalahan penyelesaian Gemini: {{error}}", - "sources": "Sumber:" + "sources": "Sumber:", + "thinking_complete_no_output": "(Berpikir selesai, tetapi tidak ada output yang dihasilkan.)", + "thinking_complete_truncated": "(Berpikir selesai, tetapi output terpotong karena batas token.)", + "thinking_complete_safety": "(Berpikir selesai, tetapi output diblokir karena pengaturan keamanan.)", + "thinking_complete_recitation": "(Berpikir selesai, tetapi output diblokir karena pemeriksaan resitasi.)" }, "cerebras": { "authenticationFailed": "Autentikasi API Cerebras gagal. Silakan periksa apakah kunci API Anda valid dan belum kedaluwarsa.", diff --git a/src/i18n/locales/it/common.json b/src/i18n/locales/it/common.json index abb22d77d37..1bb7f4544f5 100644 --- a/src/i18n/locales/it/common.json +++ b/src/i18n/locales/it/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Errore del flusso di contesto di generazione Gemini: {{error}}", "generate_complete_prompt": "Errore di completamento Gemini: {{error}}", - "sources": "Fonti:" + "sources": "Fonti:", + "thinking_complete_no_output": "(Pensiero completato, ma non è stato generato alcun output.)", + "thinking_complete_truncated": "(Pensiero completato, ma l'output è stato troncato a causa del limite di token.)", + "thinking_complete_safety": "(Pensiero completato, ma l'output è stato bloccato a causa delle impostazioni di sicurezza.)", + "thinking_complete_recitation": "(Pensiero completato, ma l'output è stato bloccato a causa del controllo di recitazione.)" }, "cerebras": { "authenticationFailed": "Autenticazione API Cerebras fallita. Verifica che la tua chiave API sia valida e non scaduta.", diff --git a/src/i18n/locales/ja/common.json b/src/i18n/locales/ja/common.json index cdd8de9a9a9..8dfafa12460 100644 --- a/src/i18n/locales/ja/common.json +++ b/src/i18n/locales/ja/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Gemini 生成コンテキスト ストリーム エラー: {{error}}", "generate_complete_prompt": "Gemini 完了エラー: {{error}}", - "sources": "ソース:" + "sources": "ソース:", + "thinking_complete_no_output": "(思考完了、出力なし)", + "thinking_complete_truncated": "(思考完了、トークン制限により出力切り捨て)", + "thinking_complete_safety": "(思考完了、安全設定により出力ブロック)", + "thinking_complete_recitation": "(思考完了、引用チェックにより出力ブロック)" }, "cerebras": { "authenticationFailed": "Cerebras API認証が失敗しました。APIキーが有効で期限切れではないことを確認してください。", diff --git a/src/i18n/locales/ko/common.json b/src/i18n/locales/ko/common.json index 0cbfc9d99ad..2a3a55d4ca9 100644 --- a/src/i18n/locales/ko/common.json +++ b/src/i18n/locales/ko/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Gemini 생성 컨텍스트 스트림 오류: {{error}}", "generate_complete_prompt": "Gemini 완료 오류: {{error}}", - "sources": "출처:" + "sources": "출처:", + "thinking_complete_no_output": "(생각 완료, 출력 없음)", + "thinking_complete_truncated": "(생각 완료, 토큰 제한으로 출력 잘림)", + "thinking_complete_safety": "(생각 완료, 안전 설정으로 출력 차단됨)", + "thinking_complete_recitation": "(생각 완료, 암송 확인으로 출력 차단됨)" }, "cerebras": { "authenticationFailed": "Cerebras API 인증에 실패했습니다. API 키가 유효하고 만료되지 않았는지 확인하세요.", diff --git a/src/i18n/locales/nl/common.json b/src/i18n/locales/nl/common.json index c989219e7b4..fc01724d46e 100644 --- a/src/i18n/locales/nl/common.json +++ b/src/i18n/locales/nl/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Fout bij het genereren van contextstream door Gemini: {{error}}", "generate_complete_prompt": "Fout bij het voltooien door Gemini: {{error}}", - "sources": "Bronnen:" + "sources": "Bronnen:", + "thinking_complete_no_output": "(Nadenken voltooid, maar er is geen uitvoer gegenereerd.)", + "thinking_complete_truncated": "(Nadenken voltooid, maar uitvoer is afgekapt vanwege tokenlimiet.)", + "thinking_complete_safety": "(Nadenken voltooid, maar uitvoer is geblokkeerd vanwege veiligheidsinstellingen.)", + "thinking_complete_recitation": "(Nadenken voltooid, maar uitvoer is geblokkeerd vanwege recitatiecontrole.)" }, "cerebras": { "authenticationFailed": "Cerebras API-authenticatie mislukt. Controleer of je API-sleutel geldig is en niet verlopen.", diff --git a/src/i18n/locales/pl/common.json b/src/i18n/locales/pl/common.json index 3a1c08cf60b..d5611ed8756 100644 --- a/src/i18n/locales/pl/common.json +++ b/src/i18n/locales/pl/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Błąd strumienia kontekstu generowania Gemini: {{error}}", "generate_complete_prompt": "Błąd uzupełniania Gemini: {{error}}", - "sources": "Źródła:" + "sources": "Źródła:", + "thinking_complete_no_output": "(Myślenie zakończone, ale nie wygenerowano żadnych danych wyjściowych.)", + "thinking_complete_truncated": "(Myślenie zakończone, ale dane wyjściowe zostały obcięte z powodu limitu tokenów.)", + "thinking_complete_safety": "(Myślenie zakończone, ale dane wyjściowe zostały zablokowane przez ustawienia bezpieczeństwa.)", + "thinking_complete_recitation": "(Myślenie zakończone, ale dane wyjściowe zostały zablokowane przez kontrolę recytacji.)" }, "cerebras": { "authenticationFailed": "Uwierzytelnianie API Cerebras nie powiodło się. Sprawdź, czy twój klucz API jest ważny i nie wygasł.", diff --git a/src/i18n/locales/pt-BR/common.json b/src/i18n/locales/pt-BR/common.json index d8782623b84..4f2e3fa488d 100644 --- a/src/i18n/locales/pt-BR/common.json +++ b/src/i18n/locales/pt-BR/common.json @@ -110,7 +110,11 @@ "gemini": { "generate_stream": "Erro de fluxo de contexto de geração do Gemini: {{error}}", "generate_complete_prompt": "Erro de conclusão do Gemini: {{error}}", - "sources": "Fontes:" + "sources": "Fontes:", + "thinking_complete_no_output": "(Pensamento concluído, mas nenhuma saída foi gerada.)", + "thinking_complete_truncated": "(Pensamento concluído, mas a saída foi truncada devido ao limite de tokens.)", + "thinking_complete_safety": "(Pensamento concluído, mas a saída foi bloqueada devido às configurações de segurança.)", + "thinking_complete_recitation": "(Pensamento concluído, mas a saída foi bloqueada devido à verificação de recitação.)" }, "cerebras": { "authenticationFailed": "Falha na autenticação da API Cerebras. Verifique se sua chave de API é válida e não expirou.", diff --git a/src/i18n/locales/ru/common.json b/src/i18n/locales/ru/common.json index d8004676385..6ff5d01f896 100644 --- a/src/i18n/locales/ru/common.json +++ b/src/i18n/locales/ru/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Ошибка потока контекста генерации Gemini: {{error}}", "generate_complete_prompt": "Ошибка завершения Gemini: {{error}}", - "sources": "Источники:" + "sources": "Источники:", + "thinking_complete_no_output": "(Размышление завершено, но вывод не сгенерирован.)", + "thinking_complete_truncated": "(Размышление завершено, но вывод урезан из-за лимита токенов.)", + "thinking_complete_safety": "(Размышление завершено, но вывод заблокирован настройками безопасности.)", + "thinking_complete_recitation": "(Размышление завершено, но вывод заблокирован проверкой цитирования.)" }, "cerebras": { "authenticationFailed": "Ошибка аутентификации Cerebras API. Убедитесь, что ваш API-ключ действителен и не истек.", diff --git a/src/i18n/locales/tr/common.json b/src/i18n/locales/tr/common.json index f163a5df834..7529c8418f8 100644 --- a/src/i18n/locales/tr/common.json +++ b/src/i18n/locales/tr/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Gemini oluşturma bağlam akışı hatası: {{error}}", "generate_complete_prompt": "Gemini tamamlama hatası: {{error}}", - "sources": "Kaynaklar:" + "sources": "Kaynaklar:", + "thinking_complete_no_output": "(Düşünme tamamlandı, ancak çıktı oluşturulmadı.)", + "thinking_complete_truncated": "(Düşünme tamamlandı, ancak çıktı jeton sınırı nedeniyle kesildi.)", + "thinking_complete_safety": "(Düşünme tamamlandı, ancak çıktı güvenlik ayarları nedeniyle engellendi.)", + "thinking_complete_recitation": "(Düşünme tamamlandı, ancak çıktı okuma kontrolü nedeniyle engellendi.)" }, "cerebras": { "authenticationFailed": "Cerebras API kimlik doğrulama başarısız oldu. API anahtarınızın geçerli olduğunu ve süresi dolmadığını kontrol edin.", diff --git a/src/i18n/locales/vi/common.json b/src/i18n/locales/vi/common.json index 47ed3c03977..94873fb7e96 100644 --- a/src/i18n/locales/vi/common.json +++ b/src/i18n/locales/vi/common.json @@ -106,7 +106,11 @@ "gemini": { "generate_stream": "Lỗi luồng ngữ cảnh tạo Gemini: {{error}}", "generate_complete_prompt": "Lỗi hoàn thành Gemini: {{error}}", - "sources": "Nguồn:" + "sources": "Nguồn:", + "thinking_complete_no_output": "(Đã suy nghĩ xong nhưng không có kết quả đầu ra.)", + "thinking_complete_truncated": "(Đã suy nghĩ xong nhưng kết quả bị cắt ngắn do giới hạn token.)", + "thinking_complete_safety": "(Đã suy nghĩ xong nhưng kết quả bị chặn do cài đặt an toàn.)", + "thinking_complete_recitation": "(Đã suy nghĩ xong nhưng kết quả bị chặn do kiểm tra trích dẫn.)" }, "cerebras": { "authenticationFailed": "Xác thực API Cerebras thất bại. Vui lòng kiểm tra khóa API của bạn có hợp lệ và chưa hết hạn.", diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json index 800a1eb5cee..df1407ee367 100644 --- a/src/i18n/locales/zh-CN/common.json +++ b/src/i18n/locales/zh-CN/common.json @@ -111,7 +111,11 @@ "gemini": { "generate_stream": "Gemini 生成上下文流错误:{{error}}", "generate_complete_prompt": "Gemini 完成错误:{{error}}", - "sources": "来源:" + "sources": "来源:", + "thinking_complete_no_output": "(思考完成,但未生成输出。)", + "thinking_complete_truncated": "(思考完成,但由于 Token 限制输出被截断。)", + "thinking_complete_safety": "(思考完成,但由于安全设置输出被阻止。)", + "thinking_complete_recitation": "(思考完成,但由于引用检查输出被阻止。)" }, "cerebras": { "authenticationFailed": "Cerebras API 身份验证失败。请检查你的 API 密钥是否有效且未过期。", diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json index a72163495a2..09d13a0fc26 100644 --- a/src/i18n/locales/zh-TW/common.json +++ b/src/i18n/locales/zh-TW/common.json @@ -105,7 +105,11 @@ "gemini": { "generate_stream": "Gemini 產生內容串流錯誤:{{error}}", "generate_complete_prompt": "Gemini 完成錯誤:{{error}}", - "sources": "來源:" + "sources": "來源:", + "thinking_complete_no_output": "(思考完成,但未產生輸出。)", + "thinking_complete_truncated": "(思考完成,但由於 Token 限制輸出被截斷。)", + "thinking_complete_safety": "(思考完成,但由於安全設定輸出被阻止。)", + "thinking_complete_recitation": "(思考完成,但由於引用檢查輸出被阻止。)" }, "cerebras": { "authenticationFailed": "Cerebras API 驗證失敗。請檢查您的 API 金鑰是否有效且未過期。",