From a1122fe5cdb48922fa21ba9c87f0b50e01e74c11 Mon Sep 17 00:00:00 2001 From: hanjianjun Date: Tue, 4 Aug 2026 20:14:59 +0800 Subject: [PATCH 1/4] feat(vision): make sidecar reasoning configurable --- docs-site/src/content/docs/guides/sidecars.md | 13 ++++++---- .../src/content/docs/ja/guides/sidecars.md | 12 +++++---- .../docs/ja/reference/configuration/server.md | 3 ++- .../src/content/docs/ko/guides/sidecars.md | 12 +++++---- .../docs/ko/reference/configuration/server.md | 3 ++- .../docs/reference/configuration/server.md | 3 ++- .../src/content/docs/ru/guides/sidecars.md | 12 +++++---- .../docs/ru/reference/configuration/server.md | 3 ++- .../src/content/docs/zh-cn/guides/sidecars.md | 11 ++++---- .../zh-cn/reference/configuration/server.md | 3 ++- gui/src/i18n/de.ts | 1 + gui/src/i18n/en.ts | 1 + gui/src/i18n/ja.ts | 1 + gui/src/i18n/ko.ts | 1 + gui/src/i18n/ru.ts | 1 + gui/src/i18n/zh.ts | 1 + gui/src/pages/dashboard-overview-sections.tsx | 25 +++++++++++++------ gui/src/pages/dashboard-shared.ts | 10 +++++--- gui/tests/dashboard-contracts.test.ts | 9 +++++++ src/server/management/config-routes.ts | 15 ++++++++++- src/types.ts | 2 ++ src/vision/describe.ts | 3 ++- src/vision/index.ts | 14 +++++++++-- tests/claude-sidecar-override.test.ts | 2 +- tests/vision-anthropic.test.ts | 11 +++++--- tests/vision-cache.test.ts | 9 ++++--- tests/vision-sidecar-e2e.test.ts | 2 ++ 27 files changed, 129 insertions(+), 54 deletions(-) diff --git a/docs-site/src/content/docs/guides/sidecars.md b/docs-site/src/content/docs/guides/sidecars.md index 006287ab9..dd8d142b4 100644 --- a/docs-site/src/content/docs/guides/sidecars.md +++ b/docs-site/src/content/docs/guides/sidecars.md @@ -76,8 +76,9 @@ persisted legacy `gpt-5.4-mini` value to Luna. If the `visionSidecar.model` fiel the vision execution path still has a `gpt-5.4-mini` code fallback. - Images can come from user, developer, and tool-result messages, including Codex's `view_image`. -- Each image is sent to the configured native vision model with `reasoning.effort: "low"`; its - description replaces the image part inline. +- Each image is sent to the configured native vision model with the selected OpenAI Responses + `reasoning.effort` (`low` by default); its description replaces the image part inline. Anthropic + vision ignores this OpenAI-specific setting. - Descriptions run with bounded concurrency (3 at a time, input order preserved). User context sent to the describer is capped at 800 characters, and each injected description is capped at 2,000 characters. The request does not send `max_output_tokens`, which the ChatGPT backend rejects. @@ -90,14 +91,16 @@ the vision execution path still has a `gpt-5.4-mini` code fallback. available, the raw image is stripped rather than forwarded to a text-only backend. - `maxDescriptionsPerTurn` (default 8) limits new descriptions per main-model turn. Cache hits and same-turn duplicates do not consume it. Successful `data:` image descriptions are cached by - backend, model, detail, image bytes, and message context; mutable `https:` images are not cached. + backend, model, reasoning effort, detail, image bytes, and message context; mutable `https:` images + are not cached. ```json { "visionSidecar": { "enabled": true, - "backend": "anthropic", - "model": "claude-sonnet-5", + "backend": "openai", + "model": "gpt-5.6-luna", + "reasoning": "medium", "maxDescriptionsPerTurn": 8, "timeoutMs": 45000 } diff --git a/docs-site/src/content/docs/ja/guides/sidecars.md b/docs-site/src/content/docs/ja/guides/sidecars.md index cc64fc789..9ee1d9163 100644 --- a/docs-site/src/content/docs/ja/guides/sidecars.md +++ b/docs-site/src/content/docs/ja/guides/sidecars.md @@ -75,8 +75,9 @@ stall は全体生成 timeout ではありません。SSE 開始前の失敗は - 画像はユーザー、developer、ツール結果メッセージから来ます。Codex の `view_image` 結果も 含まれます。 -- 各画像は設定されたネイティブビジョンモデルに `reasoning.effort: "low"` で渡され、説明が画像 - 部分をインラインに差し替えます。 +- 各画像は選択した OpenAI Responses の `reasoning.effort`(デフォルトは `low`)で設定済みの + ネイティブビジョンモデルに渡され、説明が画像部分をインラインに差し替えます。Anthropic vision + はこの OpenAI 固有の設定を無視します。 - 説明は一度に 3 件並列処理し入力順序を維持します。説明モデルに渡すユーザー文脥は 800 文字、注入する画像説明は 1 枚あたり 2,000 文字に制限します。ChatGPT バックエンドが拒否する `max_output_tokens` は送信しません。 @@ -89,14 +90,15 @@ stall は全体生成 timeout ではありません。SSE 開始前の失敗は テキスト専用バックエンドに元画像を送らず削除します。 - `maxDescriptionsPerTurn`(デフォルト 8)はメインモデル 1 ターンで新規実行する説明数を制限します。キャッシュ ヒットと同じターンの重複要求は限度を消費しません。成功した `data:` 画像説明はバックエンド、モデル、 - detail、画像バイト、メッセージ文脈を基準にキャッシュし、変わり得る `https:` 画像はキャッシュしません。 + 推論負荷、detail、画像バイト、メッセージ文脈を基準にキャッシュし、変わり得る `https:` 画像はキャッシュしません。 ```json { "visionSidecar": { "enabled": true, - "backend": "anthropic", - "model": "claude-sonnet-5", + "backend": "openai", + "model": "gpt-5.6-luna", + "reasoning": "medium", "maxDescriptionsPerTurn": 8, "timeoutMs": 45000 } diff --git a/docs-site/src/content/docs/ja/reference/configuration/server.md b/docs-site/src/content/docs/ja/reference/configuration/server.md index cb41dc273..1c6a9c87a 100644 --- a/docs-site/src/content/docs/ja/reference/configuration/server.md +++ b/docs-site/src/content/docs/ja/reference/configuration/server.md @@ -144,9 +144,10 @@ OpenAI バックエンドには、ChatGPT ログインと有効な ChatGPT `forw | `enabled?` | `boolean` |使用可能な場合はオン |マスターイメージと説明のスイッチ。 | | `backend?` | `"openai" \| "anthropic"` |自動 | Web 検索と同じ、明示的優先、人間認証情報を意識した選択。 | | `model?` | `string` |バックエンド依存 | OpenAI の場合は `gpt-5.4-mini`、Anthropic の場合は `claude-sonnet-5`。 | +| `reasoning?` | `"low" \| "medium" \| "high" \| "xhigh" \| "max"` | `"low"` | OpenAI Responses の推論負荷。Anthropic は無視します。 | | `maxDescriptionsPerTurn?` | `number` | `8` |新しい説明のキャッシュミスはメインターンごとに許可されます。 `0` は通話を無効にします。無効な値にはデフォルトが使用されます。 | | `timeoutMs?` | `number` | `45000` |サイドカーのフェッチタイムアウト。 | -Vision は、プロバイダーの `noVisionModels` のモデルに送信された画像に対してのみアクティブになります。 OpenAI には、検索と同じログイン/転送要件があります。明示的に選択された Anthropic は、使用可能な認証情報がないと失敗します。成功した `data:` 記述では、バックエンド、モデル、詳細、画像バイト、および正規化されたメッセージ コンテキストをキーとした境界付きキャッシュが使用されます。ヒットと同じターンの重複は制限を消費しません。リモート `https:` イメージと失敗した説明、または空の説明はキャッシュされません。 +Vision は、プロバイダーの `noVisionModels` のモデルに送信された画像に対してのみアクティブになります。 OpenAI には、検索と同じログイン/転送要件があります。明示的に選択された Anthropic は、使用可能な認証情報がないと失敗します。成功した `data:` 記述では、バックエンド、モデル、推論負荷、詳細、画像バイト、および正規化されたメッセージ コンテキストをキーとした境界付きキャッシュが使用されます。ヒットと同じターンの重複は制限を消費しません。リモート `https:` イメージと失敗した説明、または空の説明はキャッシュされません。 Anthropic OAuth サイドカーは、opencodex の既存のクロード コード OAuth フィンガープリントを再利用します。対象のアカウントとワークロードをソークテストします。 diff --git a/docs-site/src/content/docs/ko/guides/sidecars.md b/docs-site/src/content/docs/ko/guides/sidecars.md index 1ea7596bd..c41aaa53e 100644 --- a/docs-site/src/content/docs/ko/guides/sidecars.md +++ b/docs-site/src/content/docs/ko/guides/sidecars.md @@ -76,8 +76,9 @@ stall은 전체 생성 timeout이 아닙니다. SSE가 시작되기 전 실패 - 이미지는 사용자, developer, 도구 결과 메시지에서 올 수 있습니다. Codex의 `view_image` 결과도 포함됩니다. -- 각 이미지는 설정된 네이티브 비전 모델에 `reasoning.effort: "low"`로 전달되고, 설명이 이미지 - 부분을 인라인으로 대체합니다. +- 각 이미지는 선택한 OpenAI Responses `reasoning.effort`(기본값 `low`)로 설정된 네이티브 비전 + 모델에 전달되고, 설명이 이미지 부분을 인라인으로 대체합니다. Anthropic vision은 이 OpenAI 전용 + 설정을 무시합니다. - 설명은 한 번에 3개씩 병렬 처리하며 입력 순서를 유지합니다. 설명 모델에 전달하는 사용자 문맥은 800자, 주입하는 이미지 설명은 장당 2,000자로 제한합니다. ChatGPT 백엔드가 거부하는 `max_output_tokens`는 보내지 않습니다. @@ -90,15 +91,16 @@ stall은 전체 생성 timeout이 아닙니다. SSE가 시작되기 전 실패 없으면 텍스트 전용 백엔드에 원본 이미지를 보내지 않고 제거합니다. - `maxDescriptionsPerTurn`(기본값 8)은 메인 모델 한 턴에서 새로 실행할 설명 수를 제한합니다. 캐시 적중과 같은 턴의 중복 요청은 한도를 쓰지 않습니다. 성공한 `data:` 이미지 설명은 백엔드, 모델, - detail, 이미지 바이트, 메시지 문맥을 기준으로 캐시하며, 바뀔 수 있는 `https:` 이미지는 캐시하지 + 추론 강도, detail, 이미지 바이트, 메시지 문맥을 기준으로 캐시하며, 바뀔 수 있는 `https:` 이미지는 캐시하지 않습니다. ```json { "visionSidecar": { "enabled": true, - "backend": "anthropic", - "model": "claude-sonnet-5", + "backend": "openai", + "model": "gpt-5.6-luna", + "reasoning": "medium", "maxDescriptionsPerTurn": 8, "timeoutMs": 45000 } diff --git a/docs-site/src/content/docs/ko/reference/configuration/server.md b/docs-site/src/content/docs/ko/reference/configuration/server.md index 2632f0b16..ea406607a 100644 --- a/docs-site/src/content/docs/ko/reference/configuration/server.md +++ b/docs-site/src/content/docs/ko/reference/configuration/server.md @@ -144,9 +144,10 @@ OpenAI 백엔드는 ChatGPT 로그인과 활성화된 ChatGPT `forward` provider | `enabled?` | `boolean` | on when usable | 주 이미지 설명 스위치입니다. | | `backend?` | `"openai" \| "anthropic"` | auto | web search와 같은, 명시값 우선 및 Anthropic 자격 증명 인식 선택 방식입니다. | | `model?` | `string` | backend-dependent | OpenAI는 `gpt-5.4-mini`, Anthropic은 `claude-sonnet-5`입니다. | +| `reasoning?` | `"low" \| "medium" \| "high" \| "xhigh" \| "max"` | `"low"` | OpenAI Responses 추론 강도입니다. Anthropic은 무시합니다. | | `maxDescriptionsPerTurn?` | `number` | `8` | 메인 턴당 허용되는 새 설명 캐시 미스 수입니다. `0`이면 호출이 비활성화되며, 잘못된 값은 기본값을 사용합니다. | | `timeoutMs?` | `number` | `45000` | 사이드카 fetch 제한 시간입니다. | -Vision은 provider의 `noVisionModels`에 속한 모델로 보낸 이미지에만 활성화됩니다. OpenAI는 검색과 같은 로그인/forward 요건을 갖고 있으며, 명시적으로 선택한 Anthropic은 사용할 수 있는 자격 증명이 없으면 닫힌 상태로 실패합니다. 성공한 `data:` 설명은 backend, model, detail, image bytes, 그리고 정규화된 메시지 컨텍스트를 키로 하는 bounded cache를 사용합니다. 히트와 같은 턴의 중복은 한도를 소모하지 않습니다. 원격 `https:` 이미지와 실패했거나 비어 있는 설명은 캐시하지 않습니다. +Vision은 provider의 `noVisionModels`에 속한 모델로 보낸 이미지에만 활성화됩니다. OpenAI는 검색과 같은 로그인/forward 요건을 갖고 있으며, 명시적으로 선택한 Anthropic은 사용할 수 있는 자격 증명이 없으면 닫힌 상태로 실패합니다. 성공한 `data:` 설명은 backend, model, reasoning effort, detail, image bytes, 그리고 정규화된 메시지 컨텍스트를 키로 하는 bounded cache를 사용합니다. 히트와 같은 턴의 중복은 한도를 소모하지 않습니다. 원격 `https:` 이미지와 실패했거나 비어 있는 설명은 캐시하지 않습니다. Anthropic OAuth 사이드카는 opencodex의 기존 Claude Code OAuth fingerprint를 재사용합니다. 의도한 계정과 워크로드로 소크 테스트를 수행합니다. diff --git a/docs-site/src/content/docs/reference/configuration/server.md b/docs-site/src/content/docs/reference/configuration/server.md index ae04536cd..68e1e88f5 100644 --- a/docs-site/src/content/docs/reference/configuration/server.md +++ b/docs-site/src/content/docs/reference/configuration/server.md @@ -176,12 +176,13 @@ an inactivity guard, not a total generation deadline. | `enabled?` | `boolean` | on when usable | Master image-description switch. | | `backend?` | `"openai" \| "anthropic"` | auto | Same explicit-first, Anthropic-credential-aware selection as web search. | | `model?` | `string` | backend-dependent | `gpt-5.4-mini` for OpenAI or `claude-sonnet-5` for Anthropic. | +| `reasoning?` | `"low" \| "medium" \| "high" \| "xhigh" \| "max"` | `"low"` | OpenAI Responses reasoning effort. Anthropic ignores it. | | `maxDescriptionsPerTurn?` | `number` | `8` | New description cache misses admitted per main turn. `0` disables calls; invalid values use default. | | `timeoutMs?` | `number` | `45000` | Sidecar fetch timeout. | Vision activates only for images sent to a model in its provider's `noVisionModels`. OpenAI has the same login/forward requirements as search; explicitly selected Anthropic fails closed without a usable -credential. Successful `data:` descriptions use a bounded cache keyed by backend, model, detail, +credential. Successful `data:` descriptions use a bounded cache keyed by backend, model, reasoning effort, detail, image bytes, and normalized message context. Hits and same-turn duplicates do not consume the limit. Remote `https:` images and failed or empty descriptions are not cached. diff --git a/docs-site/src/content/docs/ru/guides/sidecars.md b/docs-site/src/content/docs/ru/guides/sidecars.md index 861d4bb05..f4483fbca 100644 --- a/docs-site/src/content/docs/ru/guides/sidecars.md +++ b/docs-site/src/content/docs/ru/guides/sidecars.md @@ -87,8 +87,9 @@ SSE-событие `response.failed`. - Изображения могут приходить из сообщений пользователя, разработчика и результатов инструментов, включая `view_image` из Codex. -- Каждое изображение отправляется в настроенную нативную vision-модель с - `reasoning.effort: "low"`; полученное описание заменяет часть с изображением на месте. +- Каждое изображение отправляется в настроенную нативную vision-модель с выбранным для OpenAI + Responses значением `reasoning.effort` (по умолчанию `low`); полученное описание заменяет часть + с изображением на месте. Anthropic vision игнорирует эту специфичную для OpenAI настройку. - Описания выполняются с ограниченной параллельностью (по 3 одновременно, порядок входа сохраняется). Пользовательский контекст, передаваемый описывающей модели, ограничен 800 символами, а каждое внедряемое описание — 2 000 символами. Запрос не отправляет @@ -102,15 +103,16 @@ SSE-событие `response.failed`. недоступен, исходное изображение удаляется, а не пересылается текстовому бэкенду. - `maxDescriptionsPerTurn` (по умолчанию 8) ограничивает число новых описаний за один ход основной модели. Попадания в кэш и дубликаты в рамках того же хода лимит не расходуют. Успешные описания - `data:`-изображений кэшируются по бэкенду, модели, детализации, байтам изображения и контексту + `data:`-изображений кэшируются по бэкенду, модели, уровню рассуждений, детализации, байтам изображения и контексту сообщения; изменяемые `https:`-изображения не кэшируются. ```json { "visionSidecar": { "enabled": true, - "backend": "anthropic", - "model": "claude-sonnet-5", + "backend": "openai", + "model": "gpt-5.6-luna", + "reasoning": "medium", "maxDescriptionsPerTurn": 8, "timeoutMs": 45000 } diff --git a/docs-site/src/content/docs/ru/reference/configuration/server.md b/docs-site/src/content/docs/ru/reference/configuration/server.md index af5f4f6f1..e2ebf2c8d 100644 --- a/docs-site/src/content/docs/ru/reference/configuration/server.md +++ b/docs-site/src/content/docs/ru/reference/configuration/server.md @@ -179,13 +179,14 @@ routed-model и hosted-search timeout. Эффективный watchdog мост | `enabled?` | `boolean` | on when usable | Главный переключатель описания изображений. | | `backend?` | `"openai" \| "anthropic"` | auto | Та же логика выбора explicit-first/Anthropic-credential-aware, что и у web search. | | `model?` | `string` | backend-dependent | `gpt-5.4-mini` для OpenAI или `claude-sonnet-5` для Anthropic. | +| `reasoning?` | `"low" \| "medium" \| "high" \| "xhigh" \| "max"` | `"low"` | Уровень рассуждений OpenAI Responses. Anthropic его игнорирует. | | `maxDescriptionsPerTurn?` | `number` | `8` | Максимум новых промахов description-cache за один main turn. `0` отключает вызовы; некорректные значения возвращают дефолт. | | `timeoutMs?` | `number` | `45000` | Таймаут запроса sidecar'а. | Vision включается только для изображений, отправленных в модель, входящую в `noVisionModels` её провайдера. У OpenAI требования по login/forward те же, что и у поиска; явный Anthropic без рабочего credential завершается ошибкой. Успешные описания `data:` используют ограниченный cache, -ключ которого включает backend, model, detail, bytes изображения и нормализованный message +ключ которого включает backend, model, reasoning effort, detail, bytes изображения и нормализованный message context. Попадания в cache и дубликаты в пределах одного turn'а не расходуют лимит. Удалённые `https:`-изображения, а также пустые и неуспешные описания не кэшируются. diff --git a/docs-site/src/content/docs/zh-cn/guides/sidecars.md b/docs-site/src/content/docs/zh-cn/guides/sidecars.md index 1b49584b1..f45818d55 100644 --- a/docs-site/src/content/docs/zh-cn/guides/sidecars.md +++ b/docs-site/src/content/docs/zh-cn/guides/sidecars.md @@ -69,8 +69,8 @@ Anthropic OAuth provider。Sidecar 错误会转换成长度受限的工具结果 `visionSidecar.model` 字段完全不存在时,vision 执行路径才会使用代码中的 `gpt-5.4-mini` 回退值。 - 图像可以来自 user、developer 和 tool-result message,也包括 Codex 的 `view_image` 结果。 -- 每张图像会以 `reasoning.effort: "low"` 发送给配置的原生 vision 模型,描述结果会就地替换 - 图像部分。 +- 每张图像会以所选的 OpenAI Responses `reasoning.effort`(默认为 `low`)发送给配置的原生 + vision 模型,描述结果会就地替换图像部分。Anthropic vision 会忽略这个 OpenAI 专用设置。 - 描述任务最多同时处理 3 张图像,并保持输入顺序。发送给描述模型的用户上下文最多 800 个字符, 每张图像注入的描述最多 2,000 个字符。请求不会发送 ChatGPT 后端不支持的 `max_output_tokens`。 @@ -82,15 +82,16 @@ Anthropic OAuth provider。Sidecar 错误会转换成长度受限的工具结果 - 如果描述失败,模型会收到简短的处理错误提示。若根本无法建立 sidecar plan,原始图像会被 移除,而不会继续转发给纯文本后端。 - `maxDescriptionsPerTurn`(默认 8)限制每个主模型 turn 的新增描述次数。缓存命中和同一 turn - 的重复请求不会消耗配额。成功的 `data:` 图像描述会按后端、模型、detail、图像字节和消息上下文 + 的重复请求不会消耗配额。成功的 `data:` 图像描述会按后端、模型、推理强度、detail、图像字节和消息上下文 缓存;内容可变的 `https:` 图像不会缓存。 ```json { "visionSidecar": { "enabled": true, - "backend": "anthropic", - "model": "claude-sonnet-5", + "backend": "openai", + "model": "gpt-5.6-luna", + "reasoning": "medium", "maxDescriptionsPerTurn": 8, "timeoutMs": 45000 } diff --git a/docs-site/src/content/docs/zh-cn/reference/configuration/server.md b/docs-site/src/content/docs/zh-cn/reference/configuration/server.md index 665588ee9..ab59e9e61 100644 --- a/docs-site/src/content/docs/zh-cn/reference/configuration/server.md +++ b/docs-site/src/content/docs/zh-cn/reference/configuration/server.md @@ -159,9 +159,10 @@ routed 重放会把主 ChatGPT 认证注入内部请求。Anthropic 后端使用 | `enabled?` | `boolean` | 在可用时启用 | 图像描述总开关。 | | `backend?` | `"openai" \| "anthropic"` | auto | 与 web search 相同的显式优先、感知 Anthropic 凭据的选择方式。 | | `model?` | `string` | 依后端而定 | OpenAI 使用 `gpt-5.4-mini`,Anthropic 使用 `claude-sonnet-5`。 | +| `reasoning?` | `"low" \| "medium" \| "high" \| "xhigh" \| "max"` | `"low"` | OpenAI Responses 推理强度;Anthropic 会忽略该项。 | | `maxDescriptionsPerTurn?` | `number` | `8` | 每个主轮次允许的新增描述缓存未命中次数。`0` 会禁用调用;无效值会使用默认值。 | | `timeoutMs?` | `number` | `45000` | 侧车获取超时。 | -Vision 只会对发送给其提供方 `noVisionModels` 中模型的图像生效。OpenAI 具有与 search 相同的登录/forward 要求;显式选择的 Anthropic 在没有可用凭据时会失败并关闭。成功的 `data:` 描述会使用一个受限缓存,其键由后端、模型、detail、图像字节以及规范化消息上下文组成。命中和同轮重复不会消耗限额。远程 `https:` 图像以及失败或空的描述不会被缓存。 +Vision 只会对发送给其提供方 `noVisionModels` 中模型的图像生效。OpenAI 具有与 search 相同的登录/forward 要求;显式选择的 Anthropic 在没有可用凭据时会失败并关闭。成功的 `data:` 描述会使用一个受限缓存,其键由后端、模型、推理强度、detail、图像字节以及规范化消息上下文组成。命中和同轮重复不会消耗限额。远程 `https:` 图像以及失败或空的描述不会被缓存。 Anthropic OAuth 侧车会复用 opencodex 现有的 Claude Code OAuth 指纹。请对目标账户和负载进行 soak 测试。 diff --git a/gui/src/i18n/de.ts b/gui/src/i18n/de.ts index 639f00c7a..d7391dd40 100644 --- a/gui/src/i18n/de.ts +++ b/gui/src/i18n/de.ts @@ -205,6 +205,7 @@ export const de: Record = { "models.shadowCallInterceptHint": "Fängt die Hintergrund-Hilfsaufrufe der Codex-App ({models}) ab und leitet sie an das gewählte Modell um.", "dash.sidecarBackend": "Backend", "dash.sidecarModel": "Modell", + "dash.visionReasoning": "Vision-Reasoning-Aufwand", "dash.backendAuto": "Automatisch", "dash.backendOpenAI": "OpenAI", "dash.backendAnthropic": "Anthropic", diff --git a/gui/src/i18n/en.ts b/gui/src/i18n/en.ts index cbfd40892..0a3e517f4 100644 --- a/gui/src/i18n/en.ts +++ b/gui/src/i18n/en.ts @@ -217,6 +217,7 @@ export const en = { "models.shadowCallInterceptHint": "Intercepts Codex App's background helper calls ({models}) for titles and commit messages and redirects them to your chosen model.", "dash.sidecarBackend": "Backend", "dash.sidecarModel": "Model", + "dash.visionReasoning": "Vision reasoning effort", "dash.backendAuto": "Auto", "dash.backendOpenAI": "OpenAI", "dash.backendAnthropic": "Anthropic", diff --git a/gui/src/i18n/ja.ts b/gui/src/i18n/ja.ts index 23df35de4..743aa6ada 100644 --- a/gui/src/i18n/ja.ts +++ b/gui/src/i18n/ja.ts @@ -214,6 +214,7 @@ export const ja: Record = { "models.shadowCallInterceptHint": "Codex App のバックグラウンドヘルパー呼び出し({models}: タイトル、コミットメッセージ)を傍受し、選択したモデルにリダイレクトします。", "dash.sidecarBackend": "バックエンド", "dash.sidecarModel": "モデル", + "dash.visionReasoning": "ビジョン推論負荷", "dash.backendAuto": "自動", "dash.backendOpenAI": "OpenAI", "dash.backendAnthropic": "Anthropic", diff --git a/gui/src/i18n/ko.ts b/gui/src/i18n/ko.ts index b08030411..0381aff96 100644 --- a/gui/src/i18n/ko.ts +++ b/gui/src/i18n/ko.ts @@ -209,6 +209,7 @@ export const ko: Record = { "models.shadowCallInterceptHint": "Codex 앱의 백그라운드 호출({models}, 제목·커밋 메시지)을 가로채 선택한 모델로 바꿉니다.", "dash.sidecarBackend": "백엔드", "dash.sidecarModel": "모델", + "dash.visionReasoning": "비전 추론 강도", "dash.backendAuto": "자동", "dash.backendOpenAI": "OpenAI", "dash.backendAnthropic": "Anthropic", diff --git a/gui/src/i18n/ru.ts b/gui/src/i18n/ru.ts index 98b7c6243..33cb65459 100644 --- a/gui/src/i18n/ru.ts +++ b/gui/src/i18n/ru.ts @@ -214,6 +214,7 @@ export const ru: Record = { "models.shadowCallInterceptHint": "Перехватывает фоновые служебные вызовы Codex App ({models}: заголовки, сообщения коммитов) и перенаправляет их на выбранную вами модель.", "dash.sidecarBackend": "Бэкенд", "dash.sidecarModel": "Модель", + "dash.visionReasoning": "Уровень рассуждений vision", "dash.backendAuto": "Авто", "dash.backendOpenAI": "OpenAI", "dash.backendAnthropic": "Anthropic", diff --git a/gui/src/i18n/zh.ts b/gui/src/i18n/zh.ts index c77a6fb6d..6b38d4427 100644 --- a/gui/src/i18n/zh.ts +++ b/gui/src/i18n/zh.ts @@ -209,6 +209,7 @@ export const zh: Record = { "models.shadowCallInterceptHint": "拦截 Codex 应用的后台辅助调用({models})并重定向到所选模型。", "dash.sidecarBackend": "后端", "dash.sidecarModel": "模型", + "dash.visionReasoning": "视觉推理强度", "dash.backendAuto": "自动", "dash.backendOpenAI": "OpenAI", "dash.backendAnthropic": "Anthropic", diff --git a/gui/src/pages/dashboard-overview-sections.tsx b/gui/src/pages/dashboard-overview-sections.tsx index d51ef4a07..18eb0edf1 100644 --- a/gui/src/pages/dashboard-overview-sections.tsx +++ b/gui/src/pages/dashboard-overview-sections.tsx @@ -2,7 +2,7 @@ import { IconAlert, IconInfo, IconRefresh } from "../icons"; import { Trans } from "../i18n/provider"; import { Select } from "../ui"; import { navigateHash } from "../hash-routing"; -import { EFFORT_CAP_LEVELS, requireJson, sidecarBackendForModel, updateJobLabel } from "./dashboard-shared"; +import { EFFORT_CAP_LEVELS, requireJson, sidecarBackendForModel, updateJobLabel, VISION_REASONING_LEVELS } from "./dashboard-shared"; import { shadowSourceModelBadge } from "./shadow-call-source"; import type { useDashboardData } from "./use-dashboard-data"; @@ -257,13 +257,22 @@ export function DashboardSidecarPanels({ d }: { d: Dash }) {
{t("dash.visionSidecar")}
- { void saveSidecar({ vision: { model, backend: sidecarBackendForModel(models, model) } }); }} + disabled={!sidecar || sidecarSaving} + label={t("dash.sidecarModel")} + /> + { void saveSidecar({ vision: { model, backend: sidecarBackendForModel(models, model) } }); }} + onChange={model => { + const ladder = visionReasoningLadder(models, model); + // Never persist an effort the new model cannot serve: clamp to its highest rung. + const reasoning = ladder.includes(visionReasoning) ? visionReasoning : ladder[ladder.length - 1]; + void saveSidecar({ vision: { model, backend: sidecarBackendForModel(models, model), reasoning } }); + }} disabled={!sidecar || sidecarSaving} label={t("dash.sidecarModel")} />