agent-dag 1.33.76 → 1.33.78
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-Ffz1bNVI.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.78",
|
|
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/installer.mjs
CHANGED
|
@@ -307,7 +307,7 @@ export function hasCodexInstalled() {
|
|
|
307
307
|
// pid keeps its old mode through writeFile, hence the explicit chmod.
|
|
308
308
|
export async function writeDiscovery({ port, workspace, token }) {
|
|
309
309
|
await ensureDir(AGENT_DAG_DIR);
|
|
310
|
-
const file =
|
|
310
|
+
const file = discoveryPath();
|
|
311
311
|
const data = {
|
|
312
312
|
pid: process.pid,
|
|
313
313
|
port,
|
|
@@ -326,6 +326,78 @@ export async function removeDiscovery(file) {
|
|
|
326
326
|
try { await unlink(file); } catch {}
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
+
/** Where this process registers itself. One file per deck, named by pid. */
|
|
330
|
+
export function discoveryPath() {
|
|
331
|
+
return join(AGENT_DAG_DIR, `${process.pid}.json`);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Make sure this deck's discovery file is on disk and says what it should.
|
|
336
|
+
*
|
|
337
|
+
* Registration was a single write at boot, so anything that took the file away
|
|
338
|
+
* afterwards — a sweep on another machine's clock, a half-finished restart, a
|
|
339
|
+
* user tidying the directory — left a deck that was listening, serving and
|
|
340
|
+
* completely invisible: hook.js enumerates this directory and nothing else, so
|
|
341
|
+
* the deck received zero events while looking perfectly healthy. Re-asserting
|
|
342
|
+
* is cheap (one small read), so the deck checks rather than assumes.
|
|
343
|
+
*
|
|
344
|
+
* A file this process wrote is left alone, mode included. Anything else — no
|
|
345
|
+
* file, unreadable, another pid, a stale port or token — is replaced.
|
|
346
|
+
*/
|
|
347
|
+
export async function ensureDiscovery({ port, workspace, token }) {
|
|
348
|
+
const file = discoveryPath();
|
|
349
|
+
try {
|
|
350
|
+
const d = JSON.parse(stripBom(await readFile(file, "utf8")));
|
|
351
|
+
if (d
|
|
352
|
+
&& d.pid === process.pid
|
|
353
|
+
&& d.port === port
|
|
354
|
+
&& (d.workspace ?? "") === (workspace ?? "")
|
|
355
|
+
&& (d.token ?? "") === (token ?? "")) {
|
|
356
|
+
return { file, rewritten: false };
|
|
357
|
+
}
|
|
358
|
+
} catch { /* missing, unreadable or corrupt — rewritten below */ }
|
|
359
|
+
await writeDiscovery({ port, workspace, token });
|
|
360
|
+
return { file, rewritten: true };
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Keep this deck registered for as long as it runs, and tell the caller when
|
|
365
|
+
* that stops being true.
|
|
366
|
+
*
|
|
367
|
+
* `onState` hears the first outcome, every change of health, and every
|
|
368
|
+
* re-registration after the first — never a steady state. A deck that cannot
|
|
369
|
+
* write the file has to say so: silently listening while no hook can find it
|
|
370
|
+
* is the failure this exists to end, not a state worth hiding.
|
|
371
|
+
*
|
|
372
|
+
* The interval is unref'd, so it never keeps a finished process alive, and
|
|
373
|
+
* `stop()` must be called before the file is removed on shutdown — otherwise
|
|
374
|
+
* the next tick would put it straight back.
|
|
375
|
+
*/
|
|
376
|
+
export function keepDiscovery({ port, workspace, token, intervalMs = 5000, onState = null } = {}) {
|
|
377
|
+
// null until the first outcome, which therefore always differs and is always
|
|
378
|
+
// reported — the caller learns where it stands before anything else happens.
|
|
379
|
+
let healthy = null;
|
|
380
|
+
|
|
381
|
+
const check = async () => {
|
|
382
|
+
let state;
|
|
383
|
+
try {
|
|
384
|
+
const { rewritten } = await ensureDiscovery({ port, workspace, token });
|
|
385
|
+
state = { ok: true, rewritten, file: discoveryPath(), error: null };
|
|
386
|
+
} catch (err) {
|
|
387
|
+
state = { ok: false, rewritten: false, file: discoveryPath(), error: err };
|
|
388
|
+
}
|
|
389
|
+
const worthSaying = healthy !== state.ok || state.rewritten;
|
|
390
|
+
healthy = state.ok;
|
|
391
|
+
if (worthSaying && onState) { try { onState(state); } catch { /* not our problem */ } }
|
|
392
|
+
return state;
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
const timer = setInterval(() => { check(); }, intervalMs);
|
|
396
|
+
timer.unref?.();
|
|
397
|
+
|
|
398
|
+
return { file: discoveryPath(), check, stop: () => clearInterval(timer) };
|
|
399
|
+
}
|
|
400
|
+
|
|
329
401
|
export const HOOK_EVENTS = CLAUDE_EVENTS;
|
|
330
402
|
export { AGENT_DAG_DIR, CLAUDE_DIR, CODEX_DIR, CLAUDE_EVENTS, CODEX_EVENTS };
|
|
331
403
|
// Exported for the other modules that rewrite settings.json — the sound toggle
|