fix(agents): support Claude Desktop aliases for Codex OAuth models

This commit is contained in:
lzt404 committed 2026-08-11 12:29:35 +08:00
1 parent 8655f6aae4
commit e9470fbe14
15 files changed
+689 -180

No files matched your search

+9 -1
View File
@@ -476,6 +476,7 @@ export const jaOverrides = {
'agents.error.noModels': '選択可能なモデルがないため、設定変更を適用できません',
'agents.error.selectionGone': '選択中のモデルは利用可能一覧にありません。更新後に選び直してください',
'agents.error.mappingSelectionGone': 'Claude Desktop のモデルマッピングに利用できないモデルがあります。モデルを更新して選び直してください',
'agents.error.claudeCodeRuntimeSettingsInvalid': '最大コンテキストは 100000~1000000、自動圧縮率は 1~100 にしてください',
'agents.error.applyFirst': '選択したモデルはまだ適用されていません。先に「設定変更を適用」をクリックしてください',
'agents.status.detecting': '検出中',
'agents.status.unsupported': 'プラットフォーム非対応',
@@ -570,7 +571,14 @@ export const jaOverrides = {
'agents.claudeDesktopMapping.title': 'Claude Desktop モデル → 上流モデル',
'agents.claudeDesktopMapping.description': '役割ごとに上流モデルとコンテキスト機能を選択します。対応モデルでのみ 1M を有効にしてください。',
'agents.claudeCodeMapping.title': 'Claude Code モデル → 上流モデル',
'agents.claudeCodeMapping.description': 'タスク役割ごとに上流モデルとコンテキスト機能を選択します。対応モデルでのみ 1M を有効にしてください。',
'agents.claudeCodeMapping.description': 'タスク役割ごとに上流モデルを選び、共通のコンテキストと自動圧縮ポリシーを設定します。',
'agents.claudeCodeRuntime.maxContextTokens': '最大コンテキスト',
'agents.claudeCodeRuntime.maxContextTokensHint': 'Claude Code の既定値は 200000 です。上流モデルの上限を超えないでください。',
'agents.claudeCodeRuntime.context1mHint': 'このマッピングで [1m] モデルを使用し、最大コンテキストを 1000000 にします。3 つすべてを無効にすると 200000 に戻ります。',
'agents.claudeCodeRuntime.autoCompactPct': '自動圧縮の開始率',
'agents.claudeCodeRuntime.autoCompactPctHint': '既定値は 100% です。小さい値ほど早く圧縮します。',
'agents.claudeCodeRuntime.disableAutoCompact': '自動圧縮を無効化',
'agents.claudeCodeRuntime.disableAutoCompactHint': '有効時は /compact による手動圧縮のみ利用できます。',
'agents.claudeDesktopMapping.customMapping': 'モデルエイリアスを使用',
'agents.claudeDesktopMapping.customMappingHint': '有効にするとエイリアスモデルのみ、無効にするとエイリアス未設定の元モデルのみ表示します。',
'agents.claudeDesktopMapping.opus': 'Claude Opus 5',
+9 -1
View File
@@ -476,6 +476,7 @@ export const en: Record<MessageKey, string> = {
'agents.error.noModels': 'No models are available, so configuration changes cannot be applied',
'agents.error.selectionGone': 'The selected model is no longer available. Refresh and select it again.',
'agents.error.mappingSelectionGone': 'A Claude Desktop mapping is no longer available. Refresh the models and select it again.',
'agents.error.claudeCodeRuntimeSettingsInvalid': 'Maximum context must be 100000–1000000 and the auto-compact percentage must be 1–100.',
'agents.error.applyFirst': 'The selected model has not been applied. Click “Apply Configuration Changes” first.',
'agents.status.detecting': 'Detecting',
'agents.status.unsupported': 'Unsupported Platform',
@@ -565,7 +566,14 @@ export const en: Record<MessageKey, string> = {
'agents.claudeDesktopMapping.title': 'Claude Desktop Model → Upstream Model',
'agents.claudeDesktopMapping.description': 'Choose the upstream model and context capability for each role. Turn on 1M only for supported models.',
'agents.claudeCodeMapping.title': 'Claude Code Model → Upstream Model',
'agents.claudeCodeMapping.description': 'Choose the upstream model and context capability for each task role. Turn on 1M only for supported models.',
'agents.claudeCodeMapping.description': 'Choose the upstream model for each task role and configure one shared context and auto-compact policy.',
'agents.claudeCodeRuntime.maxContextTokens': 'Maximum context',
'agents.claudeCodeRuntime.maxContextTokensHint': 'Claude Code defaults to 200000. Do not exceed the upstream model limit.',
'agents.claudeCodeRuntime.context1mHint': 'Uses the [1m] model for this mapping and sets the maximum context to 1000000. It returns to 200000 after all three mappings are off.',
'agents.claudeCodeRuntime.autoCompactPct': 'Auto-compact trigger',
'agents.claudeCodeRuntime.autoCompactPctHint': 'Defaults to 100%. Lower values compact earlier.',
'agents.claudeCodeRuntime.disableAutoCompact': 'Disable auto-compaction',
'agents.claudeCodeRuntime.disableAutoCompactHint': 'Only manual /compact remains available when enabled.',
'agents.claudeDesktopMapping.customMapping': 'Use Model Aliases',
'agents.claudeDesktopMapping.customMappingHint': 'When enabled, only aliased models are shown; when disabled, only original models without aliases are shown.',
'agents.claudeDesktopMapping.opus': 'Claude Opus 5',
+9 -1
View File
@@ -474,6 +474,7 @@ export const zhCN = {
'agents.error.noModels': '当前没有可选模型,无法应用配置修改',
'agents.error.selectionGone': '当前选择已不在可用模型列表中,请刷新模型后重新选择',
'agents.error.mappingSelectionGone': 'Claude Desktop 模型映射包含不可用模型,请刷新模型后重新选择',
'agents.error.claudeCodeRuntimeSettingsInvalid': '最大窗口必须为 100000–1000000,触发压缩百分比必须为 1–100',
'agents.error.applyFirst': '模型选择尚未应用,请先点击“应用配置修改”',
'agents.status.detecting': '检测中',
'agents.status.unsupported': '平台不支持',
@@ -563,7 +564,14 @@ export const zhCN = {
'agents.claudeDesktopMapping.title': 'Claude Desktop 模型 → 上游模型',
'agents.claudeDesktopMapping.description': '分别选择上游模型和上下文能力;仅为确认支持的模型打开 1M。',
'agents.claudeCodeMapping.title': 'Claude Code 模型 → 上游模型',
'agents.claudeCodeMapping.description': '分别为不同任务角色选择上游模型和上下文能力;仅为确认支持的模型打开 1M。',
'agents.claudeCodeMapping.description': '分别为不同任务角色选择上游模型,并统一配置上下文窗口与自动压缩。',
'agents.claudeCodeRuntime.maxContextTokens': '最大窗口',
'agents.claudeCodeRuntime.maxContextTokensHint': 'Claude Code 默认 200000;请勿超过上游模型实际支持的窗口。',
'agents.claudeCodeRuntime.context1mHint': '为此映射使用 [1m] 模型并将最大窗口设为 1000000;三个映射均关闭后恢复为 200000。',
'agents.claudeCodeRuntime.autoCompactPct': '触发压缩百分比',
'agents.claudeCodeRuntime.autoCompactPctHint': '默认 100;调低后会更早自动压缩。',
'agents.claudeCodeRuntime.disableAutoCompact': '禁止自动压缩',
'agents.claudeCodeRuntime.disableAutoCompactHint': '开启后仅允许用户通过 /compact 手动压缩。',
'agents.claudeDesktopMapping.customMapping': '使用模型别名',
'agents.claudeDesktopMapping.customMappingHint': '开启后只显示别名模型;关闭后只显示未设置别名的原始模型。',
'agents.claudeDesktopMapping.opus': 'Claude Opus 5',
+125 -3
View File
@@ -104,9 +104,14 @@ type ClaudeModelMappings = {
opus1m: boolean;
sonnet1m: boolean;
haiku1m: boolean;
maxContextTokens: number;
autoCompactPct: number;
disableAutoCompact: boolean;
};
const CODEX_OAUTH_LOGIN_REQUIRED_ERROR = 'CODEX_OAUTH_LOGIN_REQUIRED';
const DEFAULT_CLAUDE_CODE_MAX_CONTEXT_TOKENS = 200_000;
const DEFAULT_CLAUDE_AUTO_COMPACT_PCT = 100;
const createClaudeModelMappings = (model: string): ClaudeModelMappings => ({
opus: model,
@@ -115,6 +120,9 @@ const createClaudeModelMappings = (model: string): ClaudeModelMappings => ({
opus1m: false,
sonnet1m: false,
haiku1m: false,
maxContextTokens: DEFAULT_CLAUDE_CODE_MAX_CONTEXT_TOKENS,
autoCompactPct: DEFAULT_CLAUDE_AUTO_COMPACT_PCT,
disableAutoCompact: false,
});
const claudeMappingRoles = [
@@ -731,6 +739,9 @@ export function AgentsPage() {
opus1m: Boolean(source.opus1m),
sonnet1m: Boolean(source.sonnet1m),
haiku1m: Boolean(source.haiku1m),
maxContextTokens: source.maxContextTokens ?? DEFAULT_CLAUDE_CODE_MAX_CONTEXT_TOKENS,
autoCompactPct: source.autoCompactPct ?? DEFAULT_CLAUDE_AUTO_COMPACT_PCT,
disableAutoCompact: Boolean(source.disableAutoCompact),
};
return sameAgentModelMappings(current, next) ? current : next;
});
@@ -757,6 +768,12 @@ export function AgentsPage() {
|| claudeMappingRoles.every((role) =>
Boolean(findAgentModel(models, claudeModelMappingsDraft[role.key])),
);
const claudeCodeRuntimeSettingsReady = selected !== 'claude-code' || (
claudeModelMappingsDraft.maxContextTokens >= 100_000
&& claudeModelMappingsDraft.maxContextTokens <= 1_000_000
&& claudeModelMappingsDraft.autoCompactPct >= 1
&& claudeModelMappingsDraft.autoCompactPct <= 100
);
const claudeMappingDraftChanged = isClaudeModelMappingClient
&& activeStatus?.modificationState === 'applied'
&& !sameAgentModelMappings(
@@ -781,7 +798,7 @@ export function AgentsPage() {
&& activeStatus.installed
&& !modelLoading
&& (isClaudeModelMappingClient
? claudeMappingsReady
? claudeMappingsReady && claudeCodeRuntimeSettingsReady
: selectedModelOption),
);
const modelHint = modelSelectionError
@@ -836,7 +853,32 @@ export function AgentsPage() {
enabled: boolean,
) => {
claudeModelMappingsDirtyRef.current = true;
setClaudeModelMappingsDraft((current) => ({ ...current, [preference]: enabled }));
setClaudeModelMappingsDraft((current) => {
const next = { ...current, [preference]: enabled };
if (selected === 'claude-code') {
const any1mEnabled = next.opus1m || next.sonnet1m || next.haiku1m;
next.maxContextTokens = any1mEnabled
? 1_000_000
: DEFAULT_CLAUDE_CODE_MAX_CONTEXT_TOKENS;
}
return next;
});
};
const changeClaudeCodeRuntimeSetting = (
key: 'maxContextTokens' | 'autoCompactPct',
value: number,
) => {
claudeModelMappingsDirtyRef.current = true;
setClaudeModelMappingsDraft((current) => ({ ...current, [key]: value }));
};
const changeClaudeCodeAutoCompactDisabled = (disabled: boolean) => {
claudeModelMappingsDirtyRef.current = true;
setClaudeModelMappingsDraft((current) => ({
...current,
disableAutoCompact: disabled,
}));
};
const changeClaudeCustomMapping = (enabled: boolean) => {
@@ -850,6 +892,9 @@ export function AgentsPage() {
opus1m: current.opus1m,
sonnet1m: current.sonnet1m,
haiku1m: current.haiku1m,
maxContextTokens: current.maxContextTokens,
autoCompactPct: current.autoCompactPct,
disableAutoCompact: current.disableAutoCompact,
};
if (!sameAgentModelMappings(current, next)) {
claudeModelMappingsDirtyRef.current = true;
@@ -888,6 +933,15 @@ export function AgentsPage() {
resolved[role.key] = model.name;
resolved[role.contextKey] = claudeModelMappingsDraft[role.contextKey];
}
if (selected === 'claude-code') {
if (!claudeCodeRuntimeSettingsReady) {
setModelSelectionError(t('agents.error.claudeCodeRuntimeSettingsInvalid'));
return null;
}
}
resolved.maxContextTokens = claudeModelMappingsDraft.maxContextTokens;
resolved.autoCompactPct = claudeModelMappingsDraft.autoCompactPct;
resolved.disableAutoCompact = claudeModelMappingsDraft.disableAutoCompact;
return resolved;
};
@@ -1291,6 +1345,72 @@ export function AgentsPage() {
</label>
</div>
</div>
{selected === 'claude-code' ? (
<div className="agent-claude-code-runtime-settings">
<div className="agent-claude-code-number-field">
<span>{t('agents.claudeCodeRuntime.maxContextTokens')}</span>
<input
type="number"
min={100_000}
max={1_000_000}
step={1_000}
value={claudeModelMappingsDraft.maxContextTokens}
onChange={(event) => changeClaudeCodeRuntimeSetting(
'maxContextTokens',
Math.trunc(event.currentTarget.valueAsNumber || 0),
)}
disabled={busy || modelLoading}
aria-label={t('agents.claudeCodeRuntime.maxContextTokens')}
aria-describedby="claude-code-max-context-hint"
/>
<small id="claude-code-max-context-hint">
{t('agents.claudeCodeRuntime.maxContextTokensHint')}
</small>
</div>
<label className="agent-claude-code-number-field">
<span>{t('agents.claudeCodeRuntime.autoCompactPct')}</span>
<div className="agent-claude-code-percent-input">
<input
type="number"
min={1}
max={100}
step={1}
value={claudeModelMappingsDraft.autoCompactPct}
onChange={(event) => changeClaudeCodeRuntimeSetting(
'autoCompactPct',
Math.trunc(event.currentTarget.valueAsNumber || 0),
)}
disabled={busy || modelLoading || claudeModelMappingsDraft.disableAutoCompact}
aria-describedby="claude-code-auto-compact-hint"
/>
<span>%</span>
</div>
<small id="claude-code-auto-compact-hint">
{t('agents.claudeCodeRuntime.autoCompactPctHint')}
</small>
</label>
<label
className="agent-claude-code-disable-compact"
title={t('agents.claudeCodeRuntime.disableAutoCompactHint')}
>
<span>
<strong>{t('agents.claudeCodeRuntime.disableAutoCompact')}</strong>
<small>{t('agents.claudeCodeRuntime.disableAutoCompactHint')}</small>
</span>
<span className="switch-control">
<input
type="checkbox"
checked={claudeModelMappingsDraft.disableAutoCompact}
onChange={(event) => changeClaudeCodeAutoCompactDisabled(
event.currentTarget.checked,
)}
disabled={busy || modelLoading}
/>
<span className="switch-track" />
</span>
</label>
</div>
) : null}
<div className="agent-claude-desktop-mapping-grid">
{claudeMappingRoles.map((role) => (
<div className="agent-claude-desktop-mapping-row" key={role.key}>
@@ -1298,7 +1418,9 @@ export function AgentsPage() {
<strong>{t(role.labelKey)}</strong>
<label
className="agent-claude-context-toggle"
title={t('agents.claudeMapping.context1mHint')}
title={t(selected === 'claude-code'
? 'agents.claudeCodeRuntime.context1mHint'
: 'agents.claudeMapping.context1mHint')}
>
<span>{t('agents.claudeMapping.context1m')}</span>
<span className="switch-control">
+7 -1
View File
@@ -18,6 +18,9 @@ export type AgentModelMappings = {
opus1m?: boolean;
sonnet1m?: boolean;
haiku1m?: boolean;
maxContextTokens?: number;
autoCompactPct?: number;
disableAutoCompact?: boolean;
};
type ResolveAgentConfigurationActionOptions = {
@@ -45,7 +48,10 @@ export const sameAgentModelMappings = (
&& sameAgentModel(left.haiku, right.haiku)
&& Boolean(left.opus1m) === Boolean(right.opus1m)
&& Boolean(left.sonnet1m) === Boolean(right.sonnet1m)
&& Boolean(left.haiku1m) === Boolean(right.haiku1m);
&& Boolean(left.haiku1m) === Boolean(right.haiku1m)
&& (left.maxContextTokens ?? 200_000) === (right.maxContextTokens ?? 200_000)
&& (left.autoCompactPct ?? 100) === (right.autoCompactPct ?? 100)
&& Boolean(left.disableAutoCompact) === Boolean(right.disableAutoCompact);
export function resolveAgentConfigurationAction({
client,
+108
View File
@@ -5519,6 +5519,98 @@ textarea:focus-visible {
gap: 12px;
}
.agent-claude-code-runtime-settings {
display: grid;
grid-template-columns: minmax(180px, 1fr) minmax(180px, 1fr) minmax(240px, 1.2fr);
gap: 12px;
padding: 12px;
border: 1px solid var(--theme-e3e1db);
border-radius: 9px;
background: var(--theme-faf9f5);
}
.agent-claude-code-number-field {
display: grid;
align-content: start;
gap: 6px;
color: var(--theme-5f5a53);
font-size: var(--font-size-label);
font-weight: 700;
}
.agent-claude-code-number-field > input,
.agent-claude-code-percent-input input {
width: 100%;
min-width: 0;
padding: 8px 10px;
border: 1px solid var(--theme-d3d0c9);
border-radius: 7px;
background: var(--theme-fff);
color: var(--theme-2f2c28);
font: inherit;
font-variant-numeric: tabular-nums;
}
.agent-claude-code-number-field > input:focus,
.agent-claude-code-percent-input input:focus {
border-color: var(--theme-8069ad);
outline: 2px solid rgba(128, 105, 173, 0.14);
}
.agent-claude-code-number-field > input:disabled,
.agent-claude-code-percent-input input:disabled {
cursor: not-allowed;
opacity: 0.62;
}
.agent-claude-code-number-field small,
.agent-claude-code-disable-compact small {
color: var(--theme-817b72);
font-size: var(--font-size-caption);
font-weight: 500;
line-height: 1.4;
}
.agent-claude-code-percent-input {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
align-items: center;
gap: 7px;
}
.agent-claude-code-percent-input > span {
color: var(--theme-817b72);
font-weight: 700;
}
.agent-claude-code-disable-compact {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 10px 12px;
border: 1px solid var(--theme-e3e1db);
border-radius: 8px;
background: var(--theme-fff);
color: var(--theme-5f5a53);
cursor: pointer;
}
.agent-claude-code-disable-compact > span:first-child {
display: grid;
gap: 4px;
}
.agent-claude-code-disable-compact:has(input:checked) {
border-color: rgba(174, 92, 82, 0.48);
background: rgba(174, 92, 82, 0.06);
}
.agent-claude-code-disable-compact:has(input:disabled) {
cursor: not-allowed;
opacity: 0.62;
}
.agent-claude-desktop-mapping-row {
display: grid;
min-width: 0;
@@ -7264,6 +7356,14 @@ textarea:focus-visible {
}
@container agent-panel (max-width: 760px) {
.agent-claude-code-runtime-settings {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.agent-claude-code-disable-compact {
grid-column: 1 / -1;
}
.agent-claude-desktop-mapping-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
@@ -7283,6 +7383,14 @@ textarea:focus-visible {
grid-template-columns: 1fr;
}
.agent-claude-code-runtime-settings {
grid-template-columns: 1fr;
}
.agent-claude-code-disable-compact {
grid-column: auto;
}
.agent-codex-options {
grid-template-columns: 1fr;
}