@proagentstore/cli 0.2.0 → 0.2.2
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.
|
@@ -52,6 +52,15 @@ export class HeadlessSession {
|
|
|
52
52
|
stdio: ["pipe", "pipe", "pipe"],
|
|
53
53
|
});
|
|
54
54
|
this.run = "idle";
|
|
55
|
+
// MUST handle 'error' — without a listener, a spawn failure (e.g. `claude`
|
|
56
|
+
// not on PATH) is thrown as an uncaught exception and crashes the runner.
|
|
57
|
+
this.proc.on("error", (err) => {
|
|
58
|
+
this.run = "idle";
|
|
59
|
+
this.push(`[cannot run \`${this.config.bin ?? "claude"}\`: ${err.message} — is Claude Code installed and on your PATH?]`);
|
|
60
|
+
this.proc = null;
|
|
61
|
+
});
|
|
62
|
+
// Swallow EPIPE when writing to a process that just exited (one-shot turn).
|
|
63
|
+
this.proc.stdin?.on("error", () => { });
|
|
55
64
|
this.proc.stdout?.on("data", (d) => this.onStdout(d.toString("utf8")));
|
|
56
65
|
this.proc.stderr?.on("data", (d) => {
|
|
57
66
|
const text = d.toString("utf8").trim();
|
|
@@ -74,7 +83,7 @@ export class HeadlessSession {
|
|
|
74
83
|
input(text) {
|
|
75
84
|
if (!this.alive)
|
|
76
85
|
this.start();
|
|
77
|
-
this.push(`\n❯ ${text}`); // ❯ — your turn,
|
|
86
|
+
this.push(`\n❯ [${stamp()}] ${text}`); // ❯ — your turn, timestamped
|
|
78
87
|
this.run = "thinking";
|
|
79
88
|
const msg = JSON.stringify({ type: "user", message: { role: "user", content: [{ type: "text", text }] } });
|
|
80
89
|
try {
|
|
@@ -139,7 +148,7 @@ export class HeadlessSession {
|
|
|
139
148
|
case "assistant":
|
|
140
149
|
for (const block of ev.message?.content ?? []) {
|
|
141
150
|
if (block.type === "text" && typeof block.text === "string" && block.text.trim()) {
|
|
142
|
-
this.push(block.text.trim());
|
|
151
|
+
this.push(`[${stamp()}] ${block.text.trim()}`); // timestamped agent reply
|
|
143
152
|
}
|
|
144
153
|
else if (block.type === "tool_use") {
|
|
145
154
|
this.push(`⚙ ${String(block.name ?? "tool")} ${shortInput(block.input)}`); // ⚙
|
|
@@ -168,6 +177,10 @@ export class HeadlessSession {
|
|
|
168
177
|
this.transcript.push(line);
|
|
169
178
|
}
|
|
170
179
|
}
|
|
180
|
+
/** Local wall-clock "HH:MM:SS" for transcript timestamps (runner is a Node process). */
|
|
181
|
+
function stamp() {
|
|
182
|
+
return new Date().toTimeString().slice(0, 8);
|
|
183
|
+
}
|
|
171
184
|
/** Compact a tool_use input object to a single readable line. */
|
|
172
185
|
function shortInput(input) {
|
|
173
186
|
if (input == null)
|
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { startRunnerServer } from "./server.js";
|
|
5
|
+
// Resilience: a stray error in any runtime must NOT take the whole runner down —
|
|
6
|
+
// that drops the tunnel and forces the user to restart `pags up` (and lose their
|
|
7
|
+
// session). Log it and keep serving. Per-component handlers catch most things;
|
|
8
|
+
// this is the last-resort backstop.
|
|
9
|
+
process.on("uncaughtException", (err) => {
|
|
10
|
+
process.stderr.write(`[runner] uncaught: ${err?.stack || String(err)}\n`);
|
|
11
|
+
});
|
|
12
|
+
process.on("unhandledRejection", (reason) => {
|
|
13
|
+
process.stderr.write(`[runner] unhandled rejection: ${String(reason)}\n`);
|
|
14
|
+
});
|
|
5
15
|
function arg(name, fallback) {
|
|
6
16
|
const index = process.argv.indexOf(name);
|
|
7
17
|
if (index === -1)
|