Fix Windows AI model selection
Some checks failed
build-packages / ${{ needs.dedupe.outputs.skip_heavy_ci == 'true' && 'deduped build-linux-x64' || 'build-linux-x64' }} (push) Has been cancelled
build-packages / ${{ needs.dedupe.outputs.skip_heavy_ci == 'true' && 'deduped build-linux-arm64' || 'build-linux-arm64' }} (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / dedupe push run (push) Has been cancelled
build-packages / dedupe result (push) Has been cancelled
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled

Fix the Windows issue where AI models could not be selected.
This commit is contained in:
lengyuqu
2026-06-12 01:42:38 +08:00
committed by GitHub
parent bf9f557e42
commit ea24841939
5 changed files with 36 additions and 17 deletions

View File

@@ -22,7 +22,9 @@ export function isCopilotAgentConfig(agent?: ExternalAgentConfig): boolean {
getExternalAgentSdkBackend(agent), getExternalAgentSdkBackend(agent),
] ]
.filter((value): value is string => typeof value === 'string' && value.length > 0) .filter((value): value is string => typeof value === 'string' && value.length > 0)
.map((value) => value.split('/').pop()?.toLowerCase() ?? value.toLowerCase()); // Split on both separators so Windows command paths (e.g. "...\\copilot.exe")
// reduce to their basename rather than staying as the full path.
.map((value) => value.split(/[\\/]/).pop()?.toLowerCase() ?? value.toLowerCase());
return tokens.some((token) => token.includes('copilot')); return tokens.some((token) => token.includes('copilot'));
} }

View File

@@ -2,6 +2,7 @@ import test from 'node:test';
import assert from 'node:assert/strict'; import assert from 'node:assert/strict';
import { import {
CLAUDE_MODEL_PRESETS,
CODEBUDDY_MODEL_PRESETS, CODEBUDDY_MODEL_PRESETS,
CODEX_MODEL_PRESETS, CODEX_MODEL_PRESETS,
getAgentModelPresets, getAgentModelPresets,
@@ -19,3 +20,14 @@ test('getAgentModelPresets keeps Codex presets separate from CodeBuddy presets',
assert.deepEqual(getAgentModelPresets('codex'), CODEX_MODEL_PRESETS); assert.deepEqual(getAgentModelPresets('codex'), CODEX_MODEL_PRESETS);
assert.notDeepEqual(CODEBUDDY_MODEL_PRESETS, CODEX_MODEL_PRESETS); assert.notDeepEqual(CODEBUDDY_MODEL_PRESETS, CODEX_MODEL_PRESETS);
}); });
test('getAgentModelPresets resolves Windows command paths with backslashes', () => {
assert.deepEqual(
getAgentModelPresets('C\\Users\\foo\\AppData\\Roaming\\npm\\codex.cmd'),
CODEX_MODEL_PRESETS,
);
assert.deepEqual(
getAgentModelPresets('C\\Program Files\\nodejs\\claude.exe'),
CLAUDE_MODEL_PRESETS,
);
});

View File

@@ -477,7 +477,11 @@ export const CODEBUDDY_MODEL_PRESETS: AgentModelPreset[] = [
export function getAgentModelPresets(agentCommand?: string): AgentModelPreset[] { export function getAgentModelPresets(agentCommand?: string): AgentModelPreset[] {
if (!agentCommand) return []; if (!agentCommand) return [];
const basename = agentCommand.split('/').pop()?.toLowerCase() ?? ''; // Split on both POSIX (/) and Windows (\) separators so command paths like
// "C:\\Users\\foo\\codex.cmd" resolve to the right basename. Splitting only
// on "/" leaves the full path intact on Windows, which never matches the
// preset prefixes below and yields an empty list (presets silently lost).
const basename = agentCommand.split(/[\\/]/).pop()?.toLowerCase() ?? '';
if (basename.startsWith('claude')) return CLAUDE_MODEL_PRESETS; if (basename.startsWith('claude')) return CLAUDE_MODEL_PRESETS;
if (basename.startsWith('codex')) return CODEX_MODEL_PRESETS; if (basename.startsWith('codex')) return CODEX_MODEL_PRESETS;
if (basename.startsWith('cursor')) return CURSOR_MODEL_PRESETS; if (basename.startsWith('cursor')) return CURSOR_MODEL_PRESETS;

29
package-lock.json generated
View File

@@ -32,6 +32,7 @@
"@radix-ui/react-tooltip": "^1.2.8", "@radix-ui/react-tooltip": "^1.2.8",
"@streamdown/cjk": "^1.0.2", "@streamdown/cjk": "^1.0.2",
"@streamdown/code": "^1.1.0", "@streamdown/code": "^1.1.0",
"@tencent-ai/agent-sdk": "^0.3.173",
"@withfig/autocomplete": "^2.692.3", "@withfig/autocomplete": "^2.692.3",
"@xterm/addon-fit": "^0.11.0", "@xterm/addon-fit": "^0.11.0",
"@xterm/addon-search": "^0.16.0", "@xterm/addon-search": "^0.16.0",
@@ -90,7 +91,7 @@
"@anthropic-ai/claude-agent-sdk": "^0.3.161", "@anthropic-ai/claude-agent-sdk": "^0.3.161",
"@cursor/sdk": "^1.0.18", "@cursor/sdk": "^1.0.18",
"@github/copilot-sdk": "1.0.0", "@github/copilot-sdk": "1.0.0",
"@tencent-ai/agent-sdk": "^0.3.169", "@tencent-ai/agent-sdk": "^0.3.173",
"@vscode/windows-process-tree": "^0.7.0" "@vscode/windows-process-tree": "^0.7.0"
} }
}, },
@@ -6496,20 +6497,10 @@
"vite": "^5.2.0 || ^6 || ^7" "vite": "^5.2.0 || ^6 || ^7"
} }
}, },
"node_modules/@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
"integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/@tencent-ai/agent-sdk": { "node_modules/@tencent-ai/agent-sdk": {
"version": "0.3.169", "version": "0.3.173",
"resolved": "https://registry.npmjs.org/@tencent-ai/agent-sdk/-/agent-sdk-0.3.169.tgz", "resolved": "https://registry.npmjs.org/@tencent-ai/agent-sdk/-/agent-sdk-0.3.173.tgz",
"integrity": "sha512-iwMbrV+7KzMRjDTZPwz9VAIxokDJ1ybOY58YODSCgrsh/2cILFWl8jhMElpZScS3zsUb5IvB2xbaXhxtIEqKBw==", "integrity": "sha512-8aAZhQ1pMhcAdsPrLpk93abGMQGVdm3kf6WGMLgf1TJLW/YrHskJeOxFCCqkxyx3SLu68hi2h9EcyvQEPcta6Q==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
@@ -6520,6 +6511,16 @@
"zod": "^4.0.0" "zod": "^4.0.0"
} }
}, },
"node_modules/@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
"integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/@types/babel__core": { "node_modules/@types/babel__core": {
"version": "7.20.5", "version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",

View File

@@ -115,7 +115,7 @@
"@anthropic-ai/claude-agent-sdk": "^0.3.161", "@anthropic-ai/claude-agent-sdk": "^0.3.161",
"@cursor/sdk": "^1.0.18", "@cursor/sdk": "^1.0.18",
"@github/copilot-sdk": "1.0.0", "@github/copilot-sdk": "1.0.0",
"@tencent-ai/agent-sdk": "^0.3.169", "@tencent-ai/agent-sdk": "^0.3.173",
"@vscode/windows-process-tree": "^0.7.0" "@vscode/windows-process-tree": "^0.7.0"
}, },
"overrides": { "overrides": {