agent-theatre 1.2.3 → 1.3.1
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/cli.js +130 -93
- package/dist/cli.js.map +1 -1
- package/dist/index.js +130 -93
- package/dist/index.js.map +1 -1
- package/hooks/agent-theatre-hook.mjs +9 -7
- package/package.json +3 -3
- package/web/assets/browserAll-jpKtMttp.js +2 -0
- package/web/assets/{browserAll-KVarB43M.js.map → browserAll-jpKtMttp.js.map} +1 -1
- package/web/assets/{index-DLvIe75m.css → index-CWrWoYA0.css} +1 -1
- package/web/assets/index-DoUA_XxG.js +972 -0
- package/web/assets/index-DoUA_XxG.js.map +1 -0
- package/web/assets/webworkerAll-eBrHhNNp.js +2 -0
- package/web/assets/{webworkerAll-DDiRRkEz.js.map → webworkerAll-eBrHhNNp.js.map} +1 -1
- package/web/index.html +2 -2
- package/web/assets/browserAll-KVarB43M.js +0 -2
- package/web/assets/index-18kUlmBs.js +0 -972
- package/web/assets/index-18kUlmBs.js.map +0 -1
- package/web/assets/webworkerAll-DDiRRkEz.js +0 -2
package/dist/index.js
CHANGED
|
@@ -291,9 +291,81 @@ function claimsSuccess(text) {
|
|
|
291
291
|
if (HEDGE_LEXICON.some((r) => r.test(tail))) return false;
|
|
292
292
|
return SUCCESS_LEXICON.some((r) => r.test(tail));
|
|
293
293
|
}
|
|
294
|
-
var ROW_TYPES = /* @__PURE__ */ new Set(["user", "assistant", "system"]);
|
|
295
294
|
var obj2 = (x) => x && typeof x === "object" ? x : {};
|
|
296
295
|
var str2 = (x) => typeof x === "string" ? x : void 0;
|
|
296
|
+
var TOOL_EVENTS = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUse", "PostToolUseFailure"]);
|
|
297
|
+
function endReason(reason) {
|
|
298
|
+
switch (reason) {
|
|
299
|
+
case "clear":
|
|
300
|
+
case "logout":
|
|
301
|
+
case "prompt_input_exit":
|
|
302
|
+
return "user";
|
|
303
|
+
default:
|
|
304
|
+
return "stop";
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function hookPayloadToEvents(payload, opts = {}) {
|
|
308
|
+
const p = obj2(payload);
|
|
309
|
+
const name = str2(p.hook_event_name);
|
|
310
|
+
const sessionId = str2(p.session_id) ?? "";
|
|
311
|
+
const ts = opts.now ?? Date.now();
|
|
312
|
+
if (!name) return { events: [], warnings: [{ code: "missing_field", detail: "hook_event_name" }] };
|
|
313
|
+
const cwd = str2(p.cwd) ?? "";
|
|
314
|
+
const ctx = { cwd, ...opts.home ? { home: opts.home } : {} };
|
|
315
|
+
const agentId = TOOL_EVENTS.has(name) ? str2(p.agent_id) : void 0;
|
|
316
|
+
const extra = agentId ? { agentId } : {};
|
|
317
|
+
let seq = 0;
|
|
318
|
+
const mk = (body, id = mintId(ts)) => ({ id, seq: seq++, ts, sessionId, source: "hook", ...extra, ...body });
|
|
319
|
+
const one = (body) => ({ events: [mk(body)], warnings: [] });
|
|
320
|
+
switch (name) {
|
|
321
|
+
case "SessionStart":
|
|
322
|
+
return one({ kind: "session_start", repoId: basename(cwd) || "repo" });
|
|
323
|
+
case "SessionEnd":
|
|
324
|
+
return one({ kind: "session_end", reason: endReason(str2(p.reason)), claimedSuccess: false });
|
|
325
|
+
case "Stop":
|
|
326
|
+
return one({ kind: "turn_end", claimedSuccess: claimsSuccess(str2(p.last_assistant_message)), ...noteOf(str2(p.last_assistant_message)) });
|
|
327
|
+
case "SubagentStart": {
|
|
328
|
+
const id = str2(p.agent_id) ?? "";
|
|
329
|
+
const label = str2(p.agent_type);
|
|
330
|
+
return { events: [mk({ kind: "subagent_start", childId: id, ...label ? { label } : {} })], warnings: [] };
|
|
331
|
+
}
|
|
332
|
+
case "SubagentStop":
|
|
333
|
+
return one({ kind: "subagent_stop", childId: str2(p.agent_id) ?? "", ok: true });
|
|
334
|
+
case "Notification": {
|
|
335
|
+
const t = str2(p.notification_type);
|
|
336
|
+
if (t === "permission_prompt") return one({ kind: "waiting_for_user", reason: "permission" });
|
|
337
|
+
if (t === "idle_prompt") return one({ kind: "waiting_for_user", reason: "idle" });
|
|
338
|
+
if (t === "elicitation_dialog") return one({ kind: "waiting_for_user", reason: "question" });
|
|
339
|
+
return { events: [], warnings: [] };
|
|
340
|
+
}
|
|
341
|
+
case "PostToolUseFailure":
|
|
342
|
+
return one({ kind: "error", where: str2(p.tool_name) ?? "tool", retrying: false });
|
|
343
|
+
case "PostToolUse": {
|
|
344
|
+
const tool = str2(p.tool_name);
|
|
345
|
+
if (!tool) return { events: [], warnings: [{ code: "missing_field", detail: "tool_name" }] };
|
|
346
|
+
const dur = typeof p.duration_ms === "number" ? { durationMs: p.duration_ms } : {};
|
|
347
|
+
const out = toolCallToOutcome({ name: tool, input: p.tool_input, response: p.tool_response, ...dur }, ctx);
|
|
348
|
+
const baseId = str2(p.tool_use_id) ?? mintId(ts);
|
|
349
|
+
const events = out.bodies.map((body, i) => mk(body, i === 0 ? baseId : `${baseId}:${i}`));
|
|
350
|
+
return { events, warnings: out.warning ? [out.warning] : [] };
|
|
351
|
+
}
|
|
352
|
+
case "PreToolUse":
|
|
353
|
+
case "UserPromptSubmit":
|
|
354
|
+
case "PreCompact":
|
|
355
|
+
case "PostCompact":
|
|
356
|
+
return { events: [], warnings: [] };
|
|
357
|
+
}
|
|
358
|
+
return { events: [], warnings: [{ code: "unknown_row_type", detail: name }] };
|
|
359
|
+
}
|
|
360
|
+
function noteOf(text) {
|
|
361
|
+
if (!text) return {};
|
|
362
|
+
const para = text.trim().split(/\n{2,}/).filter((x) => x.trim()).pop()?.replace(/\s+/g, " ").trim() ?? "";
|
|
363
|
+
if (!para) return {};
|
|
364
|
+
return { note: para.length > 240 ? "\u2026" + para.slice(-239) : para };
|
|
365
|
+
}
|
|
366
|
+
var ROW_TYPES = /* @__PURE__ */ new Set(["user", "assistant", "system"]);
|
|
367
|
+
var obj3 = (x) => x && typeof x === "object" ? x : {};
|
|
368
|
+
var str3 = (x) => typeof x === "string" ? x : void 0;
|
|
297
369
|
function parseTranscript(text, opts = {}) {
|
|
298
370
|
const rows = [];
|
|
299
371
|
const warnings = [];
|
|
@@ -329,21 +401,21 @@ function parseTranscriptRows(rows, opts = {}) {
|
|
|
329
401
|
events.push({ id, seq: seq++, ts, sessionId, source: "transcript", ...extra, ...body });
|
|
330
402
|
};
|
|
331
403
|
const tsOf = (row) => {
|
|
332
|
-
const t =
|
|
404
|
+
const t = str3(row.timestamp);
|
|
333
405
|
const n = t ? Date.parse(t) : Number.NaN;
|
|
334
406
|
return Number.isFinite(n) ? n : Number.isFinite(lastTs) ? lastTs : 0;
|
|
335
407
|
};
|
|
336
|
-
const agentOf = (row) =>
|
|
408
|
+
const agentOf = (row) => str3(row.agentId) ?? (row.isSidechain === true ? opts.sidechainAgentId ?? "sidechain" : void 0);
|
|
337
409
|
for (const raw of rows) {
|
|
338
|
-
const row =
|
|
339
|
-
const type =
|
|
410
|
+
const row = obj3(raw);
|
|
411
|
+
const type = str3(row.type) ?? "";
|
|
340
412
|
if (!ROW_TYPES.has(type)) {
|
|
341
413
|
if (type) unknownTypes.add(type);
|
|
342
414
|
continue;
|
|
343
415
|
}
|
|
344
|
-
if (!sessionId &&
|
|
345
|
-
if (!cwd &&
|
|
346
|
-
if (!branch &&
|
|
416
|
+
if (!sessionId && str3(row.sessionId)) sessionId = str3(row.sessionId);
|
|
417
|
+
if (!cwd && str3(row.cwd)) cwd = str3(row.cwd);
|
|
418
|
+
if (!branch && str3(row.gitBranch)) branch = str3(row.gitBranch);
|
|
347
419
|
const ts = tsOf(row);
|
|
348
420
|
if (!Number.isFinite(firstTs)) {
|
|
349
421
|
firstTs = ts;
|
|
@@ -351,39 +423,39 @@ function parseTranscriptRows(rows, opts = {}) {
|
|
|
351
423
|
}
|
|
352
424
|
lastTs = ts;
|
|
353
425
|
const agentId = agentOf(row);
|
|
354
|
-
const message =
|
|
426
|
+
const message = obj3(row.message);
|
|
355
427
|
const content = message.content;
|
|
356
428
|
if (type === "system") {
|
|
357
429
|
if (row.subtype === "api_error") {
|
|
358
430
|
const attempt = typeof row.retryAttempt === "number" ? row.retryAttempt : 0;
|
|
359
431
|
const max = typeof row.maxRetries === "number" ? row.maxRetries : 0;
|
|
360
|
-
push(ts,
|
|
432
|
+
push(ts, str3(row.uuid) ?? `sys:${seq}`, { kind: "error", where: "api", retrying: attempt < max }, agentId ? { agentId } : {});
|
|
361
433
|
}
|
|
362
434
|
continue;
|
|
363
435
|
}
|
|
364
436
|
if (type === "assistant") {
|
|
365
437
|
const blocks2 = Array.isArray(content) ? content : [];
|
|
366
438
|
for (const b of blocks2) {
|
|
367
|
-
const block =
|
|
368
|
-
if (block.type === "tool_use" &&
|
|
369
|
-
pending.set(
|
|
439
|
+
const block = obj3(b);
|
|
440
|
+
if (block.type === "tool_use" && str3(block.id) && str3(block.name)) {
|
|
441
|
+
pending.set(str3(block.id), { name: str3(block.name), input: block.input, ts, ...agentId ? { agentId } : {} });
|
|
370
442
|
} else if (block.type === "text" && !agentId) {
|
|
371
|
-
const t =
|
|
443
|
+
const t = str3(block.text);
|
|
372
444
|
if (t) lastAssistantText = t;
|
|
373
445
|
}
|
|
374
446
|
}
|
|
375
447
|
if (typeof content === "string" && !agentId) lastAssistantText = content;
|
|
376
448
|
if (message.stop_reason === "end_turn" && !agentId) {
|
|
377
|
-
push(ts, `${
|
|
449
|
+
push(ts, `${str3(row.uuid) ?? seq}:turn`, { kind: "turn_end", claimedSuccess: claimsSuccess(lastAssistantText), ...noteOf(lastAssistantText) });
|
|
378
450
|
}
|
|
379
451
|
continue;
|
|
380
452
|
}
|
|
381
|
-
if (row.toolDenialKind !== void 0) push(ts, `${
|
|
453
|
+
if (row.toolDenialKind !== void 0) push(ts, `${str3(row.uuid) ?? seq}:deny`, { kind: "waiting_for_user", reason: "permission" });
|
|
382
454
|
const blocks = Array.isArray(content) ? content : [];
|
|
383
455
|
for (const b of blocks) {
|
|
384
|
-
const block =
|
|
456
|
+
const block = obj3(b);
|
|
385
457
|
if (block.type !== "tool_result") continue;
|
|
386
|
-
const useId =
|
|
458
|
+
const useId = str3(block.tool_use_id);
|
|
387
459
|
if (!useId) continue;
|
|
388
460
|
const p = pending.get(useId);
|
|
389
461
|
if (!p) {
|
|
@@ -404,7 +476,7 @@ function parseTranscriptRows(rows, opts = {}) {
|
|
|
404
476
|
if (out.pendingSubagent) openSubagents.set(out.pendingSubagent.childId, useId);
|
|
405
477
|
}
|
|
406
478
|
if (blocks.length === 0 && typeof content === "string" && /\[Request interrupted by user/i.test(content)) {
|
|
407
|
-
push(ts, `${
|
|
479
|
+
push(ts, `${str3(row.uuid) ?? seq}:interrupt`, { kind: "waiting_for_user", reason: "idle" });
|
|
408
480
|
}
|
|
409
481
|
}
|
|
410
482
|
for (const [useId, p] of pending) {
|
|
@@ -423,72 +495,6 @@ function parseTranscriptRows(rows, opts = {}) {
|
|
|
423
495
|
}
|
|
424
496
|
return { events, warnings };
|
|
425
497
|
}
|
|
426
|
-
var obj3 = (x) => x && typeof x === "object" ? x : {};
|
|
427
|
-
var str3 = (x) => typeof x === "string" ? x : void 0;
|
|
428
|
-
var TOOL_EVENTS = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUse", "PostToolUseFailure"]);
|
|
429
|
-
function endReason(reason) {
|
|
430
|
-
switch (reason) {
|
|
431
|
-
case "clear":
|
|
432
|
-
case "logout":
|
|
433
|
-
case "prompt_input_exit":
|
|
434
|
-
return "user";
|
|
435
|
-
default:
|
|
436
|
-
return "stop";
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
function hookPayloadToEvents(payload, opts = {}) {
|
|
440
|
-
const p = obj3(payload);
|
|
441
|
-
const name = str3(p.hook_event_name);
|
|
442
|
-
const sessionId = str3(p.session_id) ?? "";
|
|
443
|
-
const ts = opts.now ?? Date.now();
|
|
444
|
-
if (!name) return { events: [], warnings: [{ code: "missing_field", detail: "hook_event_name" }] };
|
|
445
|
-
const cwd = str3(p.cwd) ?? "";
|
|
446
|
-
const ctx = { cwd, ...opts.home ? { home: opts.home } : {} };
|
|
447
|
-
const agentId = TOOL_EVENTS.has(name) ? str3(p.agent_id) : void 0;
|
|
448
|
-
const extra = agentId ? { agentId } : {};
|
|
449
|
-
let seq = 0;
|
|
450
|
-
const mk = (body, id = mintId(ts)) => ({ id, seq: seq++, ts, sessionId, source: "hook", ...extra, ...body });
|
|
451
|
-
const one = (body) => ({ events: [mk(body)], warnings: [] });
|
|
452
|
-
switch (name) {
|
|
453
|
-
case "SessionStart":
|
|
454
|
-
return one({ kind: "session_start", repoId: basename(cwd) || "repo" });
|
|
455
|
-
case "SessionEnd":
|
|
456
|
-
return one({ kind: "session_end", reason: endReason(str3(p.reason)), claimedSuccess: false });
|
|
457
|
-
case "Stop":
|
|
458
|
-
return one({ kind: "turn_end", claimedSuccess: claimsSuccess(str3(p.last_assistant_message)) });
|
|
459
|
-
case "SubagentStart": {
|
|
460
|
-
const id = str3(p.agent_id) ?? "";
|
|
461
|
-
const label = str3(p.agent_type);
|
|
462
|
-
return { events: [mk({ kind: "subagent_start", childId: id, ...label ? { label } : {} })], warnings: [] };
|
|
463
|
-
}
|
|
464
|
-
case "SubagentStop":
|
|
465
|
-
return one({ kind: "subagent_stop", childId: str3(p.agent_id) ?? "", ok: true });
|
|
466
|
-
case "Notification": {
|
|
467
|
-
const t = str3(p.notification_type);
|
|
468
|
-
if (t === "permission_prompt") return one({ kind: "waiting_for_user", reason: "permission" });
|
|
469
|
-
if (t === "idle_prompt") return one({ kind: "waiting_for_user", reason: "idle" });
|
|
470
|
-
if (t === "elicitation_dialog") return one({ kind: "waiting_for_user", reason: "question" });
|
|
471
|
-
return { events: [], warnings: [] };
|
|
472
|
-
}
|
|
473
|
-
case "PostToolUseFailure":
|
|
474
|
-
return one({ kind: "error", where: str3(p.tool_name) ?? "tool", retrying: false });
|
|
475
|
-
case "PostToolUse": {
|
|
476
|
-
const tool = str3(p.tool_name);
|
|
477
|
-
if (!tool) return { events: [], warnings: [{ code: "missing_field", detail: "tool_name" }] };
|
|
478
|
-
const dur = typeof p.duration_ms === "number" ? { durationMs: p.duration_ms } : {};
|
|
479
|
-
const out = toolCallToOutcome({ name: tool, input: p.tool_input, response: p.tool_response, ...dur }, ctx);
|
|
480
|
-
const baseId = str3(p.tool_use_id) ?? mintId(ts);
|
|
481
|
-
const events = out.bodies.map((body, i) => mk(body, i === 0 ? baseId : `${baseId}:${i}`));
|
|
482
|
-
return { events, warnings: out.warning ? [out.warning] : [] };
|
|
483
|
-
}
|
|
484
|
-
case "PreToolUse":
|
|
485
|
-
case "UserPromptSubmit":
|
|
486
|
-
case "PreCompact":
|
|
487
|
-
case "PostCompact":
|
|
488
|
-
return { events: [], warnings: [] };
|
|
489
|
-
}
|
|
490
|
-
return { events: [], warnings: [{ code: "unknown_row_type", detail: name }] };
|
|
491
|
-
}
|
|
492
498
|
function hashString(s) {
|
|
493
499
|
let h = 2166136261;
|
|
494
500
|
for (let i = 0; i < s.length; i++) {
|
|
@@ -1030,7 +1036,7 @@ var Director = class {
|
|
|
1030
1036
|
this.emit(e, actor, { kind: "unverified_claim", gremlinId: gid }, 1400, this.mood.onClaimUnverified());
|
|
1031
1037
|
}
|
|
1032
1038
|
this.editedSinceTurn = false;
|
|
1033
|
-
this.emit(e, actor, { kind: "your_turn" }, 1e3, this.mood.mood);
|
|
1039
|
+
this.emit(e, actor, { kind: "your_turn", ...e.note ? { note: e.note } : {} }, 1e3, this.mood.mood);
|
|
1034
1040
|
break;
|
|
1035
1041
|
}
|
|
1036
1042
|
case "session_end":
|
|
@@ -1300,7 +1306,26 @@ var Theatre = class {
|
|
|
1300
1306
|
this.port = typeof addr === "object" && addr ? addr.port : port;
|
|
1301
1307
|
const home = this.opts.home ?? join2(homedir2(), ".agent-theatre");
|
|
1302
1308
|
mkdirSync(home, { recursive: true });
|
|
1309
|
+
try {
|
|
1310
|
+
const old = parseInt(readFileSync2(join2(home, "port"), "utf8").trim(), 10);
|
|
1311
|
+
if (old > 0 && old !== this.port && portAlive(old) && !existsSync(join2(home, "ports", String(old)))) {
|
|
1312
|
+
mkdirSync(join2(home, "ports"), { recursive: true });
|
|
1313
|
+
writeFileSync(join2(home, "ports", String(old)), "(started by an older build)");
|
|
1314
|
+
}
|
|
1315
|
+
} catch {
|
|
1316
|
+
}
|
|
1303
1317
|
writeFileSync(join2(home, "port"), String(this.port));
|
|
1318
|
+
mkdirSync(join2(home, "ports"), { recursive: true });
|
|
1319
|
+
for (const f of readdirSync2(join2(home, "ports"))) {
|
|
1320
|
+
const n = parseInt(f, 10);
|
|
1321
|
+
if (n > 0 && n !== this.port && !portAlive(n)) {
|
|
1322
|
+
try {
|
|
1323
|
+
rmSync(join2(home, "ports", f));
|
|
1324
|
+
} catch {
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
writeFileSync(join2(home, "ports", String(this.port)), this.opts.cwd);
|
|
1304
1329
|
const lostAfter = this.opts.lostAfterMs ?? 9e4;
|
|
1305
1330
|
this.timer = setInterval(() => {
|
|
1306
1331
|
const l = this.live;
|
|
@@ -1319,6 +1344,10 @@ var Theatre = class {
|
|
|
1319
1344
|
if (readFileSync2(join2(home, "port"), "utf8").trim() === String(this.port)) rmSync(join2(home, "port"));
|
|
1320
1345
|
} catch {
|
|
1321
1346
|
}
|
|
1347
|
+
try {
|
|
1348
|
+
rmSync(join2(home, "ports", String(this.port)));
|
|
1349
|
+
} catch {
|
|
1350
|
+
}
|
|
1322
1351
|
for (const ws of this.wss?.clients ?? []) ws.close();
|
|
1323
1352
|
this.wss?.close();
|
|
1324
1353
|
await new Promise((res) => this.server ? this.server.close(() => res()) : res());
|
|
@@ -1362,6 +1391,12 @@ function claudeBinary() {
|
|
|
1362
1391
|
}
|
|
1363
1392
|
return null;
|
|
1364
1393
|
}
|
|
1394
|
+
function portAlive(port) {
|
|
1395
|
+
const r = spawnSync("lsof", ["-nP", `-iTCP:${port}`, "-sTCP:LISTEN", "-t"], { encoding: "utf8", timeout: 2e3 });
|
|
1396
|
+
if (r.status === 0 && r.stdout.trim()) return true;
|
|
1397
|
+
if (r.error) return true;
|
|
1398
|
+
return false;
|
|
1399
|
+
}
|
|
1365
1400
|
|
|
1366
1401
|
// src/scan.ts
|
|
1367
1402
|
import { readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
@@ -1496,20 +1531,22 @@ function hasOurHooks(existing) {
|
|
|
1496
1531
|
// src/hooks/script.ts
|
|
1497
1532
|
var HOOK_SCRIPT = `#!/usr/bin/env node
|
|
1498
1533
|
// Agent Theatre hook \u2014 forwards Claude Code events to the local theatre. Never blocks the agent.
|
|
1499
|
-
import { readFileSync } from "node:fs";
|
|
1534
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
1500
1535
|
import { homedir } from "node:os";
|
|
1501
1536
|
import { join } from "node:path";
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
if (
|
|
1537
|
+
// Every running stage registers itself in ports/<port>; the event goes to all of them (browser, VS Code, a second repo\u2026).
|
|
1538
|
+
const home = process.env.AGENT_THEATRE_HOME || join(homedir(), ".agent-theatre");
|
|
1539
|
+
const ports = new Set();
|
|
1540
|
+
try { for (const f of readdirSync(join(home, "ports"))) { const n = parseInt(f, 10); if (n > 0) ports.add(n); } } catch { /* no registry yet */ }
|
|
1541
|
+
try { const n = parseInt(readFileSync(join(home, "port"), "utf8").trim(), 10); if (n > 0) ports.add(n); } catch { /* no port file */ }
|
|
1542
|
+
if (!ports.size) process.exit(0);
|
|
1506
1543
|
let body = "";
|
|
1507
1544
|
process.stdin.setEncoding("utf8");
|
|
1508
1545
|
process.stdin.on("data", (c) => { body += c; if (body.length > 2_000_000) body = body.slice(0, 2_000_000); });
|
|
1509
1546
|
process.stdin.on("end", async () => {
|
|
1510
1547
|
try {
|
|
1511
|
-
await fetch(\`http://127.0.0.1:\${port}/hook\`, { method: "POST", headers: { "content-type": "application/json" }, body, signal: AbortSignal.timeout(300) });
|
|
1512
|
-
} catch { /* theatre not running or slow: that is fine */ }
|
|
1548
|
+
await Promise.allSettled([...ports].map((port) => fetch(\`http://127.0.0.1:\${port}/hook\`, { method: "POST", headers: { "content-type": "application/json" }, body, signal: AbortSignal.timeout(300) })));
|
|
1549
|
+
} catch { /* a theatre not running or slow: that is fine */ }
|
|
1513
1550
|
process.exit(0);
|
|
1514
1551
|
});
|
|
1515
1552
|
setTimeout(() => process.exit(0), 600).unref();
|