mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-30 13:13:25 +00:00
* fix(cli): exit quietly when stdout's reader is gone When the program that launched the CLI closed its end of stdout, the output write failed with EPIPE and nothing handled the error. Node printed an unhandled 'error' event and exited 1, and the desktop app's CLI passthrough could raise Electron's main-process error dialog. runCli now exits with code 0 on EPIPE from stdout. Other stdout errors still surface as before. Closes #5982 * fix(cli): keep running when stdout's reader is gone Exiting on EPIPE ended a command's own lifecycle: `paseo daemon run` writes its ready line and then supervises the daemon child, so exiting there left the child running without its parent. Drop output nobody reads instead, and let every command finish with its own exit code. * fix(cli): stop following when stdout's reader is gone With EPIPE ignored, `paseo agent logs --follow` and `paseo agent attach` kept running after the program reading their output closed it, until interrupted. Both now wait through one helper that stops on SIGINT, SIGTERM, or EPIPE on stdout, so a closed reader stops them at their next line of output the same way Ctrl+C does. --------- Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
50 lines
1.6 KiB
TypeScript
50 lines
1.6 KiB
TypeScript
#!/usr/bin/env npx tsx
|
|
|
|
/**
|
|
* Follow commands stop when nobody reads their output
|
|
*
|
|
* `paseo agent logs --follow` and `paseo agent attach` stream until they are
|
|
* stopped. A program that closes its end of their stdout, as `| head` or a
|
|
* launcher that discards output does, stops them the same way Ctrl+C does.
|
|
*/
|
|
|
|
import assert from "node:assert";
|
|
import { connectToDaemon } from "../src/utils/client.ts";
|
|
import { runPaseoCli, startTestDaemon } from "./helpers/test-daemon.ts";
|
|
|
|
console.log("=== Follow Commands With Closed Stdout Tests ===\n");
|
|
|
|
const daemon = await startTestDaemon();
|
|
const host = `127.0.0.1:${daemon.port}`;
|
|
|
|
try {
|
|
// An agent created without a prompt stays idle, so no provider is called.
|
|
const client = await connectToDaemon({ target: { kind: "endpoint", host } });
|
|
const agent = await client.createAgent({
|
|
provider: "claude",
|
|
cwd: daemon.workDir,
|
|
title: "closed stdout",
|
|
});
|
|
await client.close();
|
|
|
|
for (const args of [
|
|
["agent", "logs", agent.id, "--follow"],
|
|
["agent", "attach", agent.id],
|
|
]) {
|
|
const label = `paseo ${args.slice(0, 2).join(" ")}`;
|
|
console.log(`Test: ${label} exits when its stdout reader is gone`);
|
|
const result = await runPaseoCli(daemon, [...args, "--host", host], {
|
|
closedStdout: true,
|
|
timeout: 20_000,
|
|
});
|
|
|
|
assert.strictEqual(result.stderr, "", `${label} should exit quietly`);
|
|
assert.strictEqual(result.exitCode, 0, `${label} should exit with code 0`);
|
|
console.log(`✓ ${label} exits when its stdout reader is gone\n`);
|
|
}
|
|
} finally {
|
|
await daemon.stop();
|
|
}
|
|
|
|
console.log("=== All follow commands with closed stdout tests passed ===");
|