@yaag/extension 0.1.1 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaag/extension",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -19,14 +19,14 @@
19
19
  },
20
20
  "scripts": {
21
21
  "typecheck": "tsc --noEmit",
22
- "test": "for file in src/*.test.ts; do bun test \"$file\" || exit 1; done",
23
- "test:e2e": "bun test e2e"
22
+ "test": "for file in src/*.test.ts; do bun test --timeout 30000 \"$file\" || exit 1; done",
23
+ "test:e2e": "bun test --timeout 30000 e2e"
24
24
  },
25
25
  "dependencies": {
26
26
  "@earendil-works/pi-tui": "^0.84.0",
27
- "@yaag/runtime": "0.1.1",
28
- "@yaag/tui": "0.1.1",
29
- "@yaag/cli": "0.1.1"
27
+ "@yaag/runtime": "0.1.4",
28
+ "@yaag/tui": "0.1.4",
29
+ "@yaag/cli": "0.1.4"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "@earendil-works/pi-coding-agent": "*",
package/src/cli-child.ts CHANGED
@@ -38,6 +38,7 @@ export function startCliChild(options: CliChildOptions): CliChild {
38
38
  });
39
39
  const stderr = new StderrTail();
40
40
  const exited = observeExit(child);
41
+ releasePipesAfterExit(child);
41
42
  const target: ReapTarget = {
42
43
  exited,
43
44
  endStdin: () => endStdin(child.stdin),
@@ -91,7 +92,30 @@ async function drain(stream: Readable | null, onChunk: (chunk: string) => void):
91
92
 
92
93
  function observeExit(child: ReturnType<typeof spawn>): Promise<void> {
93
94
  return new Promise((resolve, reject) => {
94
- child.on("close", () => resolve());
95
+ // "exit" (process death), not "close": "close" additionally waits for every
96
+ // stdio pipe to end, and a lost pipe EOF would park the Run forever.
97
+ child.on("exit", () => resolve());
95
98
  child.on("error", reject);
96
99
  });
97
100
  }
101
+
102
+ /** How long an exited child's pipes may take to deliver buffered data and EOF. */
103
+ const PIPE_EOF_GRACE_MS = 2_000;
104
+
105
+ /**
106
+ * Failsafe for a lost pipe EOF: once the child process is dead, any of its
107
+ * pipes (stdout, stderr, the fd 3 Lifecycle Event stream) that has not ended
108
+ * within a bounded grace is destroyed, so the iterators that drain them finish
109
+ * instead of parking the Run's outcome — and the test process — forever.
110
+ */
111
+ function releasePipesAfterExit(child: ReturnType<typeof spawn>): void {
112
+ child.once("exit", () => {
113
+ const timer = setTimeout(() => {
114
+ for (const stream of [child.stdout, child.stderr, child.stdio[3]]) {
115
+ if (isReadable(stream) && !stream.destroyed) stream.destroy();
116
+ }
117
+ }, PIPE_EOF_GRACE_MS);
118
+ // A housekeeping timer must never keep the host process alive.
119
+ timer.unref();
120
+ });
121
+ }
@@ -5,5 +5,5 @@ import { createRequire } from "node:module";
5
5
  * in-monorepo (workspace symlink) and from a published tarball (ADR-0015).
6
6
  */
7
7
  export function resolveCliEntry(): string {
8
- return createRequire(import.meta.url).resolve("yaag/src/cli.ts");
8
+ return createRequire(import.meta.url).resolve("@yaag/cli/src/cli.ts");
9
9
  }