From 92d399b43c69dd1c246e92319fe335f64d813914 Mon Sep 17 00:00:00 2001 From: JUN Date: Fri, 9 Oct 2026 09:07:42 +0900 Subject: [PATCH 1/4] feat(gui): add a Context accounting control to the Claude Code page The Claude Code settings page gets a 1M (default) / 200k select for claudeCode.contextAccounting. Under 200k the auto-context and auto-summarize rows are hidden (they have no effect there) and the manual env block stops exporting a compact window, matching what the runtime injects. A state cached by an older proxy, or read from one, normalizes to the 1m default. Strings are added to all eleven locales. Co-Authored-By: Claude Opus 5.5 --- gui/src/i18n/de.ts | 4 ++++ gui/src/i18n/en.ts | 4 ++++ gui/src/i18n/fr.ts | 4 ++++ gui/src/i18n/ja.ts | 4 ++++ gui/src/i18n/ko.ts | 4 ++++ gui/src/i18n/pt.ts | 4 ++++ gui/src/i18n/ru.ts | 4 ++++ gui/src/i18n/tr.ts | 4 ++++ gui/src/i18n/vi.ts | 4 ++++ gui/src/i18n/zh-TW.ts | 4 ++++ gui/src/i18n/zh.ts | 4 ++++ gui/src/pages/ClaudeCode.tsx | 5 +++- gui/src/pages/claude-code-save.ts | 2 ++ gui/src/pages/claude-code-sections.tsx | 33 ++++++++++++++++++++++---- gui/src/pages/claude-code-types.ts | 10 ++++++++ gui/src/pages/claude-manual-env.ts | 5 +++- gui/tests/claude-code-save.test.ts | 12 +++++++++- gui/tests/locale-parity.test.ts | 2 ++ tests/gui/claude-manual-env.test.ts | 5 ++++ 19 files changed, 110 insertions(+), 8 deletions(-) diff --git a/gui/src/i18n/de.ts b/gui/src/i18n/de.ts index 62e7977622b..d02601973ac 100644 --- a/gui/src/i18n/de.ts +++ b/gui/src/i18n/de.ts @@ -2423,6 +2423,10 @@ export const de: Record = { "claude.autoContext": "Großen Kontext automatisch nutzen", "claude.autoContextDesc": "Steuert, wie weit die 1M-Markierung geht. AN: jedes Modell, dessen Fenster den Komprimierungsschwellwert fasst, erhält eine Big-Context-Zeile. AUS: nur echte 1M-Modelle.", "claude.autoContextInert": "Inaktiv, weil in der Konfigurationsdatei ein alter Kontextgrößen-Wert (maxContextTokens) steht. Dort entfernen, um es wieder zu aktivieren.", + "claude.contextAccounting": "Kontextberechnung", + "claude.contextAccountingDesc": "1M (Standard): Modelle, deren Fenster den Zusammenfassungspunkt aufnehmen kann, werden überall dort mit 1M angeboten, wo opencodex die Vorgabe wählt. 200k: Claude Code rechnet jedes Modell mit 200k, außer du wählst selbst eine 1M-Zeile.", + "claude.contextAccounting1m": "1M (Standard)", + "claude.contextAccounting200k": "200k", "claude.autoCompactWindow": "Punkt für Auto-Zusammenfassung", "claude.autoCompactDefault": "{value} (Standard)", "claude.autoCompactWindowDesc": "Ältere Nachrichten werden an diesem Punkt zusammengefasst. Das eigene Limit jedes Modells wird nie überschritten — 200k-Modelle bleiben unberührt.", diff --git a/gui/src/i18n/en.ts b/gui/src/i18n/en.ts index 705ce95ad76..307769d7160 100644 --- a/gui/src/i18n/en.ts +++ b/gui/src/i18n/en.ts @@ -3047,6 +3047,10 @@ export const en = { "claude.autoContext": "Use big context automatically", "claude.autoContextDesc": "Controls how far the 1M marking goes. ON: any model whose window can host the compaction threshold gets a big-context row. OFF: only true 1M models get one.", "claude.autoContextInert": "Inactive because a legacy context-size value (maxContextTokens) exists in the config file. Remove it there to re-enable.", + "claude.contextAccounting": "Context accounting", + "claude.contextAccountingDesc": "1M (default): models whose window can host the summarize point are offered at 1M wherever opencodex picks the default. 200k: Claude Code counts every model at 200k unless you pick a 1M row yourself.", + "claude.contextAccounting1m": "1M (default)", + "claude.contextAccounting200k": "200k", "claude.autoCompactWindow": "Auto-summarize point", "claude.autoCompactDefault": "{value} (default)", "claude.autoCompactWindowDesc": "Older messages are summarized when the chat reaches this point. It never exceeds each model's own limit, so 200k models are unaffected.", diff --git a/gui/src/i18n/fr.ts b/gui/src/i18n/fr.ts index ce26f281cfa..dbaaaa29a00 100644 --- a/gui/src/i18n/fr.ts +++ b/gui/src/i18n/fr.ts @@ -2962,6 +2962,10 @@ export const fr: Record = { "claude.autoContext": "Utiliser automatiquement le grand contexte", "claude.autoContextDesc": "Contrôle l’étendue du marquage 1M. ACTIVÉ : tout modèle dont la fenêtre peut accueillir le seuil de compaction obtient une ligne de grand contexte. DÉSACTIVÉ : seuls les véritables modèles 1M en obtiennent une.", "claude.autoContextInert": "Inactif, car une ancienne valeur de taille de contexte (maxContextTokens) existe dans le fichier de configuration. Supprimez-la dans ce fichier pour réactiver l’option.", + "claude.contextAccounting": "Comptabilisation du contexte", + "claude.contextAccountingDesc": "1M (par défaut) : les modèles dont la fenêtre peut contenir le point de résumé sont proposés à 1M partout où opencodex choisit la valeur par défaut. 200k : Claude Code compte chaque modèle à 200k, sauf si vous choisissez vous-même une ligne 1M.", + "claude.contextAccounting1m": "1M (par défaut)", + "claude.contextAccounting200k": "200k", "claude.autoCompactWindow": "Seuil de résumé automatique", "claude.autoCompactDefault": "{value} (par défaut)", "claude.autoCompactWindowDesc": "Les anciens messages sont résumés lorsque la conversation atteint ce seuil. Celui-ci ne dépasse jamais la limite propre à chaque modèle; les modèles 200k ne sont donc pas affectés.", diff --git a/gui/src/i18n/ja.ts b/gui/src/i18n/ja.ts index d6f87351d7d..d736d463e32 100644 --- a/gui/src/i18n/ja.ts +++ b/gui/src/i18n/ja.ts @@ -2864,6 +2864,10 @@ export const ja: Record = { "claude.autoContext": "大きなコンテキストを自動で使用", "claude.autoContextDesc": "1M マーキングがどこまで及ぶかを制御します。オン: 圧縮しきい値を収められるウィンドウを持つモデルに大型コンテキスト行を付けます。オフ: 真の 1M モデルのみに付けます。", "claude.autoContextInert": "設定ファイルにレガシーのコンテキストサイズ値(maxContextTokens)が存在するため無効です。再び有効化するにはそれを削除してください。", + "claude.contextAccounting": "コンテキスト計算方式", + "claude.contextAccountingDesc": "1M(既定): 要約ポイントを収められるウィンドウのモデルは、opencodex が既定を選ぶすべての場所で 1M として提供されます。200k: 自分で 1M の行を選ばない限り、Claude Code はすべてのモデルを 200k として数えます。", + "claude.contextAccounting1m": "1M(既定)", + "claude.contextAccounting200k": "200k", "claude.autoCompactWindow": "自動要約ポイント", "claude.autoCompactDefault": "{value}(デフォルト)", "claude.autoCompactWindowDesc": "チャットがこのポイントに達すると古いメッセージが要約されます。各モデル自身の上限を超えることはないので、200k モデルは影響を受けません。", diff --git a/gui/src/i18n/ko.ts b/gui/src/i18n/ko.ts index 41276a77ca9..d502a937194 100644 --- a/gui/src/i18n/ko.ts +++ b/gui/src/i18n/ko.ts @@ -2470,6 +2470,10 @@ export const ko: Record = { "claude.autoContext": "큰 컨텍스트 자동 활용", "claude.autoContextDesc": "1M 표기를 어디까지 붙일지 정합니다. 켜면 컴팩션 기준치를 담을 수 있는 창을 가진 모델에 큰 컨텍스트 행이 생기고, 끄면 진짜 1M 모델에만 생깁니다.", "claude.autoContextInert": "설정 파일에 이전 방식의 컨텍스트 크기 값(maxContextTokens)이 있어 이 기능이 지금은 적용되지 않아요. 설정에서 그 값을 지우면 다시 켜집니다.", + "claude.contextAccounting": "컨텍스트 계산 방식", + "claude.contextAccountingDesc": "1M(기본): 요약 지점을 감당할 수 있는 창을 가진 모델은 opencodex가 기본값을 고르는 모든 곳에서 1M으로 잡혀요. 200k: 직접 1M 행을 고르지 않는 한 Claude Code가 모든 모델을 200k로 계산해요.", + "claude.contextAccounting1m": "1M (기본)", + "claude.contextAccounting200k": "200k", "claude.autoCompactWindow": "자동 요약 지점", "claude.autoCompactDefault": "{value} (기본값)", "claude.autoCompactWindowDesc": "대화가 이 지점에 다다르면 오래된 내용을 자동 요약합니다. 모델마다 자기 한도를 넘지 않는 선에서만 적용되니 200k 모델은 영향받지 않아요.", diff --git a/gui/src/i18n/pt.ts b/gui/src/i18n/pt.ts index cbc379f7188..224d2903c5c 100644 --- a/gui/src/i18n/pt.ts +++ b/gui/src/i18n/pt.ts @@ -3005,6 +3005,10 @@ export const pt: Record = { "claude.autoContext": "Usar contexto grande automaticamente", "claude.autoContextDesc": "Controla até onde vai a marcação de 1M. ON: qualquer modelo cuja janela comporte o limite de compactação ganha uma linha de contexto grande. OFF: só os modelos de 1M de verdade ganham uma.", "claude.autoContextInert": "Inativo porque existe um valor legado de tamanho de contexto (maxContextTokens) no arquivo de configuração. Remova-o de lá para reativar.", + "claude.contextAccounting": "Contagem de contexto", + "claude.contextAccountingDesc": "1M (padrão): modelos cuja janela comporta o ponto de resumo são oferecidos com 1M onde o opencodex escolhe o padrão. 200k: o Claude Code conta todo modelo como 200k, a menos que você escolha uma linha 1M.", + "claude.contextAccounting1m": "1M (padrão)", + "claude.contextAccounting200k": "200k", "claude.autoCompactWindow": "Ponto de resumo automático", "claude.autoCompactDefault": "{value} (padrão)", "claude.autoCompactWindowDesc": "As mensagens mais antigas são resumidas quando a conversa chega a este ponto. Ele nunca excede o limite de cada modelo, então modelos de 200k não são afetados.", diff --git a/gui/src/i18n/ru.ts b/gui/src/i18n/ru.ts index 0e916d3ad77..3a9aca7fb5b 100644 --- a/gui/src/i18n/ru.ts +++ b/gui/src/i18n/ru.ts @@ -2954,6 +2954,10 @@ export const ru: Record = { "claude.autoContext": "Автоматически использовать большой контекст", "claude.autoContextDesc": "Определяет, как широко применяется пометка 1M. ВКЛ: строку с большим контекстом получает каждая модель, окно которой вмещает порог сжатия. ВЫКЛ: её получают только модели с настоящим контекстом 1M.", "claude.autoContextInert": "Неактивно, поскольку в файле конфигурации задано устаревшее значение размера контекста (maxContextTokens). Удалите его там, чтобы снова включить эту настройку.", + "claude.contextAccounting": "Учёт контекста", + "claude.contextAccountingDesc": "1M (по умолчанию): модели, чьё окно вмещает точку сжатия, предлагаются как 1M везде, где opencodex выбирает значение по умолчанию. 200k: Claude Code считает каждую модель как 200k, если вы сами не выберете строку 1M.", + "claude.contextAccounting1m": "1M (по умолчанию)", + "claude.contextAccounting200k": "200k", "claude.autoCompactWindow": "Порог автосуммаризации", "claude.autoCompactDefault": "{value} (по умолчанию)", "claude.autoCompactWindowDesc": "Когда чат достигает этого порога, старые сообщения суммаризируются. Порог никогда не превышает собственный лимит модели, поэтому модели с контекстом 200k не затрагиваются.", diff --git a/gui/src/i18n/tr.ts b/gui/src/i18n/tr.ts index 9e57c58adc1..2b22fbea646 100644 --- a/gui/src/i18n/tr.ts +++ b/gui/src/i18n/tr.ts @@ -2983,6 +2983,10 @@ export const tr: Record = { "claude.autoContext": "Otomatik büyük bağlam kullan", "claude.autoContextDesc": "1M işaretinin ne kadar ileri gideceğini kontrol eder. AÇIK: penceresi sıkıştırma eşiğini barındırabilen her model 1M aralığı kazanır. KAPALI: yalnızca gerçek 1M modelleri alır.", "claude.autoContextInert": "Pasif durumdadır çünkü konfigürasyon dosyasında eski bir bağlam boyutu değeri (maxContextTokens) var. Yeniden etkinleştirmek için oradan kaldırın.", + "claude.contextAccounting": "Bağlam hesaplama", + "claude.contextAccountingDesc": "1M (varsayılan): Penceresi özetleme noktasını taşıyabilen modeller, opencodex'in varsayılanı seçtiği her yerde 1M olarak sunulur. 200k: Kendiniz bir 1M satırı seçmedikçe Claude Code her modeli 200k olarak sayar.", + "claude.contextAccounting1m": "1M (varsayılan)", + "claude.contextAccounting200k": "200k", "claude.autoCompactWindow": "Otomatik özetleme noktası", "claude.autoCompactDefault": "{value} (varsayılan)", "claude.autoCompactWindowDesc": "Sohbet bu noktaya ulaştığında eski mesajlar özetlenir. Her modelin kendi sınırını asla aşmaz, bu nedenle 200k modeller etkilenmez.", diff --git a/gui/src/i18n/vi.ts b/gui/src/i18n/vi.ts index 220c78d7f7f..31b787ce631 100644 --- a/gui/src/i18n/vi.ts +++ b/gui/src/i18n/vi.ts @@ -2980,6 +2980,10 @@ export const vi: Record = { "claude.autoContext": "Tự động sử dụng ngữ cảnh lớn (big context)", "claude.autoContextDesc": "Kiểm soát phạm vi áp dụng nhãn 1M. ON: bất kỳ model nào có cửa sổ (window) đủ lớn để chứa ngưỡng nén (compaction threshold) đều sẽ có hàng big-context. OFF: chỉ những model thực sự đạt 1M mới có.", "claude.autoContextInert": "Bị vô hiệu hóa vì giá trị kích thước ngữ cảnh (maxContextTokens) cũ vẫn tồn tại trong tệp cấu hình. Hãy xóa nó ở đó để kích hoạt lại.", + "claude.contextAccounting": "Cách tính ngữ cảnh", + "claude.contextAccountingDesc": "1M (mặc định): các mô hình có cửa sổ chứa được điểm tóm tắt được cung cấp ở mức 1M ở mọi nơi opencodex chọn giá trị mặc định. 200k: Claude Code tính mọi mô hình là 200k trừ khi bạn tự chọn một dòng 1M.", + "claude.contextAccounting1m": "1M (mặc định)", + "claude.contextAccounting200k": "200k", "claude.autoCompactWindow": "Điểm tự động tóm tắt", "claude.autoCompactDefault": "{value} (mặc định)", "claude.autoCompactWindowDesc": "Các tin nhắn cũ hơn sẽ được tóm tắt khi cuộc trò chuyện đạt đến điểm này. Nó không bao giờ vượt qua giới hạn riêng của từng model, do đó các model 200k sẽ không bị ảnh hưởng.", diff --git a/gui/src/i18n/zh-TW.ts b/gui/src/i18n/zh-TW.ts index 2b3c05a750d..296441c4131 100644 --- a/gui/src/i18n/zh-TW.ts +++ b/gui/src/i18n/zh-TW.ts @@ -2184,6 +2184,10 @@ export const zhTW: Record = { "claude.autoContext": "自動利用大上下文", "claude.autoContextDesc": "決定 1M 標記的範圍。開:視窗能容納壓縮門檻的模型都有大上下文條目;關:僅真正的 1M 模型有。", "claude.autoContextInert": "配置檔案中存在舊式上下文大小值(maxContextTokens),此功能暫不生效。刪除該值即可恢復。", + "claude.contextAccounting": "上下文計算方式", + "claude.contextAccountingDesc": "1M(預設):視窗能容納摘要點的模型,在 opencodex 選擇預設值的所有地方都按 1M 提供。200k:除非你自己選擇 1M 條目,Claude Code 會把所有模型按 200k 計算。", + "claude.contextAccounting1m": "1M(預設)", + "claude.contextAccounting200k": "200k", "claude.autoCompactWindow": "自動摘要觸發點", "claude.autoCompactDefault": "{value}(預設)", "claude.autoCompactWindowDesc": "對話達到該點時自動摘要舊內容。不會超過各模型自身上限,因此 200k 模型不受影響。", diff --git a/gui/src/i18n/zh.ts b/gui/src/i18n/zh.ts index a336d6066c6..2af29227794 100644 --- a/gui/src/i18n/zh.ts +++ b/gui/src/i18n/zh.ts @@ -2443,6 +2443,10 @@ export const zh: Record = { "claude.autoContext": "自动利用大上下文", "claude.autoContextDesc": "决定 1M 标记的范围。开:窗口能容纳压缩阈值的模型都有大上下文条目;关:仅真正的 1M 模型有。", "claude.autoContextInert": "配置文件中存在旧式上下文大小值(maxContextTokens),此功能暂不生效。删除该值即可恢复。", + "claude.contextAccounting": "上下文计算方式", + "claude.contextAccountingDesc": "1M(默认):窗口能容纳摘要点的模型,在 opencodex 选择默认值的所有地方都按 1M 提供。200k:除非你自己选择 1M 条目,Claude Code 会把所有模型按 200k 计算。", + "claude.contextAccounting1m": "1M(默认)", + "claude.contextAccounting200k": "200k", "claude.autoCompactWindow": "自动摘要触发点", "claude.autoCompactDefault": "{value}(默认)", "claude.autoCompactWindowDesc": "对话达到该点时自动摘要旧内容。不会超过各模型自身上限,因此 200k 模型不受影响。", diff --git a/gui/src/pages/ClaudeCode.tsx b/gui/src/pages/ClaudeCode.tsx index f9e5590f8d9..f3954cff67c 100644 --- a/gui/src/pages/ClaudeCode.tsx +++ b/gui/src/pages/ClaudeCode.tsx @@ -16,7 +16,7 @@ import { ClaudeCodeQuickstartSection, ClaudeCodeSettingsCard, } from "./claude-code-sections"; -import { AUTO_COMPACT_WINDOW_DEFAULT, formatCompactWindow, newClientId, type ClaudeCodeState, type MapRow } from "./claude-code-types"; +import { AUTO_COMPACT_WINDOW_DEFAULT, formatCompactWindow, newClientId, normalizeContextAccounting, type ClaudeCodeState, type MapRow } from "./claude-code-types"; import { SmallFastModelSetting } from "./claude-code-settings"; import { interceptReasonKey, normalizeSharedProxy, selectFirstPartyNotice, type FirstPartyNotice } from "./claude-code-first-party"; import { @@ -43,6 +43,9 @@ function normalizeFirstPartyState(state: ClaudeCodeState): ClaudeCodeState { interceptRunning: state.interceptRunning === true, interceptEligible: state.interceptEligible === undefined ? true : state.interceptEligible === true, sharedProxy: normalizeSharedProxy(state.sharedProxy), + // Shared by the session cache and the GET read, so a state cached by an older proxy (no + // field) and an older server both read as the default. + contextAccounting: normalizeContextAccounting(state.contextAccounting), }; } diff --git a/gui/src/pages/claude-code-save.ts b/gui/src/pages/claude-code-save.ts index e24f7a2d147..e9f21d467c8 100644 --- a/gui/src/pages/claude-code-save.ts +++ b/gui/src/pages/claude-code-save.ts @@ -13,6 +13,7 @@ export const EDITABLE_KEYS = [ "fastMode", "autoContext", "autoCompactWindow", + "contextAccounting", "injectAgents", "smallFastModel", "webSearchSidecar", @@ -44,6 +45,7 @@ export function claudeCodeSaveBody(state: ClaudeCodeState, rows: readonly MapRow fastMode: state.fastMode, autoContext: state.autoContext, autoCompactWindow: state.autoCompactWindow, + contextAccounting: state.contextAccounting, injectAgents: state.injectAgents, smallFastModel: state.smallFastModel, modelMap: normalizedModelMap(rows), diff --git a/gui/src/pages/claude-code-sections.tsx b/gui/src/pages/claude-code-sections.tsx index d8efea5b53e..55040beba92 100644 --- a/gui/src/pages/claude-code-sections.tsx +++ b/gui/src/pages/claude-code-sections.tsx @@ -116,14 +116,37 @@ export function ClaudeCodeSettingsCard({
- {t("claude.autoContext")} - {t("claude.autoContextDesc")} - {state.maxContextTokens !== null && {t("claude.autoContextInert")}} + {t("claude.contextAccounting")} + {t("claude.contextAccountingDesc")} +
+
+