agent-dag 1.33.97 → 1.33.99
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/dist/web/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
6
|
<title>agents-deck</title>
|
|
7
7
|
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ctext y='84' font-size='84'%3E%E2%97%89%3C/text%3E%3C/svg%3E" />
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-CZeYjQ5o.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-dwRx-2y0.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-dag",
|
|
3
|
-
"version": "1.33.
|
|
3
|
+
"version": "1.33.99",
|
|
4
4
|
"description": "Live deck of Claude Code and Codex agents — watch parallel subagents fork, call tools, and return on one calm canvas. Also available as npx ccdeck and npx agent-dag.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -555,6 +555,11 @@ export function failureText(r, what = "cswap") {
|
|
|
555
555
|
? "the claude CLI could not be run: not on PATH. Set AGENTS_DECK_CLAUDE to its full path."
|
|
556
556
|
: "cswap could not be run: not on PATH, and not in the places uv and pipx install to. Set AGENTS_DECK_CSWAP to its full path.";
|
|
557
557
|
}
|
|
558
|
+
// A run its deadline stopped has no exit status worth quoting and no last
|
|
559
|
+
// line worth quoting either — whatever it had printed, it had not finished.
|
|
560
|
+
// Asked for one anyway, this said "cswap export exited 0", a success code for
|
|
561
|
+
// a command that never completed.
|
|
562
|
+
if (r?.timedOut || r?.code === "ETIMEDOUT") return `${what} took too long and was stopped`;
|
|
558
563
|
return firstUseful(out) || `${what} exited ${r?.code}`;
|
|
559
564
|
}
|
|
560
565
|
|
package/src/server/exec.mjs
CHANGED
|
@@ -189,34 +189,54 @@ export function looksMissing(text, name = "") {
|
|
|
189
189
|
return true;
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
+
// How much of a hung child's output the deadline keeps. The full buffers belong
|
|
193
|
+
// to execFile's callback, which a timed-out run never waits for, and the tail is
|
|
194
|
+
// where a tool puts the line that explains itself.
|
|
195
|
+
const TIMEOUT_TAIL = 8 << 10;
|
|
196
|
+
|
|
192
197
|
/**
|
|
193
198
|
* Run a command and collect its output. Never rejects, and never throws —
|
|
194
199
|
* failures come back as `{ ok: false }`, because every caller here is a poll or
|
|
195
200
|
* a UI action where a missing tool is an expected state rather than an
|
|
196
201
|
* exception. execFile can throw synchronously on Windows, so the call itself is
|
|
197
202
|
* guarded as well as its callback.
|
|
203
|
+
*
|
|
204
|
+
* A run stopped by its deadline answers `{ ok: false, code: "ETIMEDOUT",
|
|
205
|
+
* killed: true, timedOut: true }` — never ok, whatever the child said on its
|
|
206
|
+
* way out.
|
|
198
207
|
*/
|
|
199
208
|
export function run(cmd, args, { timeout = 20_000, maxBuffer = 4 << 20 } = {}) {
|
|
200
209
|
const tries = candidates(cmd);
|
|
201
210
|
return new Promise((resolve) => {
|
|
202
211
|
const attempt = (i) => {
|
|
203
212
|
if (i >= tries.length) {
|
|
204
|
-
return resolve({ ok: false, code: "ENOENT", killed: false, stdout: "", stderr: "" });
|
|
213
|
+
return resolve({ ok: false, code: "ENOENT", killed: false, timedOut: false, stdout: "", stderr: "" });
|
|
205
214
|
}
|
|
206
215
|
const raw = tries[i];
|
|
207
216
|
const { file, args: argv, opts } = isBatch(raw)
|
|
208
217
|
? viaCmd(raw, args)
|
|
209
218
|
: { file: raw, args, opts: {} };
|
|
210
219
|
|
|
211
|
-
// execFile's own `timeout` ends with one signal to the process it
|
|
212
|
-
// started, which for a batch candidate is the cmd.exe wrapper: the
|
|
213
|
-
// deadline was reported as enforced while the tool underneath went on
|
|
214
|
-
// running. A batch candidate is timed here instead, on the whole tree.
|
|
215
220
|
const tree = isBatch(raw);
|
|
216
221
|
let timer = null, timedOut = false;
|
|
222
|
+
// A tail of what the child managed to say. The deadline below answers
|
|
223
|
+
// before execFile's callback does, and the callback owns the full
|
|
224
|
+
// buffers, so without this copy a timed-out run reports nothing at all —
|
|
225
|
+
// and the last line a hung tool printed is usually the only clue why it
|
|
226
|
+
// hung.
|
|
227
|
+
let sawOut = "", sawErr = "";
|
|
217
228
|
|
|
218
229
|
const done = (err, stdout, stderr) => {
|
|
219
230
|
clearTimeout(timer);
|
|
231
|
+
// The deadline already gave this attempt its verdict, and killed the
|
|
232
|
+
// child to make it stop. What the corpse reports is not news, and
|
|
233
|
+
// believing it is what put "cswap export exited 0" in front of the
|
|
234
|
+
// user: execFile calls a signalled exit `code: null`, which `?? 0`
|
|
235
|
+
// turns into a success code, and a tool that handles SIGTERM by
|
|
236
|
+
// exiting 0 — the well-behaved kind — arrives here with no error at
|
|
237
|
+
// all, so the run we cut short came back `ok: true` and got its
|
|
238
|
+
// spelling remembered as one that works.
|
|
239
|
+
if (timedOut) return;
|
|
220
240
|
// cmd.exe's "is not recognized" counts as "not this spelling" too, and
|
|
221
241
|
// it arrives as a normal non-zero exit rather than a spawn error. Only
|
|
222
242
|
// a batch candidate goes through a shell, so only there can the output
|
|
@@ -231,9 +251,8 @@ export function run(cmd, args, { timeout = 20_000, maxBuffer = 4 << 20 } = {}) {
|
|
|
231
251
|
// A tool cmd.exe could not find is missing, not "exited 1" — callers
|
|
232
252
|
// key their message off this.
|
|
233
253
|
code: missing ? "ENOENT" : (err?.code ?? 0),
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
killed: Boolean(err?.killed) || timedOut,
|
|
254
|
+
killed: Boolean(err?.killed),
|
|
255
|
+
timedOut: false,
|
|
237
256
|
stdout: String(stdout ?? ""),
|
|
238
257
|
stderr: String(stderr ?? ""),
|
|
239
258
|
});
|
|
@@ -241,11 +260,27 @@ export function run(cmd, args, { timeout = 20_000, maxBuffer = 4 << 20 } = {}) {
|
|
|
241
260
|
|
|
242
261
|
try {
|
|
243
262
|
const cp = execFile(file, argv,
|
|
244
|
-
{ timeout:
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
263
|
+
{ timeout: 0, shell: false, windowsHide: true, maxBuffer, ...opts }, done);
|
|
264
|
+
cp.stdout?.on("data", (d) => { sawOut = (sawOut + d).slice(-TIMEOUT_TAIL); });
|
|
265
|
+
cp.stderr?.on("data", (d) => { sawErr = (sawErr + d).slice(-TIMEOUT_TAIL); });
|
|
266
|
+
// The deadline states the outcome itself and only then kills, which is
|
|
267
|
+
// the order startUpgrade needs for the same reason: the answer must not
|
|
268
|
+
// depend on the killed child cooperating.
|
|
269
|
+
//
|
|
270
|
+
// execFile's own `timeout` is not used at all. It ends with one signal
|
|
271
|
+
// to the process it started, which for a batch candidate is the cmd.exe
|
|
272
|
+
// wrapper — the deadline was reported as enforced while the tool
|
|
273
|
+
// underneath went on running — and it reports through the callback,
|
|
274
|
+
// which waits for the stdio pipes. On Windows those are held by the
|
|
275
|
+
// grandchild under the wrapper, so when the tree kill could not reach
|
|
276
|
+
// it the callback never came and the run never settled at all: the
|
|
277
|
+
// accounts panel sat on a request that had already timed out.
|
|
278
|
+
timer = setTimeout(() => {
|
|
279
|
+
timedOut = true;
|
|
280
|
+
resolve({ ok: false, code: "ETIMEDOUT", killed: true, timedOut: true, stdout: sawOut, stderr: sawErr });
|
|
281
|
+
killTree(cp);
|
|
282
|
+
}, timeout);
|
|
283
|
+
timer.unref?.();
|
|
249
284
|
} catch (err) {
|
|
250
285
|
// Synchronous throw — the EINVAL case. Same handling as a callback
|
|
251
286
|
// error; letting it propagate here is what crashed the server, because
|