agent-dag 1.33.22 → 1.33.24
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-Bt8oQ4sT.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-Cpi89XJ8.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.24",
|
|
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": {
|
|
@@ -166,20 +166,35 @@ async function safePythons() {
|
|
|
166
166
|
* any `pip install --user pipx` where ~/.local/bin was never added to PATH. The
|
|
167
167
|
* two-entry version of this list reported "needs uv or pipx" to people who had
|
|
168
168
|
* pipx installed, which is the kind of wrong answer that stops someone looking.
|
|
169
|
+
*
|
|
170
|
+
* Every entry carries its UPGRADE command line as well as its install one. The
|
|
171
|
+
* upgrade used to be re-derived from the `via` label instead, and any label that
|
|
172
|
+
* derivation did not recognise fell through to `-m pipx upgrade` — so the
|
|
173
|
+
* bundled uv, which is the only installer present on a machine that had neither
|
|
174
|
+
* uv nor pipx nor a usable python, was asked to run a pipx command it rejects.
|
|
169
175
|
*/
|
|
170
176
|
async function installers() {
|
|
171
177
|
const out = [
|
|
172
|
-
{ cmd: "uv", probe: ["--version"], args: ["tool", "install", "claude-swap"], via: "uv" },
|
|
173
|
-
{ cmd: "pipx", probe: ["--version"], args: ["install", "claude-swap"], via: "pipx" },
|
|
178
|
+
{ cmd: "uv", probe: ["--version"], args: ["tool", "install", "claude-swap"], upgrade: ["tool", "upgrade", "claude-swap"], via: "uv" },
|
|
179
|
+
{ cmd: "pipx", probe: ["--version"], args: ["install", "claude-swap"], upgrade: ["upgrade", "claude-swap"], via: "pipx" },
|
|
174
180
|
];
|
|
175
181
|
// A uv fetched on an earlier run counts as installed tooling from here on.
|
|
176
182
|
const own = existingBootstrappedUv();
|
|
177
|
-
if (own)
|
|
183
|
+
if (own) {
|
|
184
|
+
out.push({
|
|
185
|
+
cmd: own,
|
|
186
|
+
probe: ["--version"],
|
|
187
|
+
args: ["tool", "install", "claude-swap"],
|
|
188
|
+
upgrade: ["tool", "upgrade", "claude-swap"],
|
|
189
|
+
via: "uv (bundled)",
|
|
190
|
+
});
|
|
191
|
+
}
|
|
178
192
|
for (const py of await safePythons()) {
|
|
179
193
|
out.push({
|
|
180
194
|
cmd: py,
|
|
181
195
|
probe: ["-m", "pipx", "--version"],
|
|
182
196
|
args: ["-m", "pipx", "install", "claude-swap"],
|
|
197
|
+
upgrade: ["-m", "pipx", "upgrade", "claude-swap"],
|
|
183
198
|
via: `${py} -m pipx`,
|
|
184
199
|
});
|
|
185
200
|
}
|
|
@@ -270,21 +285,19 @@ function isOlder(a, b) {
|
|
|
270
285
|
* Detached and unawaited: an upgrade resolves a Python environment and can
|
|
271
286
|
* take tens of seconds, which is not a thing to put in front of the server
|
|
272
287
|
* starting. The running copy keeps working; the new one is there next launch.
|
|
288
|
+
*
|
|
289
|
+
* The command line comes from the installer entry rather than from its label:
|
|
290
|
+
* runDetached captures nothing, so an upgrade aimed at the wrong tool fails
|
|
291
|
+
* where nobody can see it while the caller still reports "upgrading".
|
|
273
292
|
*/
|
|
274
|
-
function upgradeInBackground(
|
|
275
|
-
|
|
276
|
-
const args = via === "uv"
|
|
277
|
-
? ["tool", "upgrade", "claude-swap"]
|
|
278
|
-
: via === "pipx"
|
|
279
|
-
? ["upgrade", "claude-swap"]
|
|
280
|
-
: ["-m", "pipx", "upgrade", "claude-swap"]; // python -m pipx
|
|
281
|
-
runDetached(cmd, args);
|
|
293
|
+
function upgradeInBackground({ cmd, upgrade }) {
|
|
294
|
+
runDetached(cmd, upgrade);
|
|
282
295
|
}
|
|
283
296
|
|
|
284
297
|
/** Whichever Python tool installer is available, or null. */
|
|
285
298
|
async function findInstaller() {
|
|
286
|
-
for (const { cmd, probe, via } of await installers()) {
|
|
287
|
-
if ((await run(cmd, probe, { timeout: 8_000 })).ok) return { cmd, via };
|
|
299
|
+
for (const { cmd, probe, upgrade, via } of await installers()) {
|
|
300
|
+
if ((await run(cmd, probe, { timeout: 8_000 })).ok) return { cmd, upgrade, via };
|
|
288
301
|
}
|
|
289
302
|
return null;
|
|
290
303
|
}
|
package/src/server/exec.mjs
CHANGED
|
@@ -224,7 +224,16 @@ export function runInteractive(cmd, args, { timeout = 300_000, maxOutput = 256 <
|
|
|
224
224
|
if (tryNext(err) && !stdout && !stderr) { child = null; return attempt(i + 1); }
|
|
225
225
|
finish(-1, err);
|
|
226
226
|
});
|
|
227
|
-
|
|
227
|
+
// Spawning proves a spelling exists — except a .cmd/.bat one, which is
|
|
228
|
+
// launched THROUGH cmd.exe. cmd.exe is always there, so it spawns just as
|
|
229
|
+
// happily for a batch file that is not, and only says so later by exiting
|
|
230
|
+
// non-zero with "is not recognized". Caching at spawn time therefore
|
|
231
|
+
// remembered a spelling that never existed, and since `candidates` then
|
|
232
|
+
// offers only the remembered one, the tool stayed unrunnable — with the
|
|
233
|
+
// false message "not on PATH" — even after it was installed. A batch
|
|
234
|
+
// spelling is confirmed by the clean exit below instead, which is the rule
|
|
235
|
+
// `run` already applies with `if (!err)`.
|
|
236
|
+
if (!isBatch(raw)) proc.on("spawn", () => resolved.set(cmd, raw));
|
|
228
237
|
// Capped so a runaway child cannot grow the heap without bound; the tail is
|
|
229
238
|
// what carries the error, so the head is what gets dropped.
|
|
230
239
|
const keep = (buf, text) => (buf + text).slice(-maxOutput);
|
|
@@ -242,6 +251,9 @@ export function runInteractive(cmd, args, { timeout = 300_000, maxOutput = 256 <
|
|
|
242
251
|
}
|
|
243
252
|
return finish(-1, { code: "ENOENT" });
|
|
244
253
|
}
|
|
254
|
+
// Ran to a clean exit, so this spelling is real — the only confirmation a
|
|
255
|
+
// batch one ever gets.
|
|
256
|
+
if (code === 0 && !killed && !timedOut) resolved.set(cmd, raw);
|
|
245
257
|
finish(code ?? -1, null);
|
|
246
258
|
});
|
|
247
259
|
};
|
|
@@ -281,7 +293,11 @@ export function runDetached(cmd, args) {
|
|
|
281
293
|
try {
|
|
282
294
|
const child = spawn(file, argv, { stdio: "ignore", shell: false, windowsHide: true, ...opts });
|
|
283
295
|
child.on("error", (err) => { if (tryNext(err)) attempt(i + 1); });
|
|
284
|
-
|
|
296
|
+
// Same trap as above: a batch spelling is spawned through cmd.exe, which
|
|
297
|
+
// succeeds whether or not the batch file is there, so only a clean exit
|
|
298
|
+
// proves this one is worth remembering.
|
|
299
|
+
if (isBatch(raw)) child.on("exit", (code) => { if (code === 0) resolved.set(cmd, raw); });
|
|
300
|
+
else child.on("spawn", () => resolved.set(cmd, raw));
|
|
285
301
|
child.unref?.();
|
|
286
302
|
} catch {
|
|
287
303
|
attempt(i + 1);
|