frizz 0.12.9 → 0.12.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 +7850 -7778
- package/dist/codex-app-server-daemon.js +49 -10
- package/dist/dev-child.js +653 -297
- package/dist/frizz.js +118 -21
- package/package.json +1 -1
- package/runtime/cc-worker/bin/frizz-mcp.mjs +58 -5
- package/web-dist/assets/{TerminalPane-CDk5zKv9.js → TerminalPane-DHvHCziB.js} +1 -1
- package/web-dist/assets/{abnfDiagram-VRR7QNED-DmkK2qjk.js → abnfDiagram-VRR7QNED-DIzM_IN8.js} +1 -1
- package/web-dist/assets/architecture-TIHT7OUA-DBvKOf0j.js +1 -0
- package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-BFbA3OG6.js → architectureDiagram-ZJ3FMSHR-Bm_8vd5v.js} +1 -1
- package/web-dist/assets/{blockDiagram-677ZJIJ3-DTslTfq9.js → blockDiagram-677ZJIJ3-BXUW_N2o.js} +1 -1
- package/web-dist/assets/{c4Diagram-LMCZKHZV-Dmugni-f.js → c4Diagram-LMCZKHZV-C7rfqxUO.js} +1 -1
- package/web-dist/assets/channel-CbdXYswc.js +1 -0
- package/web-dist/assets/{chunk-32BRIVSS-DS7QIaUB.js → chunk-32BRIVSS-DbfUERLa.js} +1 -1
- package/web-dist/assets/{chunk-52WLFC77-CnnFIjVe.js → chunk-52WLFC77-BT_3wKSP.js} +1 -1
- package/web-dist/assets/{chunk-C7G6YPKG-BZxNdEVe.js → chunk-C7G6YPKG-JqApnOVt.js} +1 -1
- package/web-dist/assets/{chunk-EX3LRPZG-Zv7RLgbb.js → chunk-EX3LRPZG-Cj6hlA4t.js} +1 -1
- package/web-dist/assets/{chunk-FWX5IMBZ-6-Zb5eo-.js → chunk-FWX5IMBZ-BGthhuW_.js} +2 -2
- package/web-dist/assets/{chunk-HOUHSVGY-J5Ui6IxH.js → chunk-HOUHSVGY-uyLpm_YS.js} +1 -1
- package/web-dist/assets/{chunk-ICXQ74PX-DH6GE_Om.js → chunk-ICXQ74PX-BlwUMZAk.js} +1 -1
- package/web-dist/assets/{chunk-MOJQB5TN-Bjd1ChDq.js → chunk-MOJQB5TN-MXbNNk-P.js} +1 -1
- package/web-dist/assets/{chunk-OGEWGWER-BNvzjYRM.js → chunk-OGEWGWER-Da4My1Rf.js} +1 -1
- package/web-dist/assets/{chunk-PUDLZKDR-CdtfylsO.js → chunk-PUDLZKDR-C-PgvO__.js} +1 -1
- package/web-dist/assets/{chunk-Q4XR5HBZ-C7N3sKog.js → chunk-Q4XR5HBZ-BxZFe7gr.js} +1 -1
- package/web-dist/assets/{chunk-V7JOEXUC-vX-c4OzH.js → chunk-V7JOEXUC-DgERuXm_.js} +1 -1
- package/web-dist/assets/{chunk-VAUOI2AC-DtbheJmZ.js → chunk-VAUOI2AC-T5OoQE-_.js} +1 -1
- package/web-dist/assets/{chunk-VR4S4FIN-BpE1AOJR.js → chunk-VR4S4FIN--HFvJUG1.js} +1 -1
- package/web-dist/assets/{chunk-WYO6CB5R-BupZRR1a.js → chunk-WYO6CB5R-DlAvy41i.js} +1 -1
- package/web-dist/assets/{chunk-ZGVPDNZ5-XoWDM-02.js → chunk-ZGVPDNZ5-BdDg7X_H.js} +1 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-BVXwECjS.js +1 -0
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-BVXwECjS.js +1 -0
- package/web-dist/assets/{cynefin-VYW2F7L2-DOIzVENe.js → cynefin-VYW2F7L2-BhjNO28R.js} +1 -1
- package/web-dist/assets/{cynefinDiagram-TSTJHNR4-DGq-kl_q.js → cynefinDiagram-TSTJHNR4-B6VA5gCd.js} +1 -1
- package/web-dist/assets/{dagre-VKFMJZFB-Brs6wxcd.js → dagre-VKFMJZFB-6MXoEc6K.js} +1 -1
- package/web-dist/assets/{diagram-FQU43EPY-BrQd5FEw.js → diagram-FQU43EPY-D2RSPoK4.js} +1 -1
- package/web-dist/assets/{diagram-G47NLZAW-B-DN7aQk.js → diagram-G47NLZAW-BOSbtzOf.js} +1 -1
- package/web-dist/assets/{diagram-NH7WQ7WH-DB-NFs3X.js → diagram-NH7WQ7WH-Dt_u21nP.js} +1 -1
- package/web-dist/assets/{diagram-OA4YK3LP-DsrBhvMB.js → diagram-OA4YK3LP-CjuWW-7r.js} +1 -1
- package/web-dist/assets/{diagram-WEI45ONY-DYctq6PN.js → diagram-WEI45ONY-rANIKJ8N.js} +1 -1
- package/web-dist/assets/{ebnfDiagram-CCIWWBDH-C6ghRrJP.js → ebnfDiagram-CCIWWBDH-Bf3kfaKZ.js} +1 -1
- package/web-dist/assets/{erDiagram-Q63AITRT-C_iK-Ja6.js → erDiagram-Q63AITRT-6vBp0ITn.js} +1 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-STTT-geQ.js +1 -0
- package/web-dist/assets/flowDiagram-23GEKE2U-CC7DF1Fz.js +1 -0
- package/web-dist/assets/{ganttDiagram-NO4QXBWP-Y9GZAgbA.js → ganttDiagram-NO4QXBWP-C2qN2PMS.js} +1 -1
- package/web-dist/assets/{gitGraph-TEB2WS4Q-BgqW4vt7.js → gitGraph-TEB2WS4Q-CRASqc9n.js} +1 -1
- package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-eImStPZ8.js → gitGraphDiagram-IHSO6WYX-gsXSPrH2.js} +1 -1
- package/web-dist/assets/{index-BOACK0Xu.js → index-DimQCLe8.js} +96 -96
- package/web-dist/assets/index-XhfdAXcw.css +1 -0
- package/web-dist/assets/{info-DKCQHKI2-BtbNWkY3.js → info-DKCQHKI2-rDkFlFOd.js} +1 -1
- package/web-dist/assets/{infoDiagram-FWYZ7A6U-DMIPEeRd.js → infoDiagram-FWYZ7A6U-03ql8Tqr.js} +1 -1
- package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-08_raW8G.js → ishikawaDiagram-FXEZZL3T-CfDSAVNp.js} +1 -1
- package/web-dist/assets/{journeyDiagram-5HDEW3XC-hPkkufFj.js → journeyDiagram-5HDEW3XC-RWaA6AvH.js} +1 -1
- package/web-dist/assets/{kanban-definition-HUTT4EX6-CDBcUNEE.js → kanban-definition-HUTT4EX6-C89qresM.js} +1 -1
- package/web-dist/assets/{line-Njg200Gq.js → line-CZtSsvHu.js} +1 -1
- package/web-dist/assets/{mermaid-parser.core-1A-yH2Ql.js → mermaid-parser.core-DKNnvxt0.js} +3 -3
- package/web-dist/assets/{mermaid.core-D5Mvu4fo.js → mermaid.core-DX8cFeBF.js} +3 -3
- package/web-dist/assets/{mindmap-definition-LN4V7U3C-r-0LqhPG.js → mindmap-definition-LN4V7U3C-DW8ClyAX.js} +1 -1
- package/web-dist/assets/{packet-7NZHBO7P-Dj8tWs_Q.js → packet-7NZHBO7P-CUOv3apI.js} +1 -1
- package/web-dist/assets/{pegDiagram-2B236MQR-BHoUQUjJ.js → pegDiagram-2B236MQR-CFyxKEBL.js} +1 -1
- package/web-dist/assets/{pie-RZYD4A2V-GZmPkAjn.js → pie-RZYD4A2V-DyXXRie2.js} +1 -1
- package/web-dist/assets/{pieDiagram-ENE6RG2P-CL0ZHN1y.js → pieDiagram-ENE6RG2P-yUw7HA8l.js} +1 -1
- package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-vZJzUcfC.js → quadrantDiagram-ABIIQ3AL-Mc7aea_i.js} +1 -1
- package/web-dist/assets/{radar-I7S5WNFK-D3x_tyhl.js → radar-I7S5WNFK-BKj0BsQy.js} +1 -1
- package/web-dist/assets/{railroad-3IZDKUUU-HVHtGCKZ.js → railroad-3IZDKUUU-DUK_kJIY.js} +1 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-BDImJcFw.js +1 -0
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-BR2XIYqq.js +1 -0
- package/web-dist/assets/railroad-peg-LSFZ7HO6-DRCwBbJY.js +1 -0
- package/web-dist/assets/{railroadDiagram-RFXS5EU6-Dfw0JONh.js → railroadDiagram-RFXS5EU6-By0Xgb_U.js} +1 -1
- package/web-dist/assets/{requirementDiagram-TGXJPOKE-DLM4etHl.js → requirementDiagram-TGXJPOKE-CgTycsRY.js} +1 -1
- package/web-dist/assets/{sankeyDiagram-HTMAVEWB-2nsrE-nL.js → sankeyDiagram-HTMAVEWB-mJ_-Grkn.js} +1 -1
- package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-VkpQVaPX.js → sequenceDiagram-DBY2YBRQ-Dn6YyeNv.js} +1 -1
- package/web-dist/assets/{stateDiagram-2N3HPSRC-xvBH0825.js → stateDiagram-2N3HPSRC-BBws1E-e.js} +1 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-B2jOFVGG.js +1 -0
- package/web-dist/assets/{swimlanes-5IMT3BWC-DA8H4qPO.js → swimlanes-5IMT3BWC-Jab-07o9.js} +1 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-DhYK_6fH.js +8 -0
- package/web-dist/assets/{timeline-definition-FHXFAJF6-npL1KNyH.js → timeline-definition-FHXFAJF6-Cq6RznHz.js} +1 -1
- package/web-dist/assets/{treeView-QDETBFTQ-Cea7MDUV.js → treeView-QDETBFTQ-KSelJnyL.js} +1 -1
- package/web-dist/assets/{treemap-6X3UGDF4-CGHINewA.js → treemap-6X3UGDF4-B-iiUurZ.js} +1 -1
- package/web-dist/assets/{vennDiagram-L72KCM5P-D-RIigY2.js → vennDiagram-L72KCM5P-B8t4NeQy.js} +1 -1
- package/web-dist/assets/{wardley-OPB4EBWU-BXdXDctR.js → wardley-OPB4EBWU-CtkAPZLQ.js} +1 -1
- package/web-dist/assets/{wardleyDiagram-EHGQE667-tLo8yxD2.js → wardleyDiagram-EHGQE667-DC-ms_sD.js} +1 -1
- package/web-dist/assets/{xychartDiagram-FW5EYKEG-I4H6c-9Q.js → xychartDiagram-FW5EYKEG-DW6fcgjF.js} +1 -1
- package/web-dist/index.html +2 -2
- package/web-dist/assets/architecture-TIHT7OUA-c0q2ebfx.js +0 -1
- package/web-dist/assets/channel-CZ15urUA.js +0 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-DFxJiEZ1.js +0 -1
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-DFxJiEZ1.js +0 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-BdXQ9Pv4.js +0 -1
- package/web-dist/assets/flowDiagram-23GEKE2U-rTXtf38R.js +0 -1
- package/web-dist/assets/index-BIGkwpMf.css +0 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-BD2umz4T.js +0 -1
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-C1IGySZs.js +0 -1
- package/web-dist/assets/railroad-peg-LSFZ7HO6-BVCH7yeK.js +0 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-B3bLucl6.js +0 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-cYXAfa4Q.js +0 -8
package/dist/dev-child.js
CHANGED
|
@@ -13273,17 +13273,27 @@ function splitAwaitingFrontmatter(raw2) {
|
|
|
13273
13273
|
const after = delimiter2 === -1 ? [] : lines.slice(delimiter2 + 1);
|
|
13274
13274
|
const rest = [];
|
|
13275
13275
|
const yamlLines = [];
|
|
13276
|
+
const titleLines = [];
|
|
13276
13277
|
let structural = true;
|
|
13278
|
+
let inTitle = false;
|
|
13277
13279
|
for (const line of frontmatter) {
|
|
13278
13280
|
const m = line.match(AWAITING_KEY_RE);
|
|
13279
13281
|
const key = m?.[1].toLowerCase();
|
|
13280
|
-
if (m && key)
|
|
13281
|
-
|
|
13282
|
-
|
|
13282
|
+
if (m && key) {
|
|
13283
|
+
structural = AWAITING_YAML_KEYS.has(key);
|
|
13284
|
+
inTitle = key === "title";
|
|
13285
|
+
} else if (line.trim() !== "" && !/^\s/.test(line) && !/^\s*-\s/.test(line)) {
|
|
13286
|
+
structural = false;
|
|
13287
|
+
inTitle = false;
|
|
13288
|
+
}
|
|
13289
|
+
if (inTitle) titleLines.push(m && key === "title" ? m[2] ?? "" : line);
|
|
13290
|
+
else (structural ? yamlLines : rest).push(line);
|
|
13283
13291
|
}
|
|
13284
13292
|
const parsed = parseAwaitingYaml(yamlLines.join("\n"));
|
|
13285
13293
|
if (!parsed.ok) rest.push(...yamlLines);
|
|
13286
13294
|
rest.push(...after);
|
|
13295
|
+
const title = trimAwaitingTitle(titleLines.join(" "));
|
|
13296
|
+
if (title) parsed.hints.push({ kind: "title", value: title });
|
|
13287
13297
|
return { body: rest.join("\n").trim(), hints: parsed.hints.slice(0, AWAITING_HINT_MAX) };
|
|
13288
13298
|
}
|
|
13289
13299
|
function parseAwaitingYaml(text2) {
|
|
@@ -13309,8 +13319,6 @@ function parseAwaitingYaml(text2) {
|
|
|
13309
13319
|
for (const entry of Array.isArray(raw2) ? raw2 : [raw2]) push(itemKind, entry);
|
|
13310
13320
|
} else if (key === "for") {
|
|
13311
13321
|
push("for", raw2);
|
|
13312
|
-
} else if (key === "title") {
|
|
13313
|
-
if (typeof raw2 === "string" || typeof raw2 === "number") push("title", trimAwaitingTitle(String(raw2)));
|
|
13314
13322
|
}
|
|
13315
13323
|
}
|
|
13316
13324
|
return { ok: true, hints };
|
|
@@ -13671,7 +13679,7 @@ function parseGithubWakeSteer(text2) {
|
|
|
13671
13679
|
function frizzRoute(path3) {
|
|
13672
13680
|
return `${FRIZZ_ROUTE_PREFIX}${path3.startsWith("/") ? path3 : `/${path3}`}`;
|
|
13673
13681
|
}
|
|
13674
|
-
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, 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_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, SIGNOFF_NUDGE_MARKER, SIGNOFF_NUDGE_MESSAGE, PARK_CORRECTION_NAMES_LEAD, PARK_CORRECTION_RETIRED_LEAD, PARK_CORRECTION_QUESTION_LEAD, ThreadWatchKind, GithubChecksState, GithubMergeState, GithubWatchStatus, 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, AskQuestionKind, ASK_MAX_DEPTH, AskedOptionSchema, AskedQuestionSchema, AskInput, RegisteredQuestionView, AskResult, UnaskInput, UnaskResult, QuestionAnswerSchema, AnswerQuestionsInput, AnswerQuestionsResult, DismissQuestionsInput, DismissQuestionsResult, BURIED_ANSWERS_HEADER, ANSWER_FOLLOW_UP_MARKER, DISMISSED_ANSWER, MarkOwnDoneInput, MarkOwnDoneResult, ListOwnPrWatchesInput, OwnPrWatchesResult, ThreadTimerView, ThreadFence, LimitWindow, LimitPause, ProviderError, ThreadView, BoardErrorItem, BoardSnapshot, QuotaWindow, ProviderQuota, QuotaSnapshot, ProviderAuth, AccountEmails, AuthSnapshot, AccountLogoutInput, AccountLogoutResult, AccountLoginStartInput, AccountLoginStartResult, AccountLoginStatusInput, AccountLoginStatusResult, PermissionMode, LocalFileOpener, Settings, DispatchProviderPreferences, DispatchPreferences, DispatchProfileSnapshot, SetDispatchPreferenceInput, DispatchInput, ADOPT_THREAD_MESSAGE_MAX_CHARS, AdoptThreadInput, AdoptThreadResult, AdoptSessionInput, FollowUpInput, UnqueueFollowUpInput, UnqueueFollowUpResult, DeliverQueuedNowInput, DeliverQueuedNowResult, 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, 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, PROJECT_ICON_EXTENSIONS, PROJECT_ICON_MAX_BASE64_CHARS, DirectoryPickResult, ThreadLocation, FRIZZ_ROUTE_PREFIX, DEFAULT_PORT, threadIdentityName;
|
|
13682
|
+
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, 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_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, SIGNOFF_NUDGE_MARKER, SIGNOFF_NUDGE_MESSAGE, PARK_CORRECTION_NAMES_LEAD, PARK_CORRECTION_RETIRED_LEAD, PARK_CORRECTION_QUESTION_LEAD, ThreadWatchKind, GithubChecksState, GithubMergeState, GithubWatchStatus, 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, AskQuestionKind, ASK_MAX_DEPTH, AskedOptionSchema, AskedQuestionSchema, AskInput, RegisteredQuestionView, AskResult, UnaskInput, UnaskResult, QuestionAnswerSchema, AnswerQuestionsInput, AnswerQuestionsResult, DismissQuestionsInput, DismissQuestionsResult, BURIED_ANSWERS_HEADER, ANSWER_FOLLOW_UP_MARKER, DISMISSED_ANSWER, MarkOwnDoneInput, MarkOwnDoneResult, ListOwnPrWatchesInput, OwnPrWatchesResult, ThreadTimerView, ThreadFence, LimitWindow, LimitPause, ProviderError, ThreadLinkView, UpsertOwnLinkInput, UpsertOwnLinkResult, DropOwnLinkInput, DropOwnLinkResult, ThreadView, BoardErrorItem, BoardSnapshot, QuotaWindow, ProviderQuota, QuotaSnapshot, ProviderAuth, AccountEmails, AuthSnapshot, AccountLogoutInput, AccountLogoutResult, AccountLoginStartInput, AccountLoginStartResult, AccountLoginStatusInput, AccountLoginStatusResult, PermissionMode, LocalFileOpener, Settings, DispatchProviderPreferences, DispatchPreferences, DispatchProfileSnapshot, SetDispatchPreferenceInput, DispatchInput, ADOPT_THREAD_MESSAGE_MAX_CHARS, AdoptThreadInput, AdoptThreadResult, AdoptSessionInput, FollowUpInput, UnqueueFollowUpInput, UnqueueFollowUpResult, DeliverQueuedNowInput, DeliverQueuedNowResult, 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, 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, PROJECT_ICON_EXTENSIONS, PROJECT_ICON_MAX_BASE64_CHARS, DirectoryPickResult, ThreadLocation, FRIZZ_ROUTE_PREFIX, DEFAULT_PORT, threadIdentityName;
|
|
13675
13683
|
var init_src = __esm({
|
|
13676
13684
|
"packages/shared/src/index.ts"() {
|
|
13677
13685
|
"use strict";
|
|
@@ -13795,7 +13803,14 @@ var init_src = __esm({
|
|
|
13795
13803
|
slug: external_exports.string(),
|
|
13796
13804
|
displayName: external_exports.string(),
|
|
13797
13805
|
defaultEffort: external_exports.string(),
|
|
13798
|
-
efforts: external_exports.array(external_exports.string())
|
|
13806
|
+
efforts: external_exports.array(external_exports.string()),
|
|
13807
|
+
// The model's stock context window and the largest one it accepts, in tokens, straight from the
|
|
13808
|
+
// cache's `context_window` / `max_context_window` (272K / 872K on GPT-5.6, 128K / 128K on Spark).
|
|
13809
|
+
// The Settings "Context window" presets are built from these so the drawer names the numbers codex
|
|
13810
|
+
// will actually run at (maintainer 2026-09-11: "reflect the actual numbers"). Optional: a cache from
|
|
13811
|
+
// before the fields existed, or the degraded fallback, simply carries neither.
|
|
13812
|
+
contextWindow: external_exports.number().int().positive().optional(),
|
|
13813
|
+
maxContextWindow: external_exports.number().int().positive().optional()
|
|
13799
13814
|
});
|
|
13800
13815
|
ThreadProfileOption = external_exports.object({
|
|
13801
13816
|
model: external_exports.string().min(1),
|
|
@@ -14436,6 +14451,20 @@ var init_src = __esm({
|
|
|
14436
14451
|
retrying: external_exports.boolean().optional(),
|
|
14437
14452
|
at: external_exports.string().optional()
|
|
14438
14453
|
});
|
|
14454
|
+
ThreadLinkView = external_exports.object({
|
|
14455
|
+
id: external_exports.string(),
|
|
14456
|
+
kind: external_exports.enum(["link", "file"]),
|
|
14457
|
+
label: external_exports.string(),
|
|
14458
|
+
target: external_exports.string()
|
|
14459
|
+
}).strict();
|
|
14460
|
+
UpsertOwnLinkInput = external_exports.object({
|
|
14461
|
+
slug: ThreadSlug,
|
|
14462
|
+
label: external_exports.string().trim().min(1).max(240).regex(/^[^\x00-\x1f\x7f]+$/),
|
|
14463
|
+
target: external_exports.string().trim().min(1).max(8192).regex(/^[^\x00-\x1f\x7f]+$/)
|
|
14464
|
+
}).strict();
|
|
14465
|
+
UpsertOwnLinkResult = external_exports.object({ link: ThreadLinkView }).strict();
|
|
14466
|
+
DropOwnLinkInput = external_exports.object({ slug: ThreadSlug, id: external_exports.string().min(1) }).strict();
|
|
14467
|
+
DropOwnLinkResult = external_exports.object({ dropped: external_exports.boolean() }).strict();
|
|
14439
14468
|
ThreadView = external_exports.object({
|
|
14440
14469
|
id: ThreadSlug,
|
|
14441
14470
|
// slug; filename is <slug>.md
|
|
@@ -14504,6 +14533,8 @@ var init_src = __esm({
|
|
|
14504
14533
|
// Live background SHELLS the worker launched (tailer-derived). Same default-[] discipline. Rendered
|
|
14505
14534
|
// in the anchored background-ops strip alongside sub-agents; ids make current rows drillable.
|
|
14506
14535
|
bgShells: external_exports.array(BgShellView).default([]),
|
|
14536
|
+
// Optional for snapshots from a server that predates link registration.
|
|
14537
|
+
links: external_exports.array(ThreadLinkView).optional(),
|
|
14507
14538
|
// The thread's ARMED WATCHERS — registry-derived, not folded from the transcript, which is what makes
|
|
14508
14539
|
// them survive the worker saying one more sentence. Same default-[] discipline as the two above.
|
|
14509
14540
|
//
|
|
@@ -14822,6 +14853,15 @@ var init_src = __esm({
|
|
|
14822
14853
|
// writes were 51% of a day's spend while the entries were invalidated every 15–30 minutes anyway
|
|
14823
14854
|
// (see claudePromptCacheEnv). Optional so an old blob parses; defaultSettings pins "auto".
|
|
14824
14855
|
promptCacheTtl: external_exports.enum(["auto", "5m", "1h"]).optional(),
|
|
14856
|
+
// The context window a NEW Codex thread runs with, in tokens. Codex's own default is the model's
|
|
14857
|
+
// stock window (272K on GPT-5.6), but the catalogue also carries a larger `max_context_window` (872K
|
|
14858
|
+
// on GPT-5.6-sol/terra/luna and GPT-6-astra, measured 2026-09-11 in ~/.codex/models_cache.json) that
|
|
14859
|
+
// a thread only reaches when asked. Reaches codex as the `model_context_window` config override on
|
|
14860
|
+
// `thread/start` and every cold `thread/resume` (see codexContextWindowConfig); codex clamps it to
|
|
14861
|
+
// the model's maximum, so a value above it is harmless, and it moves the auto-compact threshold with
|
|
14862
|
+
// it (codex compacts at 90% of the resolved window). Unset ⇒ nothing is sent and the model's stock
|
|
14863
|
+
// window applies. Optional so an old blob parses; defaultSettings leaves it unset.
|
|
14864
|
+
codexContextWindow: external_exports.number().int().positive().optional(),
|
|
14825
14865
|
// The GitHub batch-dispatch prompt template (the picker's per-item worker prompt). Optional: when
|
|
14826
14866
|
// unset OR blank the server falls back to its exported DEFAULT_GITHUB_PROMPT. Substitution tokens
|
|
14827
14867
|
// the server fills: {repo} {n} {title} {url} {labels} {body}. The leading `THREAD: <slug>` tag is
|
|
@@ -15041,6 +15081,7 @@ var init_src = __esm({
|
|
|
15041
15081
|
}).strict();
|
|
15042
15082
|
OwnThreadActivityResult = external_exports.object({
|
|
15043
15083
|
activity: external_exports.array(ThreadActivityItem),
|
|
15084
|
+
links: external_exports.array(ThreadLinkView).optional(),
|
|
15044
15085
|
/** Every question still owed an answer. NOT a `ThreadActivityItem` and deliberately its own list: a
|
|
15045
15086
|
* question is not running work, it waits on a PERSON, and there is no `questions:` key in the awaiting
|
|
15046
15087
|
* fence for it to be written into. Until 2026-08-28 a worker could read its open questions back only
|
|
@@ -19377,6 +19418,20 @@ function createStorage(source, projectId) {
|
|
|
19377
19418
|
`);
|
|
19378
19419
|
const prWatchCursorStmt = scope.prepare("UPDATE pr_watch SET cursor = ? WHERE project_id = @project_id AND id = ? AND state = 'armed'");
|
|
19379
19420
|
const delPrWatches = scope.prepare("DELETE FROM pr_watch WHERE project_id = @project_id AND thread_slug = ?");
|
|
19421
|
+
const upsertThreadLinkStmt = scope.prepare(`
|
|
19422
|
+
INSERT INTO thread_link (project_id, id, thread_slug, kind, label, target, created_at)
|
|
19423
|
+
VALUES (@project_id, @id, @slug, @kind, @label, @target, @createdAtMs)
|
|
19424
|
+
ON CONFLICT (project_id, thread_slug, label) DO UPDATE SET kind = excluded.kind, target = excluded.target
|
|
19425
|
+
RETURNING *
|
|
19426
|
+
`);
|
|
19427
|
+
const threadLinksStmt = scope.prepare(
|
|
19428
|
+
"SELECT * FROM thread_link WHERE project_id = @project_id ORDER BY created_at, rowid"
|
|
19429
|
+
);
|
|
19430
|
+
const threadLinksBySlugStmt = scope.prepare(
|
|
19431
|
+
"SELECT * FROM thread_link WHERE project_id = @project_id AND thread_slug = ? ORDER BY created_at, rowid"
|
|
19432
|
+
);
|
|
19433
|
+
const dropThreadLinkStmt = scope.prepare("DELETE FROM thread_link WHERE project_id = @project_id AND thread_slug = ? AND id = ?");
|
|
19434
|
+
const delThreadLinks = scope.prepare("DELETE FROM thread_link WHERE project_id = @project_id AND thread_slug = ?");
|
|
19380
19435
|
const armThreadWatchStmt = scope.prepare(`
|
|
19381
19436
|
INSERT INTO thread_watch (project_id, id, thread_slug, kind, target, state, created_at, expires_at, settled_at)
|
|
19382
19437
|
VALUES (@project_id, @id, @slug, @kind, @target, 'armed', @createdAtMs, @expiresAtMs, NULL)
|
|
@@ -19516,6 +19571,7 @@ function createStorage(source, projectId) {
|
|
|
19516
19571
|
delThreadTimers.run(existing.slug);
|
|
19517
19572
|
delPrWatches.run(existing.slug);
|
|
19518
19573
|
delThreadWatches.run(existing.slug);
|
|
19574
|
+
delThreadLinks.run(existing.slug);
|
|
19519
19575
|
delThreadQuestions.run(existing.slug);
|
|
19520
19576
|
delThreadDone.run(existing.slug);
|
|
19521
19577
|
delSubAgentSteers.run(existing.slug);
|
|
@@ -19967,6 +20023,10 @@ function createStorage(source, projectId) {
|
|
|
19967
20023
|
dropPrWatch: (slug, id, settledAtMs) => dropPrWatchStmt.run(settledAtMs, id, slug).changes === 1,
|
|
19968
20024
|
settlePrWatch: (id, settledAtMs) => settlePrWatchStmt.run(settledAtMs, id).changes === 1,
|
|
19969
20025
|
setPrWatchCursor: (id, cursor) => prWatchCursorStmt.run(cursor, id).changes === 1,
|
|
20026
|
+
upsertThreadLink: (link) => upsertThreadLinkStmt.get(link),
|
|
20027
|
+
listThreadLinks: (slug) => threadLinksBySlugStmt.all(slug),
|
|
20028
|
+
threadLinksBySlug: () => groupBySlug(threadLinksStmt.all()),
|
|
20029
|
+
dropThreadLink: (slug, id) => dropThreadLinkStmt.run(slug, id).changes === 1,
|
|
19970
20030
|
// IDEMPOTENT BY (thread, kind, target), which is what the partial unique index enforces. A worker
|
|
19971
20031
|
// woken by an expiry re-registers the same wait, and a worker that simply calls twice must not end
|
|
19972
20032
|
// up with two rows to drop — so an existing armed row is RETURNED rather than replaced. Replacing
|
|
@@ -20428,6 +20488,17 @@ var init_storage = __esm({
|
|
|
20428
20488
|
ON pr_watch(project_id, state);
|
|
20429
20489
|
CREATE INDEX IF NOT EXISTS pr_watch_slug
|
|
20430
20490
|
ON pr_watch(project_id, thread_slug, state, created_at);
|
|
20491
|
+
-- Saved destinations have no liveness or expiry. The label is a stable slot within one thread.
|
|
20492
|
+
CREATE TABLE IF NOT EXISTS thread_link (
|
|
20493
|
+
id TEXT PRIMARY KEY,
|
|
20494
|
+
project_id TEXT NOT NULL,
|
|
20495
|
+
thread_slug TEXT NOT NULL,
|
|
20496
|
+
kind TEXT NOT NULL CHECK (kind IN ('link', 'file')),
|
|
20497
|
+
label TEXT NOT NULL,
|
|
20498
|
+
target TEXT NOT NULL,
|
|
20499
|
+
created_at INTEGER NOT NULL,
|
|
20500
|
+
UNIQUE (project_id, thread_slug, label)
|
|
20501
|
+
);
|
|
20431
20502
|
-- A worker's registered WATCHES on its own running work (2026-08-26). See
|
|
20432
20503
|
-- plans/rest-by-registration.md: a wait stops being a line the worker re-writes at every rest and
|
|
20433
20504
|
-- becomes a row it creates once, which the human sees in the queue and which wakes the thread itself.
|
|
@@ -20541,7 +20612,8 @@ var init_storage = __esm({
|
|
|
20541
20612
|
"thread_watch",
|
|
20542
20613
|
"thread_question",
|
|
20543
20614
|
"thread_done",
|
|
20544
|
-
"subagent_steer"
|
|
20615
|
+
"subagent_steer",
|
|
20616
|
+
"thread_link"
|
|
20545
20617
|
];
|
|
20546
20618
|
}
|
|
20547
20619
|
});
|
|
@@ -20686,6 +20758,9 @@ var init_settings = __esm({
|
|
|
20686
20758
|
// "auto" = the CLI's own tier (1h on a subscription). See the schema and claudePromptCacheEnv for
|
|
20687
20759
|
// when "5m" is the cheaper choice.
|
|
20688
20760
|
promptCacheTtl: "auto",
|
|
20761
|
+
// Unset = codex's own window for the model (272K on GPT-5.6). The schema and codexContextWindowConfig
|
|
20762
|
+
// explain the 872K ceiling a larger value is clamped to.
|
|
20763
|
+
codexContextWindow: void 0,
|
|
20689
20764
|
// Hidden until asked for — see the schema for why.
|
|
20690
20765
|
projectRail: false
|
|
20691
20766
|
});
|
|
@@ -21342,7 +21417,23 @@ function toCodexModel(raw2) {
|
|
|
21342
21417
|
const def = typeof m.default_reasoning_level === "string" ? m.default_reasoning_level : "";
|
|
21343
21418
|
const defaultEffort = def && efforts.includes(def) ? def : efforts[0];
|
|
21344
21419
|
const priority = typeof m.priority === "number" && Number.isFinite(m.priority) ? m.priority : Number.MAX_SAFE_INTEGER;
|
|
21345
|
-
|
|
21420
|
+
const window = (key) => {
|
|
21421
|
+
const v = m[key];
|
|
21422
|
+
return typeof v === "number" && Number.isInteger(v) && v > 0 ? v : void 0;
|
|
21423
|
+
};
|
|
21424
|
+
const contextWindow = window("context_window");
|
|
21425
|
+
const maxContextWindow = window("max_context_window");
|
|
21426
|
+
return {
|
|
21427
|
+
model: {
|
|
21428
|
+
slug,
|
|
21429
|
+
displayName,
|
|
21430
|
+
defaultEffort,
|
|
21431
|
+
efforts,
|
|
21432
|
+
...contextWindow === void 0 ? {} : { contextWindow },
|
|
21433
|
+
...maxContextWindow === void 0 ? {} : { maxContextWindow }
|
|
21434
|
+
},
|
|
21435
|
+
priority
|
|
21436
|
+
};
|
|
21346
21437
|
}
|
|
21347
21438
|
function parseCodexModelsCache(raw2) {
|
|
21348
21439
|
let doc;
|
|
@@ -22252,6 +22343,7 @@ function forkBroker(options) {
|
|
|
22252
22343
|
const socketPath = claudeBrokerSocketPath(options.stateDir, options.sessionId);
|
|
22253
22344
|
const recordPath2 = claudeBrokerRecordPath(options.stateDir, options.sessionId);
|
|
22254
22345
|
mkdirSync9(dirname8(recordPath2), { recursive: true });
|
|
22346
|
+
const generation = randomUUID8();
|
|
22255
22347
|
const config = {
|
|
22256
22348
|
socketPath,
|
|
22257
22349
|
cwd: options.cwd,
|
|
@@ -22260,7 +22352,7 @@ function forkBroker(options) {
|
|
|
22260
22352
|
permissionMode: options.permissionMode,
|
|
22261
22353
|
env: options.env,
|
|
22262
22354
|
recordPath: recordPath2,
|
|
22263
|
-
generation
|
|
22355
|
+
generation,
|
|
22264
22356
|
// The daemon writes its own death forensics here. Same dir as the record, so a session's socket,
|
|
22265
22357
|
// record and diagnostics stay together and a project teardown removes all three.
|
|
22266
22358
|
diagnosticLogPath: claudeBrokerDiagnosticLogPath(options.stateDir, options.sessionId),
|
|
@@ -22282,14 +22374,45 @@ function forkBroker(options) {
|
|
|
22282
22374
|
});
|
|
22283
22375
|
child.unref();
|
|
22284
22376
|
const deadline = Date.now() + (options.timeoutMs ?? 3e4);
|
|
22377
|
+
const recordedCause = () => readClaudeBrokerExit(options.stateDir, options.sessionId, generation);
|
|
22285
22378
|
return new Promise((resolve12, reject) => {
|
|
22379
|
+
let settled = false;
|
|
22380
|
+
let timer;
|
|
22381
|
+
const settle = (outcome) => {
|
|
22382
|
+
if (settled) return;
|
|
22383
|
+
settled = true;
|
|
22384
|
+
if (timer) clearTimeout(timer);
|
|
22385
|
+
outcome();
|
|
22386
|
+
};
|
|
22286
22387
|
const poll = () => {
|
|
22287
22388
|
const record = readBrokerRecord(recordPath2);
|
|
22288
|
-
if (record && pidAlive(record.daemonPid)) return resolve12(record);
|
|
22289
|
-
if (Date.now() > deadline)
|
|
22290
|
-
|
|
22389
|
+
if (record && pidAlive(record.daemonPid)) return settle(() => resolve12(record));
|
|
22390
|
+
if (Date.now() > deadline) {
|
|
22391
|
+
const exit = recordedCause();
|
|
22392
|
+
return settle(() => reject(new Error(
|
|
22393
|
+
`Claude broker for session ${options.sessionId} did not become ready${exit ? `: ${describeClaudeBrokerExit(exit)}` : ""}`
|
|
22394
|
+
)));
|
|
22395
|
+
}
|
|
22396
|
+
timer = setTimeout(poll, 50);
|
|
22291
22397
|
};
|
|
22292
|
-
child.once("error", reject);
|
|
22398
|
+
child.once("error", (error) => settle(() => reject(error)));
|
|
22399
|
+
child.once("exit", (code, signal) => {
|
|
22400
|
+
if (settled) return;
|
|
22401
|
+
const how = signal ? `signal ${signal}` : `exit code ${code ?? "unknown"}`;
|
|
22402
|
+
const until = Date.now() + 500;
|
|
22403
|
+
const read = () => {
|
|
22404
|
+
if (settled) return;
|
|
22405
|
+
const exit = recordedCause();
|
|
22406
|
+
if (!exit && Date.now() < until) {
|
|
22407
|
+
setTimeout(read, 25);
|
|
22408
|
+
return;
|
|
22409
|
+
}
|
|
22410
|
+
settle(() => reject(new Error(
|
|
22411
|
+
`Claude broker for session ${options.sessionId} exited before it became ready (${how}): ${describeClaudeBrokerExit(exit)}`
|
|
22412
|
+
)));
|
|
22413
|
+
};
|
|
22414
|
+
read();
|
|
22415
|
+
});
|
|
22293
22416
|
poll();
|
|
22294
22417
|
});
|
|
22295
22418
|
}
|
|
@@ -22788,6 +22911,7 @@ function createCodexSubAgentTracker(deps) {
|
|
|
22788
22911
|
offset: 0,
|
|
22789
22912
|
partial: "",
|
|
22790
22913
|
live: true,
|
|
22914
|
+
liveSinceMs: Date.parse(startedAt),
|
|
22791
22915
|
resolveDeadlineMs: 0
|
|
22792
22916
|
// stamped on the first poll, which is the first time we know `now`
|
|
22793
22917
|
};
|
|
@@ -22800,6 +22924,7 @@ function createCodexSubAgentTracker(deps) {
|
|
|
22800
22924
|
const slot = slots.get(sig.path);
|
|
22801
22925
|
if (!slot || slot.live) return;
|
|
22802
22926
|
slot.live = true;
|
|
22927
|
+
slot.liveSinceMs = sig.at ? Date.parse(sig.at) : NaN;
|
|
22803
22928
|
publish(slot);
|
|
22804
22929
|
return;
|
|
22805
22930
|
}
|
|
@@ -22822,6 +22947,7 @@ function createCodexSubAgentTracker(deps) {
|
|
|
22822
22947
|
else if (agent.status === "interrupted") retire(slot, sig.at, "killed");
|
|
22823
22948
|
else if (!slot.live) {
|
|
22824
22949
|
slot.live = true;
|
|
22950
|
+
slot.liveSinceMs = sig.at ? Date.parse(sig.at) : NaN;
|
|
22825
22951
|
publish(slot);
|
|
22826
22952
|
}
|
|
22827
22953
|
}
|
|
@@ -22898,6 +23024,7 @@ function createCodexSubAgentTracker(deps) {
|
|
|
22898
23024
|
open = true;
|
|
22899
23025
|
closedAt = void 0;
|
|
22900
23026
|
} else if (ev.kind === "turn-end") {
|
|
23027
|
+
if (ev.at && Number.isFinite(slot.liveSinceMs) && Date.parse(ev.at) < slot.liveSinceMs) continue;
|
|
22901
23028
|
open = false;
|
|
22902
23029
|
closedAt = ev.at;
|
|
22903
23030
|
}
|
|
@@ -23262,7 +23389,7 @@ var init_tail_cache = __esm({
|
|
|
23262
23389
|
"use strict";
|
|
23263
23390
|
SAMPLE_BYTES = 1024;
|
|
23264
23391
|
MAX_STATE_BYTES = 256 * 1024;
|
|
23265
|
-
FOLD_SOURCES = ["transcript.ts", "tailer.ts", "backend/claude.ts", "backend/codex.ts"];
|
|
23392
|
+
FOLD_SOURCES = ["transcript.ts", "tailer.ts", "backend/claude.ts", "backend/codex.ts", "../../shared/src/index.ts"];
|
|
23266
23393
|
foldSchemaMemo = null;
|
|
23267
23394
|
isEncodedMap = (value) => Boolean(value) && typeof value === "object" && Array.isArray(value.__map);
|
|
23268
23395
|
isEncodedSet = (value) => Boolean(value) && typeof value === "object" && Array.isArray(value.__set);
|
|
@@ -25967,14 +26094,15 @@ function parseToolArguments(args) {
|
|
|
25967
26094
|
}
|
|
25968
26095
|
function imageField(output) {
|
|
25969
26096
|
if (!Array.isArray(output)) return {};
|
|
26097
|
+
const images = [];
|
|
25970
26098
|
for (const part of output) {
|
|
25971
26099
|
if (!part || typeof part !== "object") continue;
|
|
25972
26100
|
const p = part;
|
|
25973
26101
|
if (p.type !== "input_image" && p.type !== "output_image" && p.type !== "image") continue;
|
|
25974
26102
|
const url = typeof p.image_url === "string" ? p.image_url : typeof p.url === "string" ? p.url : void 0;
|
|
25975
|
-
if (url?.startsWith("data:image/"))
|
|
26103
|
+
if (url?.startsWith("data:image/")) images.push(url);
|
|
25976
26104
|
}
|
|
25977
|
-
return {};
|
|
26105
|
+
return images.length ? { image: images[0], images } : {};
|
|
25978
26106
|
}
|
|
25979
26107
|
function codexItemText(content) {
|
|
25980
26108
|
if (!Array.isArray(content)) return "";
|
|
@@ -29984,6 +30112,11 @@ function claudeCompactionEnv(settings) {
|
|
|
29984
30112
|
if (window === void 0 || !Number.isInteger(window) || window <= 0) return {};
|
|
29985
30113
|
return { [CLAUDE_AUTO_COMPACT_WINDOW_ENV]: String(window) };
|
|
29986
30114
|
}
|
|
30115
|
+
function codexContextWindowConfig(settings) {
|
|
30116
|
+
const window = settings?.codexContextWindow;
|
|
30117
|
+
if (window === void 0 || !Number.isInteger(window) || window <= 0) return {};
|
|
30118
|
+
return { [CODEX_CONTEXT_WINDOW_KEY]: window };
|
|
30119
|
+
}
|
|
29987
30120
|
function claudePromptCacheEnv(settings) {
|
|
29988
30121
|
const ttl = settings?.promptCacheTtl;
|
|
29989
30122
|
if (ttl !== "5m" && ttl !== "1h") return {};
|
|
@@ -29995,7 +30128,7 @@ function claudeCompactionWindowOf(env) {
|
|
|
29995
30128
|
const window = Number(raw2);
|
|
29996
30129
|
return Number.isInteger(window) && window > 0 ? window : void 0;
|
|
29997
30130
|
}
|
|
29998
|
-
var FRIZZ_MCP, WORKER_MAX_WEB_SEARCHES, WORKER_MAX_SUBAGENTS, WORKER_MAX_CONCURRENT_SUBAGENTS, CLAUDE_WORKER_ENV, CLAUDE_AUTO_COMPACT_WINDOW_ENV, CLAUDE_PROMPT_CACHE_TTL_ENV, CLAUDE_SUBAGENT_PROMPT_CACHE_TTL_ENV, WORKER_DISALLOWED_TOOLS;
|
|
30131
|
+
var FRIZZ_MCP, WORKER_MAX_WEB_SEARCHES, WORKER_MAX_SUBAGENTS, WORKER_MAX_CONCURRENT_SUBAGENTS, CLAUDE_WORKER_ENV, CLAUDE_AUTO_COMPACT_WINDOW_ENV, CODEX_CONTEXT_WINDOW_KEY, CLAUDE_PROMPT_CACHE_TTL_ENV, CLAUDE_SUBAGENT_PROMPT_CACHE_TTL_ENV, WORKER_DISALLOWED_TOOLS;
|
|
29999
30132
|
var init_types2 = __esm({
|
|
30000
30133
|
"packages/server/src/backend/types.ts"() {
|
|
30001
30134
|
"use strict";
|
|
@@ -30013,6 +30146,7 @@ var init_types2 = __esm({
|
|
|
30013
30146
|
BASH_MAX_TIMEOUT_MS: String(24 * 60 * 60 * 1e3)
|
|
30014
30147
|
};
|
|
30015
30148
|
CLAUDE_AUTO_COMPACT_WINDOW_ENV = "CLAUDE_CODE_AUTO_COMPACT_WINDOW";
|
|
30149
|
+
CODEX_CONTEXT_WINDOW_KEY = "model_context_window";
|
|
30016
30150
|
CLAUDE_PROMPT_CACHE_TTL_ENV = "CLAUDE_CODE_PROMPT_CACHE_TTL";
|
|
30017
30151
|
CLAUDE_SUBAGENT_PROMPT_CACHE_TTL_ENV = "CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL";
|
|
30018
30152
|
WORKER_DISALLOWED_TOOLS = ["AskUserQuestion"];
|
|
@@ -31945,6 +32079,7 @@ var init_codex_app_server = __esm({
|
|
|
31945
32079
|
init_auth_status();
|
|
31946
32080
|
init_codex_mcp();
|
|
31947
32081
|
init_codex_error();
|
|
32082
|
+
init_types2();
|
|
31948
32083
|
init_logging();
|
|
31949
32084
|
CODEX_APP_SERVER_PROVIDER = "codex-app-server";
|
|
31950
32085
|
CODEX_NATIVE_LISTEN_FLAG = "FRIZZ_CODEX_NATIVE_LISTEN";
|
|
@@ -33612,19 +33747,29 @@ var init_codex_app_server = __esm({
|
|
|
33612
33747
|
*/
|
|
33613
33748
|
/**
|
|
33614
33749
|
* The `config` bag for one thread's `thread/start` / `thread/resume`: frizz's MCP server mounted
|
|
33615
|
-
* PER THREAD so it knows who is calling,
|
|
33750
|
+
* PER THREAD so it knows who is calling, the operator's Codex context window from Settings, plus
|
|
33751
|
+
* whatever the caller passed.
|
|
33616
33752
|
*
|
|
33617
33753
|
* This is the only channel that can carry a caller identity on codex. The argv mount on the
|
|
33618
33754
|
* app-server is process-wide and serves every thread in the project, so `FRIZZ_THREAD_SLUG` was
|
|
33619
33755
|
* simply absent and every tool that acts on the caller's own thread failed at the moment of use —
|
|
33620
33756
|
* see `codexThreadMcpConfig` for the list and the measurement. Returns `{}` when there is nothing
|
|
33621
|
-
* to send, so a caller with no config
|
|
33622
|
-
* exactly as before.
|
|
33757
|
+
* to send, so a caller with no config, no resolved MCP descriptor and no context-window setting
|
|
33758
|
+
* sends no `config` key at all, exactly as before.
|
|
33759
|
+
*
|
|
33760
|
+
* The context window rides the same bag rather than the process-wide argv because the app-server is
|
|
33761
|
+
* a long-lived daemon: an argv value would be frozen at its first spawn, while a per-thread override
|
|
33762
|
+
* reads Settings at every start and every cold resume — the same "next thread, and a thread that
|
|
33763
|
+
* comes back" semantics the Claude compaction window has (see codexContextWindowConfig).
|
|
33623
33764
|
*
|
|
33624
33765
|
* The caller's own config wins on a key collision: this is a default, not an override.
|
|
33625
33766
|
*/
|
|
33626
33767
|
threadConfig(threadSlug, callerConfig) {
|
|
33627
|
-
const config = {
|
|
33768
|
+
const config = {
|
|
33769
|
+
...codexThreadMcpConfig(this.options.frizzMcp, threadSlug),
|
|
33770
|
+
...codexContextWindowConfig(this.options.getSettings?.()),
|
|
33771
|
+
...callerConfig
|
|
33772
|
+
};
|
|
33628
33773
|
return Object.keys(config).length ? { config } : {};
|
|
33629
33774
|
}
|
|
33630
33775
|
resumeSandboxOverride(row) {
|
|
@@ -34272,7 +34417,6 @@ var init_codex_app_server = __esm({
|
|
|
34272
34417
|
if (binding.current_turn_id !== null) {
|
|
34273
34418
|
return;
|
|
34274
34419
|
}
|
|
34275
|
-
if (!this.pendingTurnStarts.has(turnKey(binding))) return;
|
|
34276
34420
|
this.providerErrors.delete(binding.frizz_session_id);
|
|
34277
34421
|
this.scope.prepare(`
|
|
34278
34422
|
UPDATE codex_app_server_session SET current_turn_id = ?, updated_at = ?
|
|
@@ -34670,22 +34814,140 @@ var init_quota = __esm({
|
|
|
34670
34814
|
}
|
|
34671
34815
|
});
|
|
34672
34816
|
|
|
34817
|
+
// packages/server/src/local-file.ts
|
|
34818
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
34819
|
+
import { readFileSync as readFileSync17, realpathSync as realpathSync6, statSync as statSync12 } from "node:fs";
|
|
34820
|
+
import { homedir as homedir11 } from "node:os";
|
|
34821
|
+
import { isAbsolute as isAbsolute4, join as join25, resolve as resolve5, sep as sep2 } from "node:path";
|
|
34822
|
+
function isUnder(real, root) {
|
|
34823
|
+
let rootReal;
|
|
34824
|
+
try {
|
|
34825
|
+
rootReal = realpathSync6(root);
|
|
34826
|
+
} catch {
|
|
34827
|
+
return false;
|
|
34828
|
+
}
|
|
34829
|
+
return real === rootReal || real.startsWith(rootReal.endsWith(sep2) ? rootReal : rootReal + sep2);
|
|
34830
|
+
}
|
|
34831
|
+
function resolveLocalFile(rawPath, roots) {
|
|
34832
|
+
if (!isAbsolute4(rawPath)) throw new Error("Local path must be absolute");
|
|
34833
|
+
let real;
|
|
34834
|
+
try {
|
|
34835
|
+
real = realpathSync6(rawPath);
|
|
34836
|
+
} catch {
|
|
34837
|
+
throw new Error("Local file was not found");
|
|
34838
|
+
}
|
|
34839
|
+
if (!roots.some((root) => isUnder(real, root))) throw new Error("Local file is outside Frizz's trusted roots");
|
|
34840
|
+
try {
|
|
34841
|
+
if (!statSync12(real).isFile()) throw new Error("Local path is not a regular file");
|
|
34842
|
+
} catch (error) {
|
|
34843
|
+
if (error instanceof Error && error.message === "Local path is not a regular file") throw error;
|
|
34844
|
+
throw new Error("Local file was not found");
|
|
34845
|
+
}
|
|
34846
|
+
return real;
|
|
34847
|
+
}
|
|
34848
|
+
function resolveOpenableFile(raw2, projectDir, roots, home = homedir11()) {
|
|
34849
|
+
const trimmed = raw2.trim().replace(/:\d+(?::\d+)?$/, "");
|
|
34850
|
+
if (!trimmed) return null;
|
|
34851
|
+
const abs = trimmed === "~" ? home : trimmed.startsWith("~/") ? join25(home, trimmed.slice(2)) : isAbsolute4(trimmed) ? trimmed : resolve5(projectDir, trimmed);
|
|
34852
|
+
try {
|
|
34853
|
+
return resolveLocalFile(abs, roots);
|
|
34854
|
+
} catch {
|
|
34855
|
+
return null;
|
|
34856
|
+
}
|
|
34857
|
+
}
|
|
34858
|
+
function readLocalTextFile(rawPath, roots) {
|
|
34859
|
+
const path3 = resolveLocalFile(rawPath, roots);
|
|
34860
|
+
const bytes = readFileSync17(path3);
|
|
34861
|
+
if (bytes.subarray(0, 8192).includes(0)) throw new Error("Local file is not a text file");
|
|
34862
|
+
if (bytes.length <= MARKDOWN_READ_LIMIT) return { path: path3, text: bytes.toString("utf8"), truncated: false };
|
|
34863
|
+
const head = bytes.subarray(0, MARKDOWN_READ_LIMIT);
|
|
34864
|
+
const lastBreak = head.lastIndexOf(10);
|
|
34865
|
+
return { path: path3, text: head.subarray(0, lastBreak > 0 ? lastBreak : head.length).toString("utf8"), truncated: true };
|
|
34866
|
+
}
|
|
34867
|
+
function readLocalMarkdown(rawPath, roots) {
|
|
34868
|
+
if (!MARKDOWN_FILE_EXT.test(rawPath.trim())) throw new Error("Local file is not a Markdown file");
|
|
34869
|
+
const path3 = resolveLocalFile(rawPath, roots);
|
|
34870
|
+
if (!MARKDOWN_FILE_EXT.test(path3)) throw new Error("Local file is not a Markdown file");
|
|
34871
|
+
const bytes = readFileSync17(path3);
|
|
34872
|
+
if (bytes.length <= MARKDOWN_READ_LIMIT) return { path: path3, markdown: bytes.toString("utf8"), truncated: false };
|
|
34873
|
+
const head = bytes.subarray(0, MARKDOWN_READ_LIMIT);
|
|
34874
|
+
const lastBreak = head.lastIndexOf(10);
|
|
34875
|
+
return { path: path3, markdown: head.subarray(0, lastBreak > 0 ? lastBreak : head.length).toString("utf8"), truncated: true };
|
|
34876
|
+
}
|
|
34877
|
+
function resolveWatchableLocalFile(rawPath, roots) {
|
|
34878
|
+
const path3 = resolveLocalFile(rawPath, roots);
|
|
34879
|
+
if (MARKDOWN_FILE_EXT.test(rawPath.trim()) && !MARKDOWN_FILE_EXT.test(path3)) {
|
|
34880
|
+
throw new Error("Local file is not a Markdown file");
|
|
34881
|
+
}
|
|
34882
|
+
return path3;
|
|
34883
|
+
}
|
|
34884
|
+
function defaultSpawn(command, args, options) {
|
|
34885
|
+
return spawn5(command, [...args], options);
|
|
34886
|
+
}
|
|
34887
|
+
function openLocalFile(rawPath, opener, roots, options = {}) {
|
|
34888
|
+
const path3 = resolveLocalFile(rawPath, roots);
|
|
34889
|
+
const selected = options.forceSystem ? "system" : opener;
|
|
34890
|
+
if (selected === "copy") return { action: "copy", path: path3 };
|
|
34891
|
+
const spec = process.platform === "darwin" ? selected === "cursor" ? ["open", ["-a", "Cursor", path3]] : selected === "vscode" ? ["open", ["-a", "Visual Studio Code", path3]] : selected === "finder" ? ["open", ["-R", path3]] : ["open", [path3]] : selected === "finder" ? ["xdg-open", [path3]] : selected === "cursor" ? ["cursor", [path3]] : selected === "vscode" ? ["code", [path3]] : ["xdg-open", [path3]];
|
|
34892
|
+
(options.spawn ?? defaultSpawn)(spec[0], spec[1], { detached: true, stdio: "ignore", shell: false }).unref();
|
|
34893
|
+
return { action: "opened", path: path3 };
|
|
34894
|
+
}
|
|
34895
|
+
var MARKDOWN_FILE_EXT, MARKDOWN_READ_LIMIT;
|
|
34896
|
+
var init_local_file = __esm({
|
|
34897
|
+
"packages/server/src/local-file.ts"() {
|
|
34898
|
+
"use strict";
|
|
34899
|
+
MARKDOWN_FILE_EXT = /\.(?:md|mdx|markdown)$/i;
|
|
34900
|
+
MARKDOWN_READ_LIMIT = 1024 * 1024;
|
|
34901
|
+
}
|
|
34902
|
+
});
|
|
34903
|
+
|
|
34904
|
+
// packages/server/src/thread-links.ts
|
|
34905
|
+
import { isAbsolute as isAbsolute5 } from "node:path";
|
|
34906
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
34907
|
+
function threadLinkView(row) {
|
|
34908
|
+
return { id: row.id, kind: row.kind, label: row.label, target: row.target };
|
|
34909
|
+
}
|
|
34910
|
+
function resolveThreadLink(target, projectDir, roots) {
|
|
34911
|
+
if (/^https?:\/\//i.test(target)) {
|
|
34912
|
+
const url = new URL(target);
|
|
34913
|
+
if (url.username || url.password) throw new Error("Link URLs must not contain credentials");
|
|
34914
|
+
return { kind: "link", target: url.href };
|
|
34915
|
+
}
|
|
34916
|
+
let path3 = target;
|
|
34917
|
+
if (/^file:/i.test(target)) {
|
|
34918
|
+
const url = new URL(target);
|
|
34919
|
+
if (url.search || url.hash) throw new Error("File links must not contain a query or fragment");
|
|
34920
|
+
path3 = fileURLToPath2(url);
|
|
34921
|
+
} else if (!isAbsolute5(target) && /^[a-z][a-z\d+.-]*:/i.test(target)) {
|
|
34922
|
+
throw new Error("Register an HTTP(S) URL or a local file");
|
|
34923
|
+
}
|
|
34924
|
+
const resolved = resolveOpenableFile(path3, projectDir, roots);
|
|
34925
|
+
if (!resolved) throw new Error("Local file was not found or is outside Frizz's trusted roots");
|
|
34926
|
+
return { kind: "file", target: resolved };
|
|
34927
|
+
}
|
|
34928
|
+
var init_thread_links = __esm({
|
|
34929
|
+
"packages/server/src/thread-links.ts"() {
|
|
34930
|
+
"use strict";
|
|
34931
|
+
init_local_file();
|
|
34932
|
+
}
|
|
34933
|
+
});
|
|
34934
|
+
|
|
34673
34935
|
// packages/server/src/frizz.ts
|
|
34674
34936
|
import { execFile as execFile5 } from "node:child_process";
|
|
34675
|
-
import { lstatSync as lstatSync2, realpathSync as
|
|
34676
|
-
import { basename as basename5, dirname as dirname9, join as
|
|
34937
|
+
import { lstatSync as lstatSync2, realpathSync as realpathSync7 } from "node:fs";
|
|
34938
|
+
import { basename as basename5, dirname as dirname9, join as join26, resolve as resolve6 } from "node:path";
|
|
34677
34939
|
import { promisify as promisify5 } from "node:util";
|
|
34678
34940
|
function frizzScriptsDir() {
|
|
34679
34941
|
if (process.env.FRIZZ_SCRIPTS_DIR) return process.env.FRIZZ_SCRIPTS_DIR;
|
|
34680
|
-
return
|
|
34942
|
+
return resolve6(import.meta.dirname, "..", "..", "..", "board");
|
|
34681
34943
|
}
|
|
34682
34944
|
function directFrizzRoot(projectDir) {
|
|
34683
34945
|
try {
|
|
34684
|
-
const projectRoot =
|
|
34685
|
-
const path3 =
|
|
34946
|
+
const projectRoot = realpathSync7(projectDir);
|
|
34947
|
+
const path3 = join26(projectRoot, ".frizz");
|
|
34686
34948
|
const stat2 = lstatSync2(path3);
|
|
34687
34949
|
if (!stat2.isDirectory() || stat2.isSymbolicLink()) return null;
|
|
34688
|
-
const real =
|
|
34950
|
+
const real = realpathSync7(path3);
|
|
34689
34951
|
return dirname9(real) === projectRoot && basename5(real) === ".frizz" ? real : null;
|
|
34690
34952
|
} catch {
|
|
34691
34953
|
return null;
|
|
@@ -34696,7 +34958,7 @@ function frizzDirExists(projectDir) {
|
|
|
34696
34958
|
}
|
|
34697
34959
|
async function readBoard(projectDir, scriptsDir = frizzScriptsDir()) {
|
|
34698
34960
|
if (!directFrizzRoot(projectDir)) throw new Error("unsafe or missing .frizz directory");
|
|
34699
|
-
const { stdout } = await execFileP("node", [
|
|
34961
|
+
const { stdout } = await execFileP("node", [join26(scriptsDir, "index.mjs"), "--json"], {
|
|
34700
34962
|
cwd: projectDir,
|
|
34701
34963
|
env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir },
|
|
34702
34964
|
maxBuffer: 32 * 1024 * 1024
|
|
@@ -34721,7 +34983,7 @@ async function readBoard(projectDir, scriptsDir = frizzScriptsDir()) {
|
|
|
34721
34983
|
};
|
|
34722
34984
|
}
|
|
34723
34985
|
async function runThreadUpdate(projectDir, slug, args, scriptsDir = frizzScriptsDir()) {
|
|
34724
|
-
await execFileP("node", [
|
|
34986
|
+
await execFileP("node", [join26(scriptsDir, "thread-update.mjs"), slug, ...args], {
|
|
34725
34987
|
cwd: projectDir,
|
|
34726
34988
|
env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir }
|
|
34727
34989
|
});
|
|
@@ -34806,12 +35068,12 @@ var init_awaiting = __esm({
|
|
|
34806
35068
|
});
|
|
34807
35069
|
|
|
34808
35070
|
// packages/server/src/backend/project-mcp-servers.ts
|
|
34809
|
-
import { readFileSync as
|
|
34810
|
-
import { homedir as
|
|
34811
|
-
import { join as
|
|
35071
|
+
import { readFileSync as readFileSync18 } from "node:fs";
|
|
35072
|
+
import { homedir as homedir12 } from "node:os";
|
|
35073
|
+
import { join as join27 } from "node:path";
|
|
34812
35074
|
function readJsonObject(path3) {
|
|
34813
35075
|
try {
|
|
34814
|
-
const parsed = JSON.parse(
|
|
35076
|
+
const parsed = JSON.parse(readFileSync18(path3, "utf8"));
|
|
34815
35077
|
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
34816
35078
|
} catch {
|
|
34817
35079
|
return void 0;
|
|
@@ -34902,17 +35164,17 @@ function userScopeRemoteServers(account, cwd, env) {
|
|
|
34902
35164
|
}
|
|
34903
35165
|
function projectMcpServers(cwd, options = {}) {
|
|
34904
35166
|
const env = options.env ?? process.env;
|
|
34905
|
-
const home = options.home ??
|
|
35167
|
+
const home = options.home ?? homedir12();
|
|
34906
35168
|
const configOverride = options.claudeConfigDir ?? (env.CLAUDE_CONFIG_DIR?.trim() ? env.CLAUDE_CONFIG_DIR.trim() : void 0);
|
|
34907
|
-
const accountFile = configOverride ?
|
|
34908
|
-
const userSettingsFile =
|
|
35169
|
+
const accountFile = configOverride ? join27(configOverride, ".claude.json") : join27(home, ".claude.json");
|
|
35170
|
+
const userSettingsFile = join27(configOverride ?? join27(home, ".claude"), "settings.json");
|
|
34909
35171
|
const account = readJsonObject(accountFile);
|
|
34910
35172
|
const out = userScopeRemoteServers(account, cwd, env);
|
|
34911
|
-
const declared = objectField(readJsonObject(
|
|
35173
|
+
const declared = objectField(readJsonObject(join27(cwd, ".mcp.json")), "mcpServers");
|
|
34912
35174
|
if (!declared) return out;
|
|
34913
35175
|
const approval = collectApproval([
|
|
34914
|
-
readJsonObject(
|
|
34915
|
-
readJsonObject(
|
|
35176
|
+
readJsonObject(join27(cwd, ".claude", "settings.json")),
|
|
35177
|
+
readJsonObject(join27(cwd, ".claude", "settings.local.json")),
|
|
34916
35178
|
readJsonObject(userSettingsFile),
|
|
34917
35179
|
objectField(objectField(account, "projects"), cwd)
|
|
34918
35180
|
]);
|
|
@@ -34937,16 +35199,16 @@ var init_project_mcp_servers = __esm({
|
|
|
34937
35199
|
|
|
34938
35200
|
// packages/server/src/worker-plugin-dir.ts
|
|
34939
35201
|
import { existsSync as existsSync8 } from "node:fs";
|
|
34940
|
-
import { dirname as dirname10, join as
|
|
34941
|
-
import { fileURLToPath as
|
|
35202
|
+
import { dirname as dirname10, join as join28 } from "node:path";
|
|
35203
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
34942
35204
|
function resolveWorkerPluginDir(moduleUrl = import.meta.url, env = process.env) {
|
|
34943
35205
|
const override = env.FRIZZ_WORKER_PLUGIN_DIR;
|
|
34944
|
-
if (override && existsSync8(
|
|
35206
|
+
if (override && existsSync8(join28(override, ".claude-plugin", "plugin.json")))
|
|
34945
35207
|
return override;
|
|
34946
|
-
let current = dirname10(
|
|
35208
|
+
let current = dirname10(fileURLToPath3(moduleUrl));
|
|
34947
35209
|
for (; ; ) {
|
|
34948
|
-
const candidate =
|
|
34949
|
-
if (existsSync8(
|
|
35210
|
+
const candidate = join28(current, "cc-worker");
|
|
35211
|
+
if (existsSync8(join28(candidate, ".claude-plugin", "plugin.json"))) return candidate;
|
|
34950
35212
|
const parent = dirname10(current);
|
|
34951
35213
|
if (parent === current) return void 0;
|
|
34952
35214
|
current = parent;
|
|
@@ -34974,6 +35236,7 @@ function buildWorkerPrompt(kind = "claude", opts = {}) {
|
|
|
34974
35236
|
lean ? null : THREAD_EXECUTION[kind],
|
|
34975
35237
|
AGENT_COMPLETION,
|
|
34976
35238
|
VISUAL_EVIDENCE,
|
|
35239
|
+
REGISTERED_LINKS,
|
|
34977
35240
|
QUALITY_BAR,
|
|
34978
35241
|
TOKEN_ECONOMY,
|
|
34979
35242
|
QUESTIONS,
|
|
@@ -34985,7 +35248,7 @@ function buildWorkerPrompt(kind = "claude", opts = {}) {
|
|
|
34985
35248
|
out = out.replaceAll("{{FRIZZ_MONITORS_DIR}}", opts.monitorsDir?.trim() || MONITORS_DIR_FALLBACK);
|
|
34986
35249
|
return out;
|
|
34987
35250
|
}
|
|
34988
|
-
var INLINE, INTRO, DEFER, OPENING, ACTIVITY_CAPTIONS, SIGNALS, AGENT_COMPLETION, VISUAL_EVIDENCE, QUALITY_BAR, TOKEN_ECONOMY, QUESTIONS, STOP_CRITERION, TRIVIAL_PROMPTS, THREAD_NAME, SCRATCHPAD, BACKEND, SPAWN_THREAD, THREAD_EXECUTION, MONITORS_DIR_FALLBACK;
|
|
35251
|
+
var INLINE, INTRO, DEFER, OPENING, ACTIVITY_CAPTIONS, SIGNALS, AGENT_COMPLETION, VISUAL_EVIDENCE, REGISTERED_LINKS, QUALITY_BAR, TOKEN_ECONOMY, QUESTIONS, STOP_CRITERION, TRIVIAL_PROMPTS, THREAD_NAME, SCRATCHPAD, BACKEND, SPAWN_THREAD, THREAD_EXECUTION, MONITORS_DIR_FALLBACK;
|
|
34989
35252
|
var init_workerPrompt = __esm({
|
|
34990
35253
|
"packages/server/src/workerPrompt.ts"() {
|
|
34991
35254
|
"use strict";
|
|
@@ -35170,7 +35433,8 @@ exactly ONE of them.
|
|
|
35170
35433
|
|
|
35171
35434
|
- **THE FRONTMATTER IS YAML. THE BODY IS MARKDOWN.** Four PLURAL keys taking LISTS (either list form;
|
|
35172
35435
|
a single item may be written bare), plus the scalars \`for:\` and \`title:\`. **NO PROSE ABOVE THE
|
|
35173
|
-
\`---\`, EVER** \u2014 a colon or a \` #\` inside a sentence breaks the parse.
|
|
35436
|
+
\`---\`, EVER** \u2014 a colon or a \` #\` inside a sentence breaks the parse. (The \`title:\` value is the
|
|
35437
|
+
one exception: frizz reads it verbatim, so \`#391\` and a colon are safe there.) There is no \`reason:\` key any more;
|
|
35174
35438
|
the reason goes in the body, which is the handoff the human reads. **THE SINGULAR KEYS ARE GONE** \u2014 \`shell:\`,
|
|
35175
35439
|
\`agent:\`, \`timer:\`, \`pr:\` and \`reason:\`, one per line, were the grammar until 2026-08-24; YAML
|
|
35176
35440
|
cannot express a repeated key, so they became the lists above. Write one and frizz tells you what
|
|
@@ -35276,6 +35540,12 @@ image paths through its guarded local-image proxy; only eligible workspace or ex
|
|
|
35276
35540
|
image files can embed, and a path outside that safe boundary stays non-navigable. Do not bulk-embed
|
|
35277
35541
|
irrelevant screenshots. Always keep a concise textual finding alongside them, so the handoff still
|
|
35278
35542
|
reads when images are unavailable.`;
|
|
35543
|
+
REGISTERED_LINKS = `## Saved links and files
|
|
35544
|
+
|
|
35545
|
+
Use \`mcp__frizz__link\` with \`label\` and \`target\` for a dev server, working document, report or download
|
|
35546
|
+
the human should keep at hand. It stays underneath the prompt. Reuse the label to update its destination;
|
|
35547
|
+
read registrations with \`activity\` and remove one with \`unlink\`. Register existing files, using an
|
|
35548
|
+
absolute path outside the project root. A saved reference is not a running process or a completion gate.`;
|
|
35279
35549
|
QUALITY_BAR = `## Quality bar
|
|
35280
35550
|
|
|
35281
35551
|
- Verify behavior end-to-end before calling anything done. A green suite over a stubbed implementation
|
|
@@ -36100,12 +36370,12 @@ var init_claude_broker_client = __esm({
|
|
|
36100
36370
|
});
|
|
36101
36371
|
|
|
36102
36372
|
// packages/server/src/backend/claude-permission-interactions.ts
|
|
36103
|
-
import { homedir as
|
|
36373
|
+
import { homedir as homedir13 } from "node:os";
|
|
36104
36374
|
function clip(text2, max) {
|
|
36105
36375
|
return text2.length > max ? `${text2.slice(0, max - 1)}\u2026` : text2;
|
|
36106
36376
|
}
|
|
36107
36377
|
function tildePath(path3) {
|
|
36108
|
-
const home =
|
|
36378
|
+
const home = homedir13();
|
|
36109
36379
|
if (!path3.startsWith(home)) return path3;
|
|
36110
36380
|
const rest = path3.slice(home.length);
|
|
36111
36381
|
return rest === "" ? "~" : rest.startsWith("/") ? `~${rest}` : path3;
|
|
@@ -36755,8 +37025,8 @@ var init_claude_agent_broker_bridge = __esm({
|
|
|
36755
37025
|
});
|
|
36756
37026
|
|
|
36757
37027
|
// packages/server/src/dispatch.ts
|
|
36758
|
-
import { closeSync as closeSync12, constants, existsSync as existsSync9, fstatSync as fstatSync2, lstatSync as lstatSync3, openSync as openSync13, readFileSync as
|
|
36759
|
-
import { basename as basename6, join as
|
|
37028
|
+
import { closeSync as closeSync12, constants, existsSync as existsSync9, fstatSync as fstatSync2, lstatSync as lstatSync3, openSync as openSync13, readFileSync as readFileSync19, realpathSync as realpathSync8, statSync as statSync13, writeFileSync as writeFileSync10, mkdirSync as mkdirSync13, rmSync as rmSync9 } from "node:fs";
|
|
37029
|
+
import { basename as basename6, join as join29, dirname as dirname11 } from "node:path";
|
|
36760
37030
|
import { createHash as createHash11, randomUUID as randomUUID13 } from "node:crypto";
|
|
36761
37031
|
function fallbackTitle(prompt) {
|
|
36762
37032
|
const firstLine2 = prompt.trim().split("\n", 1)[0].trim();
|
|
@@ -36775,7 +37045,7 @@ function fallbackTitle(prompt) {
|
|
|
36775
37045
|
}
|
|
36776
37046
|
function resolveSlug(frizzDir, base, taken) {
|
|
36777
37047
|
base = ThreadSlug.parse(base);
|
|
36778
|
-
const isTaken = (slug) => existsSync9(
|
|
37048
|
+
const isTaken = (slug) => existsSync9(join29(frizzDir, `${slug}.md`)) || (taken?.(slug) ?? false);
|
|
36779
37049
|
if (!isTaken(base)) return base;
|
|
36780
37050
|
for (let n = 2; ; n++) {
|
|
36781
37051
|
const suffix = `-${n}`;
|
|
@@ -36791,16 +37061,16 @@ function resolveLegacyThreadFile(projectDir, value) {
|
|
|
36791
37061
|
const parsed = ThreadSlug.safeParse(value);
|
|
36792
37062
|
if (!parsed.success) return null;
|
|
36793
37063
|
try {
|
|
36794
|
-
const projectRoot =
|
|
36795
|
-
const frizzPath =
|
|
37064
|
+
const projectRoot = realpathSync8(projectDir);
|
|
37065
|
+
const frizzPath = join29(projectRoot, ".frizz");
|
|
36796
37066
|
const frizzStat = lstatSync3(frizzPath);
|
|
36797
37067
|
if (!frizzStat.isDirectory() || frizzStat.isSymbolicLink()) return null;
|
|
36798
|
-
const realFrizz =
|
|
37068
|
+
const realFrizz = realpathSync8(frizzPath);
|
|
36799
37069
|
if (dirname11(realFrizz) !== projectRoot || basename6(realFrizz) !== ".frizz") return null;
|
|
36800
|
-
const path3 =
|
|
37070
|
+
const path3 = join29(realFrizz, `${parsed.data}.md`);
|
|
36801
37071
|
const before = lstatSync3(path3);
|
|
36802
37072
|
if (!before.isFile() || before.isSymbolicLink()) return null;
|
|
36803
|
-
const realPath =
|
|
37073
|
+
const realPath = realpathSync8(path3);
|
|
36804
37074
|
if (dirname11(realPath) !== realFrizz || basename6(realPath) !== `${parsed.data}.md`) return null;
|
|
36805
37075
|
let contents;
|
|
36806
37076
|
let openedBefore;
|
|
@@ -36808,7 +37078,7 @@ function resolveLegacyThreadFile(projectDir, value) {
|
|
|
36808
37078
|
const fd = openSync13(path3, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
36809
37079
|
try {
|
|
36810
37080
|
openedBefore = fstatSync2(fd);
|
|
36811
|
-
contents =
|
|
37081
|
+
contents = readFileSync19(fd);
|
|
36812
37082
|
openedAfter = fstatSync2(fd);
|
|
36813
37083
|
} finally {
|
|
36814
37084
|
closeSync12(fd);
|
|
@@ -36841,7 +37111,7 @@ function boardAuthorizesAdoption(board, slug) {
|
|
|
36841
37111
|
return !board.errorItems.some((item) => item.file === `${slug}.md`);
|
|
36842
37112
|
}
|
|
36843
37113
|
function ensureSafeDirectDirectory(parent, name) {
|
|
36844
|
-
const path3 =
|
|
37114
|
+
const path3 = join29(parent, name);
|
|
36845
37115
|
try {
|
|
36846
37116
|
mkdirSync13(path3);
|
|
36847
37117
|
} catch (error) {
|
|
@@ -36850,7 +37120,7 @@ function ensureSafeDirectDirectory(parent, name) {
|
|
|
36850
37120
|
}
|
|
36851
37121
|
const stat2 = lstatSync3(path3);
|
|
36852
37122
|
if (!stat2.isDirectory() || stat2.isSymbolicLink()) throw new Error("unsafe project directory");
|
|
36853
|
-
const real =
|
|
37123
|
+
const real = realpathSync8(path3);
|
|
36854
37124
|
if (dirname11(real) !== parent || basename6(real) !== name) throw new Error("unsafe project directory");
|
|
36855
37125
|
return real;
|
|
36856
37126
|
}
|
|
@@ -36859,7 +37129,7 @@ function scratchDirRelPath(sessionId) {
|
|
|
36859
37129
|
}
|
|
36860
37130
|
function writeScratchDir(projectDir, sessionId) {
|
|
36861
37131
|
if (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/.test(sessionId)) throw new Error("invalid session id");
|
|
36862
|
-
const projectRoot =
|
|
37132
|
+
const projectRoot = realpathSync8(projectDir);
|
|
36863
37133
|
const frizzDir = ensureSafeDirectDirectory(projectRoot, ".frizz");
|
|
36864
37134
|
const threadsDir = ensureSafeDirectDirectory(frizzDir, "threads");
|
|
36865
37135
|
ensureSafeDirectDirectory(threadsDir, sessionId);
|
|
@@ -36871,8 +37141,8 @@ function loadWorkerPrompt(kind = "claude") {
|
|
|
36871
37141
|
function monitorScriptsDir() {
|
|
36872
37142
|
const plugin = workerPluginDir();
|
|
36873
37143
|
if (!plugin) return void 0;
|
|
36874
|
-
const dir =
|
|
36875
|
-
return existsSync9(
|
|
37144
|
+
const dir = join29(plugin, "skills", "gh", "scripts");
|
|
37145
|
+
return existsSync9(join29(dir, "ci-watch.mjs")) ? dir : void 0;
|
|
36876
37146
|
}
|
|
36877
37147
|
function codexScratchpadHookConfig(hookScript, sessionId) {
|
|
36878
37148
|
if (!hookScript || !sessionId) return {};
|
|
@@ -36884,7 +37154,7 @@ function codexScratchpadHookConfig(hookScript, sessionId) {
|
|
|
36884
37154
|
}
|
|
36885
37155
|
]
|
|
36886
37156
|
});
|
|
36887
|
-
const bashBackgroundHook =
|
|
37157
|
+
const bashBackgroundHook = join29(dirname11(hookScript), "bash-background.mjs");
|
|
36888
37158
|
return {
|
|
36889
37159
|
bypass_hook_trust: true,
|
|
36890
37160
|
hooks: {
|
|
@@ -36910,7 +37180,7 @@ function codexScratchpadHookConfig(hookScript, sessionId) {
|
|
|
36910
37180
|
}
|
|
36911
37181
|
function scratchpadHookScript() {
|
|
36912
37182
|
const plugin = workerPluginDir();
|
|
36913
|
-
return plugin ?
|
|
37183
|
+
return plugin ? join29(plugin, "hooks", "scratchpad.mjs") : void 0;
|
|
36914
37184
|
}
|
|
36915
37185
|
function composePrompt(sessionId, prompt, kind = "claude") {
|
|
36916
37186
|
const children2 = kind === "codex" ? "Native sub-agents share it \u2014 have each write its OWN file rather than all editing one." : "Name it in a sub-agent's prompt when you want its notes to land somewhere you can read; give each child its OWN file rather than having them all edit one.";
|
|
@@ -36926,12 +37196,12 @@ function scratchpadOrientation(sessionId, kind = "claude") {
|
|
|
36926
37196
|
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, mcp__frizz__goal with post_compaction: true re-sends a prompt of your choosing.`;
|
|
36927
37197
|
}
|
|
36928
37198
|
function frizzConfigBlock(projectDir) {
|
|
36929
|
-
const path3 =
|
|
37199
|
+
const path3 = join29(projectDir, "FRIZZ.md");
|
|
36930
37200
|
let body;
|
|
36931
37201
|
try {
|
|
36932
|
-
const st =
|
|
37202
|
+
const st = statSync13(path3);
|
|
36933
37203
|
if (!st.isFile() || st.size > FRIZZ_MD_MAX_BYTES) return "";
|
|
36934
|
-
body =
|
|
37204
|
+
body = readFileSync19(path3, "utf8").trim();
|
|
36935
37205
|
} catch {
|
|
36936
37206
|
return "";
|
|
36937
37207
|
}
|
|
@@ -36970,7 +37240,7 @@ function resolveFrizzMcp(target, moduleUrl = import.meta.url, env = process.env,
|
|
|
36970
37240
|
const { stateDir, serverLock, projectId } = typeof target === "string" ? { stateDir: target } : target;
|
|
36971
37241
|
const pluginDir = resolveWorkerPluginDir(moduleUrl, env);
|
|
36972
37242
|
if (!pluginDir) return void 0;
|
|
36973
|
-
const scriptPath =
|
|
37243
|
+
const scriptPath = join29(pluginDir, "bin", FRIZZ_MCP.script);
|
|
36974
37244
|
if (!existsSync9(scriptPath)) return void 0;
|
|
36975
37245
|
return {
|
|
36976
37246
|
scriptPath,
|
|
@@ -37053,7 +37323,7 @@ function buildClaudeResumeCommand(opts) {
|
|
|
37053
37323
|
}
|
|
37054
37324
|
function createDispatcher(deps) {
|
|
37055
37325
|
const readBoardSource = deps.readBoard ?? readBoard;
|
|
37056
|
-
const frizzDir =
|
|
37326
|
+
const frizzDir = join29(deps.project.dir, ".frizz");
|
|
37057
37327
|
const adoptionRuntime = deps.adoptionRuntime ?? productionRuntime;
|
|
37058
37328
|
function cleanupPrewrites(built) {
|
|
37059
37329
|
for (const path3 of new Set(built.prewrite.map((file) => file.path))) {
|
|
@@ -37066,7 +37336,7 @@ function createDispatcher(deps) {
|
|
|
37066
37336
|
function cleanupDispatchFiles(scratchRel, built, sessionId) {
|
|
37067
37337
|
cleanupPrewrites(built);
|
|
37068
37338
|
try {
|
|
37069
|
-
rmSync9(
|
|
37339
|
+
rmSync9(join29(deps.project.dir, scratchRel), { force: true, recursive: true });
|
|
37070
37340
|
} catch {
|
|
37071
37341
|
}
|
|
37072
37342
|
cleanupAdoptionSessionFiles(deps.project.dir, sessionId);
|
|
@@ -37504,11 +37774,11 @@ var init_dispatch = __esm({
|
|
|
37504
37774
|
|
|
37505
37775
|
// packages/server/src/board.ts
|
|
37506
37776
|
import {
|
|
37507
|
-
realpathSync as
|
|
37777
|
+
realpathSync as realpathSync9,
|
|
37508
37778
|
watch as fsWatch
|
|
37509
37779
|
} from "node:fs";
|
|
37510
|
-
import { homedir as
|
|
37511
|
-
import { dirname as dirname12, join as
|
|
37780
|
+
import { homedir as homedir14 } from "node:os";
|
|
37781
|
+
import { dirname as dirname12, join as join30 } from "node:path";
|
|
37512
37782
|
import watcher from "@parcel/watcher";
|
|
37513
37783
|
function appServerTurnStalled(liveness, lastActivityAt, nowMs) {
|
|
37514
37784
|
if (!liveness) return false;
|
|
@@ -37891,6 +38161,7 @@ function registeredDoneFence(done, lastUserAt) {
|
|
|
37891
38161
|
}
|
|
37892
38162
|
function readThreadRegistries(storage) {
|
|
37893
38163
|
return {
|
|
38164
|
+
links: storage.threadLinksBySlug(),
|
|
37894
38165
|
prWatches: storage.armedPrWatchesBySlug(),
|
|
37895
38166
|
timers: storage.armedThreadTimersBySlug(),
|
|
37896
38167
|
questions: storage.threadQuestionsBySlug(),
|
|
@@ -37998,6 +38269,7 @@ function sessionThreadView(projectDir, storage, row, rawTele, registeredLegacyTe
|
|
|
37998
38269
|
lastAssistantAt: tele?.lastAssistantAt,
|
|
37999
38270
|
subAgents: stampStoppable(tele?.subAgents ?? [], row),
|
|
38000
38271
|
bgShells: stampStoppableShells(tele?.bgShells ?? [], row),
|
|
38272
|
+
links: (registries.links.get(row.slug) ?? []).map(threadLinkView),
|
|
38001
38273
|
// ONE SOURCE: the FENCE. Both kinds are derived from what the worker wrote — `prs:` entries
|
|
38002
38274
|
// become the github rows, `watch:` lines the shell rows — so this strip lists exactly what will
|
|
38003
38275
|
// actually wake the thread, and the two cannot drift into claiming different things. There is no
|
|
@@ -38245,7 +38517,7 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
|
|
|
38245
38517
|
...project.githubRepo ? { githubRepo: project.githubRepo } : {},
|
|
38246
38518
|
projectSlug: findByPath(project.dir)?.slug,
|
|
38247
38519
|
// So the client can expand a `~` a worker wrote in prose (see BoardSnapshot.homeDir).
|
|
38248
|
-
homeDir:
|
|
38520
|
+
homeDir: homedir14()
|
|
38249
38521
|
};
|
|
38250
38522
|
const sessionThreads = buildSessionThreads(assembledAtMs);
|
|
38251
38523
|
armSnoozeWake(sessionThreads, assembledAtMs);
|
|
@@ -38346,10 +38618,10 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
|
|
|
38346
38618
|
if (parcelSub || stopped) return Promise.resolve();
|
|
38347
38619
|
if (watchSetup) return watchSetup;
|
|
38348
38620
|
const setup = (async () => {
|
|
38349
|
-
const dir =
|
|
38621
|
+
const dir = join30(project.dir, ".frizz");
|
|
38350
38622
|
const roots = /* @__PURE__ */ new Set([dir]);
|
|
38351
38623
|
try {
|
|
38352
|
-
roots.add(
|
|
38624
|
+
roots.add(realpathSync9(dir));
|
|
38353
38625
|
} catch {
|
|
38354
38626
|
}
|
|
38355
38627
|
const next = await subscribe(
|
|
@@ -38361,7 +38633,7 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
|
|
|
38361
38633
|
}
|
|
38362
38634
|
if (events.some((event) => isBoardRelevantFrizzPath(roots, event.path))) scheduleRebuild();
|
|
38363
38635
|
},
|
|
38364
|
-
{ ignore: FRIZZ_WATCH_IGNORED_DIRS.map((name) =>
|
|
38636
|
+
{ ignore: FRIZZ_WATCH_IGNORED_DIRS.map((name) => join30(dir, name)) }
|
|
38365
38637
|
);
|
|
38366
38638
|
if (stopped) {
|
|
38367
38639
|
await next.unsubscribe();
|
|
@@ -38443,6 +38715,7 @@ var init_board = __esm({
|
|
|
38443
38715
|
"use strict";
|
|
38444
38716
|
init_src();
|
|
38445
38717
|
init_storage();
|
|
38718
|
+
init_thread_links();
|
|
38446
38719
|
init_thread_profiles();
|
|
38447
38720
|
init_frizz();
|
|
38448
38721
|
init_awaiting();
|
|
@@ -41038,7 +41311,7 @@ var init_resume = __esm({
|
|
|
41038
41311
|
});
|
|
41039
41312
|
|
|
41040
41313
|
// packages/server/src/backend/claude.ts
|
|
41041
|
-
import { join as
|
|
41314
|
+
import { join as join31 } from "node:path";
|
|
41042
41315
|
function toolResultText2(content) {
|
|
41043
41316
|
if (typeof content === "string") return content;
|
|
41044
41317
|
if (!Array.isArray(content)) return "";
|
|
@@ -41129,7 +41402,7 @@ function createClaudeBackend(opts) {
|
|
|
41129
41402
|
return { argv, env: claudeWorkerEnvironment(), prewrite: [] };
|
|
41130
41403
|
},
|
|
41131
41404
|
transcriptPath(sessionId) {
|
|
41132
|
-
return
|
|
41405
|
+
return join31(opts.logDir, `${sessionId}.jsonl`);
|
|
41133
41406
|
},
|
|
41134
41407
|
parseLine(line) {
|
|
41135
41408
|
return parseClaudeLine(line);
|
|
@@ -41299,13 +41572,13 @@ var init_login_utility = __esm({
|
|
|
41299
41572
|
});
|
|
41300
41573
|
|
|
41301
41574
|
// packages/server/src/backend/codex-app-server-diagnostics.ts
|
|
41302
|
-
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync14, renameSync as renameSync8, statSync as
|
|
41303
|
-
import { join as
|
|
41575
|
+
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync14, renameSync as renameSync8, statSync as statSync14 } from "node:fs";
|
|
41576
|
+
import { join as join32 } from "node:path";
|
|
41304
41577
|
function codexDiagnosticLogPath(stateDir, projectId) {
|
|
41305
|
-
return
|
|
41578
|
+
return join32(stateDir, "codex-app-server", `${projectId}.diagnostics.log`);
|
|
41306
41579
|
}
|
|
41307
41580
|
function createCodexDiagnosticSink(stateDir, projectId, now = () => /* @__PURE__ */ new Date()) {
|
|
41308
|
-
const dir =
|
|
41581
|
+
const dir = join32(stateDir, "codex-app-server");
|
|
41309
41582
|
const path3 = codexDiagnosticLogPath(stateDir, projectId);
|
|
41310
41583
|
let ensured = false;
|
|
41311
41584
|
return (event) => {
|
|
@@ -41316,7 +41589,7 @@ function createCodexDiagnosticSink(stateDir, projectId, now = () => /* @__PURE__
|
|
|
41316
41589
|
ensured = true;
|
|
41317
41590
|
}
|
|
41318
41591
|
try {
|
|
41319
|
-
if (
|
|
41592
|
+
if (statSync14(path3).size > MAX_BYTES2) renameSync8(path3, `${path3}.1`);
|
|
41320
41593
|
} catch {
|
|
41321
41594
|
}
|
|
41322
41595
|
appendFileSync3(path3, `${JSON.stringify({ at: now().toISOString(), ...event })}
|
|
@@ -41337,7 +41610,7 @@ var init_codex_app_server_diagnostics = __esm({
|
|
|
41337
41610
|
import { execFile as execFile8 } from "node:child_process";
|
|
41338
41611
|
import { readdirSync as readdirSync8, unlinkSync as unlinkSync4 } from "node:fs";
|
|
41339
41612
|
import { connect as connectSocket } from "node:net";
|
|
41340
|
-
import { join as
|
|
41613
|
+
import { join as join33 } from "node:path";
|
|
41341
41614
|
function parseLsofSocketNames(stdout) {
|
|
41342
41615
|
const referenced = /* @__PURE__ */ new Set();
|
|
41343
41616
|
for (const line of stdout.split("\n")) {
|
|
@@ -41354,7 +41627,7 @@ function sweepStaleSockets(options, deps = {}) {
|
|
|
41354
41627
|
const keep = new Set(options.keep ?? []);
|
|
41355
41628
|
let candidates;
|
|
41356
41629
|
try {
|
|
41357
|
-
candidates = (deps.readdir ?? readdirSync8)(options.dir).filter((name) => name.startsWith(options.prefix) && name.endsWith(".sock")).map((name) =>
|
|
41630
|
+
candidates = (deps.readdir ?? readdirSync8)(options.dir).filter((name) => name.startsWith(options.prefix) && name.endsWith(".sock")).map((name) => join33(options.dir, name)).filter((path3) => !keep.has(path3));
|
|
41358
41631
|
} catch {
|
|
41359
41632
|
return;
|
|
41360
41633
|
}
|
|
@@ -41404,7 +41677,7 @@ var init_stale_socket_sweep = __esm({
|
|
|
41404
41677
|
|
|
41405
41678
|
// packages/server/src/orphan-reaper.ts
|
|
41406
41679
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
41407
|
-
import { readFileSync as
|
|
41680
|
+
import { readFileSync as readFileSync20 } from "node:fs";
|
|
41408
41681
|
import { dirname as dirname13 } from "node:path";
|
|
41409
41682
|
function firstTokenBasename(command) {
|
|
41410
41683
|
const first = command.trimStart().split(/\s+/, 1)[0] ?? "";
|
|
@@ -41671,7 +41944,7 @@ var init_orphan_reaper = __esm({
|
|
|
41671
41944
|
defaultExec = (file, args) => execFileSync4(file, args, { encoding: "utf8", maxBuffer: 16 * 1024 * 1024, timeout: 1e4 });
|
|
41672
41945
|
defaultReadEnv = (pid) => {
|
|
41673
41946
|
try {
|
|
41674
|
-
return
|
|
41947
|
+
return readFileSync20(`/proc/${pid}/environ`, "utf8");
|
|
41675
41948
|
} catch {
|
|
41676
41949
|
return null;
|
|
41677
41950
|
}
|
|
@@ -41818,9 +42091,9 @@ var init_thread_hibernation = __esm({
|
|
|
41818
42091
|
});
|
|
41819
42092
|
|
|
41820
42093
|
// packages/server/src/context.ts
|
|
41821
|
-
import { join as
|
|
42094
|
+
import { join as join34 } from "node:path";
|
|
41822
42095
|
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
41823
|
-
import { homedir as
|
|
42096
|
+
import { homedir as homedir15 } from "node:os";
|
|
41824
42097
|
function reconcileSessions(storage) {
|
|
41825
42098
|
for (const row of storage.allSessions()) {
|
|
41826
42099
|
if (isHeadlessRow(row)) continue;
|
|
@@ -41966,9 +42239,9 @@ async function createContext(opts = {}) {
|
|
|
41966
42239
|
}
|
|
41967
42240
|
}
|
|
41968
42241
|
function createContextUnchecked(opts, resources) {
|
|
41969
|
-
const home = opts.home ??
|
|
42242
|
+
const home = opts.home ?? homedir15();
|
|
41970
42243
|
const project = opts.project ?? resolveProject();
|
|
41971
|
-
const storage = createStorage(opts.database ??
|
|
42244
|
+
const storage = createStorage(opts.database ?? join34(project.stateDir, "ui.db"), project.id);
|
|
41972
42245
|
resources.storage = storage;
|
|
41973
42246
|
const bus = new Bus();
|
|
41974
42247
|
const transcriptChange = new Emitter();
|
|
@@ -42078,7 +42351,10 @@ function createContextUnchecked(opts, resources) {
|
|
|
42078
42351
|
const mode = PermissionMode.safeParse(row.permission_mode);
|
|
42079
42352
|
if (!mode.success) return void 0;
|
|
42080
42353
|
return codexSandbox(mode.data);
|
|
42081
|
-
}
|
|
42354
|
+
},
|
|
42355
|
+
// Read at every thread/start and cold resume, so the Codex context window the operator picks in
|
|
42356
|
+
// Settings reaches the next thread without an app-server restart.
|
|
42357
|
+
getSettings: () => getSettings(storage, home)
|
|
42082
42358
|
}) : void 0;
|
|
42083
42359
|
resources.codexAppServer = codexAppServer;
|
|
42084
42360
|
if (codexAppServer) {
|
|
@@ -45023,8 +45299,8 @@ var init_server = __esm({
|
|
|
45023
45299
|
});
|
|
45024
45300
|
|
|
45025
45301
|
// packages/server/src/repair.ts
|
|
45026
|
-
import { existsSync as existsSync11, readFileSync as
|
|
45027
|
-
import { basename as basename7, dirname as dirname14, resolve as
|
|
45302
|
+
import { existsSync as existsSync11, readFileSync as readFileSync21, writeFileSync as writeFileSync11 } from "node:fs";
|
|
45303
|
+
import { basename as basename7, dirname as dirname14, resolve as resolve8 } from "node:path";
|
|
45028
45304
|
function quoteValue(v) {
|
|
45029
45305
|
if (/^[\w./#:+-]+$/.test(v)) return v;
|
|
45030
45306
|
return `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
@@ -45034,12 +45310,12 @@ function deriveTitle(body, slug) {
|
|
|
45034
45310
|
return m ? m[1].trim() : slug;
|
|
45035
45311
|
}
|
|
45036
45312
|
function repairThreadFile(frizzDir, file) {
|
|
45037
|
-
const root =
|
|
45038
|
-
const abs =
|
|
45313
|
+
const root = resolve8(frizzDir);
|
|
45314
|
+
const abs = resolve8(root, file);
|
|
45039
45315
|
if (dirname14(abs) !== root) throw new RepairError(`refusing to repair "${file}": not directly under .frizz/`);
|
|
45040
45316
|
if (!abs.endsWith(".md")) throw new RepairError(`refusing to repair "${file}": not a .md thread file`);
|
|
45041
45317
|
if (!existsSync11(abs)) throw new RepairError(`no thread file to repair: ${basename7(abs)}`);
|
|
45042
|
-
const content =
|
|
45318
|
+
const content = readFileSync21(abs, "utf8");
|
|
45043
45319
|
const firstLine2 = content.replace(/^/, "").split(/\r?\n/).find((l) => l.trim() !== "");
|
|
45044
45320
|
if (firstLine2?.trim() === "---") {
|
|
45045
45321
|
throw new RepairError(`${basename7(abs)} already opens with a "---" block \u2014 repair only heals a MISSING frontmatter block`);
|
|
@@ -45230,7 +45506,7 @@ var init_repo_files = __esm({
|
|
|
45230
45506
|
});
|
|
45231
45507
|
|
|
45232
45508
|
// cc-worker/hooks/bash-background.mjs
|
|
45233
|
-
import { readFileSync as
|
|
45509
|
+
import { readFileSync as readFileSync22 } from "node:fs";
|
|
45234
45510
|
import { basename as basename8 } from "node:path";
|
|
45235
45511
|
import { pathToFileURL } from "node:url";
|
|
45236
45512
|
function emit(obj) {
|
|
@@ -45379,7 +45655,7 @@ var init_bash_background = __esm({
|
|
|
45379
45655
|
if (isDirectHookExecution(process.argv[1], import.meta.url)) {
|
|
45380
45656
|
try {
|
|
45381
45657
|
const env = process.argv.includes("--frizz-thread") ? { ...process.env, FRIZZ_THREAD: process.env.FRIZZ_THREAD || "codex-worker" } : process.env;
|
|
45382
|
-
emit(evaluateBashBackgroundHook(JSON.parse(
|
|
45658
|
+
emit(evaluateBashBackgroundHook(JSON.parse(readFileSync22(0, "utf8")), env));
|
|
45383
45659
|
} catch {
|
|
45384
45660
|
emit({});
|
|
45385
45661
|
}
|
|
@@ -45388,11 +45664,11 @@ var init_bash_background = __esm({
|
|
|
45388
45664
|
});
|
|
45389
45665
|
|
|
45390
45666
|
// packages/server/src/transcript.ts
|
|
45391
|
-
import { closeSync as closeSync13, existsSync as existsSync12, fstatSync as fstatSync3, mkdirSync as mkdirSync15, openSync as openSync14, readdirSync as readdirSync9, readFileSync as
|
|
45667
|
+
import { closeSync as closeSync13, existsSync as existsSync12, fstatSync as fstatSync3, mkdirSync as mkdirSync15, openSync as openSync14, readdirSync as readdirSync9, readFileSync as readFileSync23, readSync as readSync7, renameSync as renameSync9, statSync as statSync15, unlinkSync as unlinkSync5, writeFileSync as writeFileSync12 } from "node:fs";
|
|
45392
45668
|
import { createHash as createHash13 } from "node:crypto";
|
|
45393
45669
|
import { StringDecoder as StringDecoder4 } from "node:string_decoder";
|
|
45394
|
-
import { join as
|
|
45395
|
-
import { homedir as
|
|
45670
|
+
import { join as join35 } from "node:path";
|
|
45671
|
+
import { homedir as homedir16 } from "node:os";
|
|
45396
45672
|
function formatTokens(n) {
|
|
45397
45673
|
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
45398
45674
|
if (n >= 1e3) return `${Math.round(n / 1e3)}k`;
|
|
@@ -45971,14 +46247,14 @@ function pruneScreenshotCache() {
|
|
|
45971
46247
|
if (entries2.length <= SCREENSHOT_CACHE_MAX) return;
|
|
45972
46248
|
const byMtime = entries2.map((n) => {
|
|
45973
46249
|
try {
|
|
45974
|
-
return { n, m:
|
|
46250
|
+
return { n, m: statSync15(join35(SCREENSHOT_CACHE_DIR, n)).mtimeMs };
|
|
45975
46251
|
} catch {
|
|
45976
46252
|
return { n, m: 0 };
|
|
45977
46253
|
}
|
|
45978
46254
|
}).sort((a, b) => b.m - a.m);
|
|
45979
46255
|
for (const { n } of byMtime.slice(SCREENSHOT_CACHE_MAX)) {
|
|
45980
46256
|
try {
|
|
45981
|
-
unlinkSync5(
|
|
46257
|
+
unlinkSync5(join35(SCREENSHOT_CACHE_DIR, n));
|
|
45982
46258
|
} catch {
|
|
45983
46259
|
}
|
|
45984
46260
|
}
|
|
@@ -46008,14 +46284,14 @@ function persistBase64Image(mediaType, data, idKey) {
|
|
|
46008
46284
|
const ext = IMAGE_MEDIA_EXT[typeof mediaType === "string" ? mediaType.toLowerCase() : ""];
|
|
46009
46285
|
if (!ext || !data) return void 0;
|
|
46010
46286
|
const name = createHash13("sha256").update(idKey).digest("hex").slice(0, 32);
|
|
46011
|
-
const path3 =
|
|
46287
|
+
const path3 = join35(SCREENSHOT_CACHE_DIR, `${name}.${ext}`);
|
|
46012
46288
|
try {
|
|
46013
46289
|
if (existsSync12(path3)) return path3;
|
|
46014
46290
|
if (data.length > SCREENSHOT_MAX_BASE64) return void 0;
|
|
46015
46291
|
const buf = Buffer.from(data, "base64");
|
|
46016
46292
|
if (buf.length === 0 || !looksLikeImage(buf, ext)) return void 0;
|
|
46017
46293
|
mkdirSync15(SCREENSHOT_CACHE_DIR, { recursive: true });
|
|
46018
|
-
const tmp =
|
|
46294
|
+
const tmp = join35(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
|
|
46019
46295
|
writeFileSync12(tmp, buf);
|
|
46020
46296
|
renameSync9(tmp, path3);
|
|
46021
46297
|
pruneScreenshotCache();
|
|
@@ -46030,14 +46306,14 @@ function persistSentFile(srcPath, idKey) {
|
|
|
46030
46306
|
const outExt = ext === "jpeg" ? "jpg" : ext;
|
|
46031
46307
|
try {
|
|
46032
46308
|
const name = createHash13("sha256").update(idKey).digest("hex").slice(0, 32);
|
|
46033
|
-
const dest =
|
|
46309
|
+
const dest = join35(SCREENSHOT_CACHE_DIR, `${name}.${outExt}`);
|
|
46034
46310
|
if (existsSync12(dest)) return dest;
|
|
46035
|
-
const size =
|
|
46311
|
+
const size = statSync15(srcPath).size;
|
|
46036
46312
|
if (size === 0 || size > SENT_IMAGE_MAX_BYTES) return void 0;
|
|
46037
|
-
const buf =
|
|
46313
|
+
const buf = readFileSync23(srcPath);
|
|
46038
46314
|
if (!looksLikeImage(buf, outExt)) return void 0;
|
|
46039
46315
|
mkdirSync15(SCREENSHOT_CACHE_DIR, { recursive: true });
|
|
46040
|
-
const tmp =
|
|
46316
|
+
const tmp = join35(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
|
|
46041
46317
|
writeFileSync12(tmp, buf);
|
|
46042
46318
|
renameSync9(tmp, dest);
|
|
46043
46319
|
pruneScreenshotCache();
|
|
@@ -46475,7 +46751,7 @@ function readTranscript(project, sessionId) {
|
|
|
46475
46751
|
}
|
|
46476
46752
|
function verifyIncrementalParse(path3, identityPrefix, incremental) {
|
|
46477
46753
|
try {
|
|
46478
|
-
const fresh = parseTranscript(
|
|
46754
|
+
const fresh = parseTranscript(readFileSync23(path3, "utf8"), identityPrefix);
|
|
46479
46755
|
const a = JSON.stringify(incremental);
|
|
46480
46756
|
const b = JSON.stringify(fresh);
|
|
46481
46757
|
if (a !== b) {
|
|
@@ -46495,16 +46771,16 @@ function verifyIncrementalParse(path3, identityPrefix, incremental) {
|
|
|
46495
46771
|
}
|
|
46496
46772
|
}
|
|
46497
46773
|
function logDirOf(project) {
|
|
46498
|
-
return
|
|
46774
|
+
return join35(homedir16(), ".claude", "projects", project.cwdSlug);
|
|
46499
46775
|
}
|
|
46500
46776
|
function resolveTranscriptPath(project, sessionId) {
|
|
46501
|
-
const path3 =
|
|
46777
|
+
const path3 = join35(logDirOf(project), `${sessionId}.jsonl`);
|
|
46502
46778
|
try {
|
|
46503
|
-
if (
|
|
46779
|
+
if (statSync15(path3).size > 0) return path3;
|
|
46504
46780
|
} catch {
|
|
46505
46781
|
}
|
|
46506
46782
|
const stranded = discoverTranscriptDir(logDirOf(project), sessionId);
|
|
46507
|
-
return stranded ?
|
|
46783
|
+
return stranded ? join35(stranded, `${sessionId}.jsonl`) : path3;
|
|
46508
46784
|
}
|
|
46509
46785
|
function projectCodexTranscript(raw2, identityPrefix = "codex") {
|
|
46510
46786
|
const out = [];
|
|
@@ -46569,8 +46845,9 @@ ${text2}` : text2;
|
|
|
46569
46845
|
}
|
|
46570
46846
|
case "tool-call": {
|
|
46571
46847
|
const m = openAssistant(ev.at, sourceId);
|
|
46572
|
-
const
|
|
46573
|
-
call
|
|
46848
|
+
const split = codexToolCards(ev.name, ev.input, ev.id);
|
|
46849
|
+
const call = split.owner;
|
|
46850
|
+
for (const card of split.cards) card.status = "pending";
|
|
46574
46851
|
if (pendingCaption) {
|
|
46575
46852
|
if (!call.desc) call.desc = pendingCaption;
|
|
46576
46853
|
pendingCaption = void 0;
|
|
@@ -46580,8 +46857,10 @@ ${text2}` : text2;
|
|
|
46580
46857
|
const interruptedOwner = call.name === "Interrupt process" && call.sessionId !== void 0 ? shellSessions.get(runningKey("Poll process", call.sessionId)) : void 0;
|
|
46581
46858
|
if (!owner) {
|
|
46582
46859
|
if (isPoll) call.backgroundState = "unknown";
|
|
46583
|
-
|
|
46584
|
-
|
|
46860
|
+
for (const card of split.cards) {
|
|
46861
|
+
pushToolPart(m, card);
|
|
46862
|
+
m.tools.push(card);
|
|
46863
|
+
}
|
|
46585
46864
|
}
|
|
46586
46865
|
if (call.name === "Spawn agent" && call.detail) agentDispatches.set(call.detail, { call, at: ev.at });
|
|
46587
46866
|
if (ev.id) pendingCalls.set(ev.id, {
|
|
@@ -46590,7 +46869,8 @@ ${text2}` : text2;
|
|
|
46590
46869
|
owner,
|
|
46591
46870
|
interruptedOwner,
|
|
46592
46871
|
orphanPoll: isPoll && !owner,
|
|
46593
|
-
explicitBackground: codexExplicitBackground(ev.name, ev.input)
|
|
46872
|
+
explicitBackground: codexExplicitBackground(ev.name, ev.input),
|
|
46873
|
+
...split.cards.length > 1 ? { companions: split.cards.filter((card) => card !== call), views: split.views } : {}
|
|
46594
46874
|
});
|
|
46595
46875
|
break;
|
|
46596
46876
|
}
|
|
@@ -46600,7 +46880,17 @@ ${text2}` : text2;
|
|
|
46600
46880
|
pendingCalls.delete(ev.id);
|
|
46601
46881
|
const result = codexToolResult(ev.text);
|
|
46602
46882
|
if (result.durationMs === void 0) result.durationMs = elapsedBetween(pending.at, ev.at);
|
|
46603
|
-
if (
|
|
46883
|
+
if (pending.companions) {
|
|
46884
|
+
for (const card of pending.companions) card.status = result.status === "cancelled" ? "cancelled" : "completed";
|
|
46885
|
+
if (result.status !== "cancelled") {
|
|
46886
|
+
const inline = ev.images ?? (ev.image ? [ev.image] : []);
|
|
46887
|
+
pending.views?.forEach((view, i) => {
|
|
46888
|
+
if (view.outputImage || !inline[i]) return;
|
|
46889
|
+
const shot = persistDataUrlImage(inline[i], `${ev.id}:view:${i}`);
|
|
46890
|
+
if (shot) view.outputImage = shot;
|
|
46891
|
+
});
|
|
46892
|
+
}
|
|
46893
|
+
} else if (ev.image && result.status !== "failed" && result.status !== "cancelled") {
|
|
46604
46894
|
const shot = persistDataUrlImage(ev.image, ev.id);
|
|
46605
46895
|
if (shot) (pending.owner ?? pending).call.outputImage = shot;
|
|
46606
46896
|
}
|
|
@@ -46829,6 +47119,11 @@ function latestTranscriptWindow(messages) {
|
|
|
46829
47119
|
}
|
|
46830
47120
|
return [...earlierInstructions, ...messages.slice(start), ...pinned.slice(-MAX_PINNED_BACKGROUND_OPERATIONS)];
|
|
46831
47121
|
}
|
|
47122
|
+
function codexToolCards(name, input, callId) {
|
|
47123
|
+
if (name === "exec" && typeof input === "string") return codexExecWrapperCards(input, callId);
|
|
47124
|
+
const owner = codexToolCall(name, input, callId);
|
|
47125
|
+
return { owner, cards: [owner] };
|
|
47126
|
+
}
|
|
46832
47127
|
function codexToolCall(name, input, callId) {
|
|
46833
47128
|
if (name === "exec" && typeof input === "string") return codexExecWrapperCall(input, callId);
|
|
46834
47129
|
const obj = input && typeof input === "object" && !Array.isArray(input) ? input : {};
|
|
@@ -46987,8 +47282,32 @@ function formatCompactDuration(ms) {
|
|
|
46987
47282
|
if (minutes < 60) return `${minutes}m`;
|
|
46988
47283
|
return minutes % 60 ? `${Math.floor(minutes / 60)}h ${minutes % 60}m` : `${Math.floor(minutes / 60)}h`;
|
|
46989
47284
|
}
|
|
46990
|
-
function
|
|
47285
|
+
function codexExecWrapperCards(source, callId) {
|
|
46991
47286
|
const calls = wrappedInvocations(source);
|
|
47287
|
+
const rest = [];
|
|
47288
|
+
const views = [];
|
|
47289
|
+
const order = [];
|
|
47290
|
+
if (calls.length > 1) {
|
|
47291
|
+
for (const call of calls) {
|
|
47292
|
+
if (call.name !== "view_image") {
|
|
47293
|
+
if (!rest.length) order.push("rest");
|
|
47294
|
+
rest.push(call);
|
|
47295
|
+
continue;
|
|
47296
|
+
}
|
|
47297
|
+
const view = viewImageCall(jsStringProperty(call.args, "path"), `${callId ?? source}:view:${views.length}`);
|
|
47298
|
+
views.push(view);
|
|
47299
|
+
order.push(view);
|
|
47300
|
+
}
|
|
47301
|
+
}
|
|
47302
|
+
if (!views.length) {
|
|
47303
|
+
const owner = codexExecWrapperCall(source, callId, calls);
|
|
47304
|
+
return { owner, cards: [owner] };
|
|
47305
|
+
}
|
|
47306
|
+
const remainder = rest.length ? codexExecWrapperCall(source, callId, rest) : void 0;
|
|
47307
|
+
const cards = order.map((entry) => entry === "rest" ? remainder : entry);
|
|
47308
|
+
return { owner: remainder ?? views[0], cards, views };
|
|
47309
|
+
}
|
|
47310
|
+
function codexExecWrapperCall(source, callId, calls = wrappedInvocations(source)) {
|
|
46992
47311
|
if (calls.length !== 1) {
|
|
46993
47312
|
return {
|
|
46994
47313
|
name: "Exec",
|
|
@@ -46996,7 +47315,9 @@ function codexExecWrapperCall(source, callId) {
|
|
|
46996
47315
|
input: capToolInput(source.trim())
|
|
46997
47316
|
};
|
|
46998
47317
|
}
|
|
46999
|
-
|
|
47318
|
+
return wrappedSingleCall(calls[0], source, callId);
|
|
47319
|
+
}
|
|
47320
|
+
function wrappedSingleCall(call, source, callId) {
|
|
47000
47321
|
if (call.name === "exec_command") {
|
|
47001
47322
|
const cmd = jsStringProperty(call.args, "cmd") ?? jsStringProperty(call.args, "command");
|
|
47002
47323
|
const cwd = jsStringProperty(call.args, "workdir") ?? jsStringProperty(call.args, "cwd");
|
|
@@ -47372,7 +47693,7 @@ function unifiedToolResult(text2) {
|
|
|
47372
47693
|
if (!header) return void 0;
|
|
47373
47694
|
const wrapperStatus = header[1] === "failed" ? "failed" : header[1] === "terminated" ? "cancelled" : "completed";
|
|
47374
47695
|
const wrapperDurationMs = Number(header[2]) * 1e3;
|
|
47375
|
-
const body = raw2.slice(header[0].length).trim();
|
|
47696
|
+
const body = raw2.slice(header[0].length).split("[image output]").join("").trim();
|
|
47376
47697
|
if (!body || body === "{}") return { status: wrapperStatus, durationMs: wrapperDurationMs, terminal: true };
|
|
47377
47698
|
try {
|
|
47378
47699
|
const parsed = JSON.parse(body);
|
|
@@ -47752,7 +48073,7 @@ function readEarlierThreadTranscriptPage(project, storage, slug, cursor, backend
|
|
|
47752
48073
|
}
|
|
47753
48074
|
function readCodexTranscriptFile(absPath, nativeId = absPath) {
|
|
47754
48075
|
try {
|
|
47755
|
-
return parseCodexTranscript(
|
|
48076
|
+
return parseCodexTranscript(readFileSync23(absPath, "utf8"), `codex:${nativeId}`);
|
|
47756
48077
|
} catch {
|
|
47757
48078
|
return [];
|
|
47758
48079
|
}
|
|
@@ -47850,7 +48171,7 @@ function projectTranscriptPageAgentLifecycles(page, lookup, peerLookup) {
|
|
|
47850
48171
|
function readTranscriptFile(absPath) {
|
|
47851
48172
|
try {
|
|
47852
48173
|
const pathKey = createHash13("sha256").update(absPath).digest("base64url").slice(0, 16);
|
|
47853
|
-
return parseTranscript(
|
|
48174
|
+
return parseTranscript(readFileSync23(absPath, "utf8"), `claude-file:${pathKey}`);
|
|
47854
48175
|
} catch {
|
|
47855
48176
|
return [];
|
|
47856
48177
|
}
|
|
@@ -47926,7 +48247,7 @@ var init_transcript = __esm({
|
|
|
47926
48247
|
});
|
|
47927
48248
|
|
|
47928
48249
|
// packages/server/src/open-external.ts
|
|
47929
|
-
import { spawn as
|
|
48250
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
47930
48251
|
function validateExternalUrl(raw2) {
|
|
47931
48252
|
let parsed;
|
|
47932
48253
|
try {
|
|
@@ -47943,7 +48264,7 @@ function openExternalUrl(raw2) {
|
|
|
47943
48264
|
const v = validateExternalUrl(raw2);
|
|
47944
48265
|
if (!v.ok) throw new Error(v.reason);
|
|
47945
48266
|
const [cmd, args] = process.platform === "darwin" ? ["open", [v.url]] : ["xdg-open", [v.url]];
|
|
47946
|
-
|
|
48267
|
+
spawn6(cmd, args, { detached: true, stdio: "ignore" }).unref();
|
|
47947
48268
|
}
|
|
47948
48269
|
var init_open_external = __esm({
|
|
47949
48270
|
"packages/server/src/open-external.ts"() {
|
|
@@ -47951,93 +48272,6 @@ var init_open_external = __esm({
|
|
|
47951
48272
|
}
|
|
47952
48273
|
});
|
|
47953
48274
|
|
|
47954
|
-
// packages/server/src/local-file.ts
|
|
47955
|
-
import { spawn as spawn6 } from "node:child_process";
|
|
47956
|
-
import { readFileSync as readFileSync23, realpathSync as realpathSync9, statSync as statSync15 } from "node:fs";
|
|
47957
|
-
import { homedir as homedir16 } from "node:os";
|
|
47958
|
-
import { isAbsolute as isAbsolute4, join as join35, resolve as resolve8, sep as sep2 } from "node:path";
|
|
47959
|
-
function isUnder(real, root) {
|
|
47960
|
-
let rootReal;
|
|
47961
|
-
try {
|
|
47962
|
-
rootReal = realpathSync9(root);
|
|
47963
|
-
} catch {
|
|
47964
|
-
return false;
|
|
47965
|
-
}
|
|
47966
|
-
return real === rootReal || real.startsWith(rootReal.endsWith(sep2) ? rootReal : rootReal + sep2);
|
|
47967
|
-
}
|
|
47968
|
-
function resolveLocalFile(rawPath, roots) {
|
|
47969
|
-
if (!isAbsolute4(rawPath)) throw new Error("Local path must be absolute");
|
|
47970
|
-
let real;
|
|
47971
|
-
try {
|
|
47972
|
-
real = realpathSync9(rawPath);
|
|
47973
|
-
} catch {
|
|
47974
|
-
throw new Error("Local file was not found");
|
|
47975
|
-
}
|
|
47976
|
-
if (!roots.some((root) => isUnder(real, root))) throw new Error("Local file is outside Frizz's trusted roots");
|
|
47977
|
-
try {
|
|
47978
|
-
if (!statSync15(real).isFile()) throw new Error("Local path is not a regular file");
|
|
47979
|
-
} catch (error) {
|
|
47980
|
-
if (error instanceof Error && error.message === "Local path is not a regular file") throw error;
|
|
47981
|
-
throw new Error("Local file was not found");
|
|
47982
|
-
}
|
|
47983
|
-
return real;
|
|
47984
|
-
}
|
|
47985
|
-
function resolveOpenableFile(raw2, projectDir, roots, home = homedir16()) {
|
|
47986
|
-
const trimmed = raw2.trim().replace(/:\d+(?::\d+)?$/, "");
|
|
47987
|
-
if (!trimmed) return null;
|
|
47988
|
-
const abs = trimmed === "~" ? home : trimmed.startsWith("~/") ? join35(home, trimmed.slice(2)) : isAbsolute4(trimmed) ? trimmed : resolve8(projectDir, trimmed);
|
|
47989
|
-
try {
|
|
47990
|
-
return resolveLocalFile(abs, roots);
|
|
47991
|
-
} catch {
|
|
47992
|
-
return null;
|
|
47993
|
-
}
|
|
47994
|
-
}
|
|
47995
|
-
function readLocalTextFile(rawPath, roots) {
|
|
47996
|
-
const path3 = resolveLocalFile(rawPath, roots);
|
|
47997
|
-
const bytes = readFileSync23(path3);
|
|
47998
|
-
if (bytes.subarray(0, 8192).includes(0)) throw new Error("Local file is not a text file");
|
|
47999
|
-
if (bytes.length <= MARKDOWN_READ_LIMIT) return { path: path3, text: bytes.toString("utf8"), truncated: false };
|
|
48000
|
-
const head = bytes.subarray(0, MARKDOWN_READ_LIMIT);
|
|
48001
|
-
const lastBreak = head.lastIndexOf(10);
|
|
48002
|
-
return { path: path3, text: head.subarray(0, lastBreak > 0 ? lastBreak : head.length).toString("utf8"), truncated: true };
|
|
48003
|
-
}
|
|
48004
|
-
function readLocalMarkdown(rawPath, roots) {
|
|
48005
|
-
if (!MARKDOWN_FILE_EXT.test(rawPath.trim())) throw new Error("Local file is not a Markdown file");
|
|
48006
|
-
const path3 = resolveLocalFile(rawPath, roots);
|
|
48007
|
-
if (!MARKDOWN_FILE_EXT.test(path3)) throw new Error("Local file is not a Markdown file");
|
|
48008
|
-
const bytes = readFileSync23(path3);
|
|
48009
|
-
if (bytes.length <= MARKDOWN_READ_LIMIT) return { path: path3, markdown: bytes.toString("utf8"), truncated: false };
|
|
48010
|
-
const head = bytes.subarray(0, MARKDOWN_READ_LIMIT);
|
|
48011
|
-
const lastBreak = head.lastIndexOf(10);
|
|
48012
|
-
return { path: path3, markdown: head.subarray(0, lastBreak > 0 ? lastBreak : head.length).toString("utf8"), truncated: true };
|
|
48013
|
-
}
|
|
48014
|
-
function resolveWatchableLocalFile(rawPath, roots) {
|
|
48015
|
-
const path3 = resolveLocalFile(rawPath, roots);
|
|
48016
|
-
if (MARKDOWN_FILE_EXT.test(rawPath.trim()) && !MARKDOWN_FILE_EXT.test(path3)) {
|
|
48017
|
-
throw new Error("Local file is not a Markdown file");
|
|
48018
|
-
}
|
|
48019
|
-
return path3;
|
|
48020
|
-
}
|
|
48021
|
-
function defaultSpawn(command, args, options) {
|
|
48022
|
-
return spawn6(command, [...args], options);
|
|
48023
|
-
}
|
|
48024
|
-
function openLocalFile(rawPath, opener, roots, options = {}) {
|
|
48025
|
-
const path3 = resolveLocalFile(rawPath, roots);
|
|
48026
|
-
const selected = options.forceSystem ? "system" : opener;
|
|
48027
|
-
if (selected === "copy") return { action: "copy", path: path3 };
|
|
48028
|
-
const spec = process.platform === "darwin" ? selected === "cursor" ? ["open", ["-a", "Cursor", path3]] : selected === "vscode" ? ["open", ["-a", "Visual Studio Code", path3]] : selected === "finder" ? ["open", ["-R", path3]] : ["open", [path3]] : selected === "finder" ? ["xdg-open", [path3]] : selected === "cursor" ? ["cursor", [path3]] : selected === "vscode" ? ["code", [path3]] : ["xdg-open", [path3]];
|
|
48029
|
-
(options.spawn ?? defaultSpawn)(spec[0], spec[1], { detached: true, stdio: "ignore", shell: false }).unref();
|
|
48030
|
-
return { action: "opened", path: path3 };
|
|
48031
|
-
}
|
|
48032
|
-
var MARKDOWN_FILE_EXT, MARKDOWN_READ_LIMIT;
|
|
48033
|
-
var init_local_file = __esm({
|
|
48034
|
-
"packages/server/src/local-file.ts"() {
|
|
48035
|
-
"use strict";
|
|
48036
|
-
MARKDOWN_FILE_EXT = /\.(?:md|mdx|markdown)$/i;
|
|
48037
|
-
MARKDOWN_READ_LIMIT = 1024 * 1024;
|
|
48038
|
-
}
|
|
48039
|
-
});
|
|
48040
|
-
|
|
48041
48275
|
// packages/server/src/github-hovercard.ts
|
|
48042
48276
|
function parseRef(ref) {
|
|
48043
48277
|
const match2 = REF_PATTERN.exec(ref);
|
|
@@ -49597,7 +49831,7 @@ ${gapNote}` : input.message;
|
|
|
49597
49831
|
);
|
|
49598
49832
|
const turnLive = ctx.tailer.get(input.slug)?.turn === "in-flight" && !stalled;
|
|
49599
49833
|
if (turnLive && (!binding || binding.currentTurnId === null)) {
|
|
49600
|
-
throw new Error("This thread is
|
|
49834
|
+
throw new Error("This thread is being driven outside Frizz. Wait for that turn to end, then resend.");
|
|
49601
49835
|
}
|
|
49602
49836
|
if (!binding || binding.state !== "active") {
|
|
49603
49837
|
await bridge.resumeOwnedSession(input.slug, row.session_id);
|
|
@@ -50152,7 +50386,7 @@ ${gapNote}` : input.message;
|
|
|
50152
50386
|
since: new Date(w.created_at).toISOString()
|
|
50153
50387
|
});
|
|
50154
50388
|
}
|
|
50155
|
-
return { activity, questions: openQuestionViews(input.slug) };
|
|
50389
|
+
return { activity, questions: openQuestionViews(input.slug), links: ctx.storage.listThreadLinks(input.slug).map(threadLinkView) };
|
|
50156
50390
|
}
|
|
50157
50391
|
}),
|
|
50158
50392
|
// THE WATCHER REGISTRY WAS DELETED ON 2026-08-14 AND CAME BACK ON 2026-08-26, under two narrow verbs
|
|
@@ -50166,6 +50400,34 @@ ${gapNote}` : input.message;
|
|
|
50166
50400
|
// binary naming them and gets a 404, which is the honest answer: its arguments do not fit this
|
|
50167
50401
|
// registry (there is no `for:` in them at all), so an alias would have to invent the one field that
|
|
50168
50402
|
// must not be guessed at.
|
|
50403
|
+
upsertOwnLink: mutation({
|
|
50404
|
+
input: UpsertOwnLinkInput,
|
|
50405
|
+
output: UpsertOwnLinkResult,
|
|
50406
|
+
handler: async ({ input }) => {
|
|
50407
|
+
const row = ctx.storage.getSession(input.slug);
|
|
50408
|
+
if (!row) throw new Error(`thread ${input.slug} is not registered`);
|
|
50409
|
+
if (row.state === "archived" || row.archived === 1) throw new Error("Reopen this thread before registering a link");
|
|
50410
|
+
const destination = resolveThreadLink(input.target, ctx.project.dir, openRoots);
|
|
50411
|
+
const link = ctx.storage.upsertThreadLink({
|
|
50412
|
+
id: `lnk_${randomUUID16().replace(/-/g, "").slice(0, 12)}`,
|
|
50413
|
+
slug: input.slug,
|
|
50414
|
+
label: input.label,
|
|
50415
|
+
...destination,
|
|
50416
|
+
createdAtMs: Date.now()
|
|
50417
|
+
});
|
|
50418
|
+
ctx.board.refresh();
|
|
50419
|
+
return { link: threadLinkView(link) };
|
|
50420
|
+
}
|
|
50421
|
+
}),
|
|
50422
|
+
dropOwnLink: mutation({
|
|
50423
|
+
input: DropOwnLinkInput,
|
|
50424
|
+
output: DropOwnLinkResult,
|
|
50425
|
+
handler: async ({ input }) => {
|
|
50426
|
+
const dropped = ctx.storage.dropThreadLink(input.slug, input.id);
|
|
50427
|
+
if (dropped) ctx.board.refresh();
|
|
50428
|
+
return { dropped };
|
|
50429
|
+
}
|
|
50430
|
+
}),
|
|
50169
50431
|
// ---- REGISTERED PR WATCHERS (add / drop / list) ---------------------------------------------
|
|
50170
50432
|
// The worker's own PR watchers, from `mcp__frizz__watch_pr`. Same caller and therefore the same rules
|
|
50171
50433
|
// as the timers above: slug-only (the MCP server outlives the session ids underneath it), and no
|
|
@@ -51109,6 +51371,7 @@ var init_router5 = __esm({
|
|
|
51109
51371
|
init_open_external();
|
|
51110
51372
|
init_local_file();
|
|
51111
51373
|
init_project();
|
|
51374
|
+
init_thread_links();
|
|
51112
51375
|
init_github();
|
|
51113
51376
|
init_github_hovercard();
|
|
51114
51377
|
init_dispatch();
|
|
@@ -51331,9 +51594,9 @@ var init_compression = __esm({
|
|
|
51331
51594
|
|
|
51332
51595
|
// packages/server/src/local-image.ts
|
|
51333
51596
|
import { readFileSync as readFileSync25, realpathSync as realpathSync10, statSync as statSync18 } from "node:fs";
|
|
51334
|
-
import { extname as extname2, isAbsolute as
|
|
51597
|
+
import { extname as extname2, isAbsolute as isAbsolute6 } from "node:path";
|
|
51335
51598
|
function resolveLocalImage(rawPath) {
|
|
51336
|
-
if (!rawPath || !
|
|
51599
|
+
if (!rawPath || !isAbsolute6(rawPath)) return { status: 400 };
|
|
51337
51600
|
const contentType = IMAGE_CONTENT_TYPE[extname2(rawPath).toLowerCase()];
|
|
51338
51601
|
if (!contentType) return { status: 400 };
|
|
51339
51602
|
let real;
|
|
@@ -53324,30 +53587,111 @@ var init_boot_progress = __esm({
|
|
|
53324
53587
|
}
|
|
53325
53588
|
});
|
|
53326
53589
|
|
|
53590
|
+
// packages/server/src/runtime-lease.ts
|
|
53591
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync19, readdirSync as readdirSync12, readFileSync as readFileSync29, unlinkSync as unlinkSync6, writeFileSync as writeFileSync16 } from "node:fs";
|
|
53592
|
+
import { dirname as dirname19, join as join41 } from "node:path";
|
|
53593
|
+
function runtimeVersionDir(bin) {
|
|
53594
|
+
let dir = dirname19(bin);
|
|
53595
|
+
for (let step = 0; step < MAX_ASCENT; step++) {
|
|
53596
|
+
if (existsSync14(join41(dir, PROVISIONED_MARKER))) return dir;
|
|
53597
|
+
const parent = dirname19(dir);
|
|
53598
|
+
if (parent === dir) return void 0;
|
|
53599
|
+
dir = parent;
|
|
53600
|
+
}
|
|
53601
|
+
return void 0;
|
|
53602
|
+
}
|
|
53603
|
+
function pidAlive4(pid) {
|
|
53604
|
+
try {
|
|
53605
|
+
process.kill(pid, 0);
|
|
53606
|
+
return true;
|
|
53607
|
+
} catch (error) {
|
|
53608
|
+
return error.code === "EPERM";
|
|
53609
|
+
}
|
|
53610
|
+
}
|
|
53611
|
+
function leaseRuntime(bin, role) {
|
|
53612
|
+
const versionDir = runtimeVersionDir(bin);
|
|
53613
|
+
if (!versionDir) return () => {
|
|
53614
|
+
};
|
|
53615
|
+
const path3 = join41(versionDir, LEASES_DIR, `${process.pid}.json`);
|
|
53616
|
+
try {
|
|
53617
|
+
mkdirSync19(dirname19(path3), { recursive: true });
|
|
53618
|
+
const lease = { pid: process.pid, role, bin, at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
53619
|
+
writeFileSync16(path3, JSON.stringify(lease));
|
|
53620
|
+
} catch {
|
|
53621
|
+
return () => {
|
|
53622
|
+
};
|
|
53623
|
+
}
|
|
53624
|
+
return () => {
|
|
53625
|
+
try {
|
|
53626
|
+
unlinkSync6(path3);
|
|
53627
|
+
} catch {
|
|
53628
|
+
}
|
|
53629
|
+
};
|
|
53630
|
+
}
|
|
53631
|
+
function liveRuntimeLeases(versionDir) {
|
|
53632
|
+
const dir = join41(versionDir, LEASES_DIR);
|
|
53633
|
+
let names;
|
|
53634
|
+
try {
|
|
53635
|
+
names = readdirSync12(dir);
|
|
53636
|
+
} catch {
|
|
53637
|
+
return [];
|
|
53638
|
+
}
|
|
53639
|
+
const live = [];
|
|
53640
|
+
for (const name of names) {
|
|
53641
|
+
if (!name.endsWith(".json")) continue;
|
|
53642
|
+
const path3 = join41(dir, name);
|
|
53643
|
+
let lease;
|
|
53644
|
+
try {
|
|
53645
|
+
lease = JSON.parse(readFileSync29(path3, "utf8"));
|
|
53646
|
+
} catch {
|
|
53647
|
+
continue;
|
|
53648
|
+
}
|
|
53649
|
+
if (typeof lease.pid !== "number" || !pidAlive4(lease.pid)) {
|
|
53650
|
+
try {
|
|
53651
|
+
unlinkSync6(path3);
|
|
53652
|
+
} catch {
|
|
53653
|
+
}
|
|
53654
|
+
;
|
|
53655
|
+
continue;
|
|
53656
|
+
}
|
|
53657
|
+
live.push({ pid: lease.pid, role: typeof lease.role === "string" ? lease.role : "unknown", bin: typeof lease.bin === "string" ? lease.bin : "", at: typeof lease.at === "string" ? lease.at : "" });
|
|
53658
|
+
}
|
|
53659
|
+
return live;
|
|
53660
|
+
}
|
|
53661
|
+
var PROVISIONED_MARKER, LEASES_DIR, MAX_ASCENT;
|
|
53662
|
+
var init_runtime_lease = __esm({
|
|
53663
|
+
"packages/server/src/runtime-lease.ts"() {
|
|
53664
|
+
"use strict";
|
|
53665
|
+
PROVISIONED_MARKER = "provisioned.json";
|
|
53666
|
+
LEASES_DIR = ".leases";
|
|
53667
|
+
MAX_ASCENT = 6;
|
|
53668
|
+
}
|
|
53669
|
+
});
|
|
53670
|
+
|
|
53327
53671
|
// packages/server/src/runtimes.ts
|
|
53328
53672
|
import { createHash as createHash15 } from "node:crypto";
|
|
53329
53673
|
import {
|
|
53330
53674
|
chmodSync,
|
|
53331
53675
|
closeSync as closeSync16,
|
|
53332
|
-
existsSync as
|
|
53333
|
-
mkdirSync as
|
|
53676
|
+
existsSync as existsSync15,
|
|
53677
|
+
mkdirSync as mkdirSync20,
|
|
53334
53678
|
openSync as openSync17,
|
|
53335
|
-
readFileSync as
|
|
53336
|
-
readdirSync as
|
|
53679
|
+
readFileSync as readFileSync30,
|
|
53680
|
+
readdirSync as readdirSync13,
|
|
53337
53681
|
renameSync as renameSync11,
|
|
53338
53682
|
rmSync as rmSync12,
|
|
53339
53683
|
statSync as statSync22,
|
|
53340
|
-
writeFileSync as
|
|
53684
|
+
writeFileSync as writeFileSync17,
|
|
53341
53685
|
writeSync as writeSync2
|
|
53342
53686
|
} from "node:fs";
|
|
53343
|
-
import { dirname as
|
|
53687
|
+
import { dirname as dirname20, isAbsolute as isAbsolute7, join as join42, normalize, relative as relative3, sep as sep5 } from "node:path";
|
|
53344
53688
|
import { Readable, Transform, Writable as Writable3 } from "node:stream";
|
|
53345
53689
|
import { pipeline } from "node:stream/promises";
|
|
53346
53690
|
import { createGunzip } from "node:zlib";
|
|
53347
53691
|
function runtimesRoot(env = process.env) {
|
|
53348
53692
|
const override = env[RUNTIMES_DIR_ENV];
|
|
53349
|
-
if (override &&
|
|
53350
|
-
return
|
|
53693
|
+
if (override && isAbsolute7(override)) return override;
|
|
53694
|
+
return join42(frizzRoots().cache, "runtimes");
|
|
53351
53695
|
}
|
|
53352
53696
|
function isMusl() {
|
|
53353
53697
|
if (process.platform !== "linux") return false;
|
|
@@ -53364,16 +53708,16 @@ function runtimeCoordinates(backend, platform3 = process.platform, arch = proces
|
|
|
53364
53708
|
return { pkg: "@openai/codex", packageVersion: `${CODEX_VERSION}-${platform3}-${arch}`, label: CODEX_VERSION, binary: `codex${exe}` };
|
|
53365
53709
|
}
|
|
53366
53710
|
function provisionedBinary(backend, root, label) {
|
|
53367
|
-
const dir =
|
|
53711
|
+
const dir = join42(root, backend, label);
|
|
53368
53712
|
let marker;
|
|
53369
53713
|
try {
|
|
53370
|
-
marker = JSON.parse(
|
|
53714
|
+
marker = JSON.parse(readFileSync30(join42(dir, MARKER), "utf8"));
|
|
53371
53715
|
} catch {
|
|
53372
53716
|
return void 0;
|
|
53373
53717
|
}
|
|
53374
53718
|
if (typeof marker.binary !== "string" || marker.label !== label) return void 0;
|
|
53375
|
-
const bin =
|
|
53376
|
-
return
|
|
53719
|
+
const bin = join42(dir, marker.binary);
|
|
53720
|
+
return existsSync15(bin) ? bin : void 0;
|
|
53377
53721
|
}
|
|
53378
53722
|
function octal(buffer, offset, length) {
|
|
53379
53723
|
const text2 = buffer.toString("latin1", offset, offset + length).replace(/\0.*$/su, "").trim();
|
|
@@ -53386,27 +53730,27 @@ function safeEntryPath(dest, name) {
|
|
|
53386
53730
|
const parts = name.split("/").filter((part) => part.length > 0);
|
|
53387
53731
|
if (parts.length < 2) return void 0;
|
|
53388
53732
|
const rel = normalize(parts.slice(1).join(sep5));
|
|
53389
|
-
if (
|
|
53390
|
-
const full =
|
|
53733
|
+
if (isAbsolute7(rel) || rel === ".." || rel.startsWith(`..${sep5}`)) return void 0;
|
|
53734
|
+
const full = join42(dest, rel);
|
|
53391
53735
|
const back = relative3(dest, full);
|
|
53392
|
-
if (back.startsWith("..") ||
|
|
53736
|
+
if (back.startsWith("..") || isAbsolute7(back)) return void 0;
|
|
53393
53737
|
return full;
|
|
53394
53738
|
}
|
|
53395
53739
|
function locateBinary(dir, backend, binary) {
|
|
53396
53740
|
if (backend === "claude") {
|
|
53397
|
-
const direct =
|
|
53398
|
-
return
|
|
53741
|
+
const direct = join42(dir, binary);
|
|
53742
|
+
return existsSync15(direct) ? direct : void 0;
|
|
53399
53743
|
}
|
|
53400
|
-
const vendor =
|
|
53744
|
+
const vendor = join42(dir, "vendor");
|
|
53401
53745
|
let triples;
|
|
53402
53746
|
try {
|
|
53403
|
-
triples =
|
|
53747
|
+
triples = readdirSync13(vendor);
|
|
53404
53748
|
} catch {
|
|
53405
53749
|
return void 0;
|
|
53406
53750
|
}
|
|
53407
53751
|
for (const triple of triples) {
|
|
53408
|
-
const candidate =
|
|
53409
|
-
if (
|
|
53752
|
+
const candidate = join42(vendor, triple, "bin", binary);
|
|
53753
|
+
if (existsSync15(candidate)) return candidate;
|
|
53410
53754
|
}
|
|
53411
53755
|
return void 0;
|
|
53412
53756
|
}
|
|
@@ -53421,12 +53765,12 @@ async function provisionRuntime(backend, options) {
|
|
|
53421
53765
|
const registry = options.registry ?? REGISTRY;
|
|
53422
53766
|
const progress = options.onProgress ?? (() => {
|
|
53423
53767
|
});
|
|
53424
|
-
const backendDir =
|
|
53425
|
-
const finalDir =
|
|
53426
|
-
const partial =
|
|
53427
|
-
|
|
53768
|
+
const backendDir = join42(root, backend);
|
|
53769
|
+
const finalDir = join42(backendDir, coordinates.label);
|
|
53770
|
+
const partial = join42(backendDir, `.partial-${coordinates.label}-${process.pid}`);
|
|
53771
|
+
mkdirSync20(backendDir, { recursive: true });
|
|
53428
53772
|
rmSync12(partial, { recursive: true, force: true });
|
|
53429
|
-
|
|
53773
|
+
mkdirSync20(partial);
|
|
53430
53774
|
try {
|
|
53431
53775
|
const manifestUrl = `${registry}/${coordinates.pkg.replace("/", "%2F")}/${coordinates.packageVersion}`;
|
|
53432
53776
|
progress(`resolving ${coordinates.pkg}@${coordinates.packageVersion}`);
|
|
@@ -53470,7 +53814,7 @@ async function provisionRuntime(backend, options) {
|
|
|
53470
53814
|
binary: relative3(partial, bin),
|
|
53471
53815
|
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
53472
53816
|
};
|
|
53473
|
-
|
|
53817
|
+
writeFileSync17(join42(partial, MARKER), `${JSON.stringify(marker, null, 2)}
|
|
53474
53818
|
`, "utf8");
|
|
53475
53819
|
try {
|
|
53476
53820
|
renameSync11(partial, finalDir);
|
|
@@ -53481,35 +53825,41 @@ async function provisionRuntime(backend, options) {
|
|
|
53481
53825
|
return { bin: theirs, label: coordinates.label, fetched: false };
|
|
53482
53826
|
}
|
|
53483
53827
|
progress("ready");
|
|
53484
|
-
return { bin:
|
|
53828
|
+
return { bin: join42(finalDir, marker.binary), label: coordinates.label, fetched: true };
|
|
53485
53829
|
} catch (err) {
|
|
53486
53830
|
rmSync12(partial, { recursive: true, force: true });
|
|
53487
53831
|
throw err;
|
|
53488
53832
|
}
|
|
53489
53833
|
}
|
|
53490
53834
|
function sweepRuntimes(backend, root, keepLabel, now = Date.now()) {
|
|
53491
|
-
const backendDir =
|
|
53835
|
+
const backendDir = join42(root, backend);
|
|
53492
53836
|
let entries2;
|
|
53493
53837
|
try {
|
|
53494
|
-
entries2 =
|
|
53838
|
+
entries2 = readdirSync13(backendDir);
|
|
53495
53839
|
} catch {
|
|
53496
|
-
return [];
|
|
53840
|
+
return { removed: [], kept: [] };
|
|
53497
53841
|
}
|
|
53498
|
-
const
|
|
53842
|
+
const sweep = { removed: [], kept: [] };
|
|
53499
53843
|
for (const entry of entries2) {
|
|
53500
53844
|
if (entry === keepLabel) continue;
|
|
53501
|
-
const full =
|
|
53845
|
+
const full = join42(backendDir, entry);
|
|
53502
53846
|
if (entry.startsWith(".partial-")) {
|
|
53503
53847
|
try {
|
|
53504
53848
|
if (now - statSync22(full).mtimeMs < 24 * 60 * 60 * 1e3) continue;
|
|
53505
53849
|
} catch {
|
|
53506
53850
|
continue;
|
|
53507
53851
|
}
|
|
53852
|
+
} else {
|
|
53853
|
+
const leases = liveRuntimeLeases(full);
|
|
53854
|
+
if (leases.length > 0) {
|
|
53855
|
+
sweep.kept.push({ dir: full, leases: leases.map(({ pid, role }) => ({ pid, role })) });
|
|
53856
|
+
continue;
|
|
53857
|
+
}
|
|
53508
53858
|
}
|
|
53509
53859
|
rmSync12(full, { recursive: true, force: true });
|
|
53510
|
-
removed.push(full);
|
|
53860
|
+
sweep.removed.push(full);
|
|
53511
53861
|
}
|
|
53512
|
-
return
|
|
53862
|
+
return sweep;
|
|
53513
53863
|
}
|
|
53514
53864
|
async function resolveOne(backend, explicit, options) {
|
|
53515
53865
|
const env = options.env ?? process.env;
|
|
@@ -53535,7 +53885,12 @@ async function resolveOne(backend, explicit, options) {
|
|
|
53535
53885
|
onProgress: (message) => options.onProgress?.(backend, message)
|
|
53536
53886
|
});
|
|
53537
53887
|
if (provisioned.fetched) log3("info", `runtimes: provisioned ${backend} ${provisioned.label} at ${provisioned.bin}`);
|
|
53538
|
-
|
|
53888
|
+
leaseRuntime(provisioned.bin, "server");
|
|
53889
|
+
const sweep = sweepRuntimes(backend, root, coordinates.label);
|
|
53890
|
+
for (const retired of sweep.removed) log3("info", `runtimes: retired ${retired}`);
|
|
53891
|
+
for (const { dir, leases } of sweep.kept) {
|
|
53892
|
+
log3("info", `runtimes: kept ${dir} \u2014 still used by ${leases.map((lease) => `${lease.role} pid ${lease.pid}`).join(", ")}`);
|
|
53893
|
+
}
|
|
53539
53894
|
return { bin: provisioned.bin, source: "provisioned", version: provisioned.label };
|
|
53540
53895
|
} catch (err) {
|
|
53541
53896
|
const note = err instanceof Error ? err.message : String(err);
|
|
@@ -53566,8 +53921,9 @@ var init_runtimes = __esm({
|
|
|
53566
53921
|
"use strict";
|
|
53567
53922
|
init_codex_app_server();
|
|
53568
53923
|
init_frizz_paths();
|
|
53569
|
-
|
|
53570
|
-
|
|
53924
|
+
init_runtime_lease();
|
|
53925
|
+
CLAUDE_AGENT_SDK_VERSION = "0.3.268";
|
|
53926
|
+
CLAUDE_CODE_VERSION = "2.1.268";
|
|
53571
53927
|
CODEX_VERSION = CODEX_APP_SERVER_SUPPORTED_VERSION;
|
|
53572
53928
|
RUNTIMES_MODE_ENV = "FRIZZ_RUNTIMES";
|
|
53573
53929
|
RUNTIMES_DIR_ENV = "FRIZZ_RUNTIMES_DIR";
|
|
@@ -53656,7 +54012,7 @@ var init_runtimes = __esm({
|
|
|
53656
54012
|
return;
|
|
53657
54013
|
case "5": {
|
|
53658
54014
|
const dir = safeEntryPath(this.dest, name);
|
|
53659
|
-
if (dir)
|
|
54015
|
+
if (dir) mkdirSync20(dir, { recursive: true });
|
|
53660
54016
|
return;
|
|
53661
54017
|
}
|
|
53662
54018
|
case "0":
|
|
@@ -53664,7 +54020,7 @@ var init_runtimes = __esm({
|
|
|
53664
54020
|
case "7": {
|
|
53665
54021
|
const file = safeEntryPath(this.dest, name);
|
|
53666
54022
|
if (!file) return;
|
|
53667
|
-
|
|
54023
|
+
mkdirSync20(dirname20(file), { recursive: true });
|
|
53668
54024
|
this.fd = openSync17(file, "w", octal(header, 100, 8) & 511 || 420);
|
|
53669
54025
|
this.written.push(file);
|
|
53670
54026
|
return;
|
|
@@ -54236,18 +54592,18 @@ var init_legacy_project_db = __esm({
|
|
|
54236
54592
|
});
|
|
54237
54593
|
|
|
54238
54594
|
// packages/server/src/frizz-db.ts
|
|
54239
|
-
import { existsSync as
|
|
54240
|
-
import { basename as basename13, dirname as
|
|
54595
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync21, readdirSync as readdirSync14, renameSync as renameSync12, statSync as statSync23 } from "node:fs";
|
|
54596
|
+
import { basename as basename13, dirname as dirname21, join as join43 } from "node:path";
|
|
54241
54597
|
function frizzDatabaseLocation(options) {
|
|
54242
54598
|
if (options.stateDir !== void 0) {
|
|
54243
|
-
const projectsDir =
|
|
54599
|
+
const projectsDir = dirname21(options.stateDir);
|
|
54244
54600
|
if (basename13(projectsDir) === "projects") {
|
|
54245
|
-
return { path: options.path ??
|
|
54601
|
+
return { path: options.path ?? join43(dirname21(projectsDir), "ui.db"), projectsDir };
|
|
54246
54602
|
}
|
|
54247
|
-
return { path: options.path ??
|
|
54603
|
+
return { path: options.path ?? join43(options.stateDir, "ui.db"), projectsDir: void 0 };
|
|
54248
54604
|
}
|
|
54249
54605
|
const data = options.home ? frizzPaths({ home: options.home }).data : frizzRoots().data;
|
|
54250
|
-
return { path: options.path ??
|
|
54606
|
+
return { path: options.path ?? join43(data, "ui.db"), projectsDir: join43(data, "projects") };
|
|
54251
54607
|
}
|
|
54252
54608
|
function ensureFrizzSchema(db) {
|
|
54253
54609
|
db.exec(`
|
|
@@ -54266,7 +54622,7 @@ function ensureFrizzSchema(db) {
|
|
|
54266
54622
|
}
|
|
54267
54623
|
function openFrizzDatabase(options = {}) {
|
|
54268
54624
|
const { path: path3, projectsDir } = frizzDatabaseLocation(options);
|
|
54269
|
-
|
|
54625
|
+
mkdirSync21(dirname21(path3), { recursive: true });
|
|
54270
54626
|
const db = new sqlite_default(path3);
|
|
54271
54627
|
db.pragma("busy_timeout = 5000");
|
|
54272
54628
|
db.pragma("journal_mode = WAL");
|
|
@@ -54278,10 +54634,10 @@ function openFrizzDatabase(options = {}) {
|
|
|
54278
54634
|
);
|
|
54279
54635
|
for (const projectId of retiredLegacyProjectIds(projectsDir)) {
|
|
54280
54636
|
if (alreadyImported.has(projectId)) continue;
|
|
54281
|
-
const dir =
|
|
54637
|
+
const dir = join43(projectsDir, projectId);
|
|
54282
54638
|
try {
|
|
54283
|
-
renameSync12(
|
|
54284
|
-
db.prepare("INSERT INTO imported_project (project_id, source, rows, imported_at) VALUES (?, ?, 0, ?)").run(projectId,
|
|
54639
|
+
renameSync12(join43(dir, "ui.db.imported"), join43(dir, "ui.db"));
|
|
54640
|
+
db.prepare("INSERT INTO imported_project (project_id, source, rows, imported_at) VALUES (?, ?, 0, ?)").run(projectId, join43(dir, "ui.db"), (/* @__PURE__ */ new Date()).toISOString());
|
|
54285
54641
|
alreadyImported.add(projectId);
|
|
54286
54642
|
log.info("frizz-db", `${projectId}: restored ui.db.imported to ui.db and recorded it as imported`);
|
|
54287
54643
|
} catch (error) {
|
|
@@ -54291,7 +54647,7 @@ function openFrizzDatabase(options = {}) {
|
|
|
54291
54647
|
}
|
|
54292
54648
|
for (const projectId of legacyProjectIds(projectsDir)) {
|
|
54293
54649
|
if (alreadyImported.has(projectId)) continue;
|
|
54294
|
-
const legacyPath =
|
|
54650
|
+
const legacyPath = join43(projectsDir, projectId, "ui.db");
|
|
54295
54651
|
try {
|
|
54296
54652
|
const rows = importLegacyProject(db, projectId, legacyPath);
|
|
54297
54653
|
imported.push({ projectId, rows });
|
|
@@ -54321,10 +54677,10 @@ function openFrizzDatabase(options = {}) {
|
|
|
54321
54677
|
};
|
|
54322
54678
|
}
|
|
54323
54679
|
function projectIdsWithFile(projectsDir, file) {
|
|
54324
|
-
if (!
|
|
54325
|
-
return
|
|
54680
|
+
if (!existsSync16(projectsDir)) return [];
|
|
54681
|
+
return readdirSync14(projectsDir).filter((name) => {
|
|
54326
54682
|
try {
|
|
54327
|
-
return statSync23(
|
|
54683
|
+
return statSync23(join43(projectsDir, name, file)).isFile();
|
|
54328
54684
|
} catch {
|
|
54329
54685
|
return false;
|
|
54330
54686
|
}
|
|
@@ -54334,7 +54690,7 @@ function legacyProjectIds(projectsDir) {
|
|
|
54334
54690
|
return projectIdsWithFile(projectsDir, "ui.db");
|
|
54335
54691
|
}
|
|
54336
54692
|
function retiredLegacyProjectIds(projectsDir) {
|
|
54337
|
-
return projectIdsWithFile(projectsDir, "ui.db.imported").filter((id) => !
|
|
54693
|
+
return projectIdsWithFile(projectsDir, "ui.db.imported").filter((id) => !existsSync16(join43(projectsDir, id, "ui.db")));
|
|
54338
54694
|
}
|
|
54339
54695
|
function tableColumns(db, schema, table) {
|
|
54340
54696
|
return db.prepare(`PRAGMA ${schema}.table_info(${table})`).all().map((c) => c.name);
|
|
@@ -54490,7 +54846,7 @@ var init_tenant_prime = __esm({
|
|
|
54490
54846
|
// packages/server/src/project-teardown.ts
|
|
54491
54847
|
import { rmSync as rmSync13 } from "node:fs";
|
|
54492
54848
|
import { homedir as homedir19 } from "node:os";
|
|
54493
|
-
import { dirname as
|
|
54849
|
+
import { dirname as dirname22, resolve as resolve10 } from "node:path";
|
|
54494
54850
|
async function stopProjectWorkers(ctx) {
|
|
54495
54851
|
let stopped = 0;
|
|
54496
54852
|
for (const row of ctx.storage.allSessions()) {
|
|
@@ -54510,7 +54866,7 @@ function deleteProjectState(projectId, home = homedir19()) {
|
|
|
54510
54866
|
if (!/^[\w.-]+$/u.test(projectId) || projectId === "." || projectId === "..") {
|
|
54511
54867
|
throw new Error(`Refusing to delete state for a malformed project id: ${projectId}`);
|
|
54512
54868
|
}
|
|
54513
|
-
if (
|
|
54869
|
+
if (dirname22(resolve10(target)) !== resolve10(dirname22(projectStateDir("x", home)))) {
|
|
54514
54870
|
throw new Error(`Refusing to delete ${target} \u2014 it is not a project state directory`);
|
|
54515
54871
|
}
|
|
54516
54872
|
rmSync13(target, { recursive: true, force: true });
|
|
@@ -54539,11 +54895,11 @@ __export(index_exports, {
|
|
|
54539
54895
|
unknownProjectPage: () => unknownProjectPage
|
|
54540
54896
|
});
|
|
54541
54897
|
import { createServer } from "node:http";
|
|
54542
|
-
import { readFileSync as
|
|
54543
|
-
import { dirname as
|
|
54898
|
+
import { readFileSync as readFileSync31, existsSync as existsSync17, statSync as statSync24 } from "node:fs";
|
|
54899
|
+
import { dirname as dirname23, join as join44, resolve as resolve11, extname as extname4, normalize as normalize2, sep as sep6 } from "node:path";
|
|
54544
54900
|
function readServerAddressHolder(path3) {
|
|
54545
54901
|
try {
|
|
54546
|
-
const value = JSON.parse(
|
|
54902
|
+
const value = JSON.parse(readFileSync31(path3, "utf8"));
|
|
54547
54903
|
if (typeof value?.pid !== "number") return void 0;
|
|
54548
54904
|
return { pid: value.pid, port: typeof value.port === "number" ? value.port : -1 };
|
|
54549
54905
|
} catch {
|
|
@@ -54668,12 +55024,12 @@ function staticIsFresh(req, etag, mtimeMs) {
|
|
|
54668
55024
|
}
|
|
54669
55025
|
function serveStatic(distDir, req, res) {
|
|
54670
55026
|
const rel = normalize2((req.url ?? "/").split("?")[0]).replace(/^(\.\.[/\\])+/, "");
|
|
54671
|
-
let file =
|
|
54672
|
-
if (!file.startsWith(distDir)) file =
|
|
54673
|
-
if (!
|
|
55027
|
+
let file = join44(distDir, rel === "/" ? "index.html" : rel);
|
|
55028
|
+
if (!file.startsWith(distDir)) file = join44(distDir, "index.html");
|
|
55029
|
+
if (!existsSync17(file)) file = join44(distDir, "index.html");
|
|
54674
55030
|
try {
|
|
54675
55031
|
const stats = statSync24(file);
|
|
54676
|
-
const cacheControl = file.startsWith(
|
|
55032
|
+
const cacheControl = file.startsWith(join44(distDir, "assets") + sep6) ? STATIC_CACHE_IMMUTABLE : STATIC_CACHE_REVALIDATE;
|
|
54677
55033
|
const etag = `"${stats.size.toString(16)}-${Math.trunc(stats.mtimeMs).toString(16)}"`;
|
|
54678
55034
|
const headers = {
|
|
54679
55035
|
"content-type": MIME[extname4(file)] ?? "application/octet-stream",
|
|
@@ -54689,7 +55045,7 @@ function serveStatic(distDir, req, res) {
|
|
|
54689
55045
|
res.end();
|
|
54690
55046
|
return;
|
|
54691
55047
|
}
|
|
54692
|
-
let body =
|
|
55048
|
+
let body = readFileSync31(file);
|
|
54693
55049
|
const accept = req.headers["accept-encoding"];
|
|
54694
55050
|
const encoding = negotiateEncoding(Array.isArray(accept) ? accept.join(",") : accept);
|
|
54695
55051
|
if (encoding && shouldCompress(new Headers({ "content-type": headers["content-type"] }), body.byteLength)) {
|
|
@@ -54951,7 +55307,7 @@ async function startServer(opts = {}) {
|
|
|
54951
55307
|
if (statusPath && statusIdentity) runtime.removeStatus(statusPath, statusIdentity);
|
|
54952
55308
|
if (statusPath && statusIdentity) {
|
|
54953
55309
|
try {
|
|
54954
|
-
runtime.removeStatus(serverAddressPathForStateDir(
|
|
55310
|
+
runtime.removeStatus(serverAddressPathForStateDir(dirname23(statusPath)), statusIdentity);
|
|
54955
55311
|
} catch {
|
|
54956
55312
|
}
|
|
54957
55313
|
}
|
|
@@ -55089,7 +55445,7 @@ async function startServer(opts = {}) {
|
|
|
55089
55445
|
}
|
|
55090
55446
|
statusPath = serverLockPathFor(ctx.project);
|
|
55091
55447
|
const webRoot = resolve11(import.meta.dirname, "..", "..", "web");
|
|
55092
|
-
const distDir = opts.webDistDir ? resolve11(opts.webDistDir) :
|
|
55448
|
+
const distDir = opts.webDistDir ? resolve11(opts.webDistDir) : join44(webRoot, "dist");
|
|
55093
55449
|
startupPhase = "Vite";
|
|
55094
55450
|
if (opts.dev) {
|
|
55095
55451
|
try {
|
|
@@ -55165,7 +55521,7 @@ async function startServer(opts = {}) {
|
|
|
55165
55521
|
if (vite) {
|
|
55166
55522
|
vite.middlewares(req, res, () => {
|
|
55167
55523
|
try {
|
|
55168
|
-
const html =
|
|
55524
|
+
const html = readFileSync31(join44(webRoot, "index.html"), "utf8");
|
|
55169
55525
|
void vite.transformIndexHtml(url, html).then((out) => {
|
|
55170
55526
|
res.writeHead(200, { "content-type": "text/html" });
|
|
55171
55527
|
res.end(out);
|
|
@@ -55177,7 +55533,7 @@ async function startServer(opts = {}) {
|
|
|
55177
55533
|
});
|
|
55178
55534
|
return;
|
|
55179
55535
|
}
|
|
55180
|
-
if (
|
|
55536
|
+
if (existsSync17(distDir)) {
|
|
55181
55537
|
serveStatic(distDir, req, res);
|
|
55182
55538
|
return;
|
|
55183
55539
|
}
|
|
@@ -55375,7 +55731,7 @@ var init_index = __esm({
|
|
|
55375
55731
|
}
|
|
55376
55732
|
};
|
|
55377
55733
|
isApiUrl = (url) => url === FRIZZ_ROUTE_PREFIX || url.startsWith(`${FRIZZ_ROUTE_PREFIX}/`);
|
|
55378
|
-
serverLockPathFor = (project) =>
|
|
55734
|
+
serverLockPathFor = (project) => join44(project.stateDir, "server.lock");
|
|
55379
55735
|
MIME = {
|
|
55380
55736
|
".html": "text/html",
|
|
55381
55737
|
".js": "text/javascript",
|
|
@@ -55398,8 +55754,8 @@ init_project();
|
|
|
55398
55754
|
init_project_launch();
|
|
55399
55755
|
init_shutdown();
|
|
55400
55756
|
init_logging();
|
|
55401
|
-
import { existsSync as
|
|
55402
|
-
import { join as
|
|
55757
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
55758
|
+
import { join as join45 } from "node:path";
|
|
55403
55759
|
process.on("uncaughtException", (error) => {
|
|
55404
55760
|
log.error("dev-child", `uncaught exception: ${error instanceof Error ? error.stack ?? error.message : error}`);
|
|
55405
55761
|
process.exit(1);
|
|
@@ -55437,9 +55793,9 @@ try {
|
|
|
55437
55793
|
["FRIZZ_SCRIPTS_DIR", process.env.FRIZZ_SCRIPTS_DIR, "index.mjs"],
|
|
55438
55794
|
["FRIZZ_WORKER_PLUGIN_DIR", process.env.FRIZZ_WORKER_PLUGIN_DIR, ".claude-plugin/plugin.json"]
|
|
55439
55795
|
];
|
|
55440
|
-
if (!
|
|
55796
|
+
if (!existsSync18(stableWebDist)) throw new Error("stable artifact launch is missing its verified web directory");
|
|
55441
55797
|
for (const [name, directory, requiredFile] of required) {
|
|
55442
|
-
if (!directory || !
|
|
55798
|
+
if (!directory || !existsSync18(join45(directory, requiredFile)))
|
|
55443
55799
|
throw new Error(`stable artifact launch is missing verified ${name}`);
|
|
55444
55800
|
}
|
|
55445
55801
|
}
|