fix(daemon): read Pi model list from stdout (#5637)

This commit is contained in:
coyaSONG
2026-07-15 09:14:07 +00:00
committed by GitHub
parent 75af2b13cf
commit 4c1344f8b8
2 changed files with 35 additions and 4 deletions
+3 -4
View File
@@ -12,16 +12,15 @@ export const piAgentDef = {
// every spawn). The default 3s version-probe timeout is too tight; raise it
// so detection doesn't silently abort before reaching fetchModels.
versionProbeTimeoutMs: 15_000,
// `pi --list-models` prints a TSV table to stderr (not stdout),
// so we use a custom fetchModels that reads stderr.
// `pi --list-models` prints its TSV table to stdout.
fetchModels: async (resolvedBin, env) => {
try {
const { stderr } = await execAgentFile(resolvedBin, ['--list-models'], {
const { stdout } = await execAgentFile(resolvedBin, ['--list-models'], {
env,
timeout: 60_000, // Windows: 20s exceeded under parallel detection load
maxBuffer: 8 * 1024 * 1024,
});
const parsed = parsePiModels(stderr);
const parsed = parsePiModels(stdout);
if (!parsed || parsed.length === 0) return null;
return parsed;
} catch {
@@ -269,6 +269,38 @@ test('pi args use rpc mode without --no-session and append model/thinking option
]);
});
test('pi fetchModels reads the model table from stdout', async () => {
const dir = mkdtempSync(join(tmpdir(), 'od-pi-models-'));
try {
const bin = join(dir, process.platform === 'win32' ? 'pi.cmd' : 'pi');
if (process.platform === 'win32') {
writeFileSync(
bin,
'@echo off\r\nif "%~1"=="--list-models" (\r\n echo provider model context max-out thinking images\r\n echo anthropic claude-sonnet-4-5 200K 64K yes yes\r\n exit /b 0\r\n)\r\nexit /b 1\r\n',
);
} else {
writeFileSync(
bin,
'#!/bin/sh\nif [ "$1" = "--list-models" ]; then\n printf \'%s\\n\' \\\n \'provider model context max-out thinking images\' \\\n \'anthropic claude-sonnet-4-5 200K 64K yes yes\'\n exit 0\nfi\nexit 1\n',
);
chmodSync(bin, 0o755);
}
assert.ok(pi.fetchModels, 'pi must define fetchModels');
const models = await pi.fetchModels(bin, {});
assert.deepEqual(models, [
{ id: 'default', label: 'Default (CLI config)' },
{
id: 'anthropic/claude-sonnet-4-5',
label: 'anthropic/claude-sonnet-4-5',
},
]);
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test('pi args forward extraAllowedDirs as --append-system-prompt flags', () => {
const args = pi.buildArgs(
'',