fix(cli): awaited config JSON stdout flush

- Waited for the stdout write callback before the config command exits.
- Covered JSON output larger than the 64 KiB pipe buffer.

Fixes #5309
This commit is contained in:
roboomp
2026-07-14 18:06:40 +00:00
parent d0f90f35ae
commit df7aa6d01f
3 changed files with 41 additions and 3 deletions
+4
View File
@@ -10,6 +10,10 @@
- Updated status event log to prioritize the most recent entries in the display window
### Fixed
- Fixed `omp config list --json` truncating output at 64 KiB when stdout is piped ([#5309](https://github.com/can1357/oh-my-pi/issues/5309))
### Removed
- Removed the unreliable Bing and Yahoo HTML-scraping web search providers
+15 -3
View File
@@ -241,7 +241,7 @@ export async function runConfigCommand(cmd: ConfigCommandArgs): Promise<void> {
switch (cmd.action) {
case "list":
handleList(cmd.flags);
await handleList(cmd.flags);
break;
case "get":
handleGet(cmd.key, cmd.flags);
@@ -261,7 +261,19 @@ export async function runConfigCommand(cmd: ConfigCommandArgs): Promise<void> {
}
}
function handleList(flags: { json?: boolean }): void {
async function writeStdout(text: string): Promise<void> {
const pending = Promise.withResolvers<void>();
process.stdout.write(text, error => {
if (error) {
pending.reject(error);
return;
}
pending.resolve();
});
await pending.promise;
}
async function handleList(flags: { json?: boolean }): Promise<void> {
const defs = ALL_SETTING_PATHS.map(path => findSettingDef(path)).filter((def): def is CliSettingDef => !!def);
if (flags.json) {
@@ -273,7 +285,7 @@ function handleList(flags: { json?: boolean }): void {
description: def.description,
};
}
console.log(JSON.stringify(result, null, 2));
await writeStdout(`${JSON.stringify(result, null, 2)}\n`);
return;
}
@@ -8,6 +8,7 @@ import { getConfigRootDir, setAgentDir, TempDir } from "@oh-my-pi/pi-utils";
let testAgentDir: TempDir | undefined;
const originalAgentDir = process.env.PI_CODING_AGENT_DIR;
const fallbackAgentDir = path.join(getConfigRootDir(), "agent");
const cliEntry = path.join(import.meta.dir, "..", "src", "cli.ts");
beforeEach(() => {
resetSettingsForTest();
@@ -166,4 +167,25 @@ describe("config CLI schema coverage", () => {
expect(parsed.type).toBe("enum");
expect(parsed.value).toBe("max");
});
it("fully flushes JSON larger than a pipe buffer", async () => {
if (!testAgentDir) throw new Error("Test agent directory was not initialized");
const proc = Bun.spawn([process.execPath, cliEntry, "config", "list", "--json"], {
stdout: "pipe",
stderr: "pipe",
env: {
...process.env,
NO_COLOR: "1",
PI_CODING_AGENT_DIR: testAgentDir.path(),
},
});
const stdout = new Response(proc.stdout).text();
const stderr = new Response(proc.stderr).text();
const [exitCode, output, error] = await Promise.all([proc.exited, stdout, stderr]);
expect(exitCode).toBe(0);
expect(error).toBe("");
expect(Buffer.byteLength(output)).toBeGreaterThan(65_536);
const parsed: unknown = JSON.parse(output);
expect(parsed).toMatchObject({ modelRoles: { type: "record" } });
});
});