frizz-server 0.15.24 → 0.15.25
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/dev-child.js +355 -222
- package/package.json +1 -1
- package/web-dist/assets/{abnfDiagram-VRR7QNED-Cyq_AHxV.js → abnfDiagram-VRR7QNED-BUGGhGcL.js} +1 -1
- package/web-dist/assets/{arc-Biot4XPF.js → arc-DlmiB5Kw.js} +1 -1
- package/web-dist/assets/architecture-TIHT7OUA-DvYaN-Hu.js +1 -0
- package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-rIrq0Or5.js → architectureDiagram-ZJ3FMSHR-m4afIjbT.js} +1 -1
- package/web-dist/assets/{blockDiagram-677ZJIJ3-CoU4IPAo.js → blockDiagram-677ZJIJ3-Kz2humn5.js} +1 -1
- package/web-dist/assets/{c4Diagram-LMCZKHZV-IDXrxWzC.js → c4Diagram-LMCZKHZV-SeHCCIRv.js} +1 -1
- package/web-dist/assets/channel-Og7O24Xl.js +1 -0
- package/web-dist/assets/{chunk-32BRIVSS-D4oDERCE.js → chunk-32BRIVSS-Cs4BaciL.js} +1 -1
- package/web-dist/assets/{chunk-52WLFC77-BerQKVJ0.js → chunk-52WLFC77-Hrl54hxN.js} +1 -1
- package/web-dist/assets/{chunk-C7G6YPKG-JuYJLbly.js → chunk-C7G6YPKG-C_LwXwMT.js} +1 -1
- package/web-dist/assets/{chunk-EX3LRPZG-wOWblJtm.js → chunk-EX3LRPZG-s0-pq_ja.js} +1 -1
- package/web-dist/assets/{chunk-FWX5IMBZ-CqArLPnj.js → chunk-FWX5IMBZ-Ci_L6bRR.js} +2 -2
- package/web-dist/assets/{chunk-HOUHSVGY-Bb8D8Sy0.js → chunk-HOUHSVGY-Cn43tXaT.js} +1 -1
- package/web-dist/assets/{chunk-ICXQ74PX-DKHetHix.js → chunk-ICXQ74PX-DaehSUDb.js} +1 -1
- package/web-dist/assets/{chunk-MOJQB5TN-LzEqxbeQ.js → chunk-MOJQB5TN-BOLvHrOY.js} +1 -1
- package/web-dist/assets/{chunk-OGEWGWER-Dz8CpAuR.js → chunk-OGEWGWER-B7N0H72R.js} +1 -1
- package/web-dist/assets/{chunk-PUDLZKDR-kuwrL5oa.js → chunk-PUDLZKDR-D9Tpv5xu.js} +1 -1
- package/web-dist/assets/{chunk-Q4XR5HBZ-DcOWV3Gu.js → chunk-Q4XR5HBZ-CZxzEfvh.js} +1 -1
- package/web-dist/assets/{chunk-RYQCIY6F-DnbXKsAA.js → chunk-RYQCIY6F-CH35JHMA.js} +1 -1
- package/web-dist/assets/{chunk-V7JOEXUC-BwuCBTBN.js → chunk-V7JOEXUC-28qGatq3.js} +1 -1
- package/web-dist/assets/{chunk-VAUOI2AC-CV_CZRZK.js → chunk-VAUOI2AC-CkO9u5CM.js} +1 -1
- package/web-dist/assets/{chunk-VR4S4FIN-LWPikT8q.js → chunk-VR4S4FIN-BFszczwO.js} +1 -1
- package/web-dist/assets/{chunk-WYO6CB5R-DNl2QRUu.js → chunk-WYO6CB5R-CuBoterc.js} +1 -1
- package/web-dist/assets/{chunk-XXDRQBXY-OWPjVUFR.js → chunk-XXDRQBXY-8nlDi-YO.js} +1 -1
- package/web-dist/assets/{chunk-ZGVPDNZ5-DJaQplR6.js → chunk-ZGVPDNZ5-B5WfIiLa.js} +1 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-DBua7nWT.js +1 -0
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-DBua7nWT.js +1 -0
- package/web-dist/assets/{cose-bilkent-JH36ORCC-BZT_P9wI.js → cose-bilkent-JH36ORCC-Csxg0M3P.js} +1 -1
- package/web-dist/assets/{cynefin-VYW2F7L2-DaK_8y6L.js → cynefin-VYW2F7L2-DY-oaly-.js} +1 -1
- package/web-dist/assets/{cynefinDiagram-TSTJHNR4-yIggIpo7.js → cynefinDiagram-TSTJHNR4-Baev5OIz.js} +1 -1
- package/web-dist/assets/{dagre-VKFMJZFB-DjlfaR1L.js → dagre-VKFMJZFB-VV2KSHL4.js} +1 -1
- package/web-dist/assets/{diagram-FQU43EPY-3764FQId.js → diagram-FQU43EPY-rLuhqzIC.js} +1 -1
- package/web-dist/assets/{diagram-G47NLZAW-CtEwbfs4.js → diagram-G47NLZAW-BBRVU5Kr.js} +1 -1
- package/web-dist/assets/{diagram-NH7WQ7WH-Bu-wequE.js → diagram-NH7WQ7WH-BMSjTTHf.js} +1 -1
- package/web-dist/assets/{diagram-OA4YK3LP-CGfVM6PV.js → diagram-OA4YK3LP-7NO_QsSx.js} +1 -1
- package/web-dist/assets/{diagram-WEI45ONY-IAJhjXF5.js → diagram-WEI45ONY-evQWfr1h.js} +1 -1
- package/web-dist/assets/{dist-BjMNWdF2.js → dist-BoiR_HZa.js} +1 -1
- package/web-dist/assets/{ebnfDiagram-CCIWWBDH-CtxSHYhd.js → ebnfDiagram-CCIWWBDH-BGCXILB-.js} +1 -1
- package/web-dist/assets/{erDiagram-Q63AITRT-BEfE5XiZ.js → erDiagram-Q63AITRT-CJSi0YB2.js} +1 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-CMWWvyUk.js +1 -0
- package/web-dist/assets/flowDiagram-23GEKE2U-CFOr0Vr_.js +1 -0
- package/web-dist/assets/{ganttDiagram-NO4QXBWP-DuTznSXl.js → ganttDiagram-NO4QXBWP-DfKGoGJe.js} +1 -1
- package/web-dist/assets/{gitGraph-TEB2WS4Q-Bzgogpn6.js → gitGraph-TEB2WS4Q-DDOEbCVa.js} +1 -1
- package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-BvUF8VO2.js → gitGraphDiagram-IHSO6WYX-tKMl1T5T.js} +1 -1
- package/web-dist/assets/{index-Bb1sXlKY.js → index-DYhjAs_a.js} +79 -77
- package/web-dist/assets/index-htGvcLfn.css +2 -0
- package/web-dist/assets/{info-DKCQHKI2-UcBlbSp6.js → info-DKCQHKI2-BqMXJJEF.js} +1 -1
- package/web-dist/assets/{infoDiagram-FWYZ7A6U-eAOHFBzP.js → infoDiagram-FWYZ7A6U-DXpmORxt.js} +1 -1
- package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-BonOAiJg.js → ishikawaDiagram-FXEZZL3T-D9yCb_iG.js} +1 -1
- package/web-dist/assets/{journeyDiagram-5HDEW3XC-CemMqrtD.js → journeyDiagram-5HDEW3XC-DwyXsO1X.js} +1 -1
- package/web-dist/assets/{kanban-definition-HUTT4EX6-DJa8f4EP.js → kanban-definition-HUTT4EX6-C-BupP2L.js} +1 -1
- package/web-dist/assets/{line-BYOZ3K8_.js → line-CVohBkYV.js} +1 -1
- package/web-dist/assets/{linear-x64YsWw9.js → linear-CUS0dsDf.js} +1 -1
- package/web-dist/assets/{mermaid-parser.core-C2_vS_3N.js → mermaid-parser.core-BaUI30hf.js} +3 -3
- package/web-dist/assets/{mermaid.core-CiGOTRKy.js → mermaid.core-DRwFVBM9.js} +3 -3
- package/web-dist/assets/{mindmap-definition-LN4V7U3C-Bq7vplEh.js → mindmap-definition-LN4V7U3C-Dwz7wXjl.js} +1 -1
- package/web-dist/assets/{packet-7NZHBO7P-DvLvRzf4.js → packet-7NZHBO7P-Cc8S-JIW.js} +1 -1
- package/web-dist/assets/{pegDiagram-2B236MQR-N8wJXW0W.js → pegDiagram-2B236MQR-DEvuejFX.js} +1 -1
- package/web-dist/assets/{pie-RZYD4A2V-BQGCrm7o.js → pie-RZYD4A2V-lDSko9Ox.js} +1 -1
- package/web-dist/assets/{pieDiagram-ENE6RG2P-DjxRYzEX.js → pieDiagram-ENE6RG2P-DoIHahh_.js} +1 -1
- package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-DB9fHEsF.js → quadrantDiagram-ABIIQ3AL-ttYUswX_.js} +1 -1
- package/web-dist/assets/{radar-I7S5WNFK-CD6hpAV_.js → radar-I7S5WNFK-Dlai2VWL.js} +1 -1
- package/web-dist/assets/{railroad-3IZDKUUU-DbssAzLP.js → railroad-3IZDKUUU-CfOvvQCL.js} +1 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-Br3ohVd5.js +1 -0
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-DFaY0AnY.js +1 -0
- package/web-dist/assets/railroad-peg-LSFZ7HO6-Cy2FBxXb.js +1 -0
- package/web-dist/assets/{railroadDiagram-RFXS5EU6-BWrldtcC.js → railroadDiagram-RFXS5EU6-BRpMN8zD.js} +1 -1
- package/web-dist/assets/{requirementDiagram-TGXJPOKE-cCBJjfiU.js → requirementDiagram-TGXJPOKE-C1f5KNrx.js} +1 -1
- package/web-dist/assets/{sankeyDiagram-HTMAVEWB-CmlLuCo5.js → sankeyDiagram-HTMAVEWB-CjXPLZ2A.js} +1 -1
- package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-D67ju6AD.js → sequenceDiagram-DBY2YBRQ-BxVxwb4e.js} +1 -1
- package/web-dist/assets/{src-wfmlpufd.js → src-DjcREoQq.js} +1 -1
- package/web-dist/assets/{stateDiagram-2N3HPSRC-zxIL4yYs.js → stateDiagram-2N3HPSRC-CCx9rSmu.js} +1 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-bSyE7VSt.js +1 -0
- package/web-dist/assets/{swimlanes-5IMT3BWC-Dmolliic.js → swimlanes-5IMT3BWC-L3Legvfa.js} +1 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-n0v1Z0Xu.js +8 -0
- package/web-dist/assets/{timeline-definition-FHXFAJF6-CaYKZ8d2.js → timeline-definition-FHXFAJF6-0p22547Z.js} +1 -1
- package/web-dist/assets/{treeView-QDETBFTQ-Cap29KxK.js → treeView-QDETBFTQ-Xv4-kZ7I.js} +1 -1
- package/web-dist/assets/{treemap-6X3UGDF4-DHF0hYTF.js → treemap-6X3UGDF4-MhycNmte.js} +1 -1
- package/web-dist/assets/{vennDiagram-L72KCM5P-bYB1b7LV.js → vennDiagram-L72KCM5P-P33JCPMu.js} +1 -1
- package/web-dist/assets/{wardley-OPB4EBWU-B87GYnFj.js → wardley-OPB4EBWU-CS41M7I-.js} +1 -1
- package/web-dist/assets/{wardleyDiagram-EHGQE667-d_o0fq6c.js → wardleyDiagram-EHGQE667-CbQaI_DG.js} +1 -1
- package/web-dist/assets/{xychartDiagram-FW5EYKEG-C7Yzxgsj.js → xychartDiagram-FW5EYKEG-tg1lQQ6H.js} +1 -1
- package/web-dist/index.html +2 -2
- package/web-dist/assets/architecture-TIHT7OUA-DbdGmECJ.js +0 -1
- package/web-dist/assets/channel-Bsh6-3G4.js +0 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-Ckmyj21K.js +0 -1
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-Ckmyj21K.js +0 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-Tx1KhZ5X.js +0 -1
- package/web-dist/assets/flowDiagram-23GEKE2U-Bl3doL2W.js +0 -1
- package/web-dist/assets/index-BTlrPmaN.css +0 -2
- package/web-dist/assets/railroad-abnf-AHOZXSZD-DgPnlcbw.js +0 -1
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-CKHb6BBK.js +0 -1
- package/web-dist/assets/railroad-peg-LSFZ7HO6-ElDmcV57.js +0 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-BZGt-oDY.js +0 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-wHigalOx.js +0 -8
package/dist/dev-child.js
CHANGED
|
@@ -14227,7 +14227,7 @@ function parseGithubWakeSteer(text2) {
|
|
|
14227
14227
|
function frizzRoute(path3) {
|
|
14228
14228
|
return `${FRIZZ_ROUTE_PREFIX}${path3.startsWith("/") ? path3 : `/${path3}`}`;
|
|
14229
14229
|
}
|
|
14230
|
-
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, CODEX_MODELS_FALLBACK, 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_SCALAR_KINDS, AWAITING_STEPS_MAX, AWAITING_STEP_VALUE_MAX, AWAITING_QUESTIONS_MAX, AWAITING_TITLE_MAX, AWAITING_STATUSES, 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, LEGACY_PR_WATCH_ARMED_TRAILER, LEGACY_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, COMMAND_WATCH_EVERY_MIN_MS, COMMAND_WATCH_EVERY_MAX_MS, COMMAND_WATCH_FOR_MAX_MS, COMMAND_WATCH_MAX_ARMED, COMMAND_WATCH_COMMAND_MAX, COMMAND_WATCH_OUTPUT_MAX_BYTES, COMMAND_WATCH_RUN_TIMEOUT_MS,
|
|
14230
|
+
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, CODEX_MODELS_FALLBACK, 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_SCALAR_KINDS, AWAITING_STEPS_MAX, AWAITING_STEP_VALUE_MAX, AWAITING_QUESTIONS_MAX, AWAITING_TITLE_MAX, AWAITING_STATUSES, 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, LEGACY_PR_WATCH_ARMED_TRAILER, LEGACY_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, CommandWatchRun, 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, COMMAND_WATCH_EVERY_MIN_MS, COMMAND_WATCH_EVERY_MAX_MS, COMMAND_WATCH_FOR_MAX_MS, COMMAND_WATCH_MAX_ARMED, COMMAND_WATCH_COMMAND_MAX, COMMAND_WATCH_OUTPUT_MAX_BYTES, COMMAND_WATCH_RUN_TIMEOUT_MS, CommandWatchState, CommandWatchView, AddOwnCommandWatchInput, AddOwnCommandWatchResult, DropOwnCommandWatchInput, DropOwnCommandWatchResult, ListOwnCommandWatchesInput, OwnCommandWatchesResult, QUESTION_FENCE_RETIRED_AT, NEEDS_INPUT_REQUIRED_AT, AskQuestionKind, ASK_MAX_DEPTH, AskedOptionSchema, AskedQuestionSchema, AskInput, RegisteredQuestionView, SECRET_ANSWER_PREFIX, SECRET_TTL_MS, AskResult, UnaskInput, UnaskResult, QuestionAnswerSchema, AnswerQuestionsInput, AnswerQuestionsResult, DismissQuestionsInput, DismissQuestionsResult, SettledQuestionView, ThreadSettledQuestionsResult, BURIED_ANSWERS_HEADER, ANSWER_FOLLOW_UP_MARKER, ANSWER_CONTINUATION_INDENT, indentAnswerContinuation, ANSWER_PICK_PREFIX, DISMISSED_ANSWER, ANSWERS_NOTE_HEADER, 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, SteerThreadInput, SteerThreadResult, 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, 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, MERGED_WAKE_LEAD, MERGED_WAKE_HEADING, NOISE_PREFIXES, AGENT_MESSAGE_WRAPPER, CROSS_SESSION_PREAMBLE, CROSS_SESSION_WRAPPER, CROSS_SESSION_GUIDANCE, XML_ATTRIBUTE, THREAD_MESSAGE_OPEN, THREAD_MESSAGE_CLOSE, THREAD_MESSAGE_GUIDANCE, 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;
|
|
14231
14231
|
var init_src = __esm({
|
|
14232
14232
|
"packages/shared/src/index.ts"() {
|
|
14233
14233
|
"use strict";
|
|
@@ -14675,7 +14675,7 @@ var init_src = __esm({
|
|
|
14675
14675
|
PARK_CORRECTION_RETIRED_LEAD = "\u26D4 Your ```awaiting fence uses ";
|
|
14676
14676
|
PARK_CORRECTION_QUESTION_LEAD = "\u26A0\uFE0F Your ```awaiting fence landed while ";
|
|
14677
14677
|
PARK_CORRECTION_NEEDS_INPUT_LEAD = "\u26A0\uFE0F Your ```awaiting fence gives no ";
|
|
14678
|
-
ThreadWatchKind = external_exports.enum(["shell", "github", "timer"]);
|
|
14678
|
+
ThreadWatchKind = external_exports.enum(["shell", "github", "timer", "command"]);
|
|
14679
14679
|
GithubChecksState = external_exports.enum(["none", "running", "passing", "failing"]);
|
|
14680
14680
|
GithubMergeState = external_exports.enum(["mergeable", "blocked", "conflicting", "unknown"]);
|
|
14681
14681
|
GithubWatchStatus = external_exports.object({
|
|
@@ -14729,6 +14729,12 @@ var init_src = __esm({
|
|
|
14729
14729
|
/** When frizz last heard from GitHub, for the same reason `GithubWatchStatus.polledAt` carries it. */
|
|
14730
14730
|
polledAt: external_exports.string()
|
|
14731
14731
|
}).strict();
|
|
14732
|
+
CommandWatchRun = external_exports.object({
|
|
14733
|
+
at: external_exports.string(),
|
|
14734
|
+
outcome: external_exports.enum(["exit", "timeout", "signal", "error"]),
|
|
14735
|
+
exitCode: external_exports.number().int().nullable(),
|
|
14736
|
+
output: external_exports.string()
|
|
14737
|
+
}).strict();
|
|
14732
14738
|
ThreadWatchView = external_exports.object({
|
|
14733
14739
|
id: external_exports.string(),
|
|
14734
14740
|
kind: ThreadWatchKind,
|
|
@@ -14750,7 +14756,19 @@ var init_src = __esm({
|
|
|
14750
14756
|
* worker's prompt is the row's NAME (a `tmr_…` id names nothing to a human) and the fire instant is
|
|
14751
14757
|
* its status. Unlike `github` there is no polled half to be absent: a timer that exists is fully
|
|
14752
14758
|
* known, so a timer row always carries this. */
|
|
14753
|
-
timer: external_exports.object({ fireAt: external_exports.string(), prompt: external_exports.string() }).strict().optional()
|
|
14759
|
+
timer: external_exports.object({ fireAt: external_exports.string(), prompt: external_exports.string() }).strict().optional(),
|
|
14760
|
+
/** `command` rows only: the armed command watch's registration and its last check — what the worker's
|
|
14761
|
+
* own read-back carries (CommandWatchView), minus the id and state the row already has. The command is
|
|
14762
|
+
* the row's NAME and the cadence its status. Until 2026-10-13 a command watch had no row at all, so a
|
|
14763
|
+
* thread parked on nothing else drew a card that said only "Waiting for an external update." */
|
|
14764
|
+
command: external_exports.object({
|
|
14765
|
+
command: external_exports.string(),
|
|
14766
|
+
/** The cadence in the house duration grammar (`2m`, `1h 30m`). */
|
|
14767
|
+
every: external_exports.string(),
|
|
14768
|
+
expiresAt: external_exports.string(),
|
|
14769
|
+
runs: external_exports.number().int().nonnegative(),
|
|
14770
|
+
lastRun: CommandWatchRun.optional()
|
|
14771
|
+
}).strict().optional()
|
|
14754
14772
|
}).strict();
|
|
14755
14773
|
PR_WATCH_FOR_MAX_MS = 365 * 24 * 60 * 60 * 1e3;
|
|
14756
14774
|
PR_WATCH_DEFAULT_FOR_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
@@ -14889,12 +14907,6 @@ var init_src = __esm({
|
|
|
14889
14907
|
COMMAND_WATCH_COMMAND_MAX = 4e3;
|
|
14890
14908
|
COMMAND_WATCH_OUTPUT_MAX_BYTES = 4096;
|
|
14891
14909
|
COMMAND_WATCH_RUN_TIMEOUT_MS = 2 * 6e4;
|
|
14892
|
-
CommandWatchRun = external_exports.object({
|
|
14893
|
-
at: external_exports.string(),
|
|
14894
|
-
outcome: external_exports.enum(["exit", "timeout", "signal", "error"]),
|
|
14895
|
-
exitCode: external_exports.number().int().nullable(),
|
|
14896
|
-
output: external_exports.string()
|
|
14897
|
-
}).strict();
|
|
14898
14910
|
CommandWatchState = external_exports.enum(["armed", "dropped", "passed", "expired", "cancelled"]);
|
|
14899
14911
|
CommandWatchView = external_exports.object({
|
|
14900
14912
|
id: external_exports.string(),
|
|
@@ -23434,7 +23446,8 @@ function createClaudeRuntimeIngest(deps) {
|
|
|
23434
23446
|
live2.set(item.sessionId, {
|
|
23435
23447
|
turn: signal ?? prior?.turn,
|
|
23436
23448
|
at: now,
|
|
23437
|
-
events: (prior?.events ?? 0) + 1
|
|
23449
|
+
events: (prior?.events ?? 0) + 1,
|
|
23450
|
+
messageId: signal === void 0 ? prior?.messageId : signal === "running" && item.event.kind === "assistant" ? item.event.messageId : void 0
|
|
23438
23451
|
});
|
|
23439
23452
|
deps.receipts?.publish({ type: "claude.runtime.event", slug: item.slug, sessionId: item.sessionId, kind: item.event.kind });
|
|
23440
23453
|
if (item.event.kind === "task") {
|
|
@@ -23499,9 +23512,10 @@ function createClaudeRuntimeIngest(deps) {
|
|
|
23499
23512
|
}
|
|
23500
23513
|
};
|
|
23501
23514
|
}
|
|
23502
|
-
function resolveRuntimeTurn(folded, backstopped, runtime, ageMs = 0) {
|
|
23515
|
+
function resolveRuntimeTurn(folded, backstopped, runtime, ageMs = 0, caughtUp = false) {
|
|
23503
23516
|
if (!runtime) return folded;
|
|
23504
23517
|
if (runtime === "running" && folded === "idle") {
|
|
23518
|
+
if (caughtUp) return "idle";
|
|
23505
23519
|
return ageMs > RUNNING_OVERRIDE_MAX_AGE_MS ? "idle" : "in-flight";
|
|
23506
23520
|
}
|
|
23507
23521
|
if (runtime === "settled" && backstopped) return "idle";
|
|
@@ -26158,6 +26172,7 @@ function applyRecord(state, rec) {
|
|
|
26158
26172
|
state.interrupted = void 0;
|
|
26159
26173
|
state.localCommandDone = void 0;
|
|
26160
26174
|
if (typeof rec.timestamp === "string") state.lastAssistantAt = rec.timestamp;
|
|
26175
|
+
state.lastAssistantUuid = typeof rec.uuid === "string" ? rec.uuid : void 0;
|
|
26161
26176
|
state.lastStopReason = typeof rec.message?.stop_reason === "string" ? rec.message.stop_reason : void 0;
|
|
26162
26177
|
const observedModel = typeof rec.message?.model === "string" ? rec.message.model.trim() : "";
|
|
26163
26178
|
if (observedModel && observedModel !== "<synthetic>") {
|
|
@@ -26435,7 +26450,8 @@ function createTailer(deps) {
|
|
|
26435
26450
|
if (!deps.runtimeLiveness || !isBrokerClaudeRow(row)) return detailed.turn;
|
|
26436
26451
|
const live2 = deps.runtimeLiveness(row.session_id);
|
|
26437
26452
|
const ageMs = live2 ? Math.max(0, nowMs - live2.at) : 0;
|
|
26438
|
-
|
|
26453
|
+
const caughtUp = live2?.messageId !== void 0 && live2.messageId === state.lastAssistantUuid;
|
|
26454
|
+
return resolveRuntimeTurn(detailed.turn, detailed.backstopped, live2?.turn, ageMs, caughtUp);
|
|
26439
26455
|
}
|
|
26440
26456
|
function chaseRuntime(row, state, foldAdvanced) {
|
|
26441
26457
|
if (!deps.runtimeLiveness || !isBrokerClaudeRow(row)) return false;
|
|
@@ -35554,7 +35570,7 @@ var init_codex_app_server = __esm({
|
|
|
35554
35570
|
approvalsReviewer: "user",
|
|
35555
35571
|
...this.resumeSandboxOverride(binding),
|
|
35556
35572
|
...cwdOverride,
|
|
35557
|
-
...holdsExec ? {} : this.
|
|
35573
|
+
...holdsExec ? {} : this.resumeRebuild(threadSlug, sessionId)
|
|
35558
35574
|
});
|
|
35559
35575
|
const response = ThreadResponse.parse(rawResponse);
|
|
35560
35576
|
if (response.thread.id !== binding.codex_thread_id || response.thread.ephemeral) {
|
|
@@ -35595,7 +35611,7 @@ var init_codex_app_server = __esm({
|
|
|
35595
35611
|
* with it, no thread is released to be rebuilt, and each keeps whatever its last load gave it.
|
|
35596
35612
|
*/
|
|
35597
35613
|
syncsThreadConfig() {
|
|
35598
|
-
return !this.unsubscribeRefused && process.env.FRIZZ_PLUGIN_SYNC_OFF !== "1" && (this.options.frizzMcp !== void 0 || this.options.workerConfig !== void 0);
|
|
35614
|
+
return !this.unsubscribeRefused && process.env.FRIZZ_PLUGIN_SYNC_OFF !== "1" && (this.options.frizzMcp !== void 0 || this.options.workerConfig !== void 0 || this.options.workerBaseInstructions !== void 0);
|
|
35599
35615
|
}
|
|
35600
35616
|
// Adopt a rollout this bridge did NOT create — a legacy Codex thread from before the app-server
|
|
35601
35617
|
// cutover, dispatched as its own `codex` process (its `agent_session_id` is the on-disk rollout id).
|
|
@@ -35630,7 +35646,9 @@ var init_codex_app_server = __esm({
|
|
|
35630
35646
|
// Adoption is the first time frizz owns this rollout, so it is also the first chance to give
|
|
35631
35647
|
// the thread a frizz MCP mount that knows its slug, and its hooks. The rollout belonged to a
|
|
35632
35648
|
// process of its own, so this app-server is loading it cold and the bag is what it is built from.
|
|
35633
|
-
|
|
35649
|
+
// And its contract: a pre-app-server thread carried it only in its FIRST PROMPT, so its rollout's
|
|
35650
|
+
// saved base instructions are Codex's default, and a compaction took the contract with it.
|
|
35651
|
+
...this.resumeRebuild(input.threadSlug, input.sessionId)
|
|
35634
35652
|
});
|
|
35635
35653
|
const response = ThreadResponse.parse(rawResponse);
|
|
35636
35654
|
if (response.thread.id !== input.codexThreadId || response.thread.ephemeral) {
|
|
@@ -36485,7 +36503,7 @@ var init_codex_app_server = __esm({
|
|
|
36485
36503
|
// commands and ended every one of them instead (measured 2026-10-11 on codex 0.161.0: a
|
|
36486
36504
|
// `sleep` alive after the old server left was gone after the new server's warm-up). Without
|
|
36487
36505
|
// the bag the same resume only rejoins.
|
|
36488
|
-
...execThreads.includes(row.codex_thread_id) ? {} : this.
|
|
36506
|
+
...execThreads.includes(row.codex_thread_id) ? {} : this.resumeRebuild(row.thread_slug, row.frizz_session_id)
|
|
36489
36507
|
});
|
|
36490
36508
|
const response = ThreadResponse.parse(rawResponse);
|
|
36491
36509
|
if (response.thread.id !== row.codex_thread_id || response.thread.ephemeral) throw new Error("resume ownership mismatch");
|
|
@@ -36682,6 +36700,31 @@ var init_codex_app_server = __esm({
|
|
|
36682
36700
|
};
|
|
36683
36701
|
return Object.keys(config).length ? { config } : {};
|
|
36684
36702
|
}
|
|
36703
|
+
/**
|
|
36704
|
+
* Everything a `thread/resume` that may rebuild the thread sends of this server's own: the bag, and
|
|
36705
|
+
* the worker contract as `baseInstructions`. Both or neither, because they obey the same rule.
|
|
36706
|
+
*
|
|
36707
|
+
* The contract has to ride every such resume. Codex picks a resumed thread's base instructions from
|
|
36708
|
+
* the request first, then from `model_instructions_file` / `instructions` in any config.toml layer,
|
|
36709
|
+
* and only then from the rollout's saved `session_meta` (codex 0.161.0 `config/mod.rs:4003-4011`,
|
|
36710
|
+
* `session/mod.rs:722-756`). Sending none handed a worker whose operator set either key that file in
|
|
36711
|
+
* place of the Frizz contract, after every restart and for the rest of its life — measured against a
|
|
36712
|
+
* fake model (`instructions` read the file's text on the first turn after the resume and after a
|
|
36713
|
+
* compaction), and fixed by this (the same run reads the contract).
|
|
36714
|
+
*
|
|
36715
|
+
* And it has to stay off the resumes the bag stays off. Codex counts ANY `baseInstructions` on a
|
|
36716
|
+
* resume of a loaded thread as an override (`thread_processor.rs:218`, no comparison with what the
|
|
36717
|
+
* thread already has), and an override on a loaded, idle thread nobody subscribes to tears it down
|
|
36718
|
+
* and rebuilds it (`resume_running_thread`, `:4350-4380`) — the very rebuild that ends a background
|
|
36719
|
+
* command. Measured on 0.161.0 with `_live_codex_config_sync.mts`: a restart-reconcile rejoin that
|
|
36720
|
+
* carried `baseInstructions` and no bag ended the thread's `sleep`, which survives the same rejoin
|
|
36721
|
+
* carrying neither. So a rejoin of a thread holding one carries neither; it is loaded already, with
|
|
36722
|
+
* its instructions, and the rebuild before its next turn (startTurn) brings the contract in.
|
|
36723
|
+
*/
|
|
36724
|
+
resumeRebuild(threadSlug, sessionId) {
|
|
36725
|
+
const baseInstructions = this.options.workerBaseInstructions?.(threadSlug, sessionId);
|
|
36726
|
+
return { ...this.threadConfig(threadSlug, sessionId), ...baseInstructions ? { baseInstructions } : {} };
|
|
36727
|
+
}
|
|
36685
36728
|
/** An idle thread on this connection that still runs on a previous server's config and can be
|
|
36686
36729
|
* rebuilt now — see threadConfig. */
|
|
36687
36730
|
threadConfigIsBehind(binding) {
|
|
@@ -39060,9 +39103,10 @@ exactly ONE of them.
|
|
|
39060
39103
|
followed COLD by someone who has read nothing else; frizz reads them verbatim. Steps NAME THE HUMAN
|
|
39061
39104
|
as the wait, so the fence needs no other name and no \`for:\` (add one only if you want to be woken
|
|
39062
39105
|
to re-check), and it always puts the thread in their queue \u2014 \`status:\` may be left out. Their
|
|
39063
|
-
card, headed **Awaiting human**, shows the steps over one
|
|
39064
|
-
back to you as their reply, \`Done\`, the same as anything they type
|
|
39065
|
-
|
|
39106
|
+
card, headed **Awaiting human**, shows the steps over one checkbox, **I have completed this**;
|
|
39107
|
+
ticked and sent, it comes back to you as their reply, \`Done\`, the same as anything they type,
|
|
39108
|
+
with any note they typed under it; anything else they need to tell you \u2014 a step that failed, the
|
|
39109
|
+
account they used \u2014 comes as that note or a message of their own. An act is not a decision: never ask
|
|
39066
39110
|
WHETHER they will do it, and never sign off \`done\` while it is still owed.
|
|
39067
39111
|
**THE FIRST TEST OF EVERY STEP: COULD YOU DO IT YOURSELF? THEN IT IS NOT A STEP \u2014 DO IT.** This
|
|
39068
39112
|
outranks every rule below. Steps are what is LEFT after you have done all you can: a command you
|
|
@@ -41141,6 +41185,15 @@ function composePrompt(sessionId, prompt, kind = "claude") {
|
|
|
41141
41185
|
|
|
41142
41186
|
${DISPATCH_TASK_BANNER_MARKER}${prompt}`;
|
|
41143
41187
|
}
|
|
41188
|
+
function claudeWorkerSystemPrompt(sessionId, projectDir) {
|
|
41189
|
+
return [loadWorkerPrompt("claude"), scratchpadOrientation(sessionId, "claude"), frizzConfigBlock(projectDir)].filter(Boolean).join("\n\n");
|
|
41190
|
+
}
|
|
41191
|
+
function codexWorkerBaseInstructions(sessionId, projectDir) {
|
|
41192
|
+
return [loadWorkerPrompt("codex"), scratchpadOrientation(sessionId, "codex"), frizzConfigBlock(projectDir)].filter(Boolean).join("\n\n");
|
|
41193
|
+
}
|
|
41194
|
+
function acpWorkerContract(sessionId, projectDir) {
|
|
41195
|
+
return [loadWorkerPrompt("acp"), scratchpadOrientation(sessionId, "acp"), frizzConfigBlock(projectDir)].filter(Boolean).join("\n\n");
|
|
41196
|
+
}
|
|
41144
41197
|
function scratchpadOrientation(sessionId, kind = "claude") {
|
|
41145
41198
|
const children2 = kind === "codex" ? "native sub-agents share it, so give each its own file" : "name it in a sub-agent's prompt when you want its notes back, and give each child its own file";
|
|
41146
41199
|
return `SCRATCH DIRECTORY: .frizz/threads/${sessionId}/ \u2014 yours, free-form, as many files as you like, and nothing is expected in it. A single direct task usually needs none; writing notes is never a substitute for doing the work (${children2}). Nothing in this directory is read automatically; if you want a note back after a compaction, \`frizzctl goal start --post-compaction\` re-sends a prompt of your choosing.`;
|
|
@@ -41305,6 +41358,7 @@ function createDispatcher(deps) {
|
|
|
41305
41358
|
const readBoardSource = deps.readBoard ?? readBoard;
|
|
41306
41359
|
const frizzDir = join36(deps.project.dir, ".frizz");
|
|
41307
41360
|
const adoptionRuntime = deps.adoptionRuntime ?? productionRuntime;
|
|
41361
|
+
const inFlightSlugs = /* @__PURE__ */ new Set();
|
|
41308
41362
|
function cleanupPrewrites(built) {
|
|
41309
41363
|
for (const path3 of new Set(built.prewrite.map((file) => file.path))) {
|
|
41310
41364
|
try {
|
|
@@ -41334,181 +41388,181 @@ function createDispatcher(deps) {
|
|
|
41334
41388
|
}
|
|
41335
41389
|
const title = input.title?.trim() || fallbackTitle(input.prompt);
|
|
41336
41390
|
const base = input.slug ?? slugify(title);
|
|
41337
|
-
const slug = resolveSlug(frizzDir, base, (s) => deps.storage.getSession(s) !== void 0);
|
|
41338
|
-
|
|
41339
|
-
|
|
41340
|
-
|
|
41341
|
-
|
|
41342
|
-
|
|
41343
|
-
|
|
41344
|
-
|
|
41345
|
-
|
|
41346
|
-
const
|
|
41347
|
-
if (
|
|
41348
|
-
|
|
41349
|
-
|
|
41350
|
-
|
|
41351
|
-
|
|
41352
|
-
|
|
41353
|
-
const spawned = await bridge.spawnDispatch({
|
|
41354
|
-
threadSlug: slug,
|
|
41355
|
-
sessionId,
|
|
41356
|
-
cwd: deps.project.dir,
|
|
41357
|
-
prompt,
|
|
41358
|
-
model,
|
|
41359
|
-
effort,
|
|
41360
|
-
sandbox: codexSandbox(permissionMode),
|
|
41361
|
-
baseInstructions: [loadWorkerPrompt("codex"), extraSystemPrompt].filter(Boolean).join("\n\n"),
|
|
41362
|
-
developerInstructions: CODEX_FIRST_OUTPUT_TITLE_DEVELOPER_INSTRUCTIONS
|
|
41363
|
-
// No `config` here: the hooks and the reasoning summary are the bridge's to send
|
|
41364
|
-
// (codexWorkerThreadConfig), with this start and with every resume after it.
|
|
41365
|
-
});
|
|
41366
|
-
deps.storage.upsertSession({
|
|
41367
|
-
slug,
|
|
41368
|
-
session_id: sessionId,
|
|
41369
|
-
thread_name: threadIdentityName(slug),
|
|
41370
|
-
spawned_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41371
|
-
last_read_at: null,
|
|
41372
|
-
unread: 0,
|
|
41373
|
-
exited: 0,
|
|
41374
|
-
archived: 0,
|
|
41375
|
-
rested_at: null,
|
|
41376
|
-
title_auto: input.title?.trim() ? 0 : 1,
|
|
41377
|
-
title_locked: 0,
|
|
41378
|
-
// a caller's hard-coded title is not a human's — the worker may rename it
|
|
41379
|
-
title: registryTitle,
|
|
41380
|
-
state: "open",
|
|
41381
|
-
meta: null,
|
|
41382
|
-
seen_at: null,
|
|
41383
|
-
transcript_id: null,
|
|
41384
|
-
model: model ?? null,
|
|
41385
|
-
effort: effort ?? null,
|
|
41386
|
-
permission_mode: permissionMode
|
|
41387
|
-
});
|
|
41388
|
-
deps.storage.setBackend(slug, "codex");
|
|
41389
|
-
deps.storage.setAgentSession(slug, spawned.binding.codexSessionId);
|
|
41390
|
-
deps.storage.setCodexRuntime(slug, "app-server");
|
|
41391
|
-
deps.storage.setWorkerSurface(slug, "cli");
|
|
41392
|
-
void deps.board.rebuild().catch(() => {
|
|
41393
|
-
});
|
|
41394
|
-
return { slug, sessionId };
|
|
41395
|
-
} catch (err) {
|
|
41391
|
+
const slug = resolveSlug(frizzDir, base, (s) => inFlightSlugs.has(s) || deps.storage.getSession(s) !== void 0);
|
|
41392
|
+
inFlightSlugs.add(slug);
|
|
41393
|
+
try {
|
|
41394
|
+
const registryTitle = title;
|
|
41395
|
+
const sessionId = randomUUID13();
|
|
41396
|
+
const permissionMode = workerDispatchPermission(kind, settings);
|
|
41397
|
+
const model = input.model ?? settings.model;
|
|
41398
|
+
const effort = input.effort ?? settings.effort;
|
|
41399
|
+
const scratchRel = writeScratchDir(deps.project.dir, sessionId);
|
|
41400
|
+
const prompt = composePrompt(sessionId, input.prompt, kind);
|
|
41401
|
+
if (kind === "codex") {
|
|
41402
|
+
const bridge = deps.codexAppServer;
|
|
41403
|
+
if (!bridge) {
|
|
41404
|
+
cleanupDispatchFiles(scratchRel, { argv: [], env: {}, prewrite: [] }, sessionId);
|
|
41405
|
+
throw new Error("Codex app-server is unavailable; cannot start this thread. Check that `codex` is installed and its app-server protocol matches the pinned revision (re-pin if you upgraded codex).");
|
|
41406
|
+
}
|
|
41396
41407
|
try {
|
|
41397
|
-
bridge.
|
|
41398
|
-
|
|
41408
|
+
const spawned = await bridge.spawnDispatch({
|
|
41409
|
+
threadSlug: slug,
|
|
41410
|
+
sessionId,
|
|
41411
|
+
cwd: deps.project.dir,
|
|
41412
|
+
prompt,
|
|
41413
|
+
model,
|
|
41414
|
+
effort,
|
|
41415
|
+
sandbox: codexSandbox(permissionMode),
|
|
41416
|
+
baseInstructions: codexWorkerBaseInstructions(sessionId, deps.project.dir),
|
|
41417
|
+
developerInstructions: CODEX_FIRST_OUTPUT_TITLE_DEVELOPER_INSTRUCTIONS
|
|
41418
|
+
// No `config` here: the hooks and the reasoning summary are the bridge's to send
|
|
41419
|
+
// (codexWorkerThreadConfig), with this start and with every resume after it.
|
|
41420
|
+
});
|
|
41421
|
+
deps.storage.upsertSession({
|
|
41422
|
+
slug,
|
|
41423
|
+
session_id: sessionId,
|
|
41424
|
+
thread_name: threadIdentityName(slug),
|
|
41425
|
+
spawned_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41426
|
+
last_read_at: null,
|
|
41427
|
+
unread: 0,
|
|
41428
|
+
exited: 0,
|
|
41429
|
+
archived: 0,
|
|
41430
|
+
rested_at: null,
|
|
41431
|
+
title_auto: input.title?.trim() ? 0 : 1,
|
|
41432
|
+
title_locked: 0,
|
|
41433
|
+
// a caller's hard-coded title is not a human's — the worker may rename it
|
|
41434
|
+
title: registryTitle,
|
|
41435
|
+
state: "open",
|
|
41436
|
+
meta: null,
|
|
41437
|
+
seen_at: null,
|
|
41438
|
+
transcript_id: null,
|
|
41439
|
+
model: model ?? null,
|
|
41440
|
+
effort: effort ?? null,
|
|
41441
|
+
permission_mode: permissionMode
|
|
41442
|
+
});
|
|
41443
|
+
deps.storage.setBackend(slug, "codex");
|
|
41444
|
+
deps.storage.setAgentSession(slug, spawned.binding.codexSessionId);
|
|
41445
|
+
deps.storage.setCodexRuntime(slug, "app-server");
|
|
41446
|
+
deps.storage.setWorkerSurface(slug, "cli");
|
|
41447
|
+
void deps.board.rebuild().catch(() => {
|
|
41448
|
+
});
|
|
41449
|
+
return { slug, sessionId };
|
|
41450
|
+
} catch (err) {
|
|
41451
|
+
try {
|
|
41452
|
+
bridge.releaseSession(slug, sessionId, "session-deleted");
|
|
41453
|
+
} catch {
|
|
41454
|
+
}
|
|
41455
|
+
cleanupDispatchFiles(scratchRel, { argv: [], env: {}, prewrite: [] }, sessionId);
|
|
41456
|
+
throw new Error(`Codex app-server could not start this thread: ${err.message}. Check that \`codex\` is installed and its app-server protocol matches the pinned revision (re-pin if you upgraded codex).`);
|
|
41399
41457
|
}
|
|
41400
|
-
cleanupDispatchFiles(scratchRel, { argv: [], env: {}, prewrite: [] }, sessionId);
|
|
41401
|
-
throw new Error(`Codex app-server could not start this thread: ${err.message}. Check that \`codex\` is installed and its app-server protocol matches the pinned revision (re-pin if you upgraded codex).`);
|
|
41402
|
-
}
|
|
41403
|
-
}
|
|
41404
|
-
if (kind === "acp") {
|
|
41405
|
-
const bridge = deps.acpBridge;
|
|
41406
|
-
const agentId = acpAgentIdFromModel(model);
|
|
41407
|
-
if (!bridge || !agentId) {
|
|
41408
|
-
cleanupDispatchFiles(scratchRel, { argv: [], env: {}, prewrite: [] }, sessionId);
|
|
41409
|
-
throw new Error(!bridge ? "The ACP bridge is unavailable; cannot start this thread." : `An ACP dispatch needs an agent: pick one in the composer (model \`acp:<agent>\`), got ${JSON.stringify(model ?? null)}.`);
|
|
41410
41458
|
}
|
|
41411
|
-
|
|
41412
|
-
|
|
41413
|
-
const
|
|
41414
|
-
|
|
41415
|
-
|
|
41416
|
-
|
|
41417
|
-
|
|
41418
|
-
|
|
41419
|
-
last_read_at: null,
|
|
41420
|
-
unread: 0,
|
|
41421
|
-
exited: 0,
|
|
41422
|
-
archived: 0,
|
|
41423
|
-
rested_at: null,
|
|
41424
|
-
title_auto: input.title?.trim() ? 0 : 1,
|
|
41425
|
-
title_locked: 0,
|
|
41426
|
-
title: registryTitle,
|
|
41427
|
-
state: "open",
|
|
41428
|
-
meta: null,
|
|
41429
|
-
seen_at: null,
|
|
41430
|
-
transcript_id: null,
|
|
41431
|
-
model: model ?? null,
|
|
41432
|
-
effort: null,
|
|
41433
|
-
permission_mode: permissionMode
|
|
41434
|
-
});
|
|
41435
|
-
deps.storage.setBackend(slug, "acp");
|
|
41436
|
-
deps.storage.setAgentSession(slug, spawned.acpSessionId);
|
|
41437
|
-
deps.storage.setAcpAgent(slug, agentId);
|
|
41438
|
-
deps.storage.setWorkerSurface(slug, "cli");
|
|
41439
|
-
void deps.board.rebuild().catch(() => {
|
|
41440
|
-
});
|
|
41441
|
-
return { slug, sessionId };
|
|
41442
|
-
} catch (err) {
|
|
41459
|
+
if (kind === "acp") {
|
|
41460
|
+
const bridge = deps.acpBridge;
|
|
41461
|
+
const agentId = acpAgentIdFromModel(model);
|
|
41462
|
+
if (!bridge || !agentId) {
|
|
41463
|
+
cleanupDispatchFiles(scratchRel, { argv: [], env: {}, prewrite: [] }, sessionId);
|
|
41464
|
+
throw new Error(!bridge ? "The ACP bridge is unavailable; cannot start this thread." : `An ACP dispatch needs an agent: pick one in the composer (model \`acp:<agent>\`), got ${JSON.stringify(model ?? null)}.`);
|
|
41465
|
+
}
|
|
41466
|
+
const firstPrompt = [acpWorkerContract(sessionId, deps.project.dir), prompt].filter(Boolean).join("\n\n");
|
|
41443
41467
|
try {
|
|
41444
|
-
bridge.
|
|
41445
|
-
|
|
41468
|
+
const spawned = await bridge.spawnDispatch({ threadSlug: slug, sessionId, cwd: deps.project.dir, agentId, modelId: acpModelIdFromModel(model), prompt: firstPrompt, userText: input.prompt });
|
|
41469
|
+
deps.storage.upsertSession({
|
|
41470
|
+
slug,
|
|
41471
|
+
session_id: sessionId,
|
|
41472
|
+
thread_name: threadIdentityName(slug),
|
|
41473
|
+
spawned_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41474
|
+
last_read_at: null,
|
|
41475
|
+
unread: 0,
|
|
41476
|
+
exited: 0,
|
|
41477
|
+
archived: 0,
|
|
41478
|
+
rested_at: null,
|
|
41479
|
+
title_auto: input.title?.trim() ? 0 : 1,
|
|
41480
|
+
title_locked: 0,
|
|
41481
|
+
title: registryTitle,
|
|
41482
|
+
state: "open",
|
|
41483
|
+
meta: null,
|
|
41484
|
+
seen_at: null,
|
|
41485
|
+
transcript_id: null,
|
|
41486
|
+
model: model ?? null,
|
|
41487
|
+
effort: null,
|
|
41488
|
+
permission_mode: permissionMode
|
|
41489
|
+
});
|
|
41490
|
+
deps.storage.setBackend(slug, "acp");
|
|
41491
|
+
deps.storage.setAgentSession(slug, spawned.acpSessionId);
|
|
41492
|
+
deps.storage.setAcpAgent(slug, agentId);
|
|
41493
|
+
deps.storage.setWorkerSurface(slug, "cli");
|
|
41494
|
+
void deps.board.rebuild().catch(() => {
|
|
41495
|
+
});
|
|
41496
|
+
return { slug, sessionId };
|
|
41497
|
+
} catch (err) {
|
|
41498
|
+
try {
|
|
41499
|
+
bridge.releaseSession(slug, sessionId, "session-deleted");
|
|
41500
|
+
} catch {
|
|
41501
|
+
}
|
|
41502
|
+
cleanupDispatchFiles(scratchRel, { argv: [], env: {}, prewrite: [] }, sessionId);
|
|
41503
|
+
throw new Error(`The ACP agent could not start this thread: ${err.message}`);
|
|
41446
41504
|
}
|
|
41447
|
-
cleanupDispatchFiles(scratchRel, { argv: [], env: {}, prewrite: [] }, sessionId);
|
|
41448
|
-
throw new Error(`The ACP agent could not start this thread: ${err.message}`);
|
|
41449
41505
|
}
|
|
41450
|
-
|
|
41451
|
-
|
|
41452
|
-
|
|
41453
|
-
|
|
41454
|
-
|
|
41455
|
-
|
|
41456
|
-
|
|
41457
|
-
const appendSystemPrompt = [
|
|
41458
|
-
loadWorkerPrompt("claude"),
|
|
41459
|
-
scratchpadOrientation(sessionId, kind),
|
|
41460
|
-
frizzConfigBlock(deps.project.dir)
|
|
41461
|
-
].filter(Boolean).join("\n\n");
|
|
41462
|
-
try {
|
|
41463
|
-
await bridge.spawnDispatch({
|
|
41464
|
-
threadSlug: slug,
|
|
41465
|
-
sessionId,
|
|
41466
|
-
cwd: deps.project.dir,
|
|
41467
|
-
prompt,
|
|
41468
|
-
permissionMode,
|
|
41469
|
-
appendSystemPrompt,
|
|
41470
|
-
model,
|
|
41471
|
-
effort
|
|
41472
|
-
});
|
|
41473
|
-
deps.storage.upsertSession({
|
|
41474
|
-
slug,
|
|
41475
|
-
session_id: sessionId,
|
|
41476
|
-
thread_name: threadIdentityName(slug),
|
|
41477
|
-
spawned_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41478
|
-
last_read_at: null,
|
|
41479
|
-
unread: 0,
|
|
41480
|
-
exited: 0,
|
|
41481
|
-
archived: 0,
|
|
41482
|
-
rested_at: null,
|
|
41483
|
-
title_auto: input.title?.trim() ? 0 : 1,
|
|
41484
|
-
title_locked: 0,
|
|
41485
|
-
// a caller's hard-coded title is not a human's — the worker may rename it
|
|
41486
|
-
title: registryTitle,
|
|
41487
|
-
state: "open",
|
|
41488
|
-
meta: null,
|
|
41489
|
-
seen_at: null,
|
|
41490
|
-
transcript_id: null,
|
|
41491
|
-
model: model ?? null,
|
|
41492
|
-
effort: effort ?? null,
|
|
41493
|
-
permission_mode: permissionMode
|
|
41494
|
-
});
|
|
41495
|
-
deps.storage.setBackend(slug, "claude");
|
|
41496
|
-
deps.storage.setClaudeRuntime(slug, "broker");
|
|
41497
|
-
deps.storage.setWorkerSurface(slug, "cli");
|
|
41498
|
-
void deps.board.rebuild().catch(() => {
|
|
41499
|
-
});
|
|
41500
|
-
return { slug, sessionId };
|
|
41501
|
-
} catch (err) {
|
|
41506
|
+
if (kind === "claude") {
|
|
41507
|
+
const bridge = deps.claudeBroker;
|
|
41508
|
+
if (!bridge) {
|
|
41509
|
+
cleanupDispatchFiles(scratchRel, { argv: [], env: {}, prewrite: [] }, sessionId);
|
|
41510
|
+
throw new Error("Claude session broker is unavailable; cannot start this thread.");
|
|
41511
|
+
}
|
|
41512
|
+
const appendSystemPrompt = claudeWorkerSystemPrompt(sessionId, deps.project.dir);
|
|
41502
41513
|
try {
|
|
41503
|
-
bridge.
|
|
41504
|
-
|
|
41514
|
+
await bridge.spawnDispatch({
|
|
41515
|
+
threadSlug: slug,
|
|
41516
|
+
sessionId,
|
|
41517
|
+
cwd: deps.project.dir,
|
|
41518
|
+
prompt,
|
|
41519
|
+
permissionMode,
|
|
41520
|
+
appendSystemPrompt,
|
|
41521
|
+
model,
|
|
41522
|
+
effort
|
|
41523
|
+
});
|
|
41524
|
+
deps.storage.upsertSession({
|
|
41525
|
+
slug,
|
|
41526
|
+
session_id: sessionId,
|
|
41527
|
+
thread_name: threadIdentityName(slug),
|
|
41528
|
+
spawned_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41529
|
+
last_read_at: null,
|
|
41530
|
+
unread: 0,
|
|
41531
|
+
exited: 0,
|
|
41532
|
+
archived: 0,
|
|
41533
|
+
rested_at: null,
|
|
41534
|
+
title_auto: input.title?.trim() ? 0 : 1,
|
|
41535
|
+
title_locked: 0,
|
|
41536
|
+
// a caller's hard-coded title is not a human's — the worker may rename it
|
|
41537
|
+
title: registryTitle,
|
|
41538
|
+
state: "open",
|
|
41539
|
+
meta: null,
|
|
41540
|
+
seen_at: null,
|
|
41541
|
+
transcript_id: null,
|
|
41542
|
+
model: model ?? null,
|
|
41543
|
+
effort: effort ?? null,
|
|
41544
|
+
permission_mode: permissionMode
|
|
41545
|
+
});
|
|
41546
|
+
deps.storage.setBackend(slug, "claude");
|
|
41547
|
+
deps.storage.setClaudeRuntime(slug, "broker");
|
|
41548
|
+
deps.storage.setWorkerSurface(slug, "cli");
|
|
41549
|
+
void deps.board.rebuild().catch(() => {
|
|
41550
|
+
});
|
|
41551
|
+
return { slug, sessionId };
|
|
41552
|
+
} catch (err) {
|
|
41553
|
+
try {
|
|
41554
|
+
bridge.releaseSession(slug, sessionId, "session-deleted");
|
|
41555
|
+
} catch {
|
|
41556
|
+
}
|
|
41557
|
+
cleanupDispatchFiles(scratchRel, { argv: [], env: {}, prewrite: [] }, sessionId);
|
|
41558
|
+
throw new Error(`Claude session broker could not start this thread: ${err.message}.`);
|
|
41505
41559
|
}
|
|
41506
|
-
cleanupDispatchFiles(scratchRel, { argv: [], env: {}, prewrite: [] }, sessionId);
|
|
41507
|
-
throw new Error(`Claude session broker could not start this thread: ${err.message}.`);
|
|
41508
41560
|
}
|
|
41561
|
+
cleanupDispatchFiles(scratchRel, { argv: [], env: {}, prewrite: [] }, sessionId);
|
|
41562
|
+
throw new Error(`unsupported backend for dispatch: ${String(kind)}`);
|
|
41563
|
+
} finally {
|
|
41564
|
+
inFlightSlugs.delete(slug);
|
|
41509
41565
|
}
|
|
41510
|
-
cleanupDispatchFiles(scratchRel, { argv: [], env: {}, prewrite: [] }, sessionId);
|
|
41511
|
-
throw new Error(`unsupported backend for dispatch: ${String(kind)}`);
|
|
41512
41566
|
},
|
|
41513
41567
|
// ---- PROMOTION: the human steered one of their own terminals, so it becomes a frizz thread ----
|
|
41514
41568
|
//
|
|
@@ -41678,12 +41732,7 @@ function createDispatcher(deps) {
|
|
|
41678
41732
|
cwd: deps.project.dir,
|
|
41679
41733
|
prompt,
|
|
41680
41734
|
permissionMode,
|
|
41681
|
-
appendSystemPrompt: [
|
|
41682
|
-
loadWorkerPrompt("claude"),
|
|
41683
|
-
scratchpadOrientation(sessionId),
|
|
41684
|
-
frizzConfigBlock(deps.project.dir),
|
|
41685
|
-
adoption
|
|
41686
|
-
].filter(Boolean).join("\n\n"),
|
|
41735
|
+
appendSystemPrompt: [claudeWorkerSystemPrompt(sessionId, deps.project.dir), adoption].filter(Boolean).join("\n\n"),
|
|
41687
41736
|
model: settings.model,
|
|
41688
41737
|
effort: settings.effort
|
|
41689
41738
|
});
|
|
@@ -42040,7 +42089,7 @@ function bgSnoozeArmed(row) {
|
|
|
42040
42089
|
function hasParkedExternalWait(tele, _nowMs) {
|
|
42041
42090
|
return false;
|
|
42042
42091
|
}
|
|
42043
|
-
function fenceWatchViews(slug, tele, fenceAt, github = {}, registered = [], armedTimers = [], armedWatches = [], issueBook = {}) {
|
|
42092
|
+
function fenceWatchViews(slug, tele, fenceAt, github = {}, registered = [], armedTimers = [], armedWatches = [], issueBook = {}, armedCommands = []) {
|
|
42044
42093
|
const seen = /* @__PURE__ */ new Set();
|
|
42045
42094
|
const out = [];
|
|
42046
42095
|
for (const t of armedTimers) {
|
|
@@ -42057,6 +42106,26 @@ function fenceWatchViews(slug, tele, fenceAt, github = {}, registered = [], arme
|
|
|
42057
42106
|
timer: { fireAt: t.fireAt, prompt: t.prompt }
|
|
42058
42107
|
});
|
|
42059
42108
|
}
|
|
42109
|
+
for (const w of armedCommands) {
|
|
42110
|
+
if (w.state !== "armed" || seen.has(`command:${w.id}`)) continue;
|
|
42111
|
+
seen.add(`command:${w.id}`);
|
|
42112
|
+
out.push({
|
|
42113
|
+
id: `command:${slug}:${w.id}`,
|
|
42114
|
+
kind: "command",
|
|
42115
|
+
target: w.id,
|
|
42116
|
+
state: "armed",
|
|
42117
|
+
createdAt: new Date(w.created_at).toISOString(),
|
|
42118
|
+
// The same projection as the worker's read-back (router commandWatchView), so the row and
|
|
42119
|
+
// `frizzctl watch-command` name one cadence and one last check.
|
|
42120
|
+
command: {
|
|
42121
|
+
command: w.command,
|
|
42122
|
+
every: formatElapsed(w.every_ms),
|
|
42123
|
+
expiresAt: new Date(w.expires_at).toISOString(),
|
|
42124
|
+
runs: w.runs,
|
|
42125
|
+
...w.last_run_at !== null && w.last_outcome ? { lastRun: { at: new Date(w.last_run_at).toISOString(), outcome: w.last_outcome, exitCode: w.last_exit, output: w.last_output ?? "" } } : {}
|
|
42126
|
+
}
|
|
42127
|
+
});
|
|
42128
|
+
}
|
|
42060
42129
|
for (const w of registered) {
|
|
42061
42130
|
const subject = w.kind === "issue" ? "issue" : "pull";
|
|
42062
42131
|
const dedupe = `github:${subject}:${w.target}`;
|
|
@@ -42392,7 +42461,7 @@ function sessionThreadView(projectDir, storage, row, rawTele, registeredLegacyTe
|
|
|
42392
42461
|
// become the github rows, `watch:` lines the shell rows — so this strip lists exactly what will
|
|
42393
42462
|
// actually wake the thread, and the two cannot drift into claiming different things. There is no
|
|
42394
42463
|
// registry behind either any more (`thread_watch`, retired 2026-08-14).
|
|
42395
|
-
watches: fenceWatchViews(row.slug, tele, tele?.lastAssistantAt, github, armedPrWatches, armedTimers, armedWatches, issueBook),
|
|
42464
|
+
watches: fenceWatchViews(row.slug, tele, tele?.lastAssistantAt, github, armedPrWatches, armedTimers, armedWatches, issueBook, armedCommandWatches),
|
|
42396
42465
|
pendingAsk: tele?.pendingAsk ? { questions: tele.pendingAsk.questions } : void 0,
|
|
42397
42466
|
pendingQuestion: tele?.pendingQuestion ?? false,
|
|
42398
42467
|
questions,
|
|
@@ -46241,15 +46310,31 @@ function parseAcpRecord(line) {
|
|
|
46241
46310
|
}
|
|
46242
46311
|
if (!raw2 || typeof raw2 !== "object" || typeof raw2.kind !== "string") return void 0;
|
|
46243
46312
|
const kind = raw2.kind;
|
|
46244
|
-
if (kind === "acp-session" || kind === "acp-note" || EVENT_KINDS.has(kind)) return raw2;
|
|
46313
|
+
if (kind === "acp-session" || kind === "acp-note" || kind === "acp-contract" || EVENT_KINDS.has(kind)) return raw2;
|
|
46245
46314
|
return void 0;
|
|
46246
46315
|
}
|
|
46247
46316
|
function parseAcpLine(line) {
|
|
46248
46317
|
const rec = parseAcpRecord(line);
|
|
46249
|
-
if (!rec || rec.kind === "acp-session" || rec.kind === "acp-note") return [];
|
|
46318
|
+
if (!rec || rec.kind === "acp-session" || rec.kind === "acp-note" || rec.kind === "acp-contract") return [];
|
|
46250
46319
|
const { messageId: _m2, acp: _a2, ...ev } = rec;
|
|
46251
46320
|
return [ev];
|
|
46252
46321
|
}
|
|
46322
|
+
function acpContractOwed(path3) {
|
|
46323
|
+
let text2;
|
|
46324
|
+
try {
|
|
46325
|
+
text2 = readFileSync25(path3, "utf8");
|
|
46326
|
+
} catch {
|
|
46327
|
+
return false;
|
|
46328
|
+
}
|
|
46329
|
+
let owed = false;
|
|
46330
|
+
for (const line of text2.split("\n")) {
|
|
46331
|
+
if (!line.includes('"compaction"') && !line.includes('"acp-contract"')) continue;
|
|
46332
|
+
const rec = parseAcpRecord(line);
|
|
46333
|
+
if (rec?.kind === "compaction") owed = true;
|
|
46334
|
+
else if (rec?.kind === "acp-contract") owed = false;
|
|
46335
|
+
}
|
|
46336
|
+
return owed;
|
|
46337
|
+
}
|
|
46253
46338
|
function createAcpBackend(opts) {
|
|
46254
46339
|
return {
|
|
46255
46340
|
kind: "acp",
|
|
@@ -46341,6 +46426,7 @@ function projectAcpTranscript(raw2, identityPrefix = "acp") {
|
|
|
46341
46426
|
switch (rec.kind) {
|
|
46342
46427
|
case "acp-session":
|
|
46343
46428
|
case "acp-note":
|
|
46429
|
+
case "acp-contract":
|
|
46344
46430
|
case "title":
|
|
46345
46431
|
case "context-usage":
|
|
46346
46432
|
case "compaction":
|
|
@@ -46565,7 +46651,10 @@ var init_acp_types = __esm({
|
|
|
46565
46651
|
external_exports.object({ sessionUpdate: external_exports.literal("usage_update"), used: external_exports.number(), size: external_exports.number(), cost: external_exports.unknown().optional() }).passthrough(),
|
|
46566
46652
|
external_exports.object({ sessionUpdate: external_exports.literal("session_info_update"), title: external_exports.string().nullish(), updatedAt: external_exports.string().nullish() }).passthrough(),
|
|
46567
46653
|
external_exports.object({ sessionUpdate: external_exports.literal("config_option_update"), configOptions: external_exports.array(AcpConfigOption) }).passthrough(),
|
|
46568
|
-
external_exports.object({ sessionUpdate: external_exports.literal("compaction_update"), compactionId: external_exports.string().optional(), status: external_exports.string().optional() }).passthrough()
|
|
46654
|
+
external_exports.object({ sessionUpdate: external_exports.literal("compaction_update"), compactionId: external_exports.string().optional(), status: external_exports.string().optional() }).passthrough(),
|
|
46655
|
+
// The summary streaming in while a compaction runs — sent only to a client that advertised
|
|
46656
|
+
// `session.compaction`, which the bridge does. The `completed` update is the one that matters.
|
|
46657
|
+
external_exports.object({ sessionUpdate: external_exports.literal("compaction_summary_chunk"), compactionId: external_exports.string().optional() }).passthrough()
|
|
46569
46658
|
]);
|
|
46570
46659
|
AcpSessionNotification = external_exports.object({ sessionId: external_exports.string(), update: external_exports.unknown() }).passthrough();
|
|
46571
46660
|
AcpStopReason = external_exports.enum(["end_turn", "max_tokens", "max_turn_requests", "refusal", "cancelled"]);
|
|
@@ -47107,6 +47196,14 @@ var init_acp_host = __esm({
|
|
|
47107
47196
|
function clip3(text2, max) {
|
|
47108
47197
|
return text2.length > max ? `${text2.slice(0, max - 1)}\u2026` : text2;
|
|
47109
47198
|
}
|
|
47199
|
+
function isSlashCommand(text2) {
|
|
47200
|
+
return /^\/[\w-]+(?:\s|$)/.test(text2.trimStart());
|
|
47201
|
+
}
|
|
47202
|
+
function opencodeCompactionStatus(update) {
|
|
47203
|
+
const meta = update?._meta?.["opencode/compaction"];
|
|
47204
|
+
const status = meta?.status;
|
|
47205
|
+
return typeof status === "string" ? status : void 0;
|
|
47206
|
+
}
|
|
47110
47207
|
function frizzMcpServer(mcp, slug) {
|
|
47111
47208
|
if (!mcp) return [];
|
|
47112
47209
|
return [{
|
|
@@ -47235,6 +47332,7 @@ var init_acp_bridge = __esm({
|
|
|
47235
47332
|
host() {
|
|
47236
47333
|
return this.options.host ?? (this.options.spawn ? directAcpHost(this.options.spawn) : daemonAcpHost);
|
|
47237
47334
|
}
|
|
47335
|
+
/** `dispatch` marks the open that starts a brand-new thread, whose first prompt already IS the contract. */
|
|
47238
47336
|
async open(input) {
|
|
47239
47337
|
const { threadSlug: slug, sessionId, cwd } = input;
|
|
47240
47338
|
const agent = this.resolveAgent(input.agentId);
|
|
@@ -47244,6 +47342,7 @@ var init_acp_bridge = __esm({
|
|
|
47244
47342
|
const attachment = await this.host()({ stateDir: this.options.stateDir, threadSlug: slug, sessionId, command: agent.bin, args: agent.args, cwd, env });
|
|
47245
47343
|
const proc = attachment.process;
|
|
47246
47344
|
const writer = new AcpTranscriptWriter(acpTranscriptPath(this.options.stateDir, sessionId));
|
|
47345
|
+
const owedFromTranscript = acpContractOwed(writer.path);
|
|
47247
47346
|
let live2;
|
|
47248
47347
|
let isReady = false;
|
|
47249
47348
|
const held = [];
|
|
@@ -47280,14 +47379,16 @@ var init_acp_bridge = __esm({
|
|
|
47280
47379
|
try {
|
|
47281
47380
|
init = AcpInitializeResult.parse(await conn.request("initialize", {
|
|
47282
47381
|
protocolVersion: ACP_PROTOCOL_VERSION,
|
|
47283
|
-
|
|
47382
|
+
// `session.compaction` asks for the standard `compaction_update`; without it opencode reports a
|
|
47383
|
+
// compaction only through `_meta` on a `session_info_update` (both are handled below).
|
|
47384
|
+
clientCapabilities: { fs: { readTextFile: false, writeTextFile: false }, terminal: false, session: { compaction: {} } },
|
|
47284
47385
|
clientInfo: { name: "frizz", version: "0" }
|
|
47285
47386
|
}));
|
|
47286
47387
|
} catch (err) {
|
|
47287
47388
|
return fail(err instanceof Error ? new Error(`${agent.label} did not complete the ACP handshake: ${err.message}`) : err);
|
|
47288
47389
|
}
|
|
47289
47390
|
const mcpServers = this.options.mountsMcp?.(slug) === false ? [] : frizzMcpServer(this.options.frizzMcp, slug);
|
|
47290
|
-
live2 = { slug, sessionId, cwd, agent, conn, init, acpSessionId: "", writer, loading: false, queue: [], pendingPerms: /* @__PURE__ */ new Map(), tools: /* @__PURE__ */ new Map(), exited: false, detaching: false };
|
|
47391
|
+
live2 = { slug, sessionId, cwd, agent, conn, init, acpSessionId: "", writer, loading: false, queue: [], pendingPerms: /* @__PURE__ */ new Map(), tools: /* @__PURE__ */ new Map(), exited: false, detaching: false, ...owedFromTranscript ? { contractOwed: "compaction" } : {} };
|
|
47291
47392
|
void conn.exited.then(() => {
|
|
47292
47393
|
if (live2) this.onExit(live2);
|
|
47293
47394
|
});
|
|
@@ -47343,6 +47444,7 @@ var init_acp_bridge = __esm({
|
|
|
47343
47444
|
if (resumed === "fresh") {
|
|
47344
47445
|
writer.append({ kind: "acp-session", at: this.now(), agent: { id: agent.id, ...init.agentInfo?.name ? { name: init.agentInfo.name } : {}, ...init.agentInfo?.version ? { version: init.agentInfo.version } : {} }, acpSessionId: live2.acpSessionId, cwd, ...live2.model ? { model: live2.model } : {} });
|
|
47345
47446
|
if (input.acpSessionId) writer.append({ kind: "acp-note", at: this.now(), text: `Resumed with a fresh ${agent.label} session: the previous one (${input.acpSessionId}) could not be loaded, so the agent no longer has the earlier conversation.` });
|
|
47447
|
+
if (!input.dispatch) live2.contractOwed = "fresh-session";
|
|
47346
47448
|
}
|
|
47347
47449
|
if (modelProblem) writer.append({ kind: "acp-note", at: this.now(), text: modelProblem });
|
|
47348
47450
|
this.sessions.set(sessionId, live2);
|
|
@@ -47474,7 +47576,7 @@ var init_acp_bridge = __esm({
|
|
|
47474
47576
|
// ---- public API --------------------------------------------------------------------------------
|
|
47475
47577
|
async spawnDispatch(input) {
|
|
47476
47578
|
if (this.closed) throw new Error("ACP bridge is closed");
|
|
47477
|
-
const { live: live2 } = await this.openOnce(input);
|
|
47579
|
+
const { live: live2 } = await this.openOnce({ ...input, dispatch: true });
|
|
47478
47580
|
void this.runTurn(live2, input.prompt, input.userText, void 0);
|
|
47479
47581
|
return this.info(live2);
|
|
47480
47582
|
}
|
|
@@ -47615,6 +47717,15 @@ var init_acp_bridge = __esm({
|
|
|
47615
47717
|
async runTurn(live2, sendText, recordText, deliveryId) {
|
|
47616
47718
|
const turn = this.newTurn(deliveryId);
|
|
47617
47719
|
live2.turn = turn;
|
|
47720
|
+
const owed = live2.contractOwed;
|
|
47721
|
+
const contract = owed && !isSlashCommand(sendText) ? this.options.contractFor?.(live2.slug, live2.sessionId) : void 0;
|
|
47722
|
+
if (owed && contract) {
|
|
47723
|
+
sendText = `${contract}
|
|
47724
|
+
|
|
47725
|
+
${sendText}`;
|
|
47726
|
+
live2.contractOwed = void 0;
|
|
47727
|
+
live2.writer.append({ kind: "acp-contract", at: turn.startedAt, reason: owed });
|
|
47728
|
+
}
|
|
47618
47729
|
live2.writer.append({ kind: "user-message", at: turn.startedAt, text: recordText, synthetic: false });
|
|
47619
47730
|
live2.writer.append({ kind: "turn-start", at: turn.startedAt });
|
|
47620
47731
|
this.options.onStatusChange?.();
|
|
@@ -47768,19 +47879,32 @@ var init_acp_bridge = __esm({
|
|
|
47768
47879
|
return;
|
|
47769
47880
|
case "session_info_update":
|
|
47770
47881
|
if (update.title) live2.writer.append({ kind: "title", title: clip3(update.title, 200) });
|
|
47882
|
+
if (opencodeCompactionStatus(update) === "completed") this.compacted(live2);
|
|
47771
47883
|
return;
|
|
47772
47884
|
case "config_option_update":
|
|
47773
47885
|
this.adoptModel(live2, update.configOptions);
|
|
47774
47886
|
return;
|
|
47887
|
+
case "compaction_update":
|
|
47888
|
+
if (update.status === "completed") this.compacted(live2);
|
|
47889
|
+
return;
|
|
47775
47890
|
case "plan":
|
|
47776
47891
|
case "user_message_chunk":
|
|
47777
|
-
case "
|
|
47892
|
+
case "compaction_summary_chunk":
|
|
47778
47893
|
return;
|
|
47779
47894
|
case "unknown":
|
|
47780
47895
|
this.diagnostic(live2.slug, "update", `unhandled session/update ${String(update.raw?.sessionUpdate)}`);
|
|
47781
47896
|
return;
|
|
47782
47897
|
}
|
|
47783
47898
|
}
|
|
47899
|
+
/** The agent rewrote its history. The `compaction` record is the fold's (it sets `lastCompactionAt`,
|
|
47900
|
+
* which the post-compaction Goal trigger reads, and the activity clock); the debt is this bridge's.
|
|
47901
|
+
* A `session/load` replays old compactions too, but `handleNotification` drops replays (`loading`). */
|
|
47902
|
+
compacted(live2) {
|
|
47903
|
+
this.flushThought(live2);
|
|
47904
|
+
this.flushText(live2, false);
|
|
47905
|
+
live2.writer.append({ kind: "compaction", at: this.now() });
|
|
47906
|
+
live2.contractOwed = "compaction";
|
|
47907
|
+
}
|
|
47784
47908
|
recordToolResult(live2, tc) {
|
|
47785
47909
|
const meta = live2.tools.get(tc.toolCallId);
|
|
47786
47910
|
if (meta?.status === "completed" || meta?.status === "failed") return;
|
|
@@ -74756,11 +74880,7 @@ function deliverCodexWake(deps) {
|
|
|
74756
74880
|
}
|
|
74757
74881
|
function deliverClaudeBrokerWake(deps) {
|
|
74758
74882
|
const { bridge, slug, cwd, row, settings, deliveryMessage, freshProcess } = deps;
|
|
74759
|
-
const appendSystemPrompt =
|
|
74760
|
-
loadWorkerPrompt("claude"),
|
|
74761
|
-
scratchpadOrientation(row.session_id, "claude"),
|
|
74762
|
-
frizzConfigBlock(cwd)
|
|
74763
|
-
].filter(Boolean).join("\n\n");
|
|
74883
|
+
const appendSystemPrompt = claudeWorkerSystemPrompt(row.session_id, cwd);
|
|
74764
74884
|
return bridge.followUp({
|
|
74765
74885
|
threadSlug: slug,
|
|
74766
74886
|
sessionId: row.session_id,
|
|
@@ -74926,13 +75046,18 @@ function createContextUnchecked(opts, resources) {
|
|
|
74926
75046
|
// Codex's MCP servers mount PROCESS-wide on the app-server, not per thread, so the descriptor
|
|
74927
75047
|
// is resolved once here — the codex twin of the per-dispatch resolveFrizzMcp on the claude side.
|
|
74928
75048
|
frizzMcp: resolveFrizzMcp(frizzMcpTarget),
|
|
74929
|
-
// …and only for a thread whose contract taught it the MCP tools
|
|
74930
|
-
//
|
|
75049
|
+
// …and only for a thread whose contract taught it the MCP tools. One that predates `frizzctl`
|
|
75050
|
+
// keeps its mount even though its next resume hands it the current contract: its history still
|
|
75051
|
+
// calls the tools, and a thread only rejoined (mid-turn, or holding a background command) runs
|
|
75052
|
+
// on the contract it was loaded with until it is rebuilt.
|
|
74931
75053
|
mountsMcp: (slug) => workerTaughtMcp(storage.getSession(slug)),
|
|
74932
75054
|
frizzCli: resolveFrizzCli(frizzMcpTarget),
|
|
74933
75055
|
// The rest of a worker thread's config — hooks and reasoning summaries — sent with the start
|
|
74934
75056
|
// and every resume, so a thread that comes back under this server runs on this server's.
|
|
74935
75057
|
workerConfig: (_slug, sessionId) => codexWorkerThreadConfig(sessionId),
|
|
75058
|
+
// The worker contract, rebuilt for every resume exactly as dispatch builds it for the start —
|
|
75059
|
+
// see codexWorkerBaseInstructions for why a resume that sends none can lose it.
|
|
75060
|
+
workerBaseInstructions: (_slug, sessionId) => codexWorkerBaseInstructions(sessionId, project.dir),
|
|
74936
75061
|
db: storage.db,
|
|
74937
75062
|
interactions: storage.interactions,
|
|
74938
75063
|
codexBin: opts.codexBin,
|
|
@@ -74984,6 +75109,11 @@ function createContextUnchecked(opts, resources) {
|
|
|
74984
75109
|
interactions: storage.interactions,
|
|
74985
75110
|
env: process.env,
|
|
74986
75111
|
customAgents: () => getSettings(storage, home).acpAgents,
|
|
75112
|
+
// Re-sent after the agent compacts and into a fresh session that replaced a lost one (acp-bridge.ts).
|
|
75113
|
+
// Today's contract, not the one the thread was born with: that one is gone from the session. A thread
|
|
75114
|
+
// born under the MCP contract keeps its mount (mountsMcp above), and its agent is forked with
|
|
75115
|
+
// `frizzctl` on PATH like any other (frizzCli above), so the `frizzctl` contract still holds for it.
|
|
75116
|
+
contractFor: (_slug, sessionId) => acpWorkerContract(sessionId, project.dir),
|
|
74987
75117
|
onStatusChange: () => board?.refresh()
|
|
74988
75118
|
});
|
|
74989
75119
|
resources.acpBridge = acpBridge;
|
|
@@ -78692,6 +78822,14 @@ function createTranscriptFold(identityPrefix = "claude") {
|
|
|
78692
78822
|
const childDispatchIds = /* @__PURE__ */ new Map();
|
|
78693
78823
|
const dispatchLabels = /* @__PURE__ */ new Map();
|
|
78694
78824
|
const queuedPending = [];
|
|
78825
|
+
const placed = /* @__PURE__ */ new Set();
|
|
78826
|
+
function place(m) {
|
|
78827
|
+
m.queued = false;
|
|
78828
|
+
if (placed.has(m)) return;
|
|
78829
|
+
placed.add(m);
|
|
78830
|
+
out.push(m);
|
|
78831
|
+
lastAssistantId = null;
|
|
78832
|
+
}
|
|
78695
78833
|
let deliveredDedupe = null;
|
|
78696
78834
|
let compactCommandOpen = false;
|
|
78697
78835
|
let pendingRest = null;
|
|
@@ -78728,7 +78866,7 @@ function createTranscriptFold(identityPrefix = "claude") {
|
|
|
78728
78866
|
function resolveQueuedThrough(entry) {
|
|
78729
78867
|
for (const e13 of queuedPending) {
|
|
78730
78868
|
if (e13 === entry) break;
|
|
78731
|
-
e13.message
|
|
78869
|
+
place(e13.message);
|
|
78732
78870
|
}
|
|
78733
78871
|
}
|
|
78734
78872
|
function resolveQueued(key) {
|
|
@@ -78736,7 +78874,7 @@ function createTranscriptFold(identityPrefix = "claude") {
|
|
|
78736
78874
|
if (!entry) return false;
|
|
78737
78875
|
if (entry.message.queued) resolveQueuedThrough(entry);
|
|
78738
78876
|
dropQueued(entry);
|
|
78739
|
-
entry.message
|
|
78877
|
+
place(entry.message);
|
|
78740
78878
|
return true;
|
|
78741
78879
|
}
|
|
78742
78880
|
let offset = 0;
|
|
@@ -78788,13 +78926,12 @@ function createTranscriptFold(identityPrefix = "claude") {
|
|
|
78788
78926
|
if (op2 === "enqueue" && content.trim() && !isInjectedNoise(content) && !dropCorrection(content)) {
|
|
78789
78927
|
const queuedProjection = userProjection(content, out.length === 0);
|
|
78790
78928
|
const m = { sourceId, role: "user", text: content, ...queuedProjection, tools: [], parts: [], at: thisTs, queued: true };
|
|
78791
|
-
out.push(m);
|
|
78792
78929
|
queuedPending.push({ key: content, message: m });
|
|
78793
78930
|
} else if ((op2 === "remove" || op2 === "dequeue" || op2 === "popAll") && content.trim()) {
|
|
78794
78931
|
const entry = findQueued(content);
|
|
78795
78932
|
if (entry) {
|
|
78796
78933
|
resolveQueuedThrough(entry);
|
|
78797
|
-
entry.message
|
|
78934
|
+
place(entry.message);
|
|
78798
78935
|
}
|
|
78799
78936
|
}
|
|
78800
78937
|
return;
|
|
@@ -79043,7 +79180,9 @@ ${block.text}` : block.text;
|
|
|
79043
79180
|
buffer = "";
|
|
79044
79181
|
}
|
|
79045
79182
|
function projected() {
|
|
79046
|
-
|
|
79183
|
+
const waiting = queuedPending.filter((e13) => e13.message.queued && !placed.has(e13.message)).map((e13) => e13.message);
|
|
79184
|
+
if (!pendingRest && waiting.length === 0) return out;
|
|
79185
|
+
return [...out, ...pendingRest ? [restMessage(pendingRest.sourceId, pendingRest.at)] : [], ...waiting];
|
|
79047
79186
|
}
|
|
79048
79187
|
return {
|
|
79049
79188
|
ingest,
|
|
@@ -82666,11 +82805,7 @@ ${gapNote}` : input.message;
|
|
|
82666
82805
|
if (row?.backend === "claude" && row.claude_runtime === "broker") {
|
|
82667
82806
|
const bridge = ctx.claudeBroker;
|
|
82668
82807
|
if (!bridge) throw new Error("Claude session broker is unavailable; cannot deliver this follow-up");
|
|
82669
|
-
const appendSystemPrompt =
|
|
82670
|
-
loadWorkerPrompt("claude"),
|
|
82671
|
-
scratchpadOrientation(row.session_id, "claude"),
|
|
82672
|
-
frizzConfigBlock(ctx.project.dir)
|
|
82673
|
-
].filter(Boolean).join("\n\n");
|
|
82808
|
+
const appendSystemPrompt = claudeWorkerSystemPrompt(row.session_id, ctx.project.dir);
|
|
82674
82809
|
const midTurn = (ctx.tailer.get(input.slug)?.turn ?? "in-flight") === "in-flight";
|
|
82675
82810
|
const upgradeCandidate = claudeUpgradeCandidate({ stateDir: ctx.project.stateDir, projectId: ctx.project.id, storage: ctx.storage, telemetry: ctx.tailer.get(input.slug) }, row);
|
|
82676
82811
|
const upgrade = upgradeCandidate ? claudeModelUpgradeDue(upgradeCandidate, { catalogue: peekClaudeModels(), nowMs: Date.now(), serverStartedAtMs: SERVER_STARTED_AT_MS }) : void 0;
|
|
@@ -83103,8 +83238,10 @@ ${gapNote}` : input.message;
|
|
|
83103
83238
|
// `isDaemonAlive` above is a check, not a hold: the daemon can exit before this frame lands,
|
|
83104
83239
|
// and followUp then COLD-RESUMES rather than failing. Take the same floor every other fork
|
|
83105
83240
|
// takes, so a notice that loses the race cannot be the thing that rebuilds the worker at
|
|
83106
|
-
// Claude's `default` — see coldResumePermission
|
|
83241
|
+
// Claude's `default` — see coldResumePermission — or rebuilds it with no worker contract,
|
|
83242
|
+
// which the daemon it forks would then keep for every later message.
|
|
83107
83243
|
permissionMode: coldResumePermission(row, ctx.getSettings()),
|
|
83244
|
+
appendSystemPrompt: claudeWorkerSystemPrompt(row.session_id, ctx.project.dir),
|
|
83108
83245
|
model: row.model ?? void 0,
|
|
83109
83246
|
effort: row.effort ?? void 0,
|
|
83110
83247
|
// Frizz's own notice, not the operator's reply to anything: an open card stays open.
|
|
@@ -83742,11 +83879,7 @@ ${gapNote}` : input.message;
|
|
|
83742
83879
|
}
|
|
83743
83880
|
const bridge = ctx.claudeBroker;
|
|
83744
83881
|
if (!bridge) throw new Error("Claude session broker is unavailable; cannot compact this thread");
|
|
83745
|
-
const appendSystemPrompt =
|
|
83746
|
-
loadWorkerPrompt("claude"),
|
|
83747
|
-
scratchpadOrientation(row.session_id, "claude"),
|
|
83748
|
-
frizzConfigBlock(ctx.project.dir)
|
|
83749
|
-
].filter(Boolean).join("\n\n");
|
|
83882
|
+
const appendSystemPrompt = claudeWorkerSystemPrompt(row.session_id, ctx.project.dir);
|
|
83750
83883
|
await bridge.followUp({
|
|
83751
83884
|
threadSlug: input.slug,
|
|
83752
83885
|
sessionId: row.session_id,
|