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/cli.js
CHANGED
|
@@ -300,9 +300,81 @@ function claimsSuccess(text) {
|
|
|
300
300
|
if (HEDGE_LEXICON.some((r) => r.test(tail))) return false;
|
|
301
301
|
return SUCCESS_LEXICON.some((r) => r.test(tail));
|
|
302
302
|
}
|
|
303
|
-
var ROW_TYPES = /* @__PURE__ */ new Set(["user", "assistant", "system"]);
|
|
304
303
|
var obj2 = (x) => x && typeof x === "object" ? x : {};
|
|
305
304
|
var str2 = (x) => typeof x === "string" ? x : void 0;
|
|
305
|
+
var TOOL_EVENTS = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUse", "PostToolUseFailure"]);
|
|
306
|
+
function endReason(reason) {
|
|
307
|
+
switch (reason) {
|
|
308
|
+
case "clear":
|
|
309
|
+
case "logout":
|
|
310
|
+
case "prompt_input_exit":
|
|
311
|
+
return "user";
|
|
312
|
+
default:
|
|
313
|
+
return "stop";
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function hookPayloadToEvents(payload, opts = {}) {
|
|
317
|
+
const p = obj2(payload);
|
|
318
|
+
const name = str2(p.hook_event_name);
|
|
319
|
+
const sessionId = str2(p.session_id) ?? "";
|
|
320
|
+
const ts = opts.now ?? Date.now();
|
|
321
|
+
if (!name) return { events: [], warnings: [{ code: "missing_field", detail: "hook_event_name" }] };
|
|
322
|
+
const cwd = str2(p.cwd) ?? "";
|
|
323
|
+
const ctx = { cwd, ...opts.home ? { home: opts.home } : {} };
|
|
324
|
+
const agentId = TOOL_EVENTS.has(name) ? str2(p.agent_id) : void 0;
|
|
325
|
+
const extra = agentId ? { agentId } : {};
|
|
326
|
+
let seq = 0;
|
|
327
|
+
const mk = (body, id = mintId(ts)) => ({ id, seq: seq++, ts, sessionId, source: "hook", ...extra, ...body });
|
|
328
|
+
const one = (body) => ({ events: [mk(body)], warnings: [] });
|
|
329
|
+
switch (name) {
|
|
330
|
+
case "SessionStart":
|
|
331
|
+
return one({ kind: "session_start", repoId: basename(cwd) || "repo" });
|
|
332
|
+
case "SessionEnd":
|
|
333
|
+
return one({ kind: "session_end", reason: endReason(str2(p.reason)), claimedSuccess: false });
|
|
334
|
+
case "Stop":
|
|
335
|
+
return one({ kind: "turn_end", claimedSuccess: claimsSuccess(str2(p.last_assistant_message)), ...noteOf(str2(p.last_assistant_message)) });
|
|
336
|
+
case "SubagentStart": {
|
|
337
|
+
const id = str2(p.agent_id) ?? "";
|
|
338
|
+
const label = str2(p.agent_type);
|
|
339
|
+
return { events: [mk({ kind: "subagent_start", childId: id, ...label ? { label } : {} })], warnings: [] };
|
|
340
|
+
}
|
|
341
|
+
case "SubagentStop":
|
|
342
|
+
return one({ kind: "subagent_stop", childId: str2(p.agent_id) ?? "", ok: true });
|
|
343
|
+
case "Notification": {
|
|
344
|
+
const t = str2(p.notification_type);
|
|
345
|
+
if (t === "permission_prompt") return one({ kind: "waiting_for_user", reason: "permission" });
|
|
346
|
+
if (t === "idle_prompt") return one({ kind: "waiting_for_user", reason: "idle" });
|
|
347
|
+
if (t === "elicitation_dialog") return one({ kind: "waiting_for_user", reason: "question" });
|
|
348
|
+
return { events: [], warnings: [] };
|
|
349
|
+
}
|
|
350
|
+
case "PostToolUseFailure":
|
|
351
|
+
return one({ kind: "error", where: str2(p.tool_name) ?? "tool", retrying: false });
|
|
352
|
+
case "PostToolUse": {
|
|
353
|
+
const tool = str2(p.tool_name);
|
|
354
|
+
if (!tool) return { events: [], warnings: [{ code: "missing_field", detail: "tool_name" }] };
|
|
355
|
+
const dur = typeof p.duration_ms === "number" ? { durationMs: p.duration_ms } : {};
|
|
356
|
+
const out = toolCallToOutcome({ name: tool, input: p.tool_input, response: p.tool_response, ...dur }, ctx);
|
|
357
|
+
const baseId = str2(p.tool_use_id) ?? mintId(ts);
|
|
358
|
+
const events = out.bodies.map((body, i) => mk(body, i === 0 ? baseId : `${baseId}:${i}`));
|
|
359
|
+
return { events, warnings: out.warning ? [out.warning] : [] };
|
|
360
|
+
}
|
|
361
|
+
case "PreToolUse":
|
|
362
|
+
case "UserPromptSubmit":
|
|
363
|
+
case "PreCompact":
|
|
364
|
+
case "PostCompact":
|
|
365
|
+
return { events: [], warnings: [] };
|
|
366
|
+
}
|
|
367
|
+
return { events: [], warnings: [{ code: "unknown_row_type", detail: name }] };
|
|
368
|
+
}
|
|
369
|
+
function noteOf(text) {
|
|
370
|
+
if (!text) return {};
|
|
371
|
+
const para = text.trim().split(/\n{2,}/).filter((x) => x.trim()).pop()?.replace(/\s+/g, " ").trim() ?? "";
|
|
372
|
+
if (!para) return {};
|
|
373
|
+
return { note: para.length > 240 ? "\u2026" + para.slice(-239) : para };
|
|
374
|
+
}
|
|
375
|
+
var ROW_TYPES = /* @__PURE__ */ new Set(["user", "assistant", "system"]);
|
|
376
|
+
var obj3 = (x) => x && typeof x === "object" ? x : {};
|
|
377
|
+
var str3 = (x) => typeof x === "string" ? x : void 0;
|
|
306
378
|
function parseTranscript(text, opts = {}) {
|
|
307
379
|
const rows = [];
|
|
308
380
|
const warnings = [];
|
|
@@ -338,21 +410,21 @@ function parseTranscriptRows(rows, opts = {}) {
|
|
|
338
410
|
events.push({ id, seq: seq++, ts, sessionId, source: "transcript", ...extra, ...body });
|
|
339
411
|
};
|
|
340
412
|
const tsOf = (row) => {
|
|
341
|
-
const t =
|
|
413
|
+
const t = str3(row.timestamp);
|
|
342
414
|
const n = t ? Date.parse(t) : Number.NaN;
|
|
343
415
|
return Number.isFinite(n) ? n : Number.isFinite(lastTs) ? lastTs : 0;
|
|
344
416
|
};
|
|
345
|
-
const agentOf = (row) =>
|
|
417
|
+
const agentOf = (row) => str3(row.agentId) ?? (row.isSidechain === true ? opts.sidechainAgentId ?? "sidechain" : void 0);
|
|
346
418
|
for (const raw of rows) {
|
|
347
|
-
const row =
|
|
348
|
-
const type =
|
|
419
|
+
const row = obj3(raw);
|
|
420
|
+
const type = str3(row.type) ?? "";
|
|
349
421
|
if (!ROW_TYPES.has(type)) {
|
|
350
422
|
if (type) unknownTypes.add(type);
|
|
351
423
|
continue;
|
|
352
424
|
}
|
|
353
|
-
if (!sessionId &&
|
|
354
|
-
if (!cwd &&
|
|
355
|
-
if (!branch &&
|
|
425
|
+
if (!sessionId && str3(row.sessionId)) sessionId = str3(row.sessionId);
|
|
426
|
+
if (!cwd && str3(row.cwd)) cwd = str3(row.cwd);
|
|
427
|
+
if (!branch && str3(row.gitBranch)) branch = str3(row.gitBranch);
|
|
356
428
|
const ts = tsOf(row);
|
|
357
429
|
if (!Number.isFinite(firstTs)) {
|
|
358
430
|
firstTs = ts;
|
|
@@ -360,39 +432,39 @@ function parseTranscriptRows(rows, opts = {}) {
|
|
|
360
432
|
}
|
|
361
433
|
lastTs = ts;
|
|
362
434
|
const agentId = agentOf(row);
|
|
363
|
-
const message =
|
|
435
|
+
const message = obj3(row.message);
|
|
364
436
|
const content = message.content;
|
|
365
437
|
if (type === "system") {
|
|
366
438
|
if (row.subtype === "api_error") {
|
|
367
439
|
const attempt = typeof row.retryAttempt === "number" ? row.retryAttempt : 0;
|
|
368
440
|
const max = typeof row.maxRetries === "number" ? row.maxRetries : 0;
|
|
369
|
-
push(ts,
|
|
441
|
+
push(ts, str3(row.uuid) ?? `sys:${seq}`, { kind: "error", where: "api", retrying: attempt < max }, agentId ? { agentId } : {});
|
|
370
442
|
}
|
|
371
443
|
continue;
|
|
372
444
|
}
|
|
373
445
|
if (type === "assistant") {
|
|
374
446
|
const blocks2 = Array.isArray(content) ? content : [];
|
|
375
447
|
for (const b of blocks2) {
|
|
376
|
-
const block =
|
|
377
|
-
if (block.type === "tool_use" &&
|
|
378
|
-
pending.set(
|
|
448
|
+
const block = obj3(b);
|
|
449
|
+
if (block.type === "tool_use" && str3(block.id) && str3(block.name)) {
|
|
450
|
+
pending.set(str3(block.id), { name: str3(block.name), input: block.input, ts, ...agentId ? { agentId } : {} });
|
|
379
451
|
} else if (block.type === "text" && !agentId) {
|
|
380
|
-
const t =
|
|
452
|
+
const t = str3(block.text);
|
|
381
453
|
if (t) lastAssistantText = t;
|
|
382
454
|
}
|
|
383
455
|
}
|
|
384
456
|
if (typeof content === "string" && !agentId) lastAssistantText = content;
|
|
385
457
|
if (message.stop_reason === "end_turn" && !agentId) {
|
|
386
|
-
push(ts, `${
|
|
458
|
+
push(ts, `${str3(row.uuid) ?? seq}:turn`, { kind: "turn_end", claimedSuccess: claimsSuccess(lastAssistantText), ...noteOf(lastAssistantText) });
|
|
387
459
|
}
|
|
388
460
|
continue;
|
|
389
461
|
}
|
|
390
|
-
if (row.toolDenialKind !== void 0) push(ts, `${
|
|
462
|
+
if (row.toolDenialKind !== void 0) push(ts, `${str3(row.uuid) ?? seq}:deny`, { kind: "waiting_for_user", reason: "permission" });
|
|
391
463
|
const blocks = Array.isArray(content) ? content : [];
|
|
392
464
|
for (const b of blocks) {
|
|
393
|
-
const block =
|
|
465
|
+
const block = obj3(b);
|
|
394
466
|
if (block.type !== "tool_result") continue;
|
|
395
|
-
const useId =
|
|
467
|
+
const useId = str3(block.tool_use_id);
|
|
396
468
|
if (!useId) continue;
|
|
397
469
|
const p = pending.get(useId);
|
|
398
470
|
if (!p) {
|
|
@@ -413,7 +485,7 @@ function parseTranscriptRows(rows, opts = {}) {
|
|
|
413
485
|
if (out.pendingSubagent) openSubagents.set(out.pendingSubagent.childId, useId);
|
|
414
486
|
}
|
|
415
487
|
if (blocks.length === 0 && typeof content === "string" && /\[Request interrupted by user/i.test(content)) {
|
|
416
|
-
push(ts, `${
|
|
488
|
+
push(ts, `${str3(row.uuid) ?? seq}:interrupt`, { kind: "waiting_for_user", reason: "idle" });
|
|
417
489
|
}
|
|
418
490
|
}
|
|
419
491
|
for (const [useId, p] of pending) {
|
|
@@ -432,72 +504,6 @@ function parseTranscriptRows(rows, opts = {}) {
|
|
|
432
504
|
}
|
|
433
505
|
return { events, warnings };
|
|
434
506
|
}
|
|
435
|
-
var obj3 = (x) => x && typeof x === "object" ? x : {};
|
|
436
|
-
var str3 = (x) => typeof x === "string" ? x : void 0;
|
|
437
|
-
var TOOL_EVENTS = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUse", "PostToolUseFailure"]);
|
|
438
|
-
function endReason(reason) {
|
|
439
|
-
switch (reason) {
|
|
440
|
-
case "clear":
|
|
441
|
-
case "logout":
|
|
442
|
-
case "prompt_input_exit":
|
|
443
|
-
return "user";
|
|
444
|
-
default:
|
|
445
|
-
return "stop";
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
function hookPayloadToEvents(payload, opts = {}) {
|
|
449
|
-
const p = obj3(payload);
|
|
450
|
-
const name = str3(p.hook_event_name);
|
|
451
|
-
const sessionId = str3(p.session_id) ?? "";
|
|
452
|
-
const ts = opts.now ?? Date.now();
|
|
453
|
-
if (!name) return { events: [], warnings: [{ code: "missing_field", detail: "hook_event_name" }] };
|
|
454
|
-
const cwd = str3(p.cwd) ?? "";
|
|
455
|
-
const ctx = { cwd, ...opts.home ? { home: opts.home } : {} };
|
|
456
|
-
const agentId = TOOL_EVENTS.has(name) ? str3(p.agent_id) : void 0;
|
|
457
|
-
const extra = agentId ? { agentId } : {};
|
|
458
|
-
let seq = 0;
|
|
459
|
-
const mk = (body, id = mintId(ts)) => ({ id, seq: seq++, ts, sessionId, source: "hook", ...extra, ...body });
|
|
460
|
-
const one = (body) => ({ events: [mk(body)], warnings: [] });
|
|
461
|
-
switch (name) {
|
|
462
|
-
case "SessionStart":
|
|
463
|
-
return one({ kind: "session_start", repoId: basename(cwd) || "repo" });
|
|
464
|
-
case "SessionEnd":
|
|
465
|
-
return one({ kind: "session_end", reason: endReason(str3(p.reason)), claimedSuccess: false });
|
|
466
|
-
case "Stop":
|
|
467
|
-
return one({ kind: "turn_end", claimedSuccess: claimsSuccess(str3(p.last_assistant_message)) });
|
|
468
|
-
case "SubagentStart": {
|
|
469
|
-
const id = str3(p.agent_id) ?? "";
|
|
470
|
-
const label = str3(p.agent_type);
|
|
471
|
-
return { events: [mk({ kind: "subagent_start", childId: id, ...label ? { label } : {} })], warnings: [] };
|
|
472
|
-
}
|
|
473
|
-
case "SubagentStop":
|
|
474
|
-
return one({ kind: "subagent_stop", childId: str3(p.agent_id) ?? "", ok: true });
|
|
475
|
-
case "Notification": {
|
|
476
|
-
const t = str3(p.notification_type);
|
|
477
|
-
if (t === "permission_prompt") return one({ kind: "waiting_for_user", reason: "permission" });
|
|
478
|
-
if (t === "idle_prompt") return one({ kind: "waiting_for_user", reason: "idle" });
|
|
479
|
-
if (t === "elicitation_dialog") return one({ kind: "waiting_for_user", reason: "question" });
|
|
480
|
-
return { events: [], warnings: [] };
|
|
481
|
-
}
|
|
482
|
-
case "PostToolUseFailure":
|
|
483
|
-
return one({ kind: "error", where: str3(p.tool_name) ?? "tool", retrying: false });
|
|
484
|
-
case "PostToolUse": {
|
|
485
|
-
const tool = str3(p.tool_name);
|
|
486
|
-
if (!tool) return { events: [], warnings: [{ code: "missing_field", detail: "tool_name" }] };
|
|
487
|
-
const dur = typeof p.duration_ms === "number" ? { durationMs: p.duration_ms } : {};
|
|
488
|
-
const out = toolCallToOutcome({ name: tool, input: p.tool_input, response: p.tool_response, ...dur }, ctx);
|
|
489
|
-
const baseId = str3(p.tool_use_id) ?? mintId(ts);
|
|
490
|
-
const events = out.bodies.map((body, i) => mk(body, i === 0 ? baseId : `${baseId}:${i}`));
|
|
491
|
-
return { events, warnings: out.warning ? [out.warning] : [] };
|
|
492
|
-
}
|
|
493
|
-
case "PreToolUse":
|
|
494
|
-
case "UserPromptSubmit":
|
|
495
|
-
case "PreCompact":
|
|
496
|
-
case "PostCompact":
|
|
497
|
-
return { events: [], warnings: [] };
|
|
498
|
-
}
|
|
499
|
-
return { events: [], warnings: [{ code: "unknown_row_type", detail: name }] };
|
|
500
|
-
}
|
|
501
507
|
function hashString(s) {
|
|
502
508
|
let h = 2166136261;
|
|
503
509
|
for (let i = 0; i < s.length; i++) {
|
|
@@ -1039,7 +1045,7 @@ var Director = class {
|
|
|
1039
1045
|
this.emit(e, actor, { kind: "unverified_claim", gremlinId: gid }, 1400, this.mood.onClaimUnverified());
|
|
1040
1046
|
}
|
|
1041
1047
|
this.editedSinceTurn = false;
|
|
1042
|
-
this.emit(e, actor, { kind: "your_turn" }, 1e3, this.mood.mood);
|
|
1048
|
+
this.emit(e, actor, { kind: "your_turn", ...e.note ? { note: e.note } : {} }, 1e3, this.mood.mood);
|
|
1043
1049
|
break;
|
|
1044
1050
|
}
|
|
1045
1051
|
case "session_end":
|
|
@@ -1309,7 +1315,26 @@ var Theatre = class {
|
|
|
1309
1315
|
this.port = typeof addr === "object" && addr ? addr.port : port;
|
|
1310
1316
|
const home = this.opts.home ?? join2(homedir2(), ".agent-theatre");
|
|
1311
1317
|
mkdirSync(home, { recursive: true });
|
|
1318
|
+
try {
|
|
1319
|
+
const old = parseInt(readFileSync2(join2(home, "port"), "utf8").trim(), 10);
|
|
1320
|
+
if (old > 0 && old !== this.port && portAlive(old) && !existsSync(join2(home, "ports", String(old)))) {
|
|
1321
|
+
mkdirSync(join2(home, "ports"), { recursive: true });
|
|
1322
|
+
writeFileSync(join2(home, "ports", String(old)), "(started by an older build)");
|
|
1323
|
+
}
|
|
1324
|
+
} catch {
|
|
1325
|
+
}
|
|
1312
1326
|
writeFileSync(join2(home, "port"), String(this.port));
|
|
1327
|
+
mkdirSync(join2(home, "ports"), { recursive: true });
|
|
1328
|
+
for (const f of readdirSync2(join2(home, "ports"))) {
|
|
1329
|
+
const n = parseInt(f, 10);
|
|
1330
|
+
if (n > 0 && n !== this.port && !portAlive(n)) {
|
|
1331
|
+
try {
|
|
1332
|
+
rmSync(join2(home, "ports", f));
|
|
1333
|
+
} catch {
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
writeFileSync(join2(home, "ports", String(this.port)), this.opts.cwd);
|
|
1313
1338
|
const lostAfter = this.opts.lostAfterMs ?? 9e4;
|
|
1314
1339
|
this.timer = setInterval(() => {
|
|
1315
1340
|
const l = this.live;
|
|
@@ -1328,6 +1353,10 @@ var Theatre = class {
|
|
|
1328
1353
|
if (readFileSync2(join2(home, "port"), "utf8").trim() === String(this.port)) rmSync(join2(home, "port"));
|
|
1329
1354
|
} catch {
|
|
1330
1355
|
}
|
|
1356
|
+
try {
|
|
1357
|
+
rmSync(join2(home, "ports", String(this.port)));
|
|
1358
|
+
} catch {
|
|
1359
|
+
}
|
|
1331
1360
|
for (const ws of this.wss?.clients ?? []) ws.close();
|
|
1332
1361
|
this.wss?.close();
|
|
1333
1362
|
await new Promise((res) => this.server ? this.server.close(() => res()) : res());
|
|
@@ -1371,6 +1400,12 @@ function claudeBinary() {
|
|
|
1371
1400
|
}
|
|
1372
1401
|
return null;
|
|
1373
1402
|
}
|
|
1403
|
+
function portAlive(port) {
|
|
1404
|
+
const r = spawnSync("lsof", ["-nP", `-iTCP:${port}`, "-sTCP:LISTEN", "-t"], { encoding: "utf8", timeout: 2e3 });
|
|
1405
|
+
if (r.status === 0 && r.stdout.trim()) return true;
|
|
1406
|
+
if (r.error) return true;
|
|
1407
|
+
return false;
|
|
1408
|
+
}
|
|
1374
1409
|
|
|
1375
1410
|
// src/scan.ts
|
|
1376
1411
|
import { readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
@@ -1505,20 +1540,22 @@ function hasOurHooks(existing) {
|
|
|
1505
1540
|
// src/hooks/script.ts
|
|
1506
1541
|
var HOOK_SCRIPT = `#!/usr/bin/env node
|
|
1507
1542
|
// Agent Theatre hook \u2014 forwards Claude Code events to the local theatre. Never blocks the agent.
|
|
1508
|
-
import { readFileSync } from "node:fs";
|
|
1543
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
1509
1544
|
import { homedir } from "node:os";
|
|
1510
1545
|
import { join } from "node:path";
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
if (
|
|
1546
|
+
// Every running stage registers itself in ports/<port>; the event goes to all of them (browser, VS Code, a second repo\u2026).
|
|
1547
|
+
const home = process.env.AGENT_THEATRE_HOME || join(homedir(), ".agent-theatre");
|
|
1548
|
+
const ports = new Set();
|
|
1549
|
+
try { for (const f of readdirSync(join(home, "ports"))) { const n = parseInt(f, 10); if (n > 0) ports.add(n); } } catch { /* no registry yet */ }
|
|
1550
|
+
try { const n = parseInt(readFileSync(join(home, "port"), "utf8").trim(), 10); if (n > 0) ports.add(n); } catch { /* no port file */ }
|
|
1551
|
+
if (!ports.size) process.exit(0);
|
|
1515
1552
|
let body = "";
|
|
1516
1553
|
process.stdin.setEncoding("utf8");
|
|
1517
1554
|
process.stdin.on("data", (c) => { body += c; if (body.length > 2_000_000) body = body.slice(0, 2_000_000); });
|
|
1518
1555
|
process.stdin.on("end", async () => {
|
|
1519
1556
|
try {
|
|
1520
|
-
await fetch(\`http://127.0.0.1:\${port}/hook\`, { method: "POST", headers: { "content-type": "application/json" }, body, signal: AbortSignal.timeout(300) });
|
|
1521
|
-
} catch { /* theatre not running or slow: that is fine */ }
|
|
1557
|
+
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) })));
|
|
1558
|
+
} catch { /* a theatre not running or slow: that is fine */ }
|
|
1522
1559
|
process.exit(0);
|
|
1523
1560
|
});
|
|
1524
1561
|
setTimeout(() => process.exit(0), 600).unref();
|