Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
307 changes: 274 additions & 33 deletions openless-all/app/crates/openless-core/src/llm_gemini.rs

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions openless-all/app/crates/openless-core/src/provider_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ pub fn default_llm_model(provider_type: &str) -> Option<&'static str> {
"siliconflow" => Some("Qwen/Qwen2.5-7B-Instruct"),
"atlascloud" => Some("qwen/qwen3.5-flash"),
"openai" | "cometapi" => Some("gpt-4o"),
"gemini" => Some("gemini-2.5-flash"),
"gemini" => Some("gemini-3.5-flash-lite"),
crate::polish::CODEX_OAUTH_PROVIDER_ID => Some(crate::polish::CODEX_DEFAULT_MODEL),
"mimo" => Some("xiaomi/mimo-v2-flash"),
"openrouterFree" => Some("qwen/qwen3-coder:free"),
Expand Down Expand Up @@ -740,7 +740,7 @@ pub fn default_omni_endpoint(provider_type: &str) -> Option<&'static str> {
pub fn default_omni_model(provider_type: &str) -> Option<&'static str> {
match provider_type {
"openai" => Some("gpt-4o-audio-preview"),
"gemini" => Some("gemini-2.5-flash"),
"gemini" => Some("gemini-3.5-flash-lite"),
"dashscope-omni" => Some("qwen3-omni-flash"),
_ => None,
}
Expand Down Expand Up @@ -1351,7 +1351,7 @@ mod tests {
"https://api.openai.com/v1/chat/completions/",
default_llm_endpoint("openai").unwrap()
));
assert_eq!(default_llm_model("gemini"), Some("gemini-2.5-flash"));
assert_eq!(default_llm_model("gemini"), Some("gemini-3.5-flash-lite"));
assert_eq!(
default_omni_endpoint("dashscope-omni"),
Some("https://dashscope.aliyuncs.com/compatible-mode/v1")
Expand Down
19 changes: 18 additions & 1 deletion openless-all/app/crates/openless-core/src/provider_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -688,8 +688,10 @@ fn sanitize_validation_error(error: BackendError) -> BackendError {
"llmTokenLimitInvalid",
"llmThinkingBudgetInvalid",
"llmProtocolHeaderConflict",
"llmThinkingRequired",
] {
if message == code || message == format!("parse error: {code}") {
// Polish failures arrive as "LLM provider failed: parse error: {code}".
if message == code || message.ends_with(&format!("parse error: {code}")) {
return provider_error(code);
}
}
Expand Down Expand Up @@ -2378,4 +2380,19 @@ mod tests {
assert_eq!(unique.len(), actual.len());
}
}

#[test]
fn validation_keeps_llm_codes_from_polish_failures() {
for message in [
"llmThinkingRequired",
"LLM provider failed: parse error: llmThinkingRequired",
] {
let error = sanitize_validation_error(provider_error(message));
assert_eq!(error.message, "llmThinkingRequired");
}
let error = sanitize_validation_error(provider_error(
"LLM provider failed: invalid response: status 400, body: secret",
));
assert_eq!(error.message, "providerHttpStatus:400");
}
}
3 changes: 3 additions & 0 deletions openless-all/app/src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1714,6 +1714,7 @@ export const de: typeof zhCN = {
nameHint:
'Dieser Name unterscheidet Kanäle desselben Anbieters. Er beeinflusst weder Modell noch Verbindung.',
errModel: 'Modell',
errThinking: 'Denkmodus einschalten',
verify: 'Prüfen',
verifyHint: 'Prüft diesen Kanal mit einem echten API-Aufruf auf aktuelle Funktionsfähigkeit',
errTimeout: 'Zeitüberschreitung',
Expand Down Expand Up @@ -1939,6 +1940,8 @@ export const de: typeof zhCN = {
'Messages setzt die Authentifizierungs- und Versionsheader automatisch. Entferne x-api-key und anthropic-version aus den zusätzlichen Headern.',
llmStreamError:
'Der Server hat einen Streamfehler gemeldet. Prüfe das Modell und die Anfrageparameter.',
llmThinkingRequired:
'Dieses Modell lässt sich nicht mit ausgeschaltetem Denkmodus nutzen. Schalte „Denkmodus“ neben dem Modell ein und prüfe erneut.',
saveProtocol: 'Protokolleinstellungen speichern',
thinkingModeHint:
'Aktiviere, deaktiviere oder reduziere das Denken mit den vom Anfrageformat und Modell unterstützten Parametern. Dem Prompt werden keine Steueranweisungen hinzugefügt.',
Expand Down
3 changes: 3 additions & 0 deletions openless-all/app/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1678,6 +1678,7 @@ export const en: typeof zhCN = {
nameHint:
'This name distinguishes channels from the same provider. It does not affect the model or connection.',
errModel: 'Model',
errThinking: 'turn on Thinking',
verify: 'Verify',
verifyHint: 'Makes one real API call to check this channel works right now',
errTimeout: 'timeout',
Expand Down Expand Up @@ -1902,6 +1903,8 @@ export const en: typeof zhCN = {
llmProtocolHeaderConflict:
'Messages sets authentication and version headers automatically. Remove x-api-key and anthropic-version from extra headers.',
llmStreamError: 'The server returned a stream error. Check the model and request parameters.',
llmThinkingRequired:
'This model does not accept thinking turned off. Turn on Thinking next to the model, then verify again.',
saveProtocol: 'Save protocol settings',
thinkingModeHint:
'Enable, disable, or reduce thinking using parameters supported by the selected request format and model. No control instructions are injected into prompts.',
Expand Down
3 changes: 3 additions & 0 deletions openless-all/app/src/i18n/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,7 @@ export const es: typeof zhCN = {
nameHint:
'El nombre permite distinguir canales del mismo proveedor. No afecta al modelo ni a la conexión.',
errModel: 'Modelo',
errThinking: 'activa Razonamiento',
verify: 'Verificar',
verifyHint: 'Hace una llamada real a la API para comprobar si este canal funciona ahora',
errTimeout: 'tiempo agotado',
Expand Down Expand Up @@ -1926,6 +1927,8 @@ export const es: typeof zhCN = {
'Messages establece automáticamente las cabeceras de autenticación y versión. Elimina x-api-key y anthropic-version de las cabeceras adicionales.',
llmStreamError:
'El servidor devolvió un error de transmisión. Comprueba el modelo y los parámetros de la solicitud.',
llmThinkingRequired:
'Este modelo no admite el razonamiento desactivado. Activa «Razonamiento» junto al modelo y vuelve a verificar.',
saveProtocol: 'Guardar ajustes del protocolo',
thinkingModeHint:
'Activa, desactiva o reduce el razonamiento mediante los parámetros admitidos por el formato y el modelo. No se añaden instrucciones de control al prompt.',
Expand Down
3 changes: 3 additions & 0 deletions openless-all/app/src/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1726,6 +1726,7 @@ export const fr: typeof zhCN = {
nameHint:
'Ce nom distingue les canaux d’un même fournisseur. Il n’affecte ni le modèle ni la connexion.',
errModel: 'Modèle',
errThinking: 'activez Raisonnement',
verify: 'Vérifier',
verifyHint:
'Effectue un appel réel à l’API pour vérifier que ce canal fonctionne actuellement',
Expand Down Expand Up @@ -1954,6 +1955,8 @@ export const fr: typeof zhCN = {
'Messages définit automatiquement les en-têtes d’authentification et de version. Retirez x-api-key et anthropic-version des en-têtes supplémentaires.',
llmStreamError:
'Le serveur a renvoyé une erreur de flux. Vérifiez le modèle et les paramètres de la requête.',
llmThinkingRequired:
'Ce modèle n’accepte pas le raisonnement désactivé. Activez « Raisonnement » à côté du modèle, puis vérifiez à nouveau.',
saveProtocol: 'Enregistrer les réglages du protocole',
thinkingModeHint:
'Activez, désactivez ou réduisez le raisonnement avec les paramètres pris en charge par le format et le modèle. Aucune instruction de contrôle n’est ajoutée au prompt.',
Expand Down
3 changes: 3 additions & 0 deletions openless-all/app/src/i18n/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,7 @@ export const ja: typeof zhCN = {
nameHint:
'同じプロバイダーのチャンネルを区別するための名前です。モデルや接続には影響しません。',
errModel: 'モデル',
errThinking: '思考をオンに',
verify: '検証',
verifyHint: '実際に API を1回呼んで、このチャネルが今使えるか確認します',
errTimeout: 'タイムアウト',
Expand Down Expand Up @@ -1888,6 +1889,8 @@ export const ja: typeof zhCN = {
'Messages の認証とバージョンヘッダーは自動設定されます。追加ヘッダーから x-api-key と anthropic-version を削除してください。',
llmStreamError:
'サーバーがストリームエラーを返しました。モデルとリクエスト設定を確認してください。',
llmThinkingRequired:
'このモデルは思考をオフにできません。モデル欄の横の「思考」をオンにしてから、もう一度検証してください。',
saveProtocol: 'プロトコル設定を保存',
thinkingModeHint:
'選択したリクエスト形式とモデルが対応するパラメータで思考を有効化、無効化または軽減します。プロンプトに制御指示は追加しません。',
Expand Down
3 changes: 3 additions & 0 deletions openless-all/app/src/i18n/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1654,6 +1654,7 @@ export const ko: typeof zhCN = {
nameHint:
'같은 제공업체의 여러 채널을 구분하는 이름입니다. 모델이나 연결에는 영향을 주지 않습니다.',
errModel: '모델',
errThinking: '사고 켜기 필요',
verify: '검증',
verifyHint: '실제로 API를 한 번 호출해 이 채널이 지금 되는지 확인합니다',
errTimeout: '시간 초과',
Expand Down Expand Up @@ -1876,6 +1877,8 @@ export const ko: typeof zhCN = {
llmProtocolHeaderConflict:
'Messages 인증 및 버전 헤더는 자동 설정됩니다. 추가 헤더에서 x-api-key와 anthropic-version을 제거하세요.',
llmStreamError: '서버가 스트림 오류를 반환했습니다. 모델과 요청 설정을 확인하세요.',
llmThinkingRequired:
'이 모델은 사고를 끌 수 없습니다. 모델 옆의 "사고"를 켠 뒤 다시 검증하세요.',
saveProtocol: '프로토콜 설정 저장',
thinkingModeHint:
'선택한 요청 형식과 모델이 지원하는 매개변수로 사고를 켜거나 끄거나 줄입니다. 프롬프트에 제어 지시를 추가하지 않습니다.',
Expand Down
2 changes: 2 additions & 0 deletions openless-all/app/src/i18n/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,7 @@ export const zhCN = {
autoSaveHint: '字段修改后自动保存;完成配置后,可手动验证连接。',
nameHint: '名称仅用于区分同一供应商的多个渠道,不影响模型或连接。',
errModel: '模型',
errThinking: '需开启思考',
verify: '验证',
verifyHint: '点一下真实调用一次接口,确认这张卡现在能用',
errTimeout: '超时',
Expand Down Expand Up @@ -1802,6 +1803,7 @@ export const zhCN = {
llmProtocolHeaderConflict:
'Messages 已自动设置鉴权和版本请求头,请移除额外 Headers 中的 x-api-key 和 anthropic-version。',
llmStreamError: '服务端返回流式错误,请检查模型和请求参数。',
llmThinkingRequired: '该模型不接受关闭思考。请打开模型旁的「思考」开关后重新验证。',
saveProtocol: '保存协议设置',
thinkingModeHint:
'按所选请求格式和模型支持的参数启用、关闭或降低思考,不向提示词注入控制指令。',
Expand Down
2 changes: 2 additions & 0 deletions openless-all/app/src/i18n/zh-TW.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,7 @@ export const zhTW: typeof zhCN = {
autoSaveHint: '修改欄位後會自動儲存;完成設定後,可手動驗證連線。',
nameHint: '名稱僅用於區分同一供應商的多個渠道,不影響模型或連線。',
errModel: '模型',
errThinking: '需開啟思考',
verify: '驗證',
verifyHint: '點一下會真實呼叫一次介面,確認這張卡現在可用',
errTimeout: '逾時',
Expand Down Expand Up @@ -1802,6 +1803,7 @@ export const zhTW: typeof zhCN = {
llmProtocolHeaderConflict:
'Messages 已自動設定驗證與版本標頭,請移除額外 Headers 中的 x-api-key 與 anthropic-version。',
llmStreamError: '伺服器回傳串流錯誤,請檢查模型和請求引數。',
llmThinkingRequired: '此模型不接受關閉思考。請開啟模型旁的「思考」開關後重新驗證。',
saveProtocol: '儲存協定設定',
thinkingModeHint:
'依所選請求格式與模型支援的引數啟用、關閉或降低思考,不在提示詞注入控制指令。',
Expand Down
4 changes: 2 additions & 2 deletions openless-all/app/src/lib/ipc/mock-provider-descriptors.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
"providerType": "gemini",
"labelKey": "gemini",
"defaultEndpoint": "https://generativelanguage.googleapis.com/v1beta",
"defaultModel": "gemini-2.5-flash",
"defaultModel": "gemini-3.5-flash-lite",
"authRequirement": "api_key",
"validationProbe": "llm_text",
"staticModels": [],
Expand Down Expand Up @@ -764,7 +764,7 @@
"providerType": "gemini",
"labelKey": "omniGemini",
"defaultEndpoint": "https://generativelanguage.googleapis.com/v1beta",
"defaultModel": "gemini-2.5-flash",
"defaultModel": "gemini-3.5-flash-lite",
"authRequirement": "api_key",
"validationProbe": "omni_text",
"staticModels": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@
{
"authRequirement": "api_key",
"defaultEndpoint": "https://generativelanguage.googleapis.com/v1beta",
"defaultModel": "gemini-2.5-flash",
"defaultModel": "gemini-3.5-flash-lite",
"defaultRequestFormat": null,
"kind": "llm",
"labelKey": "gemini",
Expand Down Expand Up @@ -768,7 +768,7 @@
{
"authRequirement": "api_key",
"defaultEndpoint": "https://generativelanguage.googleapis.com/v1beta",
"defaultModel": "gemini-2.5-flash",
"defaultModel": "gemini-3.5-flash-lite",
"defaultRequestFormat": null,
"kind": "omni",
"labelKey": "omniGemini",
Expand Down
1 change: 1 addition & 0 deletions openless-all/app/src/pages/settings/ChannelList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ function shortErrorLabel(raw: string | null, t: ReturnType<typeof useTranslation
if (message === 'llmModelMissing' || message === 'asrModelMissing') {
return t('settings.channels.errModel');
}
if (message === 'llmThinkingRequired') return t('settings.channels.errThinking');
return t('settings.channels.errGeneric');
}

Expand Down
1 change: 1 addition & 0 deletions openless-all/app/src/pages/settings/ProvidersSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,7 @@ function providerErrorMessage(error: unknown, t: ReturnType<typeof useTranslatio
'llmResponseIncomplete',
'llmStreamError',
'llmProtocolHeaderConflict',
'llmThinkingRequired',
]) {
if (message.includes(code)) return t(`settings.providers.${code}`);
}
Expand Down