frizz-server 0.15.10 → 0.15.11
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/claude-agent-broker.js +434 -13
- package/dist/dev-child.js +218 -72
- package/package.json +1 -1
- package/runtime/cc-worker/bin/frizz-mcp.mjs +22 -11
- package/web-dist/assets/{abnfDiagram-VRR7QNED-CPgDRCPL.js → abnfDiagram-VRR7QNED-NqOfYLl_.js} +1 -1
- package/web-dist/assets/{arc-BHLpLJBo.js → arc-D9UsqPOW.js} +1 -1
- package/web-dist/assets/architecture-TIHT7OUA-CYx5mu8e.js +1 -0
- package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-D0qwvPWx.js → architectureDiagram-ZJ3FMSHR-CRU2_T_H.js} +1 -1
- package/web-dist/assets/{blockDiagram-677ZJIJ3-C3NPa6bJ.js → blockDiagram-677ZJIJ3-DZT8OjJK.js} +1 -1
- package/web-dist/assets/{c4Diagram-LMCZKHZV-BW9GHi19.js → c4Diagram-LMCZKHZV-k-Ft1ThH.js} +1 -1
- package/web-dist/assets/channel-CD-hjjIL.js +1 -0
- package/web-dist/assets/{chunk-32BRIVSS-DHkNUXJc.js → chunk-32BRIVSS-DDMMpuZb.js} +1 -1
- package/web-dist/assets/{chunk-52WLFC77-CD7yIcMj.js → chunk-52WLFC77-BW9KF5RJ.js} +1 -1
- package/web-dist/assets/{chunk-C7G6YPKG-DCNeb-B6.js → chunk-C7G6YPKG-B4caDIAT.js} +1 -1
- package/web-dist/assets/{chunk-EX3LRPZG-YD5FxMO3.js → chunk-EX3LRPZG-Dyz0PnIY.js} +1 -1
- package/web-dist/assets/{chunk-FWX5IMBZ-XPo-YcnN.js → chunk-FWX5IMBZ-Dxhqduv9.js} +2 -2
- package/web-dist/assets/{chunk-HOUHSVGY-D6MFIjXX.js → chunk-HOUHSVGY-Du7Ln4sO.js} +1 -1
- package/web-dist/assets/{chunk-ICXQ74PX-B4YNEdT-.js → chunk-ICXQ74PX-sNRNHZp6.js} +1 -1
- package/web-dist/assets/{chunk-MOJQB5TN-DmeXNe3e.js → chunk-MOJQB5TN-BsgPysrE.js} +1 -1
- package/web-dist/assets/{chunk-OGEWGWER-DOiD4wAh.js → chunk-OGEWGWER-DZ288hvO.js} +1 -1
- package/web-dist/assets/{chunk-PUDLZKDR-1SEr54_e.js → chunk-PUDLZKDR-DuU7e-Sm.js} +1 -1
- package/web-dist/assets/{chunk-Q4XR5HBZ-CyWVwYh2.js → chunk-Q4XR5HBZ-BO2aVRAy.js} +1 -1
- package/web-dist/assets/{chunk-RYQCIY6F-ClBJ_iGr.js → chunk-RYQCIY6F-pQoqlm5b.js} +1 -1
- package/web-dist/assets/{chunk-V7JOEXUC-Bz8VXwYP.js → chunk-V7JOEXUC-DkkQI0OQ.js} +1 -1
- package/web-dist/assets/{chunk-VAUOI2AC-DawR4suA.js → chunk-VAUOI2AC-D3_hzRfs.js} +1 -1
- package/web-dist/assets/{chunk-VR4S4FIN-B-_noBva.js → chunk-VR4S4FIN-BBnj_eoh.js} +1 -1
- package/web-dist/assets/{chunk-WYO6CB5R-DL1c5T7_.js → chunk-WYO6CB5R-BqxQ9C2U.js} +1 -1
- package/web-dist/assets/{chunk-XXDRQBXY-BtfDQurg.js → chunk-XXDRQBXY-i1ZlWoHe.js} +1 -1
- package/web-dist/assets/{chunk-ZGVPDNZ5-Du753kJ-.js → chunk-ZGVPDNZ5-CsZazrsC.js} +1 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-B-BSDhSx.js +1 -0
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-B-BSDhSx.js +1 -0
- package/web-dist/assets/{cose-bilkent-JH36ORCC-B92GSF8h.js → cose-bilkent-JH36ORCC-BmEzvocR.js} +1 -1
- package/web-dist/assets/{cynefin-VYW2F7L2-K0fFe9n6.js → cynefin-VYW2F7L2-DZw7i9wG.js} +1 -1
- package/web-dist/assets/{cynefinDiagram-TSTJHNR4-DPizF8tw.js → cynefinDiagram-TSTJHNR4-vngpN5Da.js} +1 -1
- package/web-dist/assets/{dagre-VKFMJZFB-CUyDVdiG.js → dagre-VKFMJZFB-DkIdWq34.js} +1 -1
- package/web-dist/assets/{diagram-FQU43EPY-B6T_JCaJ.js → diagram-FQU43EPY-BB6mK3b6.js} +1 -1
- package/web-dist/assets/{diagram-G47NLZAW-CoDvaB51.js → diagram-G47NLZAW-DNs0n26T.js} +1 -1
- package/web-dist/assets/{diagram-NH7WQ7WH-o5OSs1Ze.js → diagram-NH7WQ7WH-DOg3HmEF.js} +1 -1
- package/web-dist/assets/{diagram-OA4YK3LP-CZLlB0ak.js → diagram-OA4YK3LP-BVKuqpaY.js} +1 -1
- package/web-dist/assets/{diagram-WEI45ONY-2VF6u7pk.js → diagram-WEI45ONY-BVnqmqct.js} +1 -1
- package/web-dist/assets/{dist-C2Rccr_W.js → dist-DuviCA4e.js} +1 -1
- package/web-dist/assets/{ebnfDiagram-CCIWWBDH-D9GSCcoU.js → ebnfDiagram-CCIWWBDH-BrqvjM1n.js} +1 -1
- package/web-dist/assets/{erDiagram-Q63AITRT-BLwWP_S8.js → erDiagram-Q63AITRT-Du1wclw9.js} +1 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-BPCrKw7m.js +1 -0
- package/web-dist/assets/flowDiagram-23GEKE2U-AA0QqWn2.js +1 -0
- package/web-dist/assets/{ganttDiagram-NO4QXBWP-BDe4wbPG.js → ganttDiagram-NO4QXBWP-CSiHPJrQ.js} +1 -1
- package/web-dist/assets/{gitGraph-TEB2WS4Q-DtGgkTGs.js → gitGraph-TEB2WS4Q-7-fFcwxj.js} +1 -1
- package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-Cz2LctIP.js → gitGraphDiagram-IHSO6WYX-CElQAu0f.js} +1 -1
- package/web-dist/assets/index-BWqGEWRg.js +330 -0
- package/web-dist/assets/index-W88ZnKOr.css +2 -0
- package/web-dist/assets/{info-DKCQHKI2-Crwk5sJH.js → info-DKCQHKI2-CXWr1yIe.js} +1 -1
- package/web-dist/assets/{infoDiagram-FWYZ7A6U-DkHHoxhz.js → infoDiagram-FWYZ7A6U-gN_v0GbL.js} +1 -1
- package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-CXMQf65c.js → ishikawaDiagram-FXEZZL3T-je5d5eKU.js} +1 -1
- package/web-dist/assets/{journeyDiagram-5HDEW3XC-BMdDsuH7.js → journeyDiagram-5HDEW3XC-CybyC_OE.js} +1 -1
- package/web-dist/assets/{kanban-definition-HUTT4EX6-BLp4VuCG.js → kanban-definition-HUTT4EX6-DthSkUsp.js} +1 -1
- package/web-dist/assets/{line-DOl515UP.js → line-C6dQfGfT.js} +1 -1
- package/web-dist/assets/{linear-DXvWeSoC.js → linear-zrRCwmn0.js} +1 -1
- package/web-dist/assets/{mermaid-parser.core-CqGam-b6.js → mermaid-parser.core-DGsIiQR5.js} +3 -3
- package/web-dist/assets/{mermaid.core-DawC2x_0.js → mermaid.core-Dk0TeuEE.js} +3 -3
- package/web-dist/assets/{mindmap-definition-LN4V7U3C-DlsS0Y-V.js → mindmap-definition-LN4V7U3C-Wo-S6GUr.js} +1 -1
- package/web-dist/assets/{packet-7NZHBO7P-CmlVYVem.js → packet-7NZHBO7P-BjJcy3q1.js} +1 -1
- package/web-dist/assets/{pegDiagram-2B236MQR-Cx0g5nsx.js → pegDiagram-2B236MQR-BBD9ezK8.js} +1 -1
- package/web-dist/assets/{pie-RZYD4A2V-C0PsjAlT.js → pie-RZYD4A2V-B9UJsCc6.js} +1 -1
- package/web-dist/assets/{pieDiagram-ENE6RG2P-CSuFf6VT.js → pieDiagram-ENE6RG2P-DvLH3PU6.js} +1 -1
- package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-CuQtvBia.js → quadrantDiagram-ABIIQ3AL-BwC1BKho.js} +1 -1
- package/web-dist/assets/{radar-I7S5WNFK-gk0WSCd9.js → radar-I7S5WNFK-BziFtIY8.js} +1 -1
- package/web-dist/assets/{railroad-3IZDKUUU-CovQLWaQ.js → railroad-3IZDKUUU-DPD8gyCw.js} +1 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-C6wFrQk2.js +1 -0
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-yv1OIO4r.js +1 -0
- package/web-dist/assets/railroad-peg-LSFZ7HO6-BNocqLQb.js +1 -0
- package/web-dist/assets/{railroadDiagram-RFXS5EU6-RU1nu6mz.js → railroadDiagram-RFXS5EU6-DkS_57bW.js} +1 -1
- package/web-dist/assets/{requirementDiagram-TGXJPOKE-VoYjpOAN.js → requirementDiagram-TGXJPOKE-DT4YnV0v.js} +1 -1
- package/web-dist/assets/{sankeyDiagram-HTMAVEWB-DOVqKs1B.js → sankeyDiagram-HTMAVEWB-DMhUiLXu.js} +1 -1
- package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-DWMCuKM1.js → sequenceDiagram-DBY2YBRQ-BzyFG5mU.js} +1 -1
- package/web-dist/assets/{src-T1UUKJjT.js → src-Bpw4w4N9.js} +1 -1
- package/web-dist/assets/{stateDiagram-2N3HPSRC-mvFnj-9X.js → stateDiagram-2N3HPSRC-DI7bXIvV.js} +1 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-BnPQRodM.js +1 -0
- package/web-dist/assets/{swimlanes-5IMT3BWC-kRCjOJ75.js → swimlanes-5IMT3BWC-ocEwjrkf.js} +1 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-Cmi6u5Ox.js +8 -0
- package/web-dist/assets/{timeline-definition-FHXFAJF6-Z8oX_ic6.js → timeline-definition-FHXFAJF6-Cx606xig.js} +1 -1
- package/web-dist/assets/{treeView-QDETBFTQ-BNFv3tbG.js → treeView-QDETBFTQ-BBjaqvh7.js} +1 -1
- package/web-dist/assets/{treemap-6X3UGDF4-DFxnrL9n.js → treemap-6X3UGDF4-Bn8fQ4vt.js} +1 -1
- package/web-dist/assets/{vennDiagram-L72KCM5P-rBeP_pn_.js → vennDiagram-L72KCM5P-DaKXvRdc.js} +1 -1
- package/web-dist/assets/{wardley-OPB4EBWU-BovK6GPr.js → wardley-OPB4EBWU-CK6Oy13G.js} +1 -1
- package/web-dist/assets/{wardleyDiagram-EHGQE667-B1yRRFsz.js → wardleyDiagram-EHGQE667-esMnbbXF.js} +1 -1
- package/web-dist/assets/{xychartDiagram-FW5EYKEG-IShFUxtM.js → xychartDiagram-FW5EYKEG-D3DoqcNr.js} +1 -1
- package/web-dist/index.html +2 -2
- package/web-dist/assets/architecture-TIHT7OUA-BxHw4J0J.js +0 -1
- package/web-dist/assets/channel-CgUG0O7S.js +0 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-CpxiJqgs.js +0 -1
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-CpxiJqgs.js +0 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-C-XvAPEG.js +0 -1
- package/web-dist/assets/flowDiagram-23GEKE2U-DYBwekLd.js +0 -1
- package/web-dist/assets/index-B9jaLEKn.js +0 -330
- package/web-dist/assets/index-Dubos_kO.css +0 -2
- package/web-dist/assets/railroad-abnf-AHOZXSZD-DSq7zK8A.js +0 -1
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-icFIsnio.js +0 -1
- package/web-dist/assets/railroad-peg-LSFZ7HO6-Csep5xwu.js +0 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-BkzW7JgJ.js +0 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-mE9The3K.js +0 -8
package/dist/dev-child.js
CHANGED
|
@@ -13348,7 +13348,9 @@ function splitAwaitingFrontmatter(raw2) {
|
|
|
13348
13348
|
const title = trimAwaitingTitle(titleLines.join(" "));
|
|
13349
13349
|
if (title) parsed.hints.push({ kind: "title", value: title });
|
|
13350
13350
|
const stepHints = steps.map((step) => step.trim()).filter(Boolean).slice(0, AWAITING_STEPS_MAX).map((step) => ({ kind: "step", value: step.slice(0, AWAITING_STEP_VALUE_MAX) }));
|
|
13351
|
-
|
|
13351
|
+
const questionHints = parsed.hints.filter((h10) => h10.kind === "question").slice(0, AWAITING_QUESTIONS_MAX);
|
|
13352
|
+
const capped = parsed.hints.filter((h10) => h10.kind !== "question").slice(0, AWAITING_HINT_MAX);
|
|
13353
|
+
return { body: rest.join("\n").trim(), hints: [...capped, ...questionHints, ...stepHints] };
|
|
13352
13354
|
}
|
|
13353
13355
|
function inlineSteps(value) {
|
|
13354
13356
|
const v3 = value.trim();
|
|
@@ -13364,6 +13366,12 @@ function inlineSteps(value) {
|
|
|
13364
13366
|
function awaitingSteps(hints) {
|
|
13365
13367
|
return (hints ?? []).filter((h10) => h10.kind === "step").map((h10) => h10.value);
|
|
13366
13368
|
}
|
|
13369
|
+
function awaitingQuestions(hints) {
|
|
13370
|
+
return (hints ?? []).filter((h10) => h10.kind === "question").map((h10) => questionIdOf(h10.value));
|
|
13371
|
+
}
|
|
13372
|
+
function questionIdOf(value) {
|
|
13373
|
+
return (/qst_[a-z0-9]+/i.exec(value)?.[0] ?? value.trim()).toLowerCase();
|
|
13374
|
+
}
|
|
13367
13375
|
function parseAwaitingYaml(text2) {
|
|
13368
13376
|
if (!text2.trim()) return { ok: true, hints: [] };
|
|
13369
13377
|
let doc;
|
|
@@ -13385,6 +13393,8 @@ function parseAwaitingYaml(text2) {
|
|
|
13385
13393
|
const itemKind = AWAITING_SEQUENCE_KEYS[key];
|
|
13386
13394
|
if (itemKind) {
|
|
13387
13395
|
for (const entry of Array.isArray(raw2) ? raw2 : [raw2]) push(itemKind, entry);
|
|
13396
|
+
} else if (key === "questions") {
|
|
13397
|
+
for (const entry of Array.isArray(raw2) ? raw2 : [raw2]) push("question", entry);
|
|
13388
13398
|
} else if (key === "for") {
|
|
13389
13399
|
push("for", raw2);
|
|
13390
13400
|
} else if (key === "needs_input" || key === "needs-input") {
|
|
@@ -13394,7 +13404,7 @@ function parseAwaitingYaml(text2) {
|
|
|
13394
13404
|
return { ok: true, hints };
|
|
13395
13405
|
}
|
|
13396
13406
|
function awaitingNeedsInput(hints) {
|
|
13397
|
-
if (awaitingSteps(hints).length > 0) return true;
|
|
13407
|
+
if (awaitingSteps(hints).length > 0 || awaitingQuestions(hints).length > 0) return true;
|
|
13398
13408
|
let answer = null;
|
|
13399
13409
|
for (const h10 of hints ?? []) {
|
|
13400
13410
|
if (h10.kind !== "needs_input") continue;
|
|
@@ -13633,6 +13643,10 @@ function signoffNudgeText(needsInput) {
|
|
|
13633
13643
|
" followed cold; frizz reads them verbatim. Steps name the HUMAN as the wait, so the fence needs no",
|
|
13634
13644
|
" other name and no `for:`, and the thread goes into their queue. Their Done comes back to you as",
|
|
13635
13645
|
" their reply; anything else they need to say comes as a message of their own.",
|
|
13646
|
+
"- `` ```awaiting `` with `questions:` \u2014 a question you registered at an EARLIER rest is still open and",
|
|
13647
|
+
" you still need its answer. Name every such question (`questions: [qst_\u2026]`) and withdraw the rest with",
|
|
13648
|
+
" `mcp__frizz__unask`: a fence that leaves an open question out is refused. A named card is drawn at",
|
|
13649
|
+
" this rest; an unnamed one stays where you asked it.",
|
|
13636
13650
|
"",
|
|
13637
13651
|
"**STILL OWED counts things you are not going to do yourself.** A decision you are RECOMMENDING, a",
|
|
13638
13652
|
"draft you wrote but did not send, follow-up work you discovered \u2014 all of it dies with the card, even",
|
|
@@ -13653,6 +13667,27 @@ function signoffNudgeText(needsInput) {
|
|
|
13653
13667
|
"frizz \u2014 so anything you assumed they had followed, they have not."
|
|
13654
13668
|
].join("\n");
|
|
13655
13669
|
}
|
|
13670
|
+
function carriedQuestionsNudgeMessage(questions, ops, needsInput = false) {
|
|
13671
|
+
const one2 = questions.length === 1;
|
|
13672
|
+
const lines = [
|
|
13673
|
+
`${SIGNOFF_NUDGE_MARKER} Nothing about your task has changed, and no new work is being asked of you.`,
|
|
13674
|
+
"",
|
|
13675
|
+
`${one2 ? "A question you registered at an EARLIER rest is" : "Questions you registered at EARLIER rests are"} still open, and this rest neither names ${one2 ? "it" : "them"} nor withdraws ${one2 ? "it" : "them"}:`,
|
|
13676
|
+
"",
|
|
13677
|
+
...questions.map((q10) => `- \`${q10.id}\` \u2014 ${q10.question}`),
|
|
13678
|
+
"",
|
|
13679
|
+
"Frizz does not draw an earlier rest's question under your newest handoff: its card stays where you",
|
|
13680
|
+
`asked it. So say where ${one2 ? "it stands" : "each one stands"}:`,
|
|
13681
|
+
"",
|
|
13682
|
+
"- STILL NEED THE ANSWER \u2192 end with an ```awaiting fence naming it, `questions: [qst_\u2026]`. A fence on",
|
|
13683
|
+
" questions needs no other name and no `for:`, and the thread stays in the human's queue. The card is",
|
|
13684
|
+
" drawn at this rest, under the reasoning you write below the `---` \u2014 what changed since you asked,",
|
|
13685
|
+
" if anything did.",
|
|
13686
|
+
"- NO LONGER NEED IT \u2192 withdraw it with `mcp__frizz__unask`, then sign off as you otherwise would.",
|
|
13687
|
+
...liveOpsLines(ops, needsInput)
|
|
13688
|
+
];
|
|
13689
|
+
return lines.join("\n");
|
|
13690
|
+
}
|
|
13656
13691
|
function isParkCorrection(text2) {
|
|
13657
13692
|
const t = text2.trimStart();
|
|
13658
13693
|
return t.startsWith(PARK_CORRECTION_NAMES_LEAD) || t.startsWith(PARK_CORRECTION_RETIRED_LEAD) || t.startsWith(PARK_CORRECTION_QUESTION_LEAD) || t.startsWith(PARK_CORRECTION_NEEDS_INPUT_LEAD);
|
|
@@ -13986,7 +14021,7 @@ function parseGithubWakeSteer(text2) {
|
|
|
13986
14021
|
function frizzRoute(path3) {
|
|
13987
14022
|
return `${FRIZZ_ROUTE_PREFIX}${path3.startsWith("/") ? path3 : `/${path3}`}`;
|
|
13988
14023
|
}
|
|
13989
|
-
var import_yaml, ATTACHMENT_IMAGE_EXTENSIONS, ATTACHMENT_TEXT_EXTENSIONS, ATTACHMENT_OFFICE_EXTENSIONS, ATTACHMENT_DATA_EXTENSIONS, ATTACHMENT_ARCHIVE_EXTENSIONS, ATTACHMENT_DOC_EXTENSIONS, ATTACHMENT_EXTENSIONS, ATTACHMENT_MAX_BASE64_CHARS, ATTACHMENT_MAX_BYTES, ATTACHMENT_EXT_SET, ATTACHMENT_ACCEPT, FrizzStatus, BlockMechanism, RuntimeState, Backend, CodexModel, ClaudeModel, AcpAgent, ACP_MODEL_PREFIX, AcpAgentModel, AcpAgentModels, AcpAgentModelsInput, ThreadProfileOption, ThreadAgent, SubAgentView, BgShellView, CompletionHoldOp, CompletionHold, AskOption, AskQuestion, PendingAsk, AwaitingHint, RETIRED_AWAITING_KINDS, RETIRED_LINE_RE, RETIRED_AWAITING_REPLACEMENT, AWAITING_KEY_RE, AWAITING_YAML_KEYS, AWAITING_SEQUENCE_KEYS, AWAITING_HINT_MAX, AWAITING_HINT_VALUE_MAX, AWAITING_STEPS_MAX, AWAITING_STEP_VALUE_MAX, AWAITING_TITLE_MAX, AWAITING_ITEM_KINDS, AWAITING_DURATION_RE, DURATION_UNIT_MS, AWAITING_FOR_MAX_MS, SnoozeUntil, SNOOZE_PROMPT_MAX, SnoozePrompt, RECURRING_PROMPT_MAX, RECURRING_MIN_INTERVAL_SECONDS, RECURRING_MAX_INTERVAL_SECONDS, RecurringPromptText, RecurringIntervalSeconds, ThreadRecurringPrompt, INTERRUPT_MARKERS, ALLDONE_SENTINEL, OPT_OUT_NOTE, OVER_QUESTION_NOTE, TIMER_PROMPT_MAX, TIMER_MAX_DELAY_SECONDS, TIMER_MAX_ARMED, TimerPromptText, PR_WATCH_SPENT_TRAILER, PR_WATCH_ARMED_TRAILER, SHELL_DONE_TRAILER, ISSUE_WATCH_SPENT_TRAILER, ISSUE_WATCH_ARMED_TRAILER, INTERRUPT_ENDED_LEAD, SIGNOFF_NUDGE_MARKER, SIGNOFF_NUDGE_MESSAGE, SIGNOFF_NUDGE_MESSAGE_NEEDS_INPUT, PARK_CORRECTION_NAMES_LEAD, PARK_CORRECTION_RETIRED_LEAD, PARK_CORRECTION_QUESTION_LEAD, PARK_CORRECTION_NEEDS_INPUT_LEAD, ThreadWatchKind, GithubChecksState, GithubMergeState, GithubWatchStatus, GithubIssueStatus, ThreadWatchView, PR_WATCH_FOR_MAX_MS, PR_WATCH_DEFAULT_FOR_MS, PR_WATCH_MAX_ARMED, PrWatchView, AddOwnPrWatchInput, AddOwnPrWatchResult, DropOwnPrWatchInput, DropOwnPrWatchResult, OwnWatchKind, AddOwnWatchInput, OwnWatchView, AddOwnWatchResult, DropOwnWatchInput, DropOwnWatchResult, OWN_WATCH_MAX_ARMED, QUESTION_FENCE_RETIRED_AT, NEEDS_INPUT_REQUIRED_AT, AskQuestionKind, ASK_MAX_DEPTH, AskedOptionSchema, AskedQuestionSchema, AskInput, RegisteredQuestionView, AskResult, UnaskInput, UnaskResult, QuestionAnswerSchema, AnswerQuestionsInput, AnswerQuestionsResult, DismissQuestionsInput, DismissQuestionsResult, SettledQuestionView, ThreadSettledQuestionsResult, BURIED_ANSWERS_HEADER, ANSWER_FOLLOW_UP_MARKER, ANSWER_CONTINUATION_INDENT, indentAnswerContinuation, DISMISSED_ANSWER, MarkOwnDoneInput, MarkOwnDoneResult, ListOwnPrWatchesInput, OwnPrWatchesResult, ThreadTimerView, ThreadFence, LimitWindow, LimitPause, ProviderError, ThreadLinkView, UpsertOwnLinkInput, UpsertOwnLinkResult, DropOwnLinkInput, DropOwnLinkResult, LiveTool, ThreadView, BoardErrorItem, BoardSnapshot, QuotaWindow, ProviderQuota, QuotaSnapshot, ProviderAuth, AccountEmails, AuthSnapshot, AccountBackend, AccountLogoutInput, AccountLogoutResult, PermissionMode, LocalFileOpener, Settings, DispatchProviderPreferences, DispatchPreferences, DispatchProfileSnapshotShape, DispatchProfileSnapshot, SetDispatchPreferenceInput, DispatchInput, ADOPT_THREAD_MESSAGE_MAX_CHARS, AdoptThreadInput, AdoptThreadResult, AdoptSessionInput, FollowUpInput, DismissFailedFollowUpInput, DismissFailedFollowUpResult, UnqueueFollowUpInput, UnqueueFollowUpResult, DeliverQueuedNowInput, DeliverQueuedNowResult, CompactThreadInput, SetThreadSnoozeInput, SetThreadPinnedInput, SetThreadRecurringPromptInput, SetOwnThreadRecurringPromptInput, SetOwnThreadRecurringPromptResult, GetOwnThreadRecurringPromptInput, OwnThreadRecurringPromptResult, SetOwnThreadTimerInput, CancelOwnThreadTimerInput, ListOwnThreadTimersInput, OwnThreadTimersResult, ThreadActivityItem, ListOwnThreadActivityInput, OwnThreadActivityResult, SetOwnThreadTimerResult, CancelOwnThreadTimerResult, SetOwnThreadStopHookInput, SetOwnThreadHeartbeatInput, ThreadPluginReloadResult, RenameThreadInput, AiRenameThreadInput, AiRenameThreadResult, SetOwnThreadTitleInput, SetOwnThreadTitleResult, SetThreadPermissionInput, SetThreadPermissionResult, ThreadProfileOptionsInput, ThreadProfileOptionsResult, ThreadSkillSource, ThreadSkill, ThreadSkillsInput, ThreadSkillsResult, SetThreadProfileInput, SetThreadProfileResult, UpgradeThreadModelInput, UpgradeThreadModelResult, DISPATCH_TASK_BANNER, DISPATCH_TASK_BANNER_MARKER, GITHUB_DISPATCH_UI_BOUNDARY, WAKE_TIME_HEADER_TAIL, WAKE_TRAILERS, HUMAN_GAP_FLOOR_MS, HUMAN_GAP_NOTE_TAIL, WAKE_DELIVERY_TOKEN_TAIL, WAKE_DELIVERY_TOKEN_LINE, NOISE_PREFIXES, AGENT_MESSAGE_WRAPPER, GithubWakeItem, GithubWakeSteer, WAKE_SCOPE, WAKE_REVIEW_LEAD, WAKE_BACKLOG_TAIL, WAKE_REF, WAKE_SINGLE, WAKE_MULTI_HEAD, WAKE_ITEM, WAKE_MORE, PR_WATCH_FINISHED, PR_WATCH_CI_PASSED, PR_WATCH_CI_GATED, PR_WATCH_STATE, PR_WATCH_CI_FAILED, GithubStatus, GithubRefCard, GithubRefPreviewInput, GithubRefPreviewResult, GithubItem, GithubListInput, GithubListResult, GithubBatchInput, GithubBatchResult, BoardMeta, ServerEvent, TranscriptEdit, TranscriptTodo, TranscriptToolCall, TranscriptPart, TranscriptMessage, TranscriptPageCursor, EditedFile, TranscriptPage, TranscriptEarlierInput, SocketTranscriptSlug, SocketFilePath, SocketTranscriptClientMsg, SocketFileClientMsg, SocketClientMsg, ProjectCard, ProjectRailCounts, PROJECT_ICON_EXTENSIONS, PROJECT_ICON_MAX_BASE64_CHARS, DirectoryPickResult, ThreadLocation, FRIZZ_ROUTE_PREFIX, DEFAULT_PORT, threadIdentityName;
|
|
14024
|
+
var import_yaml, ATTACHMENT_IMAGE_EXTENSIONS, ATTACHMENT_TEXT_EXTENSIONS, ATTACHMENT_OFFICE_EXTENSIONS, ATTACHMENT_DATA_EXTENSIONS, ATTACHMENT_ARCHIVE_EXTENSIONS, ATTACHMENT_DOC_EXTENSIONS, ATTACHMENT_EXTENSIONS, ATTACHMENT_MAX_BASE64_CHARS, ATTACHMENT_MAX_BYTES, ATTACHMENT_EXT_SET, ATTACHMENT_ACCEPT, FrizzStatus, BlockMechanism, RuntimeState, Backend, CodexModel, ClaudeModel, AcpAgent, ACP_MODEL_PREFIX, AcpAgentModel, AcpAgentModels, AcpAgentModelsInput, ThreadProfileOption, ThreadAgent, SubAgentView, BgShellView, CompletionHoldOp, CompletionHold, AskOption, AskQuestion, PendingAsk, AwaitingHint, RETIRED_AWAITING_KINDS, RETIRED_LINE_RE, RETIRED_AWAITING_REPLACEMENT, AWAITING_KEY_RE, AWAITING_YAML_KEYS, AWAITING_SEQUENCE_KEYS, AWAITING_HINT_MAX, AWAITING_HINT_VALUE_MAX, AWAITING_STEPS_MAX, AWAITING_STEP_VALUE_MAX, AWAITING_QUESTIONS_MAX, AWAITING_TITLE_MAX, AWAITING_ITEM_KINDS, AWAITING_DURATION_RE, DURATION_UNIT_MS, AWAITING_FOR_MAX_MS, SnoozeUntil, SNOOZE_PROMPT_MAX, SnoozePrompt, RECURRING_PROMPT_MAX, RECURRING_MIN_INTERVAL_SECONDS, RECURRING_MAX_INTERVAL_SECONDS, RecurringPromptText, RecurringIntervalSeconds, ThreadRecurringPrompt, INTERRUPT_MARKERS, ALLDONE_SENTINEL, OPT_OUT_NOTE, OVER_QUESTION_NOTE, TIMER_PROMPT_MAX, TIMER_MAX_DELAY_SECONDS, TIMER_MAX_ARMED, TimerPromptText, PR_WATCH_SPENT_TRAILER, PR_WATCH_ARMED_TRAILER, SHELL_DONE_TRAILER, ISSUE_WATCH_SPENT_TRAILER, ISSUE_WATCH_ARMED_TRAILER, INTERRUPT_ENDED_LEAD, SIGNOFF_NUDGE_MARKER, SIGNOFF_NUDGE_MESSAGE, SIGNOFF_NUDGE_MESSAGE_NEEDS_INPUT, PARK_CORRECTION_NAMES_LEAD, PARK_CORRECTION_RETIRED_LEAD, PARK_CORRECTION_QUESTION_LEAD, PARK_CORRECTION_NEEDS_INPUT_LEAD, ThreadWatchKind, GithubChecksState, GithubMergeState, GithubWatchStatus, GithubIssueStatus, ThreadWatchView, PR_WATCH_FOR_MAX_MS, PR_WATCH_DEFAULT_FOR_MS, PR_WATCH_MAX_ARMED, PrWatchView, AddOwnPrWatchInput, AddOwnPrWatchResult, DropOwnPrWatchInput, DropOwnPrWatchResult, OwnWatchKind, AddOwnWatchInput, OwnWatchView, AddOwnWatchResult, DropOwnWatchInput, DropOwnWatchResult, OWN_WATCH_MAX_ARMED, QUESTION_FENCE_RETIRED_AT, NEEDS_INPUT_REQUIRED_AT, AskQuestionKind, ASK_MAX_DEPTH, AskedOptionSchema, AskedQuestionSchema, AskInput, RegisteredQuestionView, AskResult, UnaskInput, UnaskResult, QuestionAnswerSchema, AnswerQuestionsInput, AnswerQuestionsResult, DismissQuestionsInput, DismissQuestionsResult, SettledQuestionView, ThreadSettledQuestionsResult, BURIED_ANSWERS_HEADER, ANSWER_FOLLOW_UP_MARKER, ANSWER_CONTINUATION_INDENT, indentAnswerContinuation, DISMISSED_ANSWER, MarkOwnDoneInput, MarkOwnDoneResult, ListOwnPrWatchesInput, OwnPrWatchesResult, ThreadTimerView, ThreadFence, LimitWindow, LimitPause, ProviderError, ThreadLinkView, UpsertOwnLinkInput, UpsertOwnLinkResult, DropOwnLinkInput, DropOwnLinkResult, LiveTool, ThreadView, BoardErrorItem, BoardSnapshot, QuotaWindow, ProviderQuota, QuotaSnapshot, ProviderAuth, AccountEmails, AuthSnapshot, AccountBackend, AccountLogoutInput, AccountLogoutResult, PermissionMode, LocalFileOpener, Settings, DispatchProviderPreferences, DispatchPreferences, DispatchProfileSnapshotShape, DispatchProfileSnapshot, SetDispatchPreferenceInput, DispatchInput, ADOPT_THREAD_MESSAGE_MAX_CHARS, AdoptThreadInput, AdoptThreadResult, AdoptSessionInput, FollowUpInput, DismissFailedFollowUpInput, DismissFailedFollowUpResult, UnqueueFollowUpInput, UnqueueFollowUpResult, DeliverQueuedNowInput, DeliverQueuedNowResult, CompactThreadInput, SetThreadSnoozeInput, SetThreadPinnedInput, SetThreadRecurringPromptInput, SetOwnThreadRecurringPromptInput, SetOwnThreadRecurringPromptResult, GetOwnThreadRecurringPromptInput, OwnThreadRecurringPromptResult, SetOwnThreadTimerInput, CancelOwnThreadTimerInput, ListOwnThreadTimersInput, OwnThreadTimersResult, ThreadActivityItem, ListOwnThreadActivityInput, OwnThreadActivityResult, SetOwnThreadTimerResult, CancelOwnThreadTimerResult, SetOwnThreadStopHookInput, SetOwnThreadHeartbeatInput, ThreadPluginReloadResult, RenameThreadInput, AiRenameThreadInput, AiRenameThreadResult, SetOwnThreadTitleInput, SetOwnThreadTitleResult, SetThreadPermissionInput, SetThreadPermissionResult, ThreadProfileOptionsInput, ThreadProfileOptionsResult, ThreadSkillSource, ThreadSkill, ThreadSkillsInput, ThreadSkillsResult, SetThreadProfileInput, SetThreadProfileResult, UpgradeThreadModelInput, UpgradeThreadModelResult, DISPATCH_TASK_BANNER, DISPATCH_TASK_BANNER_MARKER, GITHUB_DISPATCH_UI_BOUNDARY, WAKE_TIME_HEADER_TAIL, WAKE_TRAILERS, HUMAN_GAP_FLOOR_MS, HUMAN_GAP_NOTE_TAIL, WAKE_DELIVERY_TOKEN_TAIL, WAKE_DELIVERY_TOKEN_LINE, NOISE_PREFIXES, AGENT_MESSAGE_WRAPPER, GithubWakeItem, GithubWakeSteer, WAKE_SCOPE, WAKE_REVIEW_LEAD, WAKE_BACKLOG_TAIL, WAKE_REF, WAKE_SINGLE, WAKE_MULTI_HEAD, WAKE_ITEM, WAKE_MORE, PR_WATCH_FINISHED, PR_WATCH_CI_PASSED, PR_WATCH_CI_GATED, PR_WATCH_STATE, PR_WATCH_CI_FAILED, GithubStatus, GithubRefCard, GithubRefPreviewInput, GithubRefPreviewResult, GithubItem, GithubListInput, GithubListResult, GithubBatchInput, GithubBatchResult, BoardMeta, ServerEvent, TranscriptEdit, TranscriptTodo, TranscriptToolCall, TranscriptPart, TranscriptMessage, TranscriptPageCursor, EditedFile, TranscriptPage, TranscriptEarlierInput, SocketTranscriptSlug, SocketFilePath, SocketTranscriptClientMsg, SocketFileClientMsg, SocketClientMsg, ProjectCard, ProjectRailCounts, PROJECT_ICON_EXTENSIONS, PROJECT_ICON_MAX_BASE64_CHARS, DirectoryPickResult, ThreadLocation, FRIZZ_ROUTE_PREFIX, DEFAULT_PORT, threadIdentityName;
|
|
13990
14025
|
var init_src = __esm({
|
|
13991
14026
|
"packages/shared/src/index.ts"() {
|
|
13992
14027
|
"use strict";
|
|
@@ -14325,7 +14360,7 @@ var init_src = __esm({
|
|
|
14325
14360
|
questions: external_exports.array(AskQuestion)
|
|
14326
14361
|
});
|
|
14327
14362
|
AwaitingHint = external_exports.object({
|
|
14328
|
-
kind: external_exports.enum(["shell", "agent", "timer", "pr", "issue", "for", "title", "needs_input", "step"]),
|
|
14363
|
+
kind: external_exports.enum(["shell", "agent", "timer", "pr", "issue", "for", "title", "needs_input", "step", "question"]),
|
|
14329
14364
|
value: external_exports.string()
|
|
14330
14365
|
});
|
|
14331
14366
|
RETIRED_AWAITING_KINDS = ["watch", "pr-watch", "human", "ci", "session", "shell", "agent", "timer", "pr", "reason"];
|
|
@@ -14347,7 +14382,7 @@ var init_src = __esm({
|
|
|
14347
14382
|
"reason": "put it below the `---` as ordinary Markdown \u2014 the frontmatter is YAML now and takes no prose"
|
|
14348
14383
|
};
|
|
14349
14384
|
AWAITING_KEY_RE = /^([a-z][a-z_-]*):\s*(\S.*)?$/i;
|
|
14350
|
-
AWAITING_YAML_KEYS = /* @__PURE__ */ new Set(["shells", "agents", "timers", "prs", "issues", "for", "title", "steps", "needs_input", "needs-input"]);
|
|
14385
|
+
AWAITING_YAML_KEYS = /* @__PURE__ */ new Set(["shells", "agents", "timers", "prs", "issues", "questions", "for", "title", "steps", "needs_input", "needs-input"]);
|
|
14351
14386
|
AWAITING_SEQUENCE_KEYS = {
|
|
14352
14387
|
shells: "shell",
|
|
14353
14388
|
agents: "agent",
|
|
@@ -14362,6 +14397,7 @@ var init_src = __esm({
|
|
|
14362
14397
|
AWAITING_HINT_VALUE_MAX = 200;
|
|
14363
14398
|
AWAITING_STEPS_MAX = 12;
|
|
14364
14399
|
AWAITING_STEP_VALUE_MAX = 500;
|
|
14400
|
+
AWAITING_QUESTIONS_MAX = 24;
|
|
14365
14401
|
AWAITING_TITLE_MAX = 120;
|
|
14366
14402
|
AWAITING_ITEM_KINDS = ["shell", "agent", "timer", "pr", "issue"];
|
|
14367
14403
|
AWAITING_DURATION_RE = /^(\d{1,5})(s|m|h|d)$/;
|
|
@@ -24166,9 +24202,11 @@ function readTranscriptTail(path3, size, window) {
|
|
|
24166
24202
|
}
|
|
24167
24203
|
}
|
|
24168
24204
|
}
|
|
24169
|
-
async function probeShellsAlive(
|
|
24205
|
+
async function probeShellsAlive(shells, opts = {}) {
|
|
24170
24206
|
const platform3 = opts.platform ?? process.platform;
|
|
24171
24207
|
const exec = opts.exec ?? execFileAsync;
|
|
24208
|
+
const launches = shells.map((s) => typeof s === "string" ? { outputFile: s } : s);
|
|
24209
|
+
const outputFiles = launches.map((l) => l.outputFile);
|
|
24172
24210
|
const verdicts = /* @__PURE__ */ new Map();
|
|
24173
24211
|
if (platform3 === "win32") {
|
|
24174
24212
|
const present = outputFiles.filter((file) => {
|
|
@@ -24216,6 +24254,64 @@ async function probeShellsAlive(outputFiles, opts = {}) {
|
|
|
24216
24254
|
const held = /* @__PURE__ */ new Set();
|
|
24217
24255
|
for (const line of stdout.split("\n")) if (line.startsWith("n")) held.add(line.slice(1));
|
|
24218
24256
|
for (const f of live) verdicts.set(f.requested, held.has(f.real));
|
|
24257
|
+
const unheld = launches.filter((l) => verdicts.get(l.outputFile) === false && l.sessionId && l.launchedAtMs !== void 0);
|
|
24258
|
+
if (unheld.length === 0) return verdicts;
|
|
24259
|
+
const running = await findShellProcesses(unheld, { exec, nowMs: opts.nowMs ?? Date.now(), env: opts.env });
|
|
24260
|
+
for (const [file, alive] of running) if (alive !== void 0) verdicts.set(file, alive);
|
|
24261
|
+
return verdicts;
|
|
24262
|
+
}
|
|
24263
|
+
async function findShellProcesses(shells, opts = {}) {
|
|
24264
|
+
const exec = opts.exec ?? execFileAsync;
|
|
24265
|
+
const nowMs = opts.nowMs ?? Date.now();
|
|
24266
|
+
const verdicts = /* @__PURE__ */ new Map();
|
|
24267
|
+
const env = { ...opts.env ?? process.env, LC_ALL: "C" };
|
|
24268
|
+
const run3 = async (args) => {
|
|
24269
|
+
try {
|
|
24270
|
+
return (await exec("ps", args, { encoding: "utf8", timeout: 8e3, maxBuffer: 16 * 1024 * 1024, env })).stdout;
|
|
24271
|
+
} catch (err) {
|
|
24272
|
+
const e14 = err;
|
|
24273
|
+
return typeof e14.code === "number" && !e14.killed && e14.stdout ? e14.stdout : void 0;
|
|
24274
|
+
}
|
|
24275
|
+
};
|
|
24276
|
+
const table = await run3(["-ax", "-o", "pid=,ppid=,lstart="]);
|
|
24277
|
+
if (table === void 0) {
|
|
24278
|
+
for (const s of shells) verdicts.set(s.outputFile, void 0);
|
|
24279
|
+
return verdicts;
|
|
24280
|
+
}
|
|
24281
|
+
const forks = [];
|
|
24282
|
+
for (const line of table.split("\n")) {
|
|
24283
|
+
const m = /^\s*(\d+)\s+(\d+)\s+(\S.*?)\s*$/.exec(line);
|
|
24284
|
+
const at2 = m ? Date.parse(m[3]) : NaN;
|
|
24285
|
+
if (m && Number.isFinite(at2)) forks.push({ pid: Number(m[1]), ppid: Number(m[2]), at: at2 });
|
|
24286
|
+
}
|
|
24287
|
+
if (forks.length === 0) {
|
|
24288
|
+
for (const s of shells) verdicts.set(s.outputFile, void 0);
|
|
24289
|
+
return verdicts;
|
|
24290
|
+
}
|
|
24291
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
24292
|
+
for (const s of shells) {
|
|
24293
|
+
const from = Math.floor(s.launchedAtMs / 1e3) * 1e3 - 1e3;
|
|
24294
|
+
const to2 = (s.ackedAtMs ?? nowMs) + 1e3;
|
|
24295
|
+
candidates.set(s.outputFile, forks.filter((f) => f.at >= from && f.at <= to2));
|
|
24296
|
+
}
|
|
24297
|
+
const parents = [...new Set([...candidates.values()].flat().map((c) => c.ppid))];
|
|
24298
|
+
let argvOf = /* @__PURE__ */ new Map();
|
|
24299
|
+
if (parents.length > 0) {
|
|
24300
|
+
const listing = await run3(["-ww", "-o", "pid=,command=", "-p", parents.join(",")]);
|
|
24301
|
+
if (listing === void 0) {
|
|
24302
|
+
for (const s of shells) verdicts.set(s.outputFile, candidates.get(s.outputFile).length === 0 ? false : void 0);
|
|
24303
|
+
return verdicts;
|
|
24304
|
+
}
|
|
24305
|
+
argvOf = new Map(
|
|
24306
|
+
listing.split("\n").flatMap((line) => {
|
|
24307
|
+
const m = /^\s*(\d+)\s(.*)$/.exec(line);
|
|
24308
|
+
return m ? [[Number(m[1]), m[2]]] : [];
|
|
24309
|
+
})
|
|
24310
|
+
);
|
|
24311
|
+
}
|
|
24312
|
+
for (const s of shells) {
|
|
24313
|
+
verdicts.set(s.outputFile, candidates.get(s.outputFile).some((c) => argvOf.get(c.ppid)?.includes(s.sessionId) ?? false));
|
|
24314
|
+
}
|
|
24219
24315
|
return verdicts;
|
|
24220
24316
|
}
|
|
24221
24317
|
function windowsShellHolderCommand(paths, env = process.env) {
|
|
@@ -24623,6 +24719,7 @@ function trackLaunchResults(state, rec) {
|
|
|
24623
24719
|
}
|
|
24624
24720
|
if (!entry.outputFile) entry.outputFile = launchOutputFile(state, text2);
|
|
24625
24721
|
if (!entry.taskId) entry.taskId = launchTaskId(text2);
|
|
24722
|
+
if (entry.kind === "shell" && !entry.ackAt && typeof rec.timestamp === "string") entry.ackAt = rec.timestamp;
|
|
24626
24723
|
if (LAUNCH_ACK_RE.test(text2)) continue;
|
|
24627
24724
|
if (entry.kind === "shell") {
|
|
24628
24725
|
state.subAgents.delete(id2);
|
|
@@ -25341,7 +25438,7 @@ function createTailer(deps) {
|
|
|
25341
25438
|
for (const e14 of state.subAgents.values()) {
|
|
25342
25439
|
if (e14.kind !== "shell") continue;
|
|
25343
25440
|
const lastActivityAt = entryLastActivity(state, e14);
|
|
25344
|
-
const shellState = shellIsGone(e14) ? "stale" : "running";
|
|
25441
|
+
const shellState = shellIsGone(e14, state.sessionId) ? "stale" : "running";
|
|
25345
25442
|
out.push({ label: e14.label, startedAt: e14.startedAt, state: shellState, id: e14.toolUseId, ...e14.taskId ? { stoppable: true, taskId: e14.taskId } : {}, ...lastActivityAt ? { lastActivityAt } : {}, ...e14.monitor ? { outputUnavailable: true } : {} });
|
|
25346
25443
|
}
|
|
25347
25444
|
return out;
|
|
@@ -25588,7 +25685,7 @@ ${ask}`;
|
|
|
25588
25685
|
return void 0;
|
|
25589
25686
|
}
|
|
25590
25687
|
const shellAliveCache = /* @__PURE__ */ new Map();
|
|
25591
|
-
const shellProbeWanted = /* @__PURE__ */ new
|
|
25688
|
+
const shellProbeWanted = /* @__PURE__ */ new Map();
|
|
25592
25689
|
let shellProbeInFlight = false;
|
|
25593
25690
|
let shellProbeArmed;
|
|
25594
25691
|
function armShellProbeFlush() {
|
|
@@ -25601,7 +25698,7 @@ ${ask}`;
|
|
|
25601
25698
|
}
|
|
25602
25699
|
function flushShellProbes() {
|
|
25603
25700
|
if (shellProbeInFlight || shellProbeWanted.size === 0) return;
|
|
25604
|
-
const batch = [...shellProbeWanted];
|
|
25701
|
+
const batch = [...shellProbeWanted.values()];
|
|
25605
25702
|
shellProbeWanted.clear();
|
|
25606
25703
|
shellProbeInFlight = true;
|
|
25607
25704
|
void probeShellsAlive(batch).then((verdicts) => {
|
|
@@ -25615,19 +25712,21 @@ ${ask}`;
|
|
|
25615
25712
|
shellProbeInFlight = false;
|
|
25616
25713
|
});
|
|
25617
25714
|
}
|
|
25618
|
-
function shellIsGone(e14) {
|
|
25715
|
+
function shellIsGone(e14, sessionId) {
|
|
25619
25716
|
if (!e14.outputFile) return false;
|
|
25620
25717
|
const started = Date.parse(e14.startedAt);
|
|
25621
25718
|
if (!Number.isFinite(started) || now() - started < SHELL_PROBE_GRACE_MS) return false;
|
|
25622
25719
|
const cached2 = shellAliveCache.get(e14.outputFile);
|
|
25623
25720
|
if (cached2 && (cached2.alive === false || now() - cached2.at < SHELL_PROBE_TTL_MS)) return !cached2.alive;
|
|
25721
|
+
const acked = e14.ackAt ? Date.parse(e14.ackAt) : NaN;
|
|
25722
|
+
const launch = { outputFile: e14.outputFile, sessionId, launchedAtMs: started, ...Number.isFinite(acked) ? { ackedAtMs: acked } : {} };
|
|
25624
25723
|
if (deps.shellAlive) {
|
|
25625
|
-
const alive = deps.shellAlive(e14.outputFile);
|
|
25724
|
+
const alive = deps.shellAlive(e14.outputFile, launch);
|
|
25626
25725
|
if (alive === void 0) return false;
|
|
25627
25726
|
shellAliveCache.set(e14.outputFile, { at: now(), alive });
|
|
25628
25727
|
return !alive;
|
|
25629
25728
|
}
|
|
25630
|
-
shellProbeWanted.
|
|
25729
|
+
shellProbeWanted.set(e14.outputFile, launch);
|
|
25631
25730
|
armShellProbeFlush();
|
|
25632
25731
|
return false;
|
|
25633
25732
|
}
|
|
@@ -36533,7 +36632,7 @@ function readAwaitingPark(hints) {
|
|
|
36533
36632
|
forMs = parseAwaitingDurationRaw(value);
|
|
36534
36633
|
}
|
|
36535
36634
|
}
|
|
36536
|
-
return { items, forMs, steps: awaitingSteps(hints) };
|
|
36635
|
+
return { items, forMs, steps: awaitingSteps(hints), questions: awaitingQuestions(hints) };
|
|
36537
36636
|
}
|
|
36538
36637
|
function liveActivityOf(tele, registeredPrWatches, armedTimerIds, registeredIssueWatches = /* @__PURE__ */ new Set()) {
|
|
36539
36638
|
const shells = /* @__PURE__ */ new Set();
|
|
@@ -36563,11 +36662,14 @@ function liveKey(i) {
|
|
|
36563
36662
|
return i.value;
|
|
36564
36663
|
}
|
|
36565
36664
|
function parkIsHonoured(park, live) {
|
|
36566
|
-
const onHuman = park
|
|
36665
|
+
const onHuman = parkOnHuman(park);
|
|
36567
36666
|
if (park.items.length === 0 && !onHuman) return false;
|
|
36568
36667
|
if (park.forMs === null && !onHuman) return false;
|
|
36569
36668
|
return unaccountedItems(park.items, live).length === 0;
|
|
36570
36669
|
}
|
|
36670
|
+
function parkOnHuman(park) {
|
|
36671
|
+
return park.steps.length > 0 || park.questions.length > 0;
|
|
36672
|
+
}
|
|
36571
36673
|
function needsInputParkHolds(hints, live, fenceAtMs, nowMs) {
|
|
36572
36674
|
if (awaitingNeedsInput(hints) !== false) return false;
|
|
36573
36675
|
const park = readAwaitingPark(hints);
|
|
@@ -36576,7 +36678,7 @@ function needsInputParkHolds(hints, live, fenceAtMs, nowMs) {
|
|
|
36576
36678
|
return expiresAt !== null && nowMs < expiresAt;
|
|
36577
36679
|
}
|
|
36578
36680
|
function parkForMaxMs(park) {
|
|
36579
|
-
if (park.items.length === 0) return park
|
|
36681
|
+
if (park.items.length === 0) return parkOnHuman(park) ? PR_WATCH_FOR_MAX_MS : AWAITING_FOR_MAX_MS;
|
|
36580
36682
|
return park.items.every((i) => i.kind === "pr" || i.kind === "issue") ? PR_WATCH_FOR_MAX_MS : AWAITING_FOR_MAX_MS;
|
|
36581
36683
|
}
|
|
36582
36684
|
function parkExpiresAt(park, fenceAtMs) {
|
|
@@ -36905,17 +37007,17 @@ bare rest, and it lands in the human's queue. **A QUESTION HAS NO FENCE ANY MORE
|
|
|
36905
37007
|
2026-09-11): the only way to ask is \`mcp__frizz__ask\`, and a question written into a fence's body is
|
|
36906
37008
|
plain prose \u2014 no card, no answer, and no sign-off.
|
|
36907
37009
|
|
|
36908
|
-
**
|
|
36909
|
-
|
|
36910
|
-
|
|
36911
|
-
|
|
36912
|
-
|
|
36913
|
-
|
|
36914
|
-
|
|
36915
|
-
|
|
36916
|
-
|
|
36917
|
-
|
|
36918
|
-
|
|
37010
|
+
**A QUESTION YOU ASK IS THAT REST'S SIGN-OFF \u2014 REST NORMALLY.** Frizz does not bump you for a missing
|
|
37011
|
+
fence at the rest that asked. When the work that does not depend on the answer runs out, write your
|
|
37012
|
+
handoff prose and STOP. Nothing you write makes the card appear or hides it \u2014 frizz draws every open
|
|
37013
|
+
question at the rest it was asked, until it is answered or withdrawn; your write-up carries the
|
|
37014
|
+
reasoning around the ask, never a copy of it (see Questions for the human).
|
|
37015
|
+
**AT EVERY LATER REST, SAY WHERE EACH OLD QUESTION STANDS.** A question still open from an EARLIER rest
|
|
37016
|
+
is not your new rest's sign-off, and frizz does NOT redraw its card under your new handoff \u2014 it stays
|
|
37017
|
+
where you asked it. So a later rest either NAMES each one you still need under \`questions:\` in an
|
|
37018
|
+
\` \`\`\`awaiting \` fence \u2014 its card is then drawn at this rest, under your fence \u2014 or WITHDRAWS it with
|
|
37019
|
+
\`unask\`. A rest that does neither is bumped, and so is any \` \`\`\`awaiting \` fence that leaves an open
|
|
37020
|
+
question out, at whichever rest it lands.
|
|
36919
37021
|
|
|
36920
37022
|
Use at most ONE fenced signal block, at the very END (a question's PLACEMENT marker is not a signal
|
|
36921
37023
|
block \u2014 see Questions for the human). The fence language is the state; the body is the card the human
|
|
@@ -37045,7 +37147,7 @@ exactly ONE of them.
|
|
|
37045
37147
|
or with anything but \`true\`/\`false\` \u2014 is not a park: the thread queues and frizz tells you which
|
|
37046
37148
|
line is missing. And a \`false\` holds only while every name is live and \`for:\` has not run out, so a
|
|
37047
37149
|
wrong \`false\` cannot hide the thread.
|
|
37048
|
-
- **THE FRONTMATTER IS YAML. THE BODY IS MARKDOWN.**
|
|
37150
|
+
- **THE FRONTMATTER IS YAML. THE BODY IS MARKDOWN.** The PLURAL keys take LISTS (either list form;
|
|
37049
37151
|
a single item may be written bare), plus the scalars \`for:\`, \`needs_input:\` and \`title:\`. **NO PROSE ABOVE THE
|
|
37050
37152
|
\`---\`, EVER** \u2014 a colon or a \` #\` inside a sentence breaks the parse. (The \`title:\` and \`steps:\`
|
|
37051
37153
|
values are the exceptions: frizz reads them verbatim, so code, \`#391\` and a colon are safe there.) There is no \`reason:\` key any more;
|
|
@@ -37102,6 +37204,12 @@ exactly ONE of them.
|
|
|
37102
37204
|
\`Done\`, the same as anything they type; anything else they need to tell you \u2014 a step that failed,
|
|
37103
37205
|
the account they used \u2014 comes as a message of their own. An act is not a decision: never ask
|
|
37104
37206
|
WHETHER they will do it, and never call \`done\` while it is still owed.
|
|
37207
|
+
- \`questions:\` \u2014 your registered questions you are STILL waiting on, by id: \`questions: [qst_ab12cd34]\`.
|
|
37208
|
+
A fence beside open questions names EVERY one of them \u2014 withdraw any you no longer need with
|
|
37209
|
+
\`mcp__frizz__unask\` first \u2014 or frizz refuses the park and lists what it left out. Each named card is
|
|
37210
|
+
drawn at THIS rest, under your fence; to set it inside your prose instead, add its placement marker
|
|
37211
|
+
(see Questions for the human). Like \`steps:\`, questions name the human as the wait: no other name
|
|
37212
|
+
and no \`for:\` needed, and the thread stays in their queue.
|
|
37105
37213
|
- **REGISTERING IS NOT PARKING, AND PARKING IS NOT REGISTERING.** Your shells, sub-agents, timers
|
|
37106
37214
|
and PR watchers are watched AUTOMATICALLY, fence or no fence \u2014 frizz wakes you when one finishes,
|
|
37107
37215
|
every time. The fence only declares that you have STOPPED, names which of them you stopped for,
|
|
@@ -37111,9 +37219,10 @@ exactly ONE of them.
|
|
|
37111
37219
|
**A FENCE THAT NAMES NOTHING IS NOT A PARK** \u2014 \`for:\` describes a wait, it is not one \u2014 so
|
|
37112
37220
|
"waiting on the checks" plus a duration just sits in the queue: REGISTER the PR and name it, and
|
|
37113
37221
|
if nothing is actually running, end with \`\`\`done or register a question with \`mcp__frizz__ask\`.
|
|
37114
|
-
(\`steps:\` count: they name the human.)
|
|
37115
|
-
- **WAITING ON A PERSON TO DECIDE IS A REGISTERED QUESTION** \u2014 \`mcp__frizz__ask
|
|
37116
|
-
|
|
37222
|
+
(\`steps:\` and \`questions:\` count: they name the human.)
|
|
37223
|
+
- **WAITING ON A PERSON TO DECIDE IS A REGISTERED QUESTION** \u2014 \`mcp__frizz__ask\`, and at each later
|
|
37224
|
+
rest \`questions:\` names the ones you still need. **WAITING ON ONE TO ACT IS \`steps:\`.** There is
|
|
37225
|
+
no human gate, no prose park, and no question fence.
|
|
37117
37226
|
- **CI, RELEASES, DEPLOYS AND MERGE PROGRESSION ARE AUTOMATABLE \u2014 never \` \`\`\`awaiting \` them
|
|
37118
37227
|
BLINDLY.** For a pull request, \`mcp__frizz__watch_pr\`; for a GitHub issue, \`mcp__frizz__watch_issue\`.
|
|
37119
37228
|
For anything else stay ACTIVE: dispatch a sub-agent to own the wait (its return re-invokes you), or
|
|
@@ -37309,17 +37418,20 @@ paragraph that sets it up, before the one that says what happens either way:
|
|
|
37309
37418
|
Frizz draws the registered card THERE instead of at the tail. Nothing goes in the body: the card comes
|
|
37310
37419
|
from the ROW, so nothing about the question is ever guessed from prose, and a marker naming no open
|
|
37311
37420
|
question of yours draws nothing. One marker per question. Placement is OPTIONAL \u2014 a question with no
|
|
37312
|
-
marker renders at the tail of the rest, and a handoff that writes no marker loses nothing.
|
|
37313
|
-
|
|
37314
|
-
|
|
37315
|
-
|
|
37421
|
+
marker renders at the tail of the rest, and a handoff that writes no marker loses nothing. A marker in
|
|
37422
|
+
a LATER handoff moves the card into it; name the question under \`questions:\` in that rest's fence too,
|
|
37423
|
+
since the marker only places it. Every answer is sent together, whichever card's Send the human
|
|
37424
|
+
presses. (Placement was retired 2026-08-30 and restored 2026-09-11 with the free-form fence's
|
|
37425
|
+
retirement: the marker references a row, which is exactly what a fence with a body never did.)
|
|
37316
37426
|
|
|
37317
37427
|
A question you no longer want answered is not one you leave out of the write-up \u2014 it is one you
|
|
37318
37428
|
\`unask\`, which is the difference between deciding something yourself and quietly hoping nobody
|
|
37319
37429
|
answers. Questions asked in one \`ask\` call render together and send as one batch.
|
|
37320
37430
|
|
|
37321
|
-
**AN OPEN REGISTERED QUESTION IS THE HANDBACK** \u2014 emit no \`done
|
|
37322
|
-
|
|
37431
|
+
**AN OPEN REGISTERED QUESTION IS THE HANDBACK** \u2014 at the rest that asks it, emit no \`done\` fence
|
|
37432
|
+
beside it and no question fence at all; an \`awaiting\` fence beside it is only for work that is ALSO
|
|
37433
|
+
running, and it names the question under \`questions:\`. The answer arrives as your next user message,
|
|
37434
|
+
as its own wake.`;
|
|
37323
37435
|
STOP_CRITERION = `## The stop criterion
|
|
37324
37436
|
|
|
37325
37437
|
**COMING TO REST IS A STOP, and it needs the same justification as a question.** The far more common
|
|
@@ -37497,8 +37609,9 @@ answering \`needs_input: false\` keeps a rested thread out of the queue \u2014 a
|
|
|
37497
37609
|
\`mcp__frizz__watch_pr\`; for a GitHub issue, \`mcp__frizz__watch_issue\`; for anything else dispatch a
|
|
37498
37610
|
SUB-AGENT to own the wait. It runs the watcher
|
|
37499
37611
|
to completion in its own foreground and returns the verdict; you stay Active and its return
|
|
37500
|
-
re-invokes you.
|
|
37501
|
-
|
|
37612
|
+
re-invokes you. A Bash call that names no \`timeout\` moves to the background after a minute, so the
|
|
37613
|
+
watcher names one sized to the wait (up to 24h) and loops until its terminal condition. A helper must
|
|
37614
|
+
not hand back while its own watcher is still live.
|
|
37502
37615
|
- **Working alongside a process you launched** (dev server, log tail) \u2192 \`Bash\` with
|
|
37503
37616
|
\`run_in_background: true\`. Never put shell job control (\`&\`, \`nohup \u2026 &\`, \`disown\`) inside the
|
|
37504
37617
|
command to imitate the native flag: frizz's hook rejects an escaping job, because the process could
|
|
@@ -42275,7 +42388,10 @@ function createScheduler(deps) {
|
|
|
42275
42388
|
if (tele.apiFault) continue;
|
|
42276
42389
|
const needsInput = needsInputRequired(row.spawned_at);
|
|
42277
42390
|
const questionRows = deps.storage.listThreadQuestions(row.slug);
|
|
42278
|
-
|
|
42391
|
+
const openRows = questionRows.filter((q10) => q10.state === "open");
|
|
42392
|
+
const restFrom = tele.lastUserAt ? Date.parse(tele.lastUserAt) : Number.NEGATIVE_INFINITY;
|
|
42393
|
+
const carried = openRows.filter((q10) => q10.asked_at <= restFrom);
|
|
42394
|
+
if (tele.lastFence || tele.pendingQuestion || registeredDoneFence(deps.storage.getThreadDone(row.slug), tele.lastUserAt) !== void 0 || openRows.length > 0 && carried.length === 0 || answersInFlight(questionRows, tele.lastUserAt, row.recurring_on_rest === 1 && Boolean(row.recurring_prompt?.trim())) !== void 0 || !needsInput && deps.storage.listThreadWatches(row.slug, { armedOnly: true }).length > 0) {
|
|
42279
42395
|
if ((row.signoff_nudges ?? 0) > 0) deps.storage.resetSignoffNudges(row.slug);
|
|
42280
42396
|
continue;
|
|
42281
42397
|
}
|
|
@@ -42285,27 +42401,24 @@ function createScheduler(deps) {
|
|
|
42285
42401
|
const fenceId = signoffFenceId(spokeAt);
|
|
42286
42402
|
const deliveryId = wakeDeliveryId(row.slug, row.session_id, fenceId);
|
|
42287
42403
|
if (outbox.get(deliveryId)) continue;
|
|
42404
|
+
const ops = {
|
|
42405
|
+
shells: (tele.bgShells ?? []).filter((sh2) => sh2.state === "running").map((sh2) => ({ id: sh2.taskId ?? sh2.id, label: sh2.label })),
|
|
42406
|
+
subAgents: (tele.subAgents ?? []).filter((a) => a.state === "running").map((a) => ({ id: a.taskId ?? a.id, label: a.label })),
|
|
42407
|
+
// The other two registries, so the nudge lists EVERY kind an awaiting fence can name rather
|
|
42408
|
+
// than the two the fold happens to know about — a worker told about half its work writes half
|
|
42409
|
+
// a fence, and the half it left out is not what gets it bumped.
|
|
42410
|
+
timers: deps.storage.listThreadTimers(row.slug, { armedOnly: true }).map((t) => ({ id: t.id, label: t.prompt.trim().replace(/\s+/g, " ").slice(0, 80) })),
|
|
42411
|
+
prs: deps.storage.listPrWatches(row.slug, { armedOnly: true }).filter((w) => w.kind !== "issue").map((w) => ({ id: `${w.owner}/${w.repo}#${w.number}`, label: `${w.owner}/${w.repo}#${w.number}` })),
|
|
42412
|
+
issues: deps.storage.listPrWatches(row.slug, { armedOnly: true }).filter((w) => w.kind === "issue").map((w) => ({ id: `${w.owner}/${w.repo}#${w.number}`, label: `${w.owner}/${w.repo}#${w.number}` }))
|
|
42413
|
+
};
|
|
42288
42414
|
const item = outbox.enqueue({
|
|
42289
42415
|
id: deliveryId,
|
|
42290
42416
|
slug: row.slug,
|
|
42291
42417
|
sessionId: row.session_id,
|
|
42292
42418
|
fenceId,
|
|
42293
42419
|
hintKey: SIGNOFF_HINT_KEY,
|
|
42294
|
-
|
|
42295
|
-
|
|
42296
|
-
// the handle the runtime actually showed the worker — because that is the string it will
|
|
42297
|
-
// naturally reach for, and the one the fence's own integrity check matches on.
|
|
42298
|
-
message: withClock(signoffNudgeMessage({
|
|
42299
|
-
shells: (tele.bgShells ?? []).filter((sh2) => sh2.state === "running").map((sh2) => ({ id: sh2.taskId ?? sh2.id, label: sh2.label })),
|
|
42300
|
-
subAgents: (tele.subAgents ?? []).filter((a) => a.state === "running").map((a) => ({ id: a.taskId ?? a.id, label: a.label })),
|
|
42301
|
-
// The other two registries, so the nudge lists EVERY kind an awaiting fence can name rather
|
|
42302
|
-
// than the two the fold happens to know about — a worker told about half its work writes half
|
|
42303
|
-
// a fence, and the half it left out is not what gets it bumped.
|
|
42304
|
-
timers: deps.storage.listThreadTimers(row.slug, { armedOnly: true }).map((t) => ({ id: t.id, label: t.prompt.trim().replace(/\s+/g, " ").slice(0, 80) })),
|
|
42305
|
-
prs: deps.storage.listPrWatches(row.slug, { armedOnly: true }).filter((w) => w.kind !== "issue").map((w) => ({ id: `${w.owner}/${w.repo}#${w.number}`, label: `${w.owner}/${w.repo}#${w.number}` })),
|
|
42306
|
-
issues: deps.storage.listPrWatches(row.slug, { armedOnly: true }).filter((w) => w.kind === "issue").map((w) => ({ id: `${w.owner}/${w.repo}#${w.number}`, label: `${w.owner}/${w.repo}#${w.number}` }))
|
|
42307
|
-
}, needsInput), spokeAt),
|
|
42308
|
-
reason: "rested without signing off"
|
|
42420
|
+
message: withClock(carried.length > 0 ? carriedQuestionsNudgeMessage(carried.map((q10) => ({ id: q10.id, question: questionLine(q10.spec) })), ops, needsInput) : signoffNudgeMessage(ops, needsInput), spokeAt),
|
|
42421
|
+
reason: carried.length > 0 ? `rested with ${carried.length} earlier question(s) neither named nor withdrawn` : "rested without signing off"
|
|
42309
42422
|
}, nowMs).delivery;
|
|
42310
42423
|
log3(`waker: queued ${row.slug} \u2014 ${item.reason}`);
|
|
42311
42424
|
checkpoint("after-enqueue", item);
|
|
@@ -42330,23 +42443,33 @@ ${wakeTimeHeader(now(), spokeAt)}`;
|
|
|
42330
42443
|
if (!spokeAt) continue;
|
|
42331
42444
|
if (tele.lastUserAt && Date.parse(tele.lastUserAt) >= Date.parse(spokeAt)) continue;
|
|
42332
42445
|
if (tele.authFault || tele.apiFault) continue;
|
|
42333
|
-
const
|
|
42334
|
-
|
|
42446
|
+
const park = readAwaitingPark(tele.lastFence.hints);
|
|
42447
|
+
const questionRows = deps.storage.listThreadQuestions(row.slug);
|
|
42448
|
+
const openQuestions = questionRows.filter((q10) => q10.state === "open");
|
|
42449
|
+
const named = new Set(park.questions);
|
|
42450
|
+
const unnamed = openQuestions.filter((q10) => !named.has(q10.id.toLowerCase()));
|
|
42451
|
+
const spokeMs = Date.parse(spokeAt);
|
|
42452
|
+
const notOpen = park.questions.filter((id2) => {
|
|
42453
|
+
const q10 = questionRows.find((r) => r.id.toLowerCase() === id2);
|
|
42454
|
+
if (q10?.state === "open") return false;
|
|
42455
|
+
return !q10 || q10.settled_at === null || q10.settled_at <= spokeMs;
|
|
42456
|
+
});
|
|
42457
|
+
if (unnamed.length > 0 || notOpen.length > 0) {
|
|
42335
42458
|
if ((row.park_bumps ?? 0) >= PARK_BUMP_MAX) continue;
|
|
42336
42459
|
const fenceId2 = parkFenceId("question", spokeAt);
|
|
42337
42460
|
const deliveryId2 = wakeDeliveryId(row.slug, row.session_id, fenceId2);
|
|
42338
42461
|
if (outbox.get(deliveryId2)) continue;
|
|
42339
|
-
const one2 =
|
|
42462
|
+
const one2 = unnamed.length === 1;
|
|
42463
|
+
const head2 = unnamed.length > 0 ? `${one2 ? "a question of yours was" : `${unnamed.length} questions of yours were`} still OPEN and it does not name ${one2 ? "it" : "them"}, so frizz refused the park.` : `it names ${notOpen.length === 1 ? "a question that is" : "questions that are"} not open, so frizz refused the park.`;
|
|
42340
42464
|
const message2 = [
|
|
42341
|
-
`${PARK_CORRECTION_QUESTION_LEAD}${
|
|
42342
|
-
"",
|
|
42343
|
-
...
|
|
42465
|
+
`${PARK_CORRECTION_QUESTION_LEAD}${head2}`,
|
|
42466
|
+
...unnamed.length > 0 ? ["", "Open, and not named under `questions:`:", ...unnamed.map((q10) => `- \`${q10.id}\` \u2014 ${questionLine(q10.spec)}`)] : [],
|
|
42467
|
+
...notOpen.length > 0 ? ["", "Named, but not an open question of yours:", ...notOpen.map((id2) => `- \`${id2}\``)] : [],
|
|
42344
42468
|
"",
|
|
42345
|
-
"
|
|
42346
|
-
"
|
|
42347
|
-
"
|
|
42348
|
-
"
|
|
42349
|
-
"answered is one you withdraw with `mcp__frizz__unask` \u2014 only then can a park take."
|
|
42469
|
+
"A fence beside open questions names EVERY one you still need answered \u2014 `questions: [qst_\u2026]` \u2014",
|
|
42470
|
+
"and you withdraw the rest with `mcp__frizz__unask`. A named question's card is drawn at this rest;",
|
|
42471
|
+
"an unnamed one stays where you asked it. Fix the list (or unask), re-send the fence, and the park",
|
|
42472
|
+
"takes. A fence on questions needs no other name and no `for:`."
|
|
42350
42473
|
].join("\n");
|
|
42351
42474
|
const item2 = outbox.enqueue({
|
|
42352
42475
|
id: deliveryId2,
|
|
@@ -42357,14 +42480,13 @@ ${wakeTimeHeader(now(), spokeAt)}`;
|
|
|
42357
42480
|
message: `${message2}
|
|
42358
42481
|
|
|
42359
42482
|
${wakeTimeHeader(nowMs, spokeAt)}`,
|
|
42360
|
-
reason: `awaiting fence
|
|
42483
|
+
reason: `awaiting fence leaves ${unnamed.length} open question(s) unnamed${notOpen.length ? `, names ${notOpen.length} that are not open` : ""}`
|
|
42361
42484
|
}, nowMs).delivery;
|
|
42362
42485
|
deps.storage.countParkBump(row.slug, fenceId2);
|
|
42363
42486
|
log3(`waker: queued ${row.slug} \u2014 ${item2.reason}`);
|
|
42364
42487
|
checkpoint("after-enqueue", item2);
|
|
42365
42488
|
continue;
|
|
42366
42489
|
}
|
|
42367
|
-
const park = readAwaitingPark(tele.lastFence.hints);
|
|
42368
42490
|
const live = liveActivityOf(
|
|
42369
42491
|
tele,
|
|
42370
42492
|
registeredPrWatchesOf(deps.storage, row.slug),
|
|
@@ -42374,7 +42496,7 @@ ${wakeTimeHeader(nowMs, spokeAt)}`,
|
|
|
42374
42496
|
const dead = unaccountedItems(park.items, live);
|
|
42375
42497
|
const expiresAt = parkExpiresAt(park, Date.parse(spokeAt));
|
|
42376
42498
|
const expired = expiresAt !== null && nowMs >= expiresAt;
|
|
42377
|
-
const nameless = park.items.length === 0 && park
|
|
42499
|
+
const nameless = park.items.length === 0 && !parkOnHuman(park);
|
|
42378
42500
|
const unanswered2 = needsInputRequired(row.spawned_at) && awaitingNeedsInput(tele.lastFence.hints) === null;
|
|
42379
42501
|
if (parkIsHonoured(park, live) && !unanswered2 && (row.park_bumps ?? 0) > 0) deps.storage.resetParkBumps(row.slug);
|
|
42380
42502
|
if (dead.length === 0 && !expired && !nameless) {
|
|
@@ -42420,18 +42542,26 @@ ${wakeTimeHeader(nowMs, spokeAt)}`,
|
|
|
42420
42542
|
if (a.state !== "rested") continue;
|
|
42421
42543
|
for (const h10 of [a.taskId, a.id, a.label]) if (h10) finishedHandles.add(h10);
|
|
42422
42544
|
}
|
|
42545
|
+
const staleShellHandles = /* @__PURE__ */ new Set();
|
|
42546
|
+
for (const sh2 of tele.bgShells ?? []) {
|
|
42547
|
+
if (sh2.state !== "stale") continue;
|
|
42548
|
+
for (const h10 of [sh2.taskId, sh2.id, sh2.label]) if (h10) staleShellHandles.add(h10);
|
|
42549
|
+
}
|
|
42423
42550
|
const firedTimers = new Set(
|
|
42424
42551
|
deps.storage.listThreadTimers(row.slug).filter((t) => t.state === "fired").map((t) => t.id)
|
|
42425
42552
|
);
|
|
42426
42553
|
const finishedItem = (i) => finishedHandles.has(i.value) || i.kind === "timer" && firedTimers.has(i.value);
|
|
42427
42554
|
const status = park.items.map((i) => {
|
|
42428
42555
|
const gone = dead.some((d) => d.kind === i.kind && d.value === i.value);
|
|
42429
|
-
const note = !gone ? "still running" : i.kind === "timer" && firedTimers.has(i.value) ? "already FIRED \u2014 its wake was delivered; there is nothing left to wait on" : finishedItem(i) ? "FINISHED \u2014 its result is waiting for you" : i.kind === "pr" ? "NOT REGISTERED \u2014 register it with `mcp__frizz__watch_pr` first, then name it here" : i.kind === "issue" ? "NOT REGISTERED \u2014 register it with `mcp__frizz__watch_issue` first, then name it here" : "NOT RUNNING (nothing by that name)";
|
|
42556
|
+
const note = !gone ? "still running" : i.kind === "timer" && firedTimers.has(i.value) ? "already FIRED \u2014 its wake was delivered; there is nothing left to wait on" : finishedItem(i) ? "FINISHED \u2014 its result is waiting for you" : i.kind === "shell" && staleShellHandles.has(i.value) ? "GONE WITHOUT A COMPLETION NOTICE \u2014 frizz knows this shell, but nothing holds its output file and no process it could be is still running; read its output to see how it ended" : i.kind === "pr" ? "NOT REGISTERED \u2014 register it with `mcp__frizz__watch_pr` first, then name it here" : i.kind === "issue" ? "NOT REGISTERED \u2014 register it with `mcp__frizz__watch_issue` first, then name it here" : "NOT RUNNING (nothing by that name)";
|
|
42430
42557
|
return `- \`${AWAITING_KEY_OF[i.kind]}: [${i.value}]\` \u2014 ${note}`;
|
|
42431
42558
|
});
|
|
42432
42559
|
if (park.steps.length > 0) {
|
|
42433
42560
|
status.push(`- \`steps:\` (${park.steps.length}) \u2014 the human has not replied; check whether they were done anyway before you post them again`);
|
|
42434
42561
|
}
|
|
42562
|
+
if (park.questions.length > 0) {
|
|
42563
|
+
status.push(`- \`questions:\` (${park.questions.length}) \u2014 not answered yet; name the ones you still need in your next fence and withdraw the rest`);
|
|
42564
|
+
}
|
|
42435
42565
|
const allFinished = dead.length > 0 && dead.every(finishedItem);
|
|
42436
42566
|
const retired = retiredAwaitingKindsIn(tele.lastFence.body ?? "");
|
|
42437
42567
|
const head = retired.length > 0 ? [
|
|
@@ -75367,6 +75497,16 @@ function claudeSidechainInstruction(text2) {
|
|
|
75367
75497
|
if (wrapperStart < 0 || wrapperEnd < 0) return void 0;
|
|
75368
75498
|
return parseAgentMessage(trimmed.slice(wrapperStart, wrapperEnd + "</agent-message>".length))?.body.trim() || void 0;
|
|
75369
75499
|
}
|
|
75500
|
+
function blockedInCallSince(messages) {
|
|
75501
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
75502
|
+
const m = messages[i];
|
|
75503
|
+
if (m.queued || m.kind === "event") continue;
|
|
75504
|
+
if (m.role !== "assistant" || !m.tools.some((t) => t.status === "pending" && !t.backgroundState)) return void 0;
|
|
75505
|
+
const at2 = m.at === void 0 ? NaN : Date.parse(m.at);
|
|
75506
|
+
return Number.isFinite(at2) ? at2 : void 0;
|
|
75507
|
+
}
|
|
75508
|
+
return void 0;
|
|
75509
|
+
}
|
|
75370
75510
|
function retireStaleQueuedBubbles(messages, nowMs = Date.now()) {
|
|
75371
75511
|
let stale = false;
|
|
75372
75512
|
for (const m of messages) {
|
|
@@ -75378,10 +75518,13 @@ function retireStaleQueuedBubbles(messages, nowMs = Date.now()) {
|
|
|
75378
75518
|
}
|
|
75379
75519
|
}
|
|
75380
75520
|
if (!stale) return messages;
|
|
75521
|
+
const blockedSince = blockedInCallSince(messages);
|
|
75381
75522
|
return messages.map((m) => {
|
|
75382
75523
|
if (!m.queued) return m;
|
|
75383
75524
|
const at2 = m.at === void 0 ? NaN : Date.parse(m.at);
|
|
75384
|
-
|
|
75525
|
+
if (!(Number.isFinite(at2) && nowMs - at2 > QUEUED_STALE_MS)) return m;
|
|
75526
|
+
if (blockedSince !== void 0 && blockedSince <= at2 && nowMs - at2 <= QUEUED_BLOCKED_CEILING_MS) return m;
|
|
75527
|
+
return { ...m, queued: false };
|
|
75385
75528
|
});
|
|
75386
75529
|
}
|
|
75387
75530
|
function createTranscriptFold(identityPrefix = "claude") {
|
|
@@ -77752,11 +77895,12 @@ function readTranscriptFile(absPath) {
|
|
|
77752
77895
|
return [];
|
|
77753
77896
|
}
|
|
77754
77897
|
}
|
|
77755
|
-
var MAX_MESSAGES, LATEST_WINDOW_ASK_REACH_ITEMS, LATEST_WINDOW_ASK_REACH_BYTES, LATEST_WINDOW_MAX_BYTES, REST_LABEL, LEGACY_TASK_MARKER, LEGACY_BANNER_PREAMBLE, COMMAND_NAME_RE, COMMAND_ARGS_RE, LOCAL_COMMAND_RECEIPT2, PEER_SESSION_PREAMBLE, CLAUDE_COORDINATOR_INSTRUCTION_PREFIX, CLAUDE_COORDINATOR_INSTRUCTION_SUFFIX, CLAUDE_PEER_INSTRUCTION_PREFIX, QUEUED_STALE_MS, EDIT_CAP, TRUNC_MARKER, AGENT_PROMPT_CAP, SEND_BODY_CAP, COMMAND_CAP, TOOL_INPUT_CAP, READ_LINE_CAP, READ_BYTE_CAP, IMAGE_MEDIA_EXT, SCREENSHOT_CACHE_DIR, SCREENSHOT_CACHE_MAX, SCREENSHOT_MAX_BASE64, screenshotTmpSeq, SENT_IMAGE_MAX_BYTES, SENT_FILES_MAX, TODO_ROWS_MAX, TODO_TEXT_CAP, TRANSCRIPT_CACHE_CAP, transcriptCache, PARSE_VERIFY_SAMPLE, TRANSCRIPT_DECODE_WINDOW, FOREIGN_SESSION_ID_RE, MAX_PINNED_BACKGROUND_OPERATIONS, CAPTION_MAX, _defaultCodexBackend, TRANSCRIPT_EARLIER_MAX_ITEMS, TRANSCRIPT_EARLIER_MAX_BYTES, fullDigestCache, FULL_DIGEST_CACHE_CAP, EMPTY_RETIRED_OPS;
|
|
77898
|
+
var MAX_MESSAGES, LATEST_WINDOW_ASK_REACH_ITEMS, LATEST_WINDOW_ASK_REACH_BYTES, LATEST_WINDOW_MAX_BYTES, REST_LABEL, LEGACY_TASK_MARKER, LEGACY_BANNER_PREAMBLE, COMMAND_NAME_RE, COMMAND_ARGS_RE, LOCAL_COMMAND_RECEIPT2, PEER_SESSION_PREAMBLE, CLAUDE_COORDINATOR_INSTRUCTION_PREFIX, CLAUDE_COORDINATOR_INSTRUCTION_SUFFIX, CLAUDE_PEER_INSTRUCTION_PREFIX, QUEUED_STALE_MS, QUEUED_BLOCKED_CEILING_MS, EDIT_CAP, TRUNC_MARKER, AGENT_PROMPT_CAP, SEND_BODY_CAP, COMMAND_CAP, TOOL_INPUT_CAP, READ_LINE_CAP, READ_BYTE_CAP, IMAGE_MEDIA_EXT, SCREENSHOT_CACHE_DIR, SCREENSHOT_CACHE_MAX, SCREENSHOT_MAX_BASE64, screenshotTmpSeq, SENT_IMAGE_MAX_BYTES, SENT_FILES_MAX, TODO_ROWS_MAX, TODO_TEXT_CAP, TRANSCRIPT_CACHE_CAP, transcriptCache, PARSE_VERIFY_SAMPLE, TRANSCRIPT_DECODE_WINDOW, FOREIGN_SESSION_ID_RE, MAX_PINNED_BACKGROUND_OPERATIONS, CAPTION_MAX, _defaultCodexBackend, TRANSCRIPT_EARLIER_MAX_ITEMS, TRANSCRIPT_EARLIER_MAX_BYTES, fullDigestCache, FULL_DIGEST_CACHE_CAP, EMPTY_RETIRED_OPS;
|
|
77756
77899
|
var init_transcript = __esm({
|
|
77757
77900
|
"packages/server/src/transcript.ts"() {
|
|
77758
77901
|
"use strict";
|
|
77759
77902
|
init_src();
|
|
77903
|
+
init_types2();
|
|
77760
77904
|
init_delivery_ledger();
|
|
77761
77905
|
init_edited_files();
|
|
77762
77906
|
init_repo_files();
|
|
@@ -77785,6 +77929,7 @@ var init_transcript = __esm({
|
|
|
77785
77929
|
CLAUDE_COORDINATOR_INSTRUCTION_SUFFIX = "\n\nAddress this before completing your current task.";
|
|
77786
77930
|
CLAUDE_PEER_INSTRUCTION_PREFIX = "Another Claude session sent a message while you were working:\n";
|
|
77787
77931
|
QUEUED_STALE_MS = 2 * 60 * 6e4;
|
|
77932
|
+
QUEUED_BLOCKED_CEILING_MS = Number(CLAUDE_WORKER_ENV.BASH_MAX_TIMEOUT_MS);
|
|
77788
77933
|
EDIT_CAP = 4e3;
|
|
77789
77934
|
TRUNC_MARKER = "\n\u2026 (truncated)";
|
|
77790
77935
|
AGENT_PROMPT_CAP = 4e3;
|
|
@@ -79177,7 +79322,8 @@ function createRouter(ctx) {
|
|
|
79177
79322
|
if (!info) return blocked(null);
|
|
79178
79323
|
const shell = ctx.tailer.backgroundShell?.(slug, id2);
|
|
79179
79324
|
const noun = shell ? "background shell" : "sub-agent";
|
|
79180
|
-
|
|
79325
|
+
const shellGone = shell !== void 0 && ctx.tailer.get(slug)?.bgShells?.find((s) => s.id === id2)?.state === "stale";
|
|
79326
|
+
if (!(shell ? shell.state === "running" && !shellGone : info.state === "running")) return blocked(null);
|
|
79181
79327
|
const row = ctx.storage.getSession(slug);
|
|
79182
79328
|
if (!row) return blocked(null);
|
|
79183
79329
|
if (row.backend === "codex") {
|