agent-dag 1.33.55 → 1.33.56
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-CwR-2lK9.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-CF2yG9oG.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.56",
|
|
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": {
|
package/src/server/exec.mjs
CHANGED
|
@@ -126,8 +126,23 @@ export const tryNext = (err) =>
|
|
|
126
126
|
Boolean(err) && (err.code === "ENOENT" || err.code === "EACCES" ||
|
|
127
127
|
err.code === "EINVAL" || err.code === "UNKNOWN");
|
|
128
128
|
|
|
129
|
+
// The three lines cmd.exe prints when it cannot find what it was asked to run,
|
|
130
|
+
// anchored to a whole line each. First the two-line pair for a bare name, then
|
|
131
|
+
// the one it uses when a directory in an explicit path does not exist.
|
|
132
|
+
const CMD_UNKNOWN = /^'(.+)' is not recognized as an internal or external command,?$/i;
|
|
133
|
+
const CMD_UNKNOWN_TAIL = /^operable program or batch file\.?$/i;
|
|
134
|
+
const CMD_NO_PATH = /^the system cannot find the (?:path|file) specified\.?$/i;
|
|
135
|
+
|
|
136
|
+
// cmd.exe echoes the command token exactly as it was given, so an exact match
|
|
137
|
+
// is what we expect; the comparison is only case- and quote-insensitive because
|
|
138
|
+
// Windows paths are.
|
|
139
|
+
const sameCommand = (quoted, name) => {
|
|
140
|
+
const norm = (s) => String(s).trim().replace(/^"+|"+$/g, "").toLowerCase();
|
|
141
|
+
return norm(quoted) === norm(name);
|
|
142
|
+
};
|
|
143
|
+
|
|
129
144
|
/**
|
|
130
|
-
* cmd.exe's way of saying ENOENT.
|
|
145
|
+
* cmd.exe's way of saying ENOENT — and only cmd.exe's.
|
|
131
146
|
*
|
|
132
147
|
* A .cmd or .bat candidate is launched THROUGH cmd.exe, and cmd.exe exists — so
|
|
133
148
|
* a missing tool is not a spawn error at all. It is a healthy shell exiting 1
|
|
@@ -140,11 +155,39 @@ export const tryNext = (err) =>
|
|
|
140
155
|
* second line — on its own, meaningless — in front of the user. Reported from
|
|
141
156
|
* Windows on 2026-08-14: the accounts panel said only "operable program or
|
|
142
157
|
* batch file." when sharing an account.
|
|
158
|
+
*
|
|
159
|
+
* The fussiness is about the other direction, which is worse. "The system
|
|
160
|
+
* cannot find the file specified" is Windows' generic text for ENOENT, and it
|
|
161
|
+
* appears INSIDE the output of tools that ran perfectly well — cswap is a
|
|
162
|
+
* Python CLI, and a FileNotFoundError traceback ends in that exact sentence.
|
|
163
|
+
* Believed there, it threw the real error away, told the user the tool was not
|
|
164
|
+
* on PATH when PATH was fine, and — the dangerous half — sent the candidate
|
|
165
|
+
* loop on to re-run the entire command, which for `cswap remove 3` means asking
|
|
166
|
+
* to delete an account a second time.
|
|
167
|
+
*
|
|
168
|
+
* So the output has to be cmd.exe's message and nothing else: cmd.exe prints it
|
|
169
|
+
* INSTEAD of running anything, so any other line, or any prefix on the line,
|
|
170
|
+
* means something ran and this is its report. And when cmd.exe names the
|
|
171
|
+
* command it could not find, that name must be the candidate we asked for — a
|
|
172
|
+
* tool that shells out itself can forward the message about some other command.
|
|
173
|
+
*
|
|
174
|
+
* `name` is the candidate spelling that produced the output. Callers that only
|
|
175
|
+
* have the text (failureText) omit it and get the shape rules alone.
|
|
143
176
|
*/
|
|
144
|
-
export
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
177
|
+
export function looksMissing(text, name = "") {
|
|
178
|
+
const lines = String(text ?? "").split(/\r?\n/).map(l => l.trim()).filter(Boolean);
|
|
179
|
+
if (!lines.length) return false;
|
|
180
|
+
for (const line of lines) {
|
|
181
|
+
const named = CMD_UNKNOWN.exec(line);
|
|
182
|
+
if (named) {
|
|
183
|
+
if (name && !sameCommand(named[1], name)) return false;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (CMD_UNKNOWN_TAIL.test(line) || CMD_NO_PATH.test(line)) continue;
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
148
191
|
|
|
149
192
|
/**
|
|
150
193
|
* Run a command and collect its output. Never rejects, and never throws —
|
|
@@ -175,8 +218,12 @@ export function run(cmd, args, { timeout = 20_000, maxBuffer = 4 << 20 } = {}) {
|
|
|
175
218
|
const done = (err, stdout, stderr) => {
|
|
176
219
|
clearTimeout(timer);
|
|
177
220
|
// cmd.exe's "is not recognized" counts as "not this spelling" too, and
|
|
178
|
-
// it arrives as a normal non-zero exit rather than a spawn error.
|
|
179
|
-
|
|
221
|
+
// it arrives as a normal non-zero exit rather than a spawn error. Only
|
|
222
|
+
// a batch candidate goes through a shell, so only there can the output
|
|
223
|
+
// be a shell's verdict rather than the tool's own words — spawned
|
|
224
|
+
// directly, a missing file is a plain ENOENT and anything printed came
|
|
225
|
+
// from a tool that ran.
|
|
226
|
+
const missing = Boolean(err) && tree && looksMissing(`${stderr ?? ""}\n${stdout ?? ""}`, raw);
|
|
180
227
|
if (err && (tryNext(err) || missing) && i + 1 < tries.length) return attempt(i + 1);
|
|
181
228
|
if (!err) resolved.set(cmd, raw);
|
|
182
229
|
resolve({
|
|
@@ -317,8 +364,11 @@ export function runInteractive(cmd, args, { timeout = 300_000, maxOutput = 256 <
|
|
|
317
364
|
proc.on("close", (code) => {
|
|
318
365
|
if (stale()) return;
|
|
319
366
|
// Same cmd.exe case as in `run`: exit 1 with "is not recognized" means
|
|
320
|
-
// this spelling does not exist, not that the tool failed.
|
|
321
|
-
|
|
367
|
+
// this spelling does not exist, not that the tool failed. Restricted to a
|
|
368
|
+
// batch candidate, which is the only kind launched through a shell, and
|
|
369
|
+
// to output that is cmd.exe's message alone — everything below re-runs
|
|
370
|
+
// the whole command, and these commands remove accounts.
|
|
371
|
+
if (code !== 0 && isBatch(raw) && looksMissing(`${stderr}\n${stdout}`, raw)) {
|
|
322
372
|
if (i + 1 < tries.length) {
|
|
323
373
|
stdout = ""; stderr = ""; pending = "";
|
|
324
374
|
child = null;
|