agent-dag 1.33.48 → 1.33.50
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-BS3_wQrE.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.50",
|
|
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": {
|
|
@@ -158,7 +158,27 @@ export function extractLoginUrl(text) {
|
|
|
158
158
|
|
|
159
159
|
// The prompt the CLI blocks on. Matched rather than assumed: writing a code
|
|
160
160
|
// into a child that is not asking for one would send it somewhere unknown.
|
|
161
|
-
const CODE_PROMPT = /paste code here/
|
|
161
|
+
const CODE_PROMPT = /paste code here/gi;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* How many times one line of output asks for the code.
|
|
165
|
+
*
|
|
166
|
+
* Per LINE, not per delivery. The prompt ends without a newline, so exec.mjs
|
|
167
|
+
* re-offers the same unterminated line on every chunk as it grows — and both
|
|
168
|
+
* streams share that buffer, so a progress dot, a `\r` spinner frame on stderr,
|
|
169
|
+
* or simply the prompt split across two writes all arrive as the ask again,
|
|
170
|
+
* a few characters longer. Counting an ask whenever the text merely CHANGED, as
|
|
171
|
+
* this used to, turned any of those into a phantom second prompt, and a second
|
|
172
|
+
* prompt is exactly how submitLoginCode hears "that code was rejected": a
|
|
173
|
+
* login the CLI was busy completing came back as `code_rejected`, with the
|
|
174
|
+
* account unregistered and the live credentials left switched.
|
|
175
|
+
*
|
|
176
|
+
* A real re-ask writes the prompt again — on a fresh line, or after a `\r`
|
|
177
|
+
* redraw of this one — so it shows up as another match, not as a longer tail.
|
|
178
|
+
*/
|
|
179
|
+
export function countCodePrompts(line) {
|
|
180
|
+
return (stripTerminalEscapes(line).match(CODE_PROMPT) ?? []).length;
|
|
181
|
+
}
|
|
162
182
|
|
|
163
183
|
/**
|
|
164
184
|
* The whole login, as one object, because the browser talks to it twice: once
|
|
@@ -219,23 +239,27 @@ export async function startLogin({ email } = {}) {
|
|
|
219
239
|
// exit, it just asks again, so waiting for exit would hang for the whole
|
|
220
240
|
// five-minute window on a typo.
|
|
221
241
|
prompts: 0,
|
|
222
|
-
lastPromptText: "",
|
|
223
242
|
};
|
|
224
243
|
const flow = _login;
|
|
225
244
|
|
|
226
|
-
|
|
245
|
+
// How many asks the line currently being written has already contributed.
|
|
246
|
+
// The prompt is an unterminated line, re-delivered as it grows, so the same
|
|
247
|
+
// ask arrives over and over — and once more, whole, when something else
|
|
248
|
+
// finally ends the line.
|
|
249
|
+
let countedOnLine = 0;
|
|
250
|
+
|
|
251
|
+
child.onLine((line, partial) => {
|
|
227
252
|
if (!flow.url) {
|
|
228
253
|
const url = extractLoginUrl(line);
|
|
229
254
|
if (url) { flow.url = url; flow.state = "awaiting_code"; }
|
|
230
255
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
if (clean !== flow.lastPromptText) { flow.prompts += 1; flow.lastPromptText = clean; }
|
|
236
|
-
} else if (clean.trim()) {
|
|
237
|
-
flow.lastPromptText = "";
|
|
256
|
+
const asks = countCodePrompts(line);
|
|
257
|
+
if (asks > countedOnLine) {
|
|
258
|
+
flow.prompts += asks - countedOnLine;
|
|
259
|
+
countedOnLine = asks;
|
|
238
260
|
}
|
|
261
|
+
// A newline ended that line; whatever comes next is a new one.
|
|
262
|
+
if (!partial) countedOnLine = 0;
|
|
239
263
|
});
|
|
240
264
|
// The child dying before the code was accepted is a failure of the login, not
|
|
241
265
|
// of the deck; say so rather than leaving the dialog spinning.
|
package/src/server/index.mjs
CHANGED
|
@@ -898,9 +898,18 @@ async function codexScanOnce(firstRun) {
|
|
|
898
898
|
}
|
|
899
899
|
}
|
|
900
900
|
|
|
901
|
-
function startCodexWatcher(workspace) {
|
|
901
|
+
export function startCodexWatcher(workspace) {
|
|
902
902
|
codexWorkspace = workspace ?? "";
|
|
903
|
-
|
|
903
|
+
// Deliberately not gated on CODEX_SESSIONS_DIR existing. `codex login`
|
|
904
|
+
// creates ~/.codex, but sessions/ only appears when the first session
|
|
905
|
+
// starts — and rollout tailing is the only Codex capture path there is, so
|
|
906
|
+
// bailing out here meant a fresh install had to restart the deck before any
|
|
907
|
+
// Codex agent ever showed up, while the banner claimed to be watching.
|
|
908
|
+
// listRecentCodexRollouts returns [] while the directory is missing, so the
|
|
909
|
+
// poll below is a cheap no-op that doubles as the existence re-check. A
|
|
910
|
+
// filesystem watch is no help: fs.watch on a missing path throws, and
|
|
911
|
+
// watching the parent recursively is macOS/Windows-only.
|
|
912
|
+
//
|
|
904
913
|
// Initial catalog: create roots for in-progress sessions, skip their
|
|
905
914
|
// history, then poll for new lines.
|
|
906
915
|
codexScanOnce(true).catch(() => {});
|
|
@@ -909,6 +918,12 @@ function startCodexWatcher(workspace) {
|
|
|
909
918
|
return codexWatchTimer;
|
|
910
919
|
}
|
|
911
920
|
|
|
921
|
+
/** Envelopes newer than `seq` from the ring buffer, oldest first. */
|
|
922
|
+
export function eventsSince(seq) {
|
|
923
|
+
const after = Number(seq) || 0;
|
|
924
|
+
return events.filter(e => e.seq > after);
|
|
925
|
+
}
|
|
926
|
+
|
|
912
927
|
function pushEvent(raw, source, opts = {}) {
|
|
913
928
|
// Synchronous enrichment: if we already know this session's model, stamp
|
|
914
929
|
// it on the payload so the client's recursive scanner picks it up.
|
|
@@ -1513,8 +1528,7 @@ export async function startServer({ port = 4317, host = "127.0.0.1", persist = n
|
|
|
1513
1528
|
if (req.method === "POST" && url.pathname === "/api/cswap-auto") return guard(handleCswapAutoAction(req, res), res);
|
|
1514
1529
|
|
|
1515
1530
|
if (req.method === "GET" && url.pathname === "/api/events") {
|
|
1516
|
-
|
|
1517
|
-
return send(res, 200, events.filter(e => e.seq > since));
|
|
1531
|
+
return send(res, 200, eventsSince(url.searchParams.get("since") ?? 0));
|
|
1518
1532
|
}
|
|
1519
1533
|
|
|
1520
1534
|
// POST /api/clear — wipe in-memory buffer + persistence file (UI reset)
|