frizz 0.12.10 → 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 +56 -17
- package/dist/codex-app-server-daemon.js +49 -10
- package/dist/dev-child.js +630 -286
- 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-BLyRh8S1.js → TerminalPane-DHvHCziB.js} +1 -1
- package/web-dist/assets/{abnfDiagram-VRR7QNED-B0n1m57h.js → abnfDiagram-VRR7QNED-DIzM_IN8.js} +1 -1
- package/web-dist/assets/architecture-TIHT7OUA-DBvKOf0j.js +1 -0
- package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-CW78Jo4Q.js → architectureDiagram-ZJ3FMSHR-Bm_8vd5v.js} +1 -1
- package/web-dist/assets/{blockDiagram-677ZJIJ3-DasDnytT.js → blockDiagram-677ZJIJ3-BXUW_N2o.js} +1 -1
- package/web-dist/assets/{c4Diagram-LMCZKHZV-B7cCJxqg.js → c4Diagram-LMCZKHZV-C7rfqxUO.js} +1 -1
- package/web-dist/assets/channel-CbdXYswc.js +1 -0
- package/web-dist/assets/{chunk-32BRIVSS-BBBSn1aq.js → chunk-32BRIVSS-DbfUERLa.js} +1 -1
- package/web-dist/assets/{chunk-52WLFC77-B5lATDKz.js → chunk-52WLFC77-BT_3wKSP.js} +1 -1
- package/web-dist/assets/{chunk-C7G6YPKG-B86e9JiF.js → chunk-C7G6YPKG-JqApnOVt.js} +1 -1
- package/web-dist/assets/{chunk-EX3LRPZG-CpKL4dGX.js → chunk-EX3LRPZG-Cj6hlA4t.js} +1 -1
- package/web-dist/assets/{chunk-FWX5IMBZ-Dp3AvQlT.js → chunk-FWX5IMBZ-BGthhuW_.js} +2 -2
- package/web-dist/assets/{chunk-HOUHSVGY-i9yVPrLo.js → chunk-HOUHSVGY-uyLpm_YS.js} +1 -1
- package/web-dist/assets/{chunk-ICXQ74PX--Y7uMkOf.js → chunk-ICXQ74PX-BlwUMZAk.js} +1 -1
- package/web-dist/assets/{chunk-MOJQB5TN-DyMHpsmW.js → chunk-MOJQB5TN-MXbNNk-P.js} +1 -1
- package/web-dist/assets/{chunk-OGEWGWER-1mtDKLBA.js → chunk-OGEWGWER-Da4My1Rf.js} +1 -1
- package/web-dist/assets/{chunk-PUDLZKDR-CFgSrqyc.js → chunk-PUDLZKDR-C-PgvO__.js} +1 -1
- package/web-dist/assets/{chunk-Q4XR5HBZ-BPhNENQ8.js → chunk-Q4XR5HBZ-BxZFe7gr.js} +1 -1
- package/web-dist/assets/{chunk-V7JOEXUC-CMrXD-em.js → chunk-V7JOEXUC-DgERuXm_.js} +1 -1
- package/web-dist/assets/{chunk-VAUOI2AC-B6lbggln.js → chunk-VAUOI2AC-T5OoQE-_.js} +1 -1
- package/web-dist/assets/{chunk-VR4S4FIN-B9qypAjb.js → chunk-VR4S4FIN--HFvJUG1.js} +1 -1
- package/web-dist/assets/{chunk-WYO6CB5R-CI9tkIhS.js → chunk-WYO6CB5R-DlAvy41i.js} +1 -1
- package/web-dist/assets/{chunk-ZGVPDNZ5-DFJPi6M6.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-g28vb2Hf.js → cynefin-VYW2F7L2-BhjNO28R.js} +1 -1
- package/web-dist/assets/{cynefinDiagram-TSTJHNR4-bBtOt0pp.js → cynefinDiagram-TSTJHNR4-B6VA5gCd.js} +1 -1
- package/web-dist/assets/{dagre-VKFMJZFB-DuIcY2-t.js → dagre-VKFMJZFB-6MXoEc6K.js} +1 -1
- package/web-dist/assets/{diagram-FQU43EPY-CsYoD3ve.js → diagram-FQU43EPY-D2RSPoK4.js} +1 -1
- package/web-dist/assets/{diagram-G47NLZAW-H3NxrIKS.js → diagram-G47NLZAW-BOSbtzOf.js} +1 -1
- package/web-dist/assets/{diagram-NH7WQ7WH-DIojGMfZ.js → diagram-NH7WQ7WH-Dt_u21nP.js} +1 -1
- package/web-dist/assets/{diagram-OA4YK3LP-D0L444Xe.js → diagram-OA4YK3LP-CjuWW-7r.js} +1 -1
- package/web-dist/assets/{diagram-WEI45ONY-C3PEfMxp.js → diagram-WEI45ONY-rANIKJ8N.js} +1 -1
- package/web-dist/assets/{ebnfDiagram-CCIWWBDH-Dknugppg.js → ebnfDiagram-CCIWWBDH-Bf3kfaKZ.js} +1 -1
- package/web-dist/assets/{erDiagram-Q63AITRT-Ds5u_SEw.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-KFFdgLKc.js → ganttDiagram-NO4QXBWP-C2qN2PMS.js} +1 -1
- package/web-dist/assets/{gitGraph-TEB2WS4Q-B62DXBoO.js → gitGraph-TEB2WS4Q-CRASqc9n.js} +1 -1
- package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-BPtTY3Ld.js → gitGraphDiagram-IHSO6WYX-gsXSPrH2.js} +1 -1
- package/web-dist/assets/{index-B-zUKqGI.js → index-DimQCLe8.js} +93 -93
- package/web-dist/assets/index-XhfdAXcw.css +1 -0
- package/web-dist/assets/{info-DKCQHKI2-Ct-TkGHr.js → info-DKCQHKI2-rDkFlFOd.js} +1 -1
- package/web-dist/assets/{infoDiagram-FWYZ7A6U-j0jFbDdJ.js → infoDiagram-FWYZ7A6U-03ql8Tqr.js} +1 -1
- package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-DgfNQn9k.js → ishikawaDiagram-FXEZZL3T-CfDSAVNp.js} +1 -1
- package/web-dist/assets/{journeyDiagram-5HDEW3XC-BfykOv3I.js → journeyDiagram-5HDEW3XC-RWaA6AvH.js} +1 -1
- package/web-dist/assets/{kanban-definition-HUTT4EX6-BvhHHrMj.js → kanban-definition-HUTT4EX6-C89qresM.js} +1 -1
- package/web-dist/assets/{line-DZ-APW6S.js → line-CZtSsvHu.js} +1 -1
- package/web-dist/assets/{mermaid-parser.core-BWisef3-.js → mermaid-parser.core-DKNnvxt0.js} +3 -3
- package/web-dist/assets/{mermaid.core-DnlDGPhM.js → mermaid.core-DX8cFeBF.js} +3 -3
- package/web-dist/assets/{mindmap-definition-LN4V7U3C-BoTGWSEy.js → mindmap-definition-LN4V7U3C-DW8ClyAX.js} +1 -1
- package/web-dist/assets/{packet-7NZHBO7P-DaifVkPE.js → packet-7NZHBO7P-CUOv3apI.js} +1 -1
- package/web-dist/assets/{pegDiagram-2B236MQR-DpLfBJwm.js → pegDiagram-2B236MQR-CFyxKEBL.js} +1 -1
- package/web-dist/assets/{pie-RZYD4A2V-BvB0Jxcm.js → pie-RZYD4A2V-DyXXRie2.js} +1 -1
- package/web-dist/assets/{pieDiagram-ENE6RG2P-CSdBcMSK.js → pieDiagram-ENE6RG2P-yUw7HA8l.js} +1 -1
- package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-i7k-hoMS.js → quadrantDiagram-ABIIQ3AL-Mc7aea_i.js} +1 -1
- package/web-dist/assets/{radar-I7S5WNFK-DpnvOCzG.js → radar-I7S5WNFK-BKj0BsQy.js} +1 -1
- package/web-dist/assets/{railroad-3IZDKUUU-Bj4Lhzob.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-3HJeC9YI.js → railroadDiagram-RFXS5EU6-By0Xgb_U.js} +1 -1
- package/web-dist/assets/{requirementDiagram-TGXJPOKE-CeBCsZVw.js → requirementDiagram-TGXJPOKE-CgTycsRY.js} +1 -1
- package/web-dist/assets/{sankeyDiagram-HTMAVEWB-BPhonqDa.js → sankeyDiagram-HTMAVEWB-mJ_-Grkn.js} +1 -1
- package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-C5nocNwQ.js → sequenceDiagram-DBY2YBRQ-Dn6YyeNv.js} +1 -1
- package/web-dist/assets/{stateDiagram-2N3HPSRC-CzAZsCPb.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-DRn8Vs4e.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-Bc99eShR.js → timeline-definition-FHXFAJF6-Cq6RznHz.js} +1 -1
- package/web-dist/assets/{treeView-QDETBFTQ--Hn_52w1.js → treeView-QDETBFTQ-KSelJnyL.js} +1 -1
- package/web-dist/assets/{treemap-6X3UGDF4-BCI_8eXP.js → treemap-6X3UGDF4-B-iiUurZ.js} +1 -1
- package/web-dist/assets/{vennDiagram-L72KCM5P-BR-5GJF6.js → vennDiagram-L72KCM5P-B8t4NeQy.js} +1 -1
- package/web-dist/assets/{wardley-OPB4EBWU-4HuUekM-.js → wardley-OPB4EBWU-CtkAPZLQ.js} +1 -1
- package/web-dist/assets/{wardleyDiagram-EHGQE667-BI9w8zpX.js → wardleyDiagram-EHGQE667-DC-ms_sD.js} +1 -1
- package/web-dist/assets/{xychartDiagram-FW5EYKEG-BZ72575j.js → xychartDiagram-FW5EYKEG-DW6fcgjF.js} +1 -1
- package/web-dist/index.html +2 -2
- package/web-dist/assets/architecture-TIHT7OUA-BOgxi8qb.js +0 -1
- package/web-dist/assets/channel-cwFXt8Vr.js +0 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-BLP_ClYo.js +0 -1
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-BLP_ClYo.js +0 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-DgF-cIkx.js +0 -1
- package/web-dist/assets/flowDiagram-23GEKE2U-CB3C8FCr.js +0 -1
- package/web-dist/assets/index-BIGkwpMf.css +0 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-scsBBZv_.js +0 -1
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-z2-UIe31.js +0 -1
- package/web-dist/assets/railroad-peg-LSFZ7HO6-Dm1rBPEF.js +0 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-DEGF_nZS.js +0 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-CBLKdauI.js +0 -8
package/dist/dev-child.js
CHANGED
|
@@ -13679,7 +13679,7 @@ function parseGithubWakeSteer(text2) {
|
|
|
13679
13679
|
function frizzRoute(path3) {
|
|
13680
13680
|
return `${FRIZZ_ROUTE_PREFIX}${path3.startsWith("/") ? path3 : `/${path3}`}`;
|
|
13681
13681
|
}
|
|
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, 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;
|
|
13683
13683
|
var init_src = __esm({
|
|
13684
13684
|
"packages/shared/src/index.ts"() {
|
|
13685
13685
|
"use strict";
|
|
@@ -13803,7 +13803,14 @@ var init_src = __esm({
|
|
|
13803
13803
|
slug: external_exports.string(),
|
|
13804
13804
|
displayName: external_exports.string(),
|
|
13805
13805
|
defaultEffort: external_exports.string(),
|
|
13806
|
-
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()
|
|
13807
13814
|
});
|
|
13808
13815
|
ThreadProfileOption = external_exports.object({
|
|
13809
13816
|
model: external_exports.string().min(1),
|
|
@@ -14444,6 +14451,20 @@ var init_src = __esm({
|
|
|
14444
14451
|
retrying: external_exports.boolean().optional(),
|
|
14445
14452
|
at: external_exports.string().optional()
|
|
14446
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();
|
|
14447
14468
|
ThreadView = external_exports.object({
|
|
14448
14469
|
id: ThreadSlug,
|
|
14449
14470
|
// slug; filename is <slug>.md
|
|
@@ -14512,6 +14533,8 @@ var init_src = __esm({
|
|
|
14512
14533
|
// Live background SHELLS the worker launched (tailer-derived). Same default-[] discipline. Rendered
|
|
14513
14534
|
// in the anchored background-ops strip alongside sub-agents; ids make current rows drillable.
|
|
14514
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(),
|
|
14515
14538
|
// The thread's ARMED WATCHERS — registry-derived, not folded from the transcript, which is what makes
|
|
14516
14539
|
// them survive the worker saying one more sentence. Same default-[] discipline as the two above.
|
|
14517
14540
|
//
|
|
@@ -14830,6 +14853,15 @@ var init_src = __esm({
|
|
|
14830
14853
|
// writes were 51% of a day's spend while the entries were invalidated every 15–30 minutes anyway
|
|
14831
14854
|
// (see claudePromptCacheEnv). Optional so an old blob parses; defaultSettings pins "auto".
|
|
14832
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(),
|
|
14833
14865
|
// The GitHub batch-dispatch prompt template (the picker's per-item worker prompt). Optional: when
|
|
14834
14866
|
// unset OR blank the server falls back to its exported DEFAULT_GITHUB_PROMPT. Substitution tokens
|
|
14835
14867
|
// the server fills: {repo} {n} {title} {url} {labels} {body}. The leading `THREAD: <slug>` tag is
|
|
@@ -15049,6 +15081,7 @@ var init_src = __esm({
|
|
|
15049
15081
|
}).strict();
|
|
15050
15082
|
OwnThreadActivityResult = external_exports.object({
|
|
15051
15083
|
activity: external_exports.array(ThreadActivityItem),
|
|
15084
|
+
links: external_exports.array(ThreadLinkView).optional(),
|
|
15052
15085
|
/** Every question still owed an answer. NOT a `ThreadActivityItem` and deliberately its own list: a
|
|
15053
15086
|
* question is not running work, it waits on a PERSON, and there is no `questions:` key in the awaiting
|
|
15054
15087
|
* fence for it to be written into. Until 2026-08-28 a worker could read its open questions back only
|
|
@@ -19385,6 +19418,20 @@ function createStorage(source, projectId) {
|
|
|
19385
19418
|
`);
|
|
19386
19419
|
const prWatchCursorStmt = scope.prepare("UPDATE pr_watch SET cursor = ? WHERE project_id = @project_id AND id = ? AND state = 'armed'");
|
|
19387
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 = ?");
|
|
19388
19435
|
const armThreadWatchStmt = scope.prepare(`
|
|
19389
19436
|
INSERT INTO thread_watch (project_id, id, thread_slug, kind, target, state, created_at, expires_at, settled_at)
|
|
19390
19437
|
VALUES (@project_id, @id, @slug, @kind, @target, 'armed', @createdAtMs, @expiresAtMs, NULL)
|
|
@@ -19524,6 +19571,7 @@ function createStorage(source, projectId) {
|
|
|
19524
19571
|
delThreadTimers.run(existing.slug);
|
|
19525
19572
|
delPrWatches.run(existing.slug);
|
|
19526
19573
|
delThreadWatches.run(existing.slug);
|
|
19574
|
+
delThreadLinks.run(existing.slug);
|
|
19527
19575
|
delThreadQuestions.run(existing.slug);
|
|
19528
19576
|
delThreadDone.run(existing.slug);
|
|
19529
19577
|
delSubAgentSteers.run(existing.slug);
|
|
@@ -19975,6 +20023,10 @@ function createStorage(source, projectId) {
|
|
|
19975
20023
|
dropPrWatch: (slug, id, settledAtMs) => dropPrWatchStmt.run(settledAtMs, id, slug).changes === 1,
|
|
19976
20024
|
settlePrWatch: (id, settledAtMs) => settlePrWatchStmt.run(settledAtMs, id).changes === 1,
|
|
19977
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,
|
|
19978
20030
|
// IDEMPOTENT BY (thread, kind, target), which is what the partial unique index enforces. A worker
|
|
19979
20031
|
// woken by an expiry re-registers the same wait, and a worker that simply calls twice must not end
|
|
19980
20032
|
// up with two rows to drop — so an existing armed row is RETURNED rather than replaced. Replacing
|
|
@@ -20436,6 +20488,17 @@ var init_storage = __esm({
|
|
|
20436
20488
|
ON pr_watch(project_id, state);
|
|
20437
20489
|
CREATE INDEX IF NOT EXISTS pr_watch_slug
|
|
20438
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
|
+
);
|
|
20439
20502
|
-- A worker's registered WATCHES on its own running work (2026-08-26). See
|
|
20440
20503
|
-- plans/rest-by-registration.md: a wait stops being a line the worker re-writes at every rest and
|
|
20441
20504
|
-- becomes a row it creates once, which the human sees in the queue and which wakes the thread itself.
|
|
@@ -20549,7 +20612,8 @@ var init_storage = __esm({
|
|
|
20549
20612
|
"thread_watch",
|
|
20550
20613
|
"thread_question",
|
|
20551
20614
|
"thread_done",
|
|
20552
|
-
"subagent_steer"
|
|
20615
|
+
"subagent_steer",
|
|
20616
|
+
"thread_link"
|
|
20553
20617
|
];
|
|
20554
20618
|
}
|
|
20555
20619
|
});
|
|
@@ -20694,6 +20758,9 @@ var init_settings = __esm({
|
|
|
20694
20758
|
// "auto" = the CLI's own tier (1h on a subscription). See the schema and claudePromptCacheEnv for
|
|
20695
20759
|
// when "5m" is the cheaper choice.
|
|
20696
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,
|
|
20697
20764
|
// Hidden until asked for — see the schema for why.
|
|
20698
20765
|
projectRail: false
|
|
20699
20766
|
});
|
|
@@ -21350,7 +21417,23 @@ function toCodexModel(raw2) {
|
|
|
21350
21417
|
const def = typeof m.default_reasoning_level === "string" ? m.default_reasoning_level : "";
|
|
21351
21418
|
const defaultEffort = def && efforts.includes(def) ? def : efforts[0];
|
|
21352
21419
|
const priority = typeof m.priority === "number" && Number.isFinite(m.priority) ? m.priority : Number.MAX_SAFE_INTEGER;
|
|
21353
|
-
|
|
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
|
+
};
|
|
21354
21437
|
}
|
|
21355
21438
|
function parseCodexModelsCache(raw2) {
|
|
21356
21439
|
let doc;
|
|
@@ -22260,6 +22343,7 @@ function forkBroker(options) {
|
|
|
22260
22343
|
const socketPath = claudeBrokerSocketPath(options.stateDir, options.sessionId);
|
|
22261
22344
|
const recordPath2 = claudeBrokerRecordPath(options.stateDir, options.sessionId);
|
|
22262
22345
|
mkdirSync9(dirname8(recordPath2), { recursive: true });
|
|
22346
|
+
const generation = randomUUID8();
|
|
22263
22347
|
const config = {
|
|
22264
22348
|
socketPath,
|
|
22265
22349
|
cwd: options.cwd,
|
|
@@ -22268,7 +22352,7 @@ function forkBroker(options) {
|
|
|
22268
22352
|
permissionMode: options.permissionMode,
|
|
22269
22353
|
env: options.env,
|
|
22270
22354
|
recordPath: recordPath2,
|
|
22271
|
-
generation
|
|
22355
|
+
generation,
|
|
22272
22356
|
// The daemon writes its own death forensics here. Same dir as the record, so a session's socket,
|
|
22273
22357
|
// record and diagnostics stay together and a project teardown removes all three.
|
|
22274
22358
|
diagnosticLogPath: claudeBrokerDiagnosticLogPath(options.stateDir, options.sessionId),
|
|
@@ -22290,14 +22374,45 @@ function forkBroker(options) {
|
|
|
22290
22374
|
});
|
|
22291
22375
|
child.unref();
|
|
22292
22376
|
const deadline = Date.now() + (options.timeoutMs ?? 3e4);
|
|
22377
|
+
const recordedCause = () => readClaudeBrokerExit(options.stateDir, options.sessionId, generation);
|
|
22293
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
|
+
};
|
|
22294
22387
|
const poll = () => {
|
|
22295
22388
|
const record = readBrokerRecord(recordPath2);
|
|
22296
|
-
if (record && pidAlive(record.daemonPid)) return resolve12(record);
|
|
22297
|
-
if (Date.now() > deadline)
|
|
22298
|
-
|
|
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);
|
|
22299
22397
|
};
|
|
22300
|
-
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
|
+
});
|
|
22301
22416
|
poll();
|
|
22302
22417
|
});
|
|
22303
22418
|
}
|
|
@@ -25979,14 +26094,15 @@ function parseToolArguments(args) {
|
|
|
25979
26094
|
}
|
|
25980
26095
|
function imageField(output) {
|
|
25981
26096
|
if (!Array.isArray(output)) return {};
|
|
26097
|
+
const images = [];
|
|
25982
26098
|
for (const part of output) {
|
|
25983
26099
|
if (!part || typeof part !== "object") continue;
|
|
25984
26100
|
const p = part;
|
|
25985
26101
|
if (p.type !== "input_image" && p.type !== "output_image" && p.type !== "image") continue;
|
|
25986
26102
|
const url = typeof p.image_url === "string" ? p.image_url : typeof p.url === "string" ? p.url : void 0;
|
|
25987
|
-
if (url?.startsWith("data:image/"))
|
|
26103
|
+
if (url?.startsWith("data:image/")) images.push(url);
|
|
25988
26104
|
}
|
|
25989
|
-
return {};
|
|
26105
|
+
return images.length ? { image: images[0], images } : {};
|
|
25990
26106
|
}
|
|
25991
26107
|
function codexItemText(content) {
|
|
25992
26108
|
if (!Array.isArray(content)) return "";
|
|
@@ -29996,6 +30112,11 @@ function claudeCompactionEnv(settings) {
|
|
|
29996
30112
|
if (window === void 0 || !Number.isInteger(window) || window <= 0) return {};
|
|
29997
30113
|
return { [CLAUDE_AUTO_COMPACT_WINDOW_ENV]: String(window) };
|
|
29998
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
|
+
}
|
|
29999
30120
|
function claudePromptCacheEnv(settings) {
|
|
30000
30121
|
const ttl = settings?.promptCacheTtl;
|
|
30001
30122
|
if (ttl !== "5m" && ttl !== "1h") return {};
|
|
@@ -30007,7 +30128,7 @@ function claudeCompactionWindowOf(env) {
|
|
|
30007
30128
|
const window = Number(raw2);
|
|
30008
30129
|
return Number.isInteger(window) && window > 0 ? window : void 0;
|
|
30009
30130
|
}
|
|
30010
|
-
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;
|
|
30011
30132
|
var init_types2 = __esm({
|
|
30012
30133
|
"packages/server/src/backend/types.ts"() {
|
|
30013
30134
|
"use strict";
|
|
@@ -30025,6 +30146,7 @@ var init_types2 = __esm({
|
|
|
30025
30146
|
BASH_MAX_TIMEOUT_MS: String(24 * 60 * 60 * 1e3)
|
|
30026
30147
|
};
|
|
30027
30148
|
CLAUDE_AUTO_COMPACT_WINDOW_ENV = "CLAUDE_CODE_AUTO_COMPACT_WINDOW";
|
|
30149
|
+
CODEX_CONTEXT_WINDOW_KEY = "model_context_window";
|
|
30028
30150
|
CLAUDE_PROMPT_CACHE_TTL_ENV = "CLAUDE_CODE_PROMPT_CACHE_TTL";
|
|
30029
30151
|
CLAUDE_SUBAGENT_PROMPT_CACHE_TTL_ENV = "CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL";
|
|
30030
30152
|
WORKER_DISALLOWED_TOOLS = ["AskUserQuestion"];
|
|
@@ -31957,6 +32079,7 @@ var init_codex_app_server = __esm({
|
|
|
31957
32079
|
init_auth_status();
|
|
31958
32080
|
init_codex_mcp();
|
|
31959
32081
|
init_codex_error();
|
|
32082
|
+
init_types2();
|
|
31960
32083
|
init_logging();
|
|
31961
32084
|
CODEX_APP_SERVER_PROVIDER = "codex-app-server";
|
|
31962
32085
|
CODEX_NATIVE_LISTEN_FLAG = "FRIZZ_CODEX_NATIVE_LISTEN";
|
|
@@ -33624,19 +33747,29 @@ var init_codex_app_server = __esm({
|
|
|
33624
33747
|
*/
|
|
33625
33748
|
/**
|
|
33626
33749
|
* The `config` bag for one thread's `thread/start` / `thread/resume`: frizz's MCP server mounted
|
|
33627
|
-
* 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.
|
|
33628
33752
|
*
|
|
33629
33753
|
* This is the only channel that can carry a caller identity on codex. The argv mount on the
|
|
33630
33754
|
* app-server is process-wide and serves every thread in the project, so `FRIZZ_THREAD_SLUG` was
|
|
33631
33755
|
* simply absent and every tool that acts on the caller's own thread failed at the moment of use —
|
|
33632
33756
|
* see `codexThreadMcpConfig` for the list and the measurement. Returns `{}` when there is nothing
|
|
33633
|
-
* to send, so a caller with no config
|
|
33634
|
-
* 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).
|
|
33635
33764
|
*
|
|
33636
33765
|
* The caller's own config wins on a key collision: this is a default, not an override.
|
|
33637
33766
|
*/
|
|
33638
33767
|
threadConfig(threadSlug, callerConfig) {
|
|
33639
|
-
const config = {
|
|
33768
|
+
const config = {
|
|
33769
|
+
...codexThreadMcpConfig(this.options.frizzMcp, threadSlug),
|
|
33770
|
+
...codexContextWindowConfig(this.options.getSettings?.()),
|
|
33771
|
+
...callerConfig
|
|
33772
|
+
};
|
|
33640
33773
|
return Object.keys(config).length ? { config } : {};
|
|
33641
33774
|
}
|
|
33642
33775
|
resumeSandboxOverride(row) {
|
|
@@ -34681,22 +34814,140 @@ var init_quota = __esm({
|
|
|
34681
34814
|
}
|
|
34682
34815
|
});
|
|
34683
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
|
+
|
|
34684
34935
|
// packages/server/src/frizz.ts
|
|
34685
34936
|
import { execFile as execFile5 } from "node:child_process";
|
|
34686
|
-
import { lstatSync as lstatSync2, realpathSync as
|
|
34687
|
-
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";
|
|
34688
34939
|
import { promisify as promisify5 } from "node:util";
|
|
34689
34940
|
function frizzScriptsDir() {
|
|
34690
34941
|
if (process.env.FRIZZ_SCRIPTS_DIR) return process.env.FRIZZ_SCRIPTS_DIR;
|
|
34691
|
-
return
|
|
34942
|
+
return resolve6(import.meta.dirname, "..", "..", "..", "board");
|
|
34692
34943
|
}
|
|
34693
34944
|
function directFrizzRoot(projectDir) {
|
|
34694
34945
|
try {
|
|
34695
|
-
const projectRoot =
|
|
34696
|
-
const path3 =
|
|
34946
|
+
const projectRoot = realpathSync7(projectDir);
|
|
34947
|
+
const path3 = join26(projectRoot, ".frizz");
|
|
34697
34948
|
const stat2 = lstatSync2(path3);
|
|
34698
34949
|
if (!stat2.isDirectory() || stat2.isSymbolicLink()) return null;
|
|
34699
|
-
const real =
|
|
34950
|
+
const real = realpathSync7(path3);
|
|
34700
34951
|
return dirname9(real) === projectRoot && basename5(real) === ".frizz" ? real : null;
|
|
34701
34952
|
} catch {
|
|
34702
34953
|
return null;
|
|
@@ -34707,7 +34958,7 @@ function frizzDirExists(projectDir) {
|
|
|
34707
34958
|
}
|
|
34708
34959
|
async function readBoard(projectDir, scriptsDir = frizzScriptsDir()) {
|
|
34709
34960
|
if (!directFrizzRoot(projectDir)) throw new Error("unsafe or missing .frizz directory");
|
|
34710
|
-
const { stdout } = await execFileP("node", [
|
|
34961
|
+
const { stdout } = await execFileP("node", [join26(scriptsDir, "index.mjs"), "--json"], {
|
|
34711
34962
|
cwd: projectDir,
|
|
34712
34963
|
env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir },
|
|
34713
34964
|
maxBuffer: 32 * 1024 * 1024
|
|
@@ -34732,7 +34983,7 @@ async function readBoard(projectDir, scriptsDir = frizzScriptsDir()) {
|
|
|
34732
34983
|
};
|
|
34733
34984
|
}
|
|
34734
34985
|
async function runThreadUpdate(projectDir, slug, args, scriptsDir = frizzScriptsDir()) {
|
|
34735
|
-
await execFileP("node", [
|
|
34986
|
+
await execFileP("node", [join26(scriptsDir, "thread-update.mjs"), slug, ...args], {
|
|
34736
34987
|
cwd: projectDir,
|
|
34737
34988
|
env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir }
|
|
34738
34989
|
});
|
|
@@ -34817,12 +35068,12 @@ var init_awaiting = __esm({
|
|
|
34817
35068
|
});
|
|
34818
35069
|
|
|
34819
35070
|
// packages/server/src/backend/project-mcp-servers.ts
|
|
34820
|
-
import { readFileSync as
|
|
34821
|
-
import { homedir as
|
|
34822
|
-
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";
|
|
34823
35074
|
function readJsonObject(path3) {
|
|
34824
35075
|
try {
|
|
34825
|
-
const parsed = JSON.parse(
|
|
35076
|
+
const parsed = JSON.parse(readFileSync18(path3, "utf8"));
|
|
34826
35077
|
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
34827
35078
|
} catch {
|
|
34828
35079
|
return void 0;
|
|
@@ -34913,17 +35164,17 @@ function userScopeRemoteServers(account, cwd, env) {
|
|
|
34913
35164
|
}
|
|
34914
35165
|
function projectMcpServers(cwd, options = {}) {
|
|
34915
35166
|
const env = options.env ?? process.env;
|
|
34916
|
-
const home = options.home ??
|
|
35167
|
+
const home = options.home ?? homedir12();
|
|
34917
35168
|
const configOverride = options.claudeConfigDir ?? (env.CLAUDE_CONFIG_DIR?.trim() ? env.CLAUDE_CONFIG_DIR.trim() : void 0);
|
|
34918
|
-
const accountFile = configOverride ?
|
|
34919
|
-
const userSettingsFile =
|
|
35169
|
+
const accountFile = configOverride ? join27(configOverride, ".claude.json") : join27(home, ".claude.json");
|
|
35170
|
+
const userSettingsFile = join27(configOverride ?? join27(home, ".claude"), "settings.json");
|
|
34920
35171
|
const account = readJsonObject(accountFile);
|
|
34921
35172
|
const out = userScopeRemoteServers(account, cwd, env);
|
|
34922
|
-
const declared = objectField(readJsonObject(
|
|
35173
|
+
const declared = objectField(readJsonObject(join27(cwd, ".mcp.json")), "mcpServers");
|
|
34923
35174
|
if (!declared) return out;
|
|
34924
35175
|
const approval = collectApproval([
|
|
34925
|
-
readJsonObject(
|
|
34926
|
-
readJsonObject(
|
|
35176
|
+
readJsonObject(join27(cwd, ".claude", "settings.json")),
|
|
35177
|
+
readJsonObject(join27(cwd, ".claude", "settings.local.json")),
|
|
34927
35178
|
readJsonObject(userSettingsFile),
|
|
34928
35179
|
objectField(objectField(account, "projects"), cwd)
|
|
34929
35180
|
]);
|
|
@@ -34948,16 +35199,16 @@ var init_project_mcp_servers = __esm({
|
|
|
34948
35199
|
|
|
34949
35200
|
// packages/server/src/worker-plugin-dir.ts
|
|
34950
35201
|
import { existsSync as existsSync8 } from "node:fs";
|
|
34951
|
-
import { dirname as dirname10, join as
|
|
34952
|
-
import { fileURLToPath as
|
|
35202
|
+
import { dirname as dirname10, join as join28 } from "node:path";
|
|
35203
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
34953
35204
|
function resolveWorkerPluginDir(moduleUrl = import.meta.url, env = process.env) {
|
|
34954
35205
|
const override = env.FRIZZ_WORKER_PLUGIN_DIR;
|
|
34955
|
-
if (override && existsSync8(
|
|
35206
|
+
if (override && existsSync8(join28(override, ".claude-plugin", "plugin.json")))
|
|
34956
35207
|
return override;
|
|
34957
|
-
let current = dirname10(
|
|
35208
|
+
let current = dirname10(fileURLToPath3(moduleUrl));
|
|
34958
35209
|
for (; ; ) {
|
|
34959
|
-
const candidate =
|
|
34960
|
-
if (existsSync8(
|
|
35210
|
+
const candidate = join28(current, "cc-worker");
|
|
35211
|
+
if (existsSync8(join28(candidate, ".claude-plugin", "plugin.json"))) return candidate;
|
|
34961
35212
|
const parent = dirname10(current);
|
|
34962
35213
|
if (parent === current) return void 0;
|
|
34963
35214
|
current = parent;
|
|
@@ -34985,6 +35236,7 @@ function buildWorkerPrompt(kind = "claude", opts = {}) {
|
|
|
34985
35236
|
lean ? null : THREAD_EXECUTION[kind],
|
|
34986
35237
|
AGENT_COMPLETION,
|
|
34987
35238
|
VISUAL_EVIDENCE,
|
|
35239
|
+
REGISTERED_LINKS,
|
|
34988
35240
|
QUALITY_BAR,
|
|
34989
35241
|
TOKEN_ECONOMY,
|
|
34990
35242
|
QUESTIONS,
|
|
@@ -34996,7 +35248,7 @@ function buildWorkerPrompt(kind = "claude", opts = {}) {
|
|
|
34996
35248
|
out = out.replaceAll("{{FRIZZ_MONITORS_DIR}}", opts.monitorsDir?.trim() || MONITORS_DIR_FALLBACK);
|
|
34997
35249
|
return out;
|
|
34998
35250
|
}
|
|
34999
|
-
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;
|
|
35000
35252
|
var init_workerPrompt = __esm({
|
|
35001
35253
|
"packages/server/src/workerPrompt.ts"() {
|
|
35002
35254
|
"use strict";
|
|
@@ -35288,6 +35540,12 @@ image paths through its guarded local-image proxy; only eligible workspace or ex
|
|
|
35288
35540
|
image files can embed, and a path outside that safe boundary stays non-navigable. Do not bulk-embed
|
|
35289
35541
|
irrelevant screenshots. Always keep a concise textual finding alongside them, so the handoff still
|
|
35290
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.`;
|
|
35291
35549
|
QUALITY_BAR = `## Quality bar
|
|
35292
35550
|
|
|
35293
35551
|
- Verify behavior end-to-end before calling anything done. A green suite over a stubbed implementation
|
|
@@ -36112,12 +36370,12 @@ var init_claude_broker_client = __esm({
|
|
|
36112
36370
|
});
|
|
36113
36371
|
|
|
36114
36372
|
// packages/server/src/backend/claude-permission-interactions.ts
|
|
36115
|
-
import { homedir as
|
|
36373
|
+
import { homedir as homedir13 } from "node:os";
|
|
36116
36374
|
function clip(text2, max) {
|
|
36117
36375
|
return text2.length > max ? `${text2.slice(0, max - 1)}\u2026` : text2;
|
|
36118
36376
|
}
|
|
36119
36377
|
function tildePath(path3) {
|
|
36120
|
-
const home =
|
|
36378
|
+
const home = homedir13();
|
|
36121
36379
|
if (!path3.startsWith(home)) return path3;
|
|
36122
36380
|
const rest = path3.slice(home.length);
|
|
36123
36381
|
return rest === "" ? "~" : rest.startsWith("/") ? `~${rest}` : path3;
|
|
@@ -36767,8 +37025,8 @@ var init_claude_agent_broker_bridge = __esm({
|
|
|
36767
37025
|
});
|
|
36768
37026
|
|
|
36769
37027
|
// packages/server/src/dispatch.ts
|
|
36770
|
-
import { closeSync as closeSync12, constants, existsSync as existsSync9, fstatSync as fstatSync2, lstatSync as lstatSync3, openSync as openSync13, readFileSync as
|
|
36771
|
-
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";
|
|
36772
37030
|
import { createHash as createHash11, randomUUID as randomUUID13 } from "node:crypto";
|
|
36773
37031
|
function fallbackTitle(prompt) {
|
|
36774
37032
|
const firstLine2 = prompt.trim().split("\n", 1)[0].trim();
|
|
@@ -36787,7 +37045,7 @@ function fallbackTitle(prompt) {
|
|
|
36787
37045
|
}
|
|
36788
37046
|
function resolveSlug(frizzDir, base, taken) {
|
|
36789
37047
|
base = ThreadSlug.parse(base);
|
|
36790
|
-
const isTaken = (slug) => existsSync9(
|
|
37048
|
+
const isTaken = (slug) => existsSync9(join29(frizzDir, `${slug}.md`)) || (taken?.(slug) ?? false);
|
|
36791
37049
|
if (!isTaken(base)) return base;
|
|
36792
37050
|
for (let n = 2; ; n++) {
|
|
36793
37051
|
const suffix = `-${n}`;
|
|
@@ -36803,16 +37061,16 @@ function resolveLegacyThreadFile(projectDir, value) {
|
|
|
36803
37061
|
const parsed = ThreadSlug.safeParse(value);
|
|
36804
37062
|
if (!parsed.success) return null;
|
|
36805
37063
|
try {
|
|
36806
|
-
const projectRoot =
|
|
36807
|
-
const frizzPath =
|
|
37064
|
+
const projectRoot = realpathSync8(projectDir);
|
|
37065
|
+
const frizzPath = join29(projectRoot, ".frizz");
|
|
36808
37066
|
const frizzStat = lstatSync3(frizzPath);
|
|
36809
37067
|
if (!frizzStat.isDirectory() || frizzStat.isSymbolicLink()) return null;
|
|
36810
|
-
const realFrizz =
|
|
37068
|
+
const realFrizz = realpathSync8(frizzPath);
|
|
36811
37069
|
if (dirname11(realFrizz) !== projectRoot || basename6(realFrizz) !== ".frizz") return null;
|
|
36812
|
-
const path3 =
|
|
37070
|
+
const path3 = join29(realFrizz, `${parsed.data}.md`);
|
|
36813
37071
|
const before = lstatSync3(path3);
|
|
36814
37072
|
if (!before.isFile() || before.isSymbolicLink()) return null;
|
|
36815
|
-
const realPath =
|
|
37073
|
+
const realPath = realpathSync8(path3);
|
|
36816
37074
|
if (dirname11(realPath) !== realFrizz || basename6(realPath) !== `${parsed.data}.md`) return null;
|
|
36817
37075
|
let contents;
|
|
36818
37076
|
let openedBefore;
|
|
@@ -36820,7 +37078,7 @@ function resolveLegacyThreadFile(projectDir, value) {
|
|
|
36820
37078
|
const fd = openSync13(path3, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
36821
37079
|
try {
|
|
36822
37080
|
openedBefore = fstatSync2(fd);
|
|
36823
|
-
contents =
|
|
37081
|
+
contents = readFileSync19(fd);
|
|
36824
37082
|
openedAfter = fstatSync2(fd);
|
|
36825
37083
|
} finally {
|
|
36826
37084
|
closeSync12(fd);
|
|
@@ -36853,7 +37111,7 @@ function boardAuthorizesAdoption(board, slug) {
|
|
|
36853
37111
|
return !board.errorItems.some((item) => item.file === `${slug}.md`);
|
|
36854
37112
|
}
|
|
36855
37113
|
function ensureSafeDirectDirectory(parent, name) {
|
|
36856
|
-
const path3 =
|
|
37114
|
+
const path3 = join29(parent, name);
|
|
36857
37115
|
try {
|
|
36858
37116
|
mkdirSync13(path3);
|
|
36859
37117
|
} catch (error) {
|
|
@@ -36862,7 +37120,7 @@ function ensureSafeDirectDirectory(parent, name) {
|
|
|
36862
37120
|
}
|
|
36863
37121
|
const stat2 = lstatSync3(path3);
|
|
36864
37122
|
if (!stat2.isDirectory() || stat2.isSymbolicLink()) throw new Error("unsafe project directory");
|
|
36865
|
-
const real =
|
|
37123
|
+
const real = realpathSync8(path3);
|
|
36866
37124
|
if (dirname11(real) !== parent || basename6(real) !== name) throw new Error("unsafe project directory");
|
|
36867
37125
|
return real;
|
|
36868
37126
|
}
|
|
@@ -36871,7 +37129,7 @@ function scratchDirRelPath(sessionId) {
|
|
|
36871
37129
|
}
|
|
36872
37130
|
function writeScratchDir(projectDir, sessionId) {
|
|
36873
37131
|
if (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/.test(sessionId)) throw new Error("invalid session id");
|
|
36874
|
-
const projectRoot =
|
|
37132
|
+
const projectRoot = realpathSync8(projectDir);
|
|
36875
37133
|
const frizzDir = ensureSafeDirectDirectory(projectRoot, ".frizz");
|
|
36876
37134
|
const threadsDir = ensureSafeDirectDirectory(frizzDir, "threads");
|
|
36877
37135
|
ensureSafeDirectDirectory(threadsDir, sessionId);
|
|
@@ -36883,8 +37141,8 @@ function loadWorkerPrompt(kind = "claude") {
|
|
|
36883
37141
|
function monitorScriptsDir() {
|
|
36884
37142
|
const plugin = workerPluginDir();
|
|
36885
37143
|
if (!plugin) return void 0;
|
|
36886
|
-
const dir =
|
|
36887
|
-
return existsSync9(
|
|
37144
|
+
const dir = join29(plugin, "skills", "gh", "scripts");
|
|
37145
|
+
return existsSync9(join29(dir, "ci-watch.mjs")) ? dir : void 0;
|
|
36888
37146
|
}
|
|
36889
37147
|
function codexScratchpadHookConfig(hookScript, sessionId) {
|
|
36890
37148
|
if (!hookScript || !sessionId) return {};
|
|
@@ -36896,7 +37154,7 @@ function codexScratchpadHookConfig(hookScript, sessionId) {
|
|
|
36896
37154
|
}
|
|
36897
37155
|
]
|
|
36898
37156
|
});
|
|
36899
|
-
const bashBackgroundHook =
|
|
37157
|
+
const bashBackgroundHook = join29(dirname11(hookScript), "bash-background.mjs");
|
|
36900
37158
|
return {
|
|
36901
37159
|
bypass_hook_trust: true,
|
|
36902
37160
|
hooks: {
|
|
@@ -36922,7 +37180,7 @@ function codexScratchpadHookConfig(hookScript, sessionId) {
|
|
|
36922
37180
|
}
|
|
36923
37181
|
function scratchpadHookScript() {
|
|
36924
37182
|
const plugin = workerPluginDir();
|
|
36925
|
-
return plugin ?
|
|
37183
|
+
return plugin ? join29(plugin, "hooks", "scratchpad.mjs") : void 0;
|
|
36926
37184
|
}
|
|
36927
37185
|
function composePrompt(sessionId, prompt, kind = "claude") {
|
|
36928
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.";
|
|
@@ -36938,12 +37196,12 @@ function scratchpadOrientation(sessionId, kind = "claude") {
|
|
|
36938
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.`;
|
|
36939
37197
|
}
|
|
36940
37198
|
function frizzConfigBlock(projectDir) {
|
|
36941
|
-
const path3 =
|
|
37199
|
+
const path3 = join29(projectDir, "FRIZZ.md");
|
|
36942
37200
|
let body;
|
|
36943
37201
|
try {
|
|
36944
|
-
const st =
|
|
37202
|
+
const st = statSync13(path3);
|
|
36945
37203
|
if (!st.isFile() || st.size > FRIZZ_MD_MAX_BYTES) return "";
|
|
36946
|
-
body =
|
|
37204
|
+
body = readFileSync19(path3, "utf8").trim();
|
|
36947
37205
|
} catch {
|
|
36948
37206
|
return "";
|
|
36949
37207
|
}
|
|
@@ -36982,7 +37240,7 @@ function resolveFrizzMcp(target, moduleUrl = import.meta.url, env = process.env,
|
|
|
36982
37240
|
const { stateDir, serverLock, projectId } = typeof target === "string" ? { stateDir: target } : target;
|
|
36983
37241
|
const pluginDir = resolveWorkerPluginDir(moduleUrl, env);
|
|
36984
37242
|
if (!pluginDir) return void 0;
|
|
36985
|
-
const scriptPath =
|
|
37243
|
+
const scriptPath = join29(pluginDir, "bin", FRIZZ_MCP.script);
|
|
36986
37244
|
if (!existsSync9(scriptPath)) return void 0;
|
|
36987
37245
|
return {
|
|
36988
37246
|
scriptPath,
|
|
@@ -37065,7 +37323,7 @@ function buildClaudeResumeCommand(opts) {
|
|
|
37065
37323
|
}
|
|
37066
37324
|
function createDispatcher(deps) {
|
|
37067
37325
|
const readBoardSource = deps.readBoard ?? readBoard;
|
|
37068
|
-
const frizzDir =
|
|
37326
|
+
const frizzDir = join29(deps.project.dir, ".frizz");
|
|
37069
37327
|
const adoptionRuntime = deps.adoptionRuntime ?? productionRuntime;
|
|
37070
37328
|
function cleanupPrewrites(built) {
|
|
37071
37329
|
for (const path3 of new Set(built.prewrite.map((file) => file.path))) {
|
|
@@ -37078,7 +37336,7 @@ function createDispatcher(deps) {
|
|
|
37078
37336
|
function cleanupDispatchFiles(scratchRel, built, sessionId) {
|
|
37079
37337
|
cleanupPrewrites(built);
|
|
37080
37338
|
try {
|
|
37081
|
-
rmSync9(
|
|
37339
|
+
rmSync9(join29(deps.project.dir, scratchRel), { force: true, recursive: true });
|
|
37082
37340
|
} catch {
|
|
37083
37341
|
}
|
|
37084
37342
|
cleanupAdoptionSessionFiles(deps.project.dir, sessionId);
|
|
@@ -37516,11 +37774,11 @@ var init_dispatch = __esm({
|
|
|
37516
37774
|
|
|
37517
37775
|
// packages/server/src/board.ts
|
|
37518
37776
|
import {
|
|
37519
|
-
realpathSync as
|
|
37777
|
+
realpathSync as realpathSync9,
|
|
37520
37778
|
watch as fsWatch
|
|
37521
37779
|
} from "node:fs";
|
|
37522
|
-
import { homedir as
|
|
37523
|
-
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";
|
|
37524
37782
|
import watcher from "@parcel/watcher";
|
|
37525
37783
|
function appServerTurnStalled(liveness, lastActivityAt, nowMs) {
|
|
37526
37784
|
if (!liveness) return false;
|
|
@@ -37903,6 +38161,7 @@ function registeredDoneFence(done, lastUserAt) {
|
|
|
37903
38161
|
}
|
|
37904
38162
|
function readThreadRegistries(storage) {
|
|
37905
38163
|
return {
|
|
38164
|
+
links: storage.threadLinksBySlug(),
|
|
37906
38165
|
prWatches: storage.armedPrWatchesBySlug(),
|
|
37907
38166
|
timers: storage.armedThreadTimersBySlug(),
|
|
37908
38167
|
questions: storage.threadQuestionsBySlug(),
|
|
@@ -38010,6 +38269,7 @@ function sessionThreadView(projectDir, storage, row, rawTele, registeredLegacyTe
|
|
|
38010
38269
|
lastAssistantAt: tele?.lastAssistantAt,
|
|
38011
38270
|
subAgents: stampStoppable(tele?.subAgents ?? [], row),
|
|
38012
38271
|
bgShells: stampStoppableShells(tele?.bgShells ?? [], row),
|
|
38272
|
+
links: (registries.links.get(row.slug) ?? []).map(threadLinkView),
|
|
38013
38273
|
// ONE SOURCE: the FENCE. Both kinds are derived from what the worker wrote — `prs:` entries
|
|
38014
38274
|
// become the github rows, `watch:` lines the shell rows — so this strip lists exactly what will
|
|
38015
38275
|
// actually wake the thread, and the two cannot drift into claiming different things. There is no
|
|
@@ -38257,7 +38517,7 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
|
|
|
38257
38517
|
...project.githubRepo ? { githubRepo: project.githubRepo } : {},
|
|
38258
38518
|
projectSlug: findByPath(project.dir)?.slug,
|
|
38259
38519
|
// So the client can expand a `~` a worker wrote in prose (see BoardSnapshot.homeDir).
|
|
38260
|
-
homeDir:
|
|
38520
|
+
homeDir: homedir14()
|
|
38261
38521
|
};
|
|
38262
38522
|
const sessionThreads = buildSessionThreads(assembledAtMs);
|
|
38263
38523
|
armSnoozeWake(sessionThreads, assembledAtMs);
|
|
@@ -38358,10 +38618,10 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
|
|
|
38358
38618
|
if (parcelSub || stopped) return Promise.resolve();
|
|
38359
38619
|
if (watchSetup) return watchSetup;
|
|
38360
38620
|
const setup = (async () => {
|
|
38361
|
-
const dir =
|
|
38621
|
+
const dir = join30(project.dir, ".frizz");
|
|
38362
38622
|
const roots = /* @__PURE__ */ new Set([dir]);
|
|
38363
38623
|
try {
|
|
38364
|
-
roots.add(
|
|
38624
|
+
roots.add(realpathSync9(dir));
|
|
38365
38625
|
} catch {
|
|
38366
38626
|
}
|
|
38367
38627
|
const next = await subscribe(
|
|
@@ -38373,7 +38633,7 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
|
|
|
38373
38633
|
}
|
|
38374
38634
|
if (events.some((event) => isBoardRelevantFrizzPath(roots, event.path))) scheduleRebuild();
|
|
38375
38635
|
},
|
|
38376
|
-
{ ignore: FRIZZ_WATCH_IGNORED_DIRS.map((name) =>
|
|
38636
|
+
{ ignore: FRIZZ_WATCH_IGNORED_DIRS.map((name) => join30(dir, name)) }
|
|
38377
38637
|
);
|
|
38378
38638
|
if (stopped) {
|
|
38379
38639
|
await next.unsubscribe();
|
|
@@ -38455,6 +38715,7 @@ var init_board = __esm({
|
|
|
38455
38715
|
"use strict";
|
|
38456
38716
|
init_src();
|
|
38457
38717
|
init_storage();
|
|
38718
|
+
init_thread_links();
|
|
38458
38719
|
init_thread_profiles();
|
|
38459
38720
|
init_frizz();
|
|
38460
38721
|
init_awaiting();
|
|
@@ -41050,7 +41311,7 @@ var init_resume = __esm({
|
|
|
41050
41311
|
});
|
|
41051
41312
|
|
|
41052
41313
|
// packages/server/src/backend/claude.ts
|
|
41053
|
-
import { join as
|
|
41314
|
+
import { join as join31 } from "node:path";
|
|
41054
41315
|
function toolResultText2(content) {
|
|
41055
41316
|
if (typeof content === "string") return content;
|
|
41056
41317
|
if (!Array.isArray(content)) return "";
|
|
@@ -41141,7 +41402,7 @@ function createClaudeBackend(opts) {
|
|
|
41141
41402
|
return { argv, env: claudeWorkerEnvironment(), prewrite: [] };
|
|
41142
41403
|
},
|
|
41143
41404
|
transcriptPath(sessionId) {
|
|
41144
|
-
return
|
|
41405
|
+
return join31(opts.logDir, `${sessionId}.jsonl`);
|
|
41145
41406
|
},
|
|
41146
41407
|
parseLine(line) {
|
|
41147
41408
|
return parseClaudeLine(line);
|
|
@@ -41311,13 +41572,13 @@ var init_login_utility = __esm({
|
|
|
41311
41572
|
});
|
|
41312
41573
|
|
|
41313
41574
|
// packages/server/src/backend/codex-app-server-diagnostics.ts
|
|
41314
|
-
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync14, renameSync as renameSync8, statSync as
|
|
41315
|
-
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";
|
|
41316
41577
|
function codexDiagnosticLogPath(stateDir, projectId) {
|
|
41317
|
-
return
|
|
41578
|
+
return join32(stateDir, "codex-app-server", `${projectId}.diagnostics.log`);
|
|
41318
41579
|
}
|
|
41319
41580
|
function createCodexDiagnosticSink(stateDir, projectId, now = () => /* @__PURE__ */ new Date()) {
|
|
41320
|
-
const dir =
|
|
41581
|
+
const dir = join32(stateDir, "codex-app-server");
|
|
41321
41582
|
const path3 = codexDiagnosticLogPath(stateDir, projectId);
|
|
41322
41583
|
let ensured = false;
|
|
41323
41584
|
return (event) => {
|
|
@@ -41328,7 +41589,7 @@ function createCodexDiagnosticSink(stateDir, projectId, now = () => /* @__PURE__
|
|
|
41328
41589
|
ensured = true;
|
|
41329
41590
|
}
|
|
41330
41591
|
try {
|
|
41331
|
-
if (
|
|
41592
|
+
if (statSync14(path3).size > MAX_BYTES2) renameSync8(path3, `${path3}.1`);
|
|
41332
41593
|
} catch {
|
|
41333
41594
|
}
|
|
41334
41595
|
appendFileSync3(path3, `${JSON.stringify({ at: now().toISOString(), ...event })}
|
|
@@ -41349,7 +41610,7 @@ var init_codex_app_server_diagnostics = __esm({
|
|
|
41349
41610
|
import { execFile as execFile8 } from "node:child_process";
|
|
41350
41611
|
import { readdirSync as readdirSync8, unlinkSync as unlinkSync4 } from "node:fs";
|
|
41351
41612
|
import { connect as connectSocket } from "node:net";
|
|
41352
|
-
import { join as
|
|
41613
|
+
import { join as join33 } from "node:path";
|
|
41353
41614
|
function parseLsofSocketNames(stdout) {
|
|
41354
41615
|
const referenced = /* @__PURE__ */ new Set();
|
|
41355
41616
|
for (const line of stdout.split("\n")) {
|
|
@@ -41366,7 +41627,7 @@ function sweepStaleSockets(options, deps = {}) {
|
|
|
41366
41627
|
const keep = new Set(options.keep ?? []);
|
|
41367
41628
|
let candidates;
|
|
41368
41629
|
try {
|
|
41369
|
-
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));
|
|
41370
41631
|
} catch {
|
|
41371
41632
|
return;
|
|
41372
41633
|
}
|
|
@@ -41416,7 +41677,7 @@ var init_stale_socket_sweep = __esm({
|
|
|
41416
41677
|
|
|
41417
41678
|
// packages/server/src/orphan-reaper.ts
|
|
41418
41679
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
41419
|
-
import { readFileSync as
|
|
41680
|
+
import { readFileSync as readFileSync20 } from "node:fs";
|
|
41420
41681
|
import { dirname as dirname13 } from "node:path";
|
|
41421
41682
|
function firstTokenBasename(command) {
|
|
41422
41683
|
const first = command.trimStart().split(/\s+/, 1)[0] ?? "";
|
|
@@ -41683,7 +41944,7 @@ var init_orphan_reaper = __esm({
|
|
|
41683
41944
|
defaultExec = (file, args) => execFileSync4(file, args, { encoding: "utf8", maxBuffer: 16 * 1024 * 1024, timeout: 1e4 });
|
|
41684
41945
|
defaultReadEnv = (pid) => {
|
|
41685
41946
|
try {
|
|
41686
|
-
return
|
|
41947
|
+
return readFileSync20(`/proc/${pid}/environ`, "utf8");
|
|
41687
41948
|
} catch {
|
|
41688
41949
|
return null;
|
|
41689
41950
|
}
|
|
@@ -41830,9 +42091,9 @@ var init_thread_hibernation = __esm({
|
|
|
41830
42091
|
});
|
|
41831
42092
|
|
|
41832
42093
|
// packages/server/src/context.ts
|
|
41833
|
-
import { join as
|
|
42094
|
+
import { join as join34 } from "node:path";
|
|
41834
42095
|
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
41835
|
-
import { homedir as
|
|
42096
|
+
import { homedir as homedir15 } from "node:os";
|
|
41836
42097
|
function reconcileSessions(storage) {
|
|
41837
42098
|
for (const row of storage.allSessions()) {
|
|
41838
42099
|
if (isHeadlessRow(row)) continue;
|
|
@@ -41978,9 +42239,9 @@ async function createContext(opts = {}) {
|
|
|
41978
42239
|
}
|
|
41979
42240
|
}
|
|
41980
42241
|
function createContextUnchecked(opts, resources) {
|
|
41981
|
-
const home = opts.home ??
|
|
42242
|
+
const home = opts.home ?? homedir15();
|
|
41982
42243
|
const project = opts.project ?? resolveProject();
|
|
41983
|
-
const storage = createStorage(opts.database ??
|
|
42244
|
+
const storage = createStorage(opts.database ?? join34(project.stateDir, "ui.db"), project.id);
|
|
41984
42245
|
resources.storage = storage;
|
|
41985
42246
|
const bus = new Bus();
|
|
41986
42247
|
const transcriptChange = new Emitter();
|
|
@@ -42090,7 +42351,10 @@ function createContextUnchecked(opts, resources) {
|
|
|
42090
42351
|
const mode = PermissionMode.safeParse(row.permission_mode);
|
|
42091
42352
|
if (!mode.success) return void 0;
|
|
42092
42353
|
return codexSandbox(mode.data);
|
|
42093
|
-
}
|
|
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)
|
|
42094
42358
|
}) : void 0;
|
|
42095
42359
|
resources.codexAppServer = codexAppServer;
|
|
42096
42360
|
if (codexAppServer) {
|
|
@@ -45035,8 +45299,8 @@ var init_server = __esm({
|
|
|
45035
45299
|
});
|
|
45036
45300
|
|
|
45037
45301
|
// packages/server/src/repair.ts
|
|
45038
|
-
import { existsSync as existsSync11, readFileSync as
|
|
45039
|
-
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";
|
|
45040
45304
|
function quoteValue(v) {
|
|
45041
45305
|
if (/^[\w./#:+-]+$/.test(v)) return v;
|
|
45042
45306
|
return `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
@@ -45046,12 +45310,12 @@ function deriveTitle(body, slug) {
|
|
|
45046
45310
|
return m ? m[1].trim() : slug;
|
|
45047
45311
|
}
|
|
45048
45312
|
function repairThreadFile(frizzDir, file) {
|
|
45049
|
-
const root =
|
|
45050
|
-
const abs =
|
|
45313
|
+
const root = resolve8(frizzDir);
|
|
45314
|
+
const abs = resolve8(root, file);
|
|
45051
45315
|
if (dirname14(abs) !== root) throw new RepairError(`refusing to repair "${file}": not directly under .frizz/`);
|
|
45052
45316
|
if (!abs.endsWith(".md")) throw new RepairError(`refusing to repair "${file}": not a .md thread file`);
|
|
45053
45317
|
if (!existsSync11(abs)) throw new RepairError(`no thread file to repair: ${basename7(abs)}`);
|
|
45054
|
-
const content =
|
|
45318
|
+
const content = readFileSync21(abs, "utf8");
|
|
45055
45319
|
const firstLine2 = content.replace(/^/, "").split(/\r?\n/).find((l) => l.trim() !== "");
|
|
45056
45320
|
if (firstLine2?.trim() === "---") {
|
|
45057
45321
|
throw new RepairError(`${basename7(abs)} already opens with a "---" block \u2014 repair only heals a MISSING frontmatter block`);
|
|
@@ -45242,7 +45506,7 @@ var init_repo_files = __esm({
|
|
|
45242
45506
|
});
|
|
45243
45507
|
|
|
45244
45508
|
// cc-worker/hooks/bash-background.mjs
|
|
45245
|
-
import { readFileSync as
|
|
45509
|
+
import { readFileSync as readFileSync22 } from "node:fs";
|
|
45246
45510
|
import { basename as basename8 } from "node:path";
|
|
45247
45511
|
import { pathToFileURL } from "node:url";
|
|
45248
45512
|
function emit(obj) {
|
|
@@ -45391,7 +45655,7 @@ var init_bash_background = __esm({
|
|
|
45391
45655
|
if (isDirectHookExecution(process.argv[1], import.meta.url)) {
|
|
45392
45656
|
try {
|
|
45393
45657
|
const env = process.argv.includes("--frizz-thread") ? { ...process.env, FRIZZ_THREAD: process.env.FRIZZ_THREAD || "codex-worker" } : process.env;
|
|
45394
|
-
emit(evaluateBashBackgroundHook(JSON.parse(
|
|
45658
|
+
emit(evaluateBashBackgroundHook(JSON.parse(readFileSync22(0, "utf8")), env));
|
|
45395
45659
|
} catch {
|
|
45396
45660
|
emit({});
|
|
45397
45661
|
}
|
|
@@ -45400,11 +45664,11 @@ var init_bash_background = __esm({
|
|
|
45400
45664
|
});
|
|
45401
45665
|
|
|
45402
45666
|
// packages/server/src/transcript.ts
|
|
45403
|
-
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";
|
|
45404
45668
|
import { createHash as createHash13 } from "node:crypto";
|
|
45405
45669
|
import { StringDecoder as StringDecoder4 } from "node:string_decoder";
|
|
45406
|
-
import { join as
|
|
45407
|
-
import { homedir as
|
|
45670
|
+
import { join as join35 } from "node:path";
|
|
45671
|
+
import { homedir as homedir16 } from "node:os";
|
|
45408
45672
|
function formatTokens(n) {
|
|
45409
45673
|
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
45410
45674
|
if (n >= 1e3) return `${Math.round(n / 1e3)}k`;
|
|
@@ -45983,14 +46247,14 @@ function pruneScreenshotCache() {
|
|
|
45983
46247
|
if (entries2.length <= SCREENSHOT_CACHE_MAX) return;
|
|
45984
46248
|
const byMtime = entries2.map((n) => {
|
|
45985
46249
|
try {
|
|
45986
|
-
return { n, m:
|
|
46250
|
+
return { n, m: statSync15(join35(SCREENSHOT_CACHE_DIR, n)).mtimeMs };
|
|
45987
46251
|
} catch {
|
|
45988
46252
|
return { n, m: 0 };
|
|
45989
46253
|
}
|
|
45990
46254
|
}).sort((a, b) => b.m - a.m);
|
|
45991
46255
|
for (const { n } of byMtime.slice(SCREENSHOT_CACHE_MAX)) {
|
|
45992
46256
|
try {
|
|
45993
|
-
unlinkSync5(
|
|
46257
|
+
unlinkSync5(join35(SCREENSHOT_CACHE_DIR, n));
|
|
45994
46258
|
} catch {
|
|
45995
46259
|
}
|
|
45996
46260
|
}
|
|
@@ -46020,14 +46284,14 @@ function persistBase64Image(mediaType, data, idKey) {
|
|
|
46020
46284
|
const ext = IMAGE_MEDIA_EXT[typeof mediaType === "string" ? mediaType.toLowerCase() : ""];
|
|
46021
46285
|
if (!ext || !data) return void 0;
|
|
46022
46286
|
const name = createHash13("sha256").update(idKey).digest("hex").slice(0, 32);
|
|
46023
|
-
const path3 =
|
|
46287
|
+
const path3 = join35(SCREENSHOT_CACHE_DIR, `${name}.${ext}`);
|
|
46024
46288
|
try {
|
|
46025
46289
|
if (existsSync12(path3)) return path3;
|
|
46026
46290
|
if (data.length > SCREENSHOT_MAX_BASE64) return void 0;
|
|
46027
46291
|
const buf = Buffer.from(data, "base64");
|
|
46028
46292
|
if (buf.length === 0 || !looksLikeImage(buf, ext)) return void 0;
|
|
46029
46293
|
mkdirSync15(SCREENSHOT_CACHE_DIR, { recursive: true });
|
|
46030
|
-
const tmp =
|
|
46294
|
+
const tmp = join35(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
|
|
46031
46295
|
writeFileSync12(tmp, buf);
|
|
46032
46296
|
renameSync9(tmp, path3);
|
|
46033
46297
|
pruneScreenshotCache();
|
|
@@ -46042,14 +46306,14 @@ function persistSentFile(srcPath, idKey) {
|
|
|
46042
46306
|
const outExt = ext === "jpeg" ? "jpg" : ext;
|
|
46043
46307
|
try {
|
|
46044
46308
|
const name = createHash13("sha256").update(idKey).digest("hex").slice(0, 32);
|
|
46045
|
-
const dest =
|
|
46309
|
+
const dest = join35(SCREENSHOT_CACHE_DIR, `${name}.${outExt}`);
|
|
46046
46310
|
if (existsSync12(dest)) return dest;
|
|
46047
|
-
const size =
|
|
46311
|
+
const size = statSync15(srcPath).size;
|
|
46048
46312
|
if (size === 0 || size > SENT_IMAGE_MAX_BYTES) return void 0;
|
|
46049
|
-
const buf =
|
|
46313
|
+
const buf = readFileSync23(srcPath);
|
|
46050
46314
|
if (!looksLikeImage(buf, outExt)) return void 0;
|
|
46051
46315
|
mkdirSync15(SCREENSHOT_CACHE_DIR, { recursive: true });
|
|
46052
|
-
const tmp =
|
|
46316
|
+
const tmp = join35(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
|
|
46053
46317
|
writeFileSync12(tmp, buf);
|
|
46054
46318
|
renameSync9(tmp, dest);
|
|
46055
46319
|
pruneScreenshotCache();
|
|
@@ -46487,7 +46751,7 @@ function readTranscript(project, sessionId) {
|
|
|
46487
46751
|
}
|
|
46488
46752
|
function verifyIncrementalParse(path3, identityPrefix, incremental) {
|
|
46489
46753
|
try {
|
|
46490
|
-
const fresh = parseTranscript(
|
|
46754
|
+
const fresh = parseTranscript(readFileSync23(path3, "utf8"), identityPrefix);
|
|
46491
46755
|
const a = JSON.stringify(incremental);
|
|
46492
46756
|
const b = JSON.stringify(fresh);
|
|
46493
46757
|
if (a !== b) {
|
|
@@ -46507,16 +46771,16 @@ function verifyIncrementalParse(path3, identityPrefix, incremental) {
|
|
|
46507
46771
|
}
|
|
46508
46772
|
}
|
|
46509
46773
|
function logDirOf(project) {
|
|
46510
|
-
return
|
|
46774
|
+
return join35(homedir16(), ".claude", "projects", project.cwdSlug);
|
|
46511
46775
|
}
|
|
46512
46776
|
function resolveTranscriptPath(project, sessionId) {
|
|
46513
|
-
const path3 =
|
|
46777
|
+
const path3 = join35(logDirOf(project), `${sessionId}.jsonl`);
|
|
46514
46778
|
try {
|
|
46515
|
-
if (
|
|
46779
|
+
if (statSync15(path3).size > 0) return path3;
|
|
46516
46780
|
} catch {
|
|
46517
46781
|
}
|
|
46518
46782
|
const stranded = discoverTranscriptDir(logDirOf(project), sessionId);
|
|
46519
|
-
return stranded ?
|
|
46783
|
+
return stranded ? join35(stranded, `${sessionId}.jsonl`) : path3;
|
|
46520
46784
|
}
|
|
46521
46785
|
function projectCodexTranscript(raw2, identityPrefix = "codex") {
|
|
46522
46786
|
const out = [];
|
|
@@ -46581,8 +46845,9 @@ ${text2}` : text2;
|
|
|
46581
46845
|
}
|
|
46582
46846
|
case "tool-call": {
|
|
46583
46847
|
const m = openAssistant(ev.at, sourceId);
|
|
46584
|
-
const
|
|
46585
|
-
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";
|
|
46586
46851
|
if (pendingCaption) {
|
|
46587
46852
|
if (!call.desc) call.desc = pendingCaption;
|
|
46588
46853
|
pendingCaption = void 0;
|
|
@@ -46592,8 +46857,10 @@ ${text2}` : text2;
|
|
|
46592
46857
|
const interruptedOwner = call.name === "Interrupt process" && call.sessionId !== void 0 ? shellSessions.get(runningKey("Poll process", call.sessionId)) : void 0;
|
|
46593
46858
|
if (!owner) {
|
|
46594
46859
|
if (isPoll) call.backgroundState = "unknown";
|
|
46595
|
-
|
|
46596
|
-
|
|
46860
|
+
for (const card of split.cards) {
|
|
46861
|
+
pushToolPart(m, card);
|
|
46862
|
+
m.tools.push(card);
|
|
46863
|
+
}
|
|
46597
46864
|
}
|
|
46598
46865
|
if (call.name === "Spawn agent" && call.detail) agentDispatches.set(call.detail, { call, at: ev.at });
|
|
46599
46866
|
if (ev.id) pendingCalls.set(ev.id, {
|
|
@@ -46602,7 +46869,8 @@ ${text2}` : text2;
|
|
|
46602
46869
|
owner,
|
|
46603
46870
|
interruptedOwner,
|
|
46604
46871
|
orphanPoll: isPoll && !owner,
|
|
46605
|
-
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 } : {}
|
|
46606
46874
|
});
|
|
46607
46875
|
break;
|
|
46608
46876
|
}
|
|
@@ -46612,7 +46880,17 @@ ${text2}` : text2;
|
|
|
46612
46880
|
pendingCalls.delete(ev.id);
|
|
46613
46881
|
const result = codexToolResult(ev.text);
|
|
46614
46882
|
if (result.durationMs === void 0) result.durationMs = elapsedBetween(pending.at, ev.at);
|
|
46615
|
-
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") {
|
|
46616
46894
|
const shot = persistDataUrlImage(ev.image, ev.id);
|
|
46617
46895
|
if (shot) (pending.owner ?? pending).call.outputImage = shot;
|
|
46618
46896
|
}
|
|
@@ -46841,6 +47119,11 @@ function latestTranscriptWindow(messages) {
|
|
|
46841
47119
|
}
|
|
46842
47120
|
return [...earlierInstructions, ...messages.slice(start), ...pinned.slice(-MAX_PINNED_BACKGROUND_OPERATIONS)];
|
|
46843
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
|
+
}
|
|
46844
47127
|
function codexToolCall(name, input, callId) {
|
|
46845
47128
|
if (name === "exec" && typeof input === "string") return codexExecWrapperCall(input, callId);
|
|
46846
47129
|
const obj = input && typeof input === "object" && !Array.isArray(input) ? input : {};
|
|
@@ -46999,8 +47282,32 @@ function formatCompactDuration(ms) {
|
|
|
46999
47282
|
if (minutes < 60) return `${minutes}m`;
|
|
47000
47283
|
return minutes % 60 ? `${Math.floor(minutes / 60)}h ${minutes % 60}m` : `${Math.floor(minutes / 60)}h`;
|
|
47001
47284
|
}
|
|
47002
|
-
function
|
|
47285
|
+
function codexExecWrapperCards(source, callId) {
|
|
47003
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)) {
|
|
47004
47311
|
if (calls.length !== 1) {
|
|
47005
47312
|
return {
|
|
47006
47313
|
name: "Exec",
|
|
@@ -47008,7 +47315,9 @@ function codexExecWrapperCall(source, callId) {
|
|
|
47008
47315
|
input: capToolInput(source.trim())
|
|
47009
47316
|
};
|
|
47010
47317
|
}
|
|
47011
|
-
|
|
47318
|
+
return wrappedSingleCall(calls[0], source, callId);
|
|
47319
|
+
}
|
|
47320
|
+
function wrappedSingleCall(call, source, callId) {
|
|
47012
47321
|
if (call.name === "exec_command") {
|
|
47013
47322
|
const cmd = jsStringProperty(call.args, "cmd") ?? jsStringProperty(call.args, "command");
|
|
47014
47323
|
const cwd = jsStringProperty(call.args, "workdir") ?? jsStringProperty(call.args, "cwd");
|
|
@@ -47384,7 +47693,7 @@ function unifiedToolResult(text2) {
|
|
|
47384
47693
|
if (!header) return void 0;
|
|
47385
47694
|
const wrapperStatus = header[1] === "failed" ? "failed" : header[1] === "terminated" ? "cancelled" : "completed";
|
|
47386
47695
|
const wrapperDurationMs = Number(header[2]) * 1e3;
|
|
47387
|
-
const body = raw2.slice(header[0].length).trim();
|
|
47696
|
+
const body = raw2.slice(header[0].length).split("[image output]").join("").trim();
|
|
47388
47697
|
if (!body || body === "{}") return { status: wrapperStatus, durationMs: wrapperDurationMs, terminal: true };
|
|
47389
47698
|
try {
|
|
47390
47699
|
const parsed = JSON.parse(body);
|
|
@@ -47764,7 +48073,7 @@ function readEarlierThreadTranscriptPage(project, storage, slug, cursor, backend
|
|
|
47764
48073
|
}
|
|
47765
48074
|
function readCodexTranscriptFile(absPath, nativeId = absPath) {
|
|
47766
48075
|
try {
|
|
47767
|
-
return parseCodexTranscript(
|
|
48076
|
+
return parseCodexTranscript(readFileSync23(absPath, "utf8"), `codex:${nativeId}`);
|
|
47768
48077
|
} catch {
|
|
47769
48078
|
return [];
|
|
47770
48079
|
}
|
|
@@ -47862,7 +48171,7 @@ function projectTranscriptPageAgentLifecycles(page, lookup, peerLookup) {
|
|
|
47862
48171
|
function readTranscriptFile(absPath) {
|
|
47863
48172
|
try {
|
|
47864
48173
|
const pathKey = createHash13("sha256").update(absPath).digest("base64url").slice(0, 16);
|
|
47865
|
-
return parseTranscript(
|
|
48174
|
+
return parseTranscript(readFileSync23(absPath, "utf8"), `claude-file:${pathKey}`);
|
|
47866
48175
|
} catch {
|
|
47867
48176
|
return [];
|
|
47868
48177
|
}
|
|
@@ -47938,7 +48247,7 @@ var init_transcript = __esm({
|
|
|
47938
48247
|
});
|
|
47939
48248
|
|
|
47940
48249
|
// packages/server/src/open-external.ts
|
|
47941
|
-
import { spawn as
|
|
48250
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
47942
48251
|
function validateExternalUrl(raw2) {
|
|
47943
48252
|
let parsed;
|
|
47944
48253
|
try {
|
|
@@ -47955,7 +48264,7 @@ function openExternalUrl(raw2) {
|
|
|
47955
48264
|
const v = validateExternalUrl(raw2);
|
|
47956
48265
|
if (!v.ok) throw new Error(v.reason);
|
|
47957
48266
|
const [cmd, args] = process.platform === "darwin" ? ["open", [v.url]] : ["xdg-open", [v.url]];
|
|
47958
|
-
|
|
48267
|
+
spawn6(cmd, args, { detached: true, stdio: "ignore" }).unref();
|
|
47959
48268
|
}
|
|
47960
48269
|
var init_open_external = __esm({
|
|
47961
48270
|
"packages/server/src/open-external.ts"() {
|
|
@@ -47963,93 +48272,6 @@ var init_open_external = __esm({
|
|
|
47963
48272
|
}
|
|
47964
48273
|
});
|
|
47965
48274
|
|
|
47966
|
-
// packages/server/src/local-file.ts
|
|
47967
|
-
import { spawn as spawn6 } from "node:child_process";
|
|
47968
|
-
import { readFileSync as readFileSync23, realpathSync as realpathSync9, statSync as statSync15 } from "node:fs";
|
|
47969
|
-
import { homedir as homedir16 } from "node:os";
|
|
47970
|
-
import { isAbsolute as isAbsolute4, join as join35, resolve as resolve8, sep as sep2 } from "node:path";
|
|
47971
|
-
function isUnder(real, root) {
|
|
47972
|
-
let rootReal;
|
|
47973
|
-
try {
|
|
47974
|
-
rootReal = realpathSync9(root);
|
|
47975
|
-
} catch {
|
|
47976
|
-
return false;
|
|
47977
|
-
}
|
|
47978
|
-
return real === rootReal || real.startsWith(rootReal.endsWith(sep2) ? rootReal : rootReal + sep2);
|
|
47979
|
-
}
|
|
47980
|
-
function resolveLocalFile(rawPath, roots) {
|
|
47981
|
-
if (!isAbsolute4(rawPath)) throw new Error("Local path must be absolute");
|
|
47982
|
-
let real;
|
|
47983
|
-
try {
|
|
47984
|
-
real = realpathSync9(rawPath);
|
|
47985
|
-
} catch {
|
|
47986
|
-
throw new Error("Local file was not found");
|
|
47987
|
-
}
|
|
47988
|
-
if (!roots.some((root) => isUnder(real, root))) throw new Error("Local file is outside Frizz's trusted roots");
|
|
47989
|
-
try {
|
|
47990
|
-
if (!statSync15(real).isFile()) throw new Error("Local path is not a regular file");
|
|
47991
|
-
} catch (error) {
|
|
47992
|
-
if (error instanceof Error && error.message === "Local path is not a regular file") throw error;
|
|
47993
|
-
throw new Error("Local file was not found");
|
|
47994
|
-
}
|
|
47995
|
-
return real;
|
|
47996
|
-
}
|
|
47997
|
-
function resolveOpenableFile(raw2, projectDir, roots, home = homedir16()) {
|
|
47998
|
-
const trimmed = raw2.trim().replace(/:\d+(?::\d+)?$/, "");
|
|
47999
|
-
if (!trimmed) return null;
|
|
48000
|
-
const abs = trimmed === "~" ? home : trimmed.startsWith("~/") ? join35(home, trimmed.slice(2)) : isAbsolute4(trimmed) ? trimmed : resolve8(projectDir, trimmed);
|
|
48001
|
-
try {
|
|
48002
|
-
return resolveLocalFile(abs, roots);
|
|
48003
|
-
} catch {
|
|
48004
|
-
return null;
|
|
48005
|
-
}
|
|
48006
|
-
}
|
|
48007
|
-
function readLocalTextFile(rawPath, roots) {
|
|
48008
|
-
const path3 = resolveLocalFile(rawPath, roots);
|
|
48009
|
-
const bytes = readFileSync23(path3);
|
|
48010
|
-
if (bytes.subarray(0, 8192).includes(0)) throw new Error("Local file is not a text file");
|
|
48011
|
-
if (bytes.length <= MARKDOWN_READ_LIMIT) return { path: path3, text: bytes.toString("utf8"), truncated: false };
|
|
48012
|
-
const head = bytes.subarray(0, MARKDOWN_READ_LIMIT);
|
|
48013
|
-
const lastBreak = head.lastIndexOf(10);
|
|
48014
|
-
return { path: path3, text: head.subarray(0, lastBreak > 0 ? lastBreak : head.length).toString("utf8"), truncated: true };
|
|
48015
|
-
}
|
|
48016
|
-
function readLocalMarkdown(rawPath, roots) {
|
|
48017
|
-
if (!MARKDOWN_FILE_EXT.test(rawPath.trim())) throw new Error("Local file is not a Markdown file");
|
|
48018
|
-
const path3 = resolveLocalFile(rawPath, roots);
|
|
48019
|
-
if (!MARKDOWN_FILE_EXT.test(path3)) throw new Error("Local file is not a Markdown file");
|
|
48020
|
-
const bytes = readFileSync23(path3);
|
|
48021
|
-
if (bytes.length <= MARKDOWN_READ_LIMIT) return { path: path3, markdown: bytes.toString("utf8"), truncated: false };
|
|
48022
|
-
const head = bytes.subarray(0, MARKDOWN_READ_LIMIT);
|
|
48023
|
-
const lastBreak = head.lastIndexOf(10);
|
|
48024
|
-
return { path: path3, markdown: head.subarray(0, lastBreak > 0 ? lastBreak : head.length).toString("utf8"), truncated: true };
|
|
48025
|
-
}
|
|
48026
|
-
function resolveWatchableLocalFile(rawPath, roots) {
|
|
48027
|
-
const path3 = resolveLocalFile(rawPath, roots);
|
|
48028
|
-
if (MARKDOWN_FILE_EXT.test(rawPath.trim()) && !MARKDOWN_FILE_EXT.test(path3)) {
|
|
48029
|
-
throw new Error("Local file is not a Markdown file");
|
|
48030
|
-
}
|
|
48031
|
-
return path3;
|
|
48032
|
-
}
|
|
48033
|
-
function defaultSpawn(command, args, options) {
|
|
48034
|
-
return spawn6(command, [...args], options);
|
|
48035
|
-
}
|
|
48036
|
-
function openLocalFile(rawPath, opener, roots, options = {}) {
|
|
48037
|
-
const path3 = resolveLocalFile(rawPath, roots);
|
|
48038
|
-
const selected = options.forceSystem ? "system" : opener;
|
|
48039
|
-
if (selected === "copy") return { action: "copy", path: path3 };
|
|
48040
|
-
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]];
|
|
48041
|
-
(options.spawn ?? defaultSpawn)(spec[0], spec[1], { detached: true, stdio: "ignore", shell: false }).unref();
|
|
48042
|
-
return { action: "opened", path: path3 };
|
|
48043
|
-
}
|
|
48044
|
-
var MARKDOWN_FILE_EXT, MARKDOWN_READ_LIMIT;
|
|
48045
|
-
var init_local_file = __esm({
|
|
48046
|
-
"packages/server/src/local-file.ts"() {
|
|
48047
|
-
"use strict";
|
|
48048
|
-
MARKDOWN_FILE_EXT = /\.(?:md|mdx|markdown)$/i;
|
|
48049
|
-
MARKDOWN_READ_LIMIT = 1024 * 1024;
|
|
48050
|
-
}
|
|
48051
|
-
});
|
|
48052
|
-
|
|
48053
48275
|
// packages/server/src/github-hovercard.ts
|
|
48054
48276
|
function parseRef(ref) {
|
|
48055
48277
|
const match2 = REF_PATTERN.exec(ref);
|
|
@@ -50164,7 +50386,7 @@ ${gapNote}` : input.message;
|
|
|
50164
50386
|
since: new Date(w.created_at).toISOString()
|
|
50165
50387
|
});
|
|
50166
50388
|
}
|
|
50167
|
-
return { activity, questions: openQuestionViews(input.slug) };
|
|
50389
|
+
return { activity, questions: openQuestionViews(input.slug), links: ctx.storage.listThreadLinks(input.slug).map(threadLinkView) };
|
|
50168
50390
|
}
|
|
50169
50391
|
}),
|
|
50170
50392
|
// THE WATCHER REGISTRY WAS DELETED ON 2026-08-14 AND CAME BACK ON 2026-08-26, under two narrow verbs
|
|
@@ -50178,6 +50400,34 @@ ${gapNote}` : input.message;
|
|
|
50178
50400
|
// binary naming them and gets a 404, which is the honest answer: its arguments do not fit this
|
|
50179
50401
|
// registry (there is no `for:` in them at all), so an alias would have to invent the one field that
|
|
50180
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
|
+
}),
|
|
50181
50431
|
// ---- REGISTERED PR WATCHERS (add / drop / list) ---------------------------------------------
|
|
50182
50432
|
// The worker's own PR watchers, from `mcp__frizz__watch_pr`. Same caller and therefore the same rules
|
|
50183
50433
|
// as the timers above: slug-only (the MCP server outlives the session ids underneath it), and no
|
|
@@ -51121,6 +51371,7 @@ var init_router5 = __esm({
|
|
|
51121
51371
|
init_open_external();
|
|
51122
51372
|
init_local_file();
|
|
51123
51373
|
init_project();
|
|
51374
|
+
init_thread_links();
|
|
51124
51375
|
init_github();
|
|
51125
51376
|
init_github_hovercard();
|
|
51126
51377
|
init_dispatch();
|
|
@@ -51343,9 +51594,9 @@ var init_compression = __esm({
|
|
|
51343
51594
|
|
|
51344
51595
|
// packages/server/src/local-image.ts
|
|
51345
51596
|
import { readFileSync as readFileSync25, realpathSync as realpathSync10, statSync as statSync18 } from "node:fs";
|
|
51346
|
-
import { extname as extname2, isAbsolute as
|
|
51597
|
+
import { extname as extname2, isAbsolute as isAbsolute6 } from "node:path";
|
|
51347
51598
|
function resolveLocalImage(rawPath) {
|
|
51348
|
-
if (!rawPath || !
|
|
51599
|
+
if (!rawPath || !isAbsolute6(rawPath)) return { status: 400 };
|
|
51349
51600
|
const contentType = IMAGE_CONTENT_TYPE[extname2(rawPath).toLowerCase()];
|
|
51350
51601
|
if (!contentType) return { status: 400 };
|
|
51351
51602
|
let real;
|
|
@@ -53336,30 +53587,111 @@ var init_boot_progress = __esm({
|
|
|
53336
53587
|
}
|
|
53337
53588
|
});
|
|
53338
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
|
+
|
|
53339
53671
|
// packages/server/src/runtimes.ts
|
|
53340
53672
|
import { createHash as createHash15 } from "node:crypto";
|
|
53341
53673
|
import {
|
|
53342
53674
|
chmodSync,
|
|
53343
53675
|
closeSync as closeSync16,
|
|
53344
|
-
existsSync as
|
|
53345
|
-
mkdirSync as
|
|
53676
|
+
existsSync as existsSync15,
|
|
53677
|
+
mkdirSync as mkdirSync20,
|
|
53346
53678
|
openSync as openSync17,
|
|
53347
|
-
readFileSync as
|
|
53348
|
-
readdirSync as
|
|
53679
|
+
readFileSync as readFileSync30,
|
|
53680
|
+
readdirSync as readdirSync13,
|
|
53349
53681
|
renameSync as renameSync11,
|
|
53350
53682
|
rmSync as rmSync12,
|
|
53351
53683
|
statSync as statSync22,
|
|
53352
|
-
writeFileSync as
|
|
53684
|
+
writeFileSync as writeFileSync17,
|
|
53353
53685
|
writeSync as writeSync2
|
|
53354
53686
|
} from "node:fs";
|
|
53355
|
-
import { dirname as
|
|
53687
|
+
import { dirname as dirname20, isAbsolute as isAbsolute7, join as join42, normalize, relative as relative3, sep as sep5 } from "node:path";
|
|
53356
53688
|
import { Readable, Transform, Writable as Writable3 } from "node:stream";
|
|
53357
53689
|
import { pipeline } from "node:stream/promises";
|
|
53358
53690
|
import { createGunzip } from "node:zlib";
|
|
53359
53691
|
function runtimesRoot(env = process.env) {
|
|
53360
53692
|
const override = env[RUNTIMES_DIR_ENV];
|
|
53361
|
-
if (override &&
|
|
53362
|
-
return
|
|
53693
|
+
if (override && isAbsolute7(override)) return override;
|
|
53694
|
+
return join42(frizzRoots().cache, "runtimes");
|
|
53363
53695
|
}
|
|
53364
53696
|
function isMusl() {
|
|
53365
53697
|
if (process.platform !== "linux") return false;
|
|
@@ -53376,16 +53708,16 @@ function runtimeCoordinates(backend, platform3 = process.platform, arch = proces
|
|
|
53376
53708
|
return { pkg: "@openai/codex", packageVersion: `${CODEX_VERSION}-${platform3}-${arch}`, label: CODEX_VERSION, binary: `codex${exe}` };
|
|
53377
53709
|
}
|
|
53378
53710
|
function provisionedBinary(backend, root, label) {
|
|
53379
|
-
const dir =
|
|
53711
|
+
const dir = join42(root, backend, label);
|
|
53380
53712
|
let marker;
|
|
53381
53713
|
try {
|
|
53382
|
-
marker = JSON.parse(
|
|
53714
|
+
marker = JSON.parse(readFileSync30(join42(dir, MARKER), "utf8"));
|
|
53383
53715
|
} catch {
|
|
53384
53716
|
return void 0;
|
|
53385
53717
|
}
|
|
53386
53718
|
if (typeof marker.binary !== "string" || marker.label !== label) return void 0;
|
|
53387
|
-
const bin =
|
|
53388
|
-
return
|
|
53719
|
+
const bin = join42(dir, marker.binary);
|
|
53720
|
+
return existsSync15(bin) ? bin : void 0;
|
|
53389
53721
|
}
|
|
53390
53722
|
function octal(buffer, offset, length) {
|
|
53391
53723
|
const text2 = buffer.toString("latin1", offset, offset + length).replace(/\0.*$/su, "").trim();
|
|
@@ -53398,27 +53730,27 @@ function safeEntryPath(dest, name) {
|
|
|
53398
53730
|
const parts = name.split("/").filter((part) => part.length > 0);
|
|
53399
53731
|
if (parts.length < 2) return void 0;
|
|
53400
53732
|
const rel = normalize(parts.slice(1).join(sep5));
|
|
53401
|
-
if (
|
|
53402
|
-
const full =
|
|
53733
|
+
if (isAbsolute7(rel) || rel === ".." || rel.startsWith(`..${sep5}`)) return void 0;
|
|
53734
|
+
const full = join42(dest, rel);
|
|
53403
53735
|
const back = relative3(dest, full);
|
|
53404
|
-
if (back.startsWith("..") ||
|
|
53736
|
+
if (back.startsWith("..") || isAbsolute7(back)) return void 0;
|
|
53405
53737
|
return full;
|
|
53406
53738
|
}
|
|
53407
53739
|
function locateBinary(dir, backend, binary) {
|
|
53408
53740
|
if (backend === "claude") {
|
|
53409
|
-
const direct =
|
|
53410
|
-
return
|
|
53741
|
+
const direct = join42(dir, binary);
|
|
53742
|
+
return existsSync15(direct) ? direct : void 0;
|
|
53411
53743
|
}
|
|
53412
|
-
const vendor =
|
|
53744
|
+
const vendor = join42(dir, "vendor");
|
|
53413
53745
|
let triples;
|
|
53414
53746
|
try {
|
|
53415
|
-
triples =
|
|
53747
|
+
triples = readdirSync13(vendor);
|
|
53416
53748
|
} catch {
|
|
53417
53749
|
return void 0;
|
|
53418
53750
|
}
|
|
53419
53751
|
for (const triple of triples) {
|
|
53420
|
-
const candidate =
|
|
53421
|
-
if (
|
|
53752
|
+
const candidate = join42(vendor, triple, "bin", binary);
|
|
53753
|
+
if (existsSync15(candidate)) return candidate;
|
|
53422
53754
|
}
|
|
53423
53755
|
return void 0;
|
|
53424
53756
|
}
|
|
@@ -53433,12 +53765,12 @@ async function provisionRuntime(backend, options) {
|
|
|
53433
53765
|
const registry = options.registry ?? REGISTRY;
|
|
53434
53766
|
const progress = options.onProgress ?? (() => {
|
|
53435
53767
|
});
|
|
53436
|
-
const backendDir =
|
|
53437
|
-
const finalDir =
|
|
53438
|
-
const partial =
|
|
53439
|
-
|
|
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 });
|
|
53440
53772
|
rmSync12(partial, { recursive: true, force: true });
|
|
53441
|
-
|
|
53773
|
+
mkdirSync20(partial);
|
|
53442
53774
|
try {
|
|
53443
53775
|
const manifestUrl = `${registry}/${coordinates.pkg.replace("/", "%2F")}/${coordinates.packageVersion}`;
|
|
53444
53776
|
progress(`resolving ${coordinates.pkg}@${coordinates.packageVersion}`);
|
|
@@ -53482,7 +53814,7 @@ async function provisionRuntime(backend, options) {
|
|
|
53482
53814
|
binary: relative3(partial, bin),
|
|
53483
53815
|
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
53484
53816
|
};
|
|
53485
|
-
|
|
53817
|
+
writeFileSync17(join42(partial, MARKER), `${JSON.stringify(marker, null, 2)}
|
|
53486
53818
|
`, "utf8");
|
|
53487
53819
|
try {
|
|
53488
53820
|
renameSync11(partial, finalDir);
|
|
@@ -53493,35 +53825,41 @@ async function provisionRuntime(backend, options) {
|
|
|
53493
53825
|
return { bin: theirs, label: coordinates.label, fetched: false };
|
|
53494
53826
|
}
|
|
53495
53827
|
progress("ready");
|
|
53496
|
-
return { bin:
|
|
53828
|
+
return { bin: join42(finalDir, marker.binary), label: coordinates.label, fetched: true };
|
|
53497
53829
|
} catch (err) {
|
|
53498
53830
|
rmSync12(partial, { recursive: true, force: true });
|
|
53499
53831
|
throw err;
|
|
53500
53832
|
}
|
|
53501
53833
|
}
|
|
53502
53834
|
function sweepRuntimes(backend, root, keepLabel, now = Date.now()) {
|
|
53503
|
-
const backendDir =
|
|
53835
|
+
const backendDir = join42(root, backend);
|
|
53504
53836
|
let entries2;
|
|
53505
53837
|
try {
|
|
53506
|
-
entries2 =
|
|
53838
|
+
entries2 = readdirSync13(backendDir);
|
|
53507
53839
|
} catch {
|
|
53508
|
-
return [];
|
|
53840
|
+
return { removed: [], kept: [] };
|
|
53509
53841
|
}
|
|
53510
|
-
const
|
|
53842
|
+
const sweep = { removed: [], kept: [] };
|
|
53511
53843
|
for (const entry of entries2) {
|
|
53512
53844
|
if (entry === keepLabel) continue;
|
|
53513
|
-
const full =
|
|
53845
|
+
const full = join42(backendDir, entry);
|
|
53514
53846
|
if (entry.startsWith(".partial-")) {
|
|
53515
53847
|
try {
|
|
53516
53848
|
if (now - statSync22(full).mtimeMs < 24 * 60 * 60 * 1e3) continue;
|
|
53517
53849
|
} catch {
|
|
53518
53850
|
continue;
|
|
53519
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
|
+
}
|
|
53520
53858
|
}
|
|
53521
53859
|
rmSync12(full, { recursive: true, force: true });
|
|
53522
|
-
removed.push(full);
|
|
53860
|
+
sweep.removed.push(full);
|
|
53523
53861
|
}
|
|
53524
|
-
return
|
|
53862
|
+
return sweep;
|
|
53525
53863
|
}
|
|
53526
53864
|
async function resolveOne(backend, explicit, options) {
|
|
53527
53865
|
const env = options.env ?? process.env;
|
|
@@ -53547,7 +53885,12 @@ async function resolveOne(backend, explicit, options) {
|
|
|
53547
53885
|
onProgress: (message) => options.onProgress?.(backend, message)
|
|
53548
53886
|
});
|
|
53549
53887
|
if (provisioned.fetched) log3("info", `runtimes: provisioned ${backend} ${provisioned.label} at ${provisioned.bin}`);
|
|
53550
|
-
|
|
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
|
+
}
|
|
53551
53894
|
return { bin: provisioned.bin, source: "provisioned", version: provisioned.label };
|
|
53552
53895
|
} catch (err) {
|
|
53553
53896
|
const note = err instanceof Error ? err.message : String(err);
|
|
@@ -53578,6 +53921,7 @@ var init_runtimes = __esm({
|
|
|
53578
53921
|
"use strict";
|
|
53579
53922
|
init_codex_app_server();
|
|
53580
53923
|
init_frizz_paths();
|
|
53924
|
+
init_runtime_lease();
|
|
53581
53925
|
CLAUDE_AGENT_SDK_VERSION = "0.3.268";
|
|
53582
53926
|
CLAUDE_CODE_VERSION = "2.1.268";
|
|
53583
53927
|
CODEX_VERSION = CODEX_APP_SERVER_SUPPORTED_VERSION;
|
|
@@ -53668,7 +54012,7 @@ var init_runtimes = __esm({
|
|
|
53668
54012
|
return;
|
|
53669
54013
|
case "5": {
|
|
53670
54014
|
const dir = safeEntryPath(this.dest, name);
|
|
53671
|
-
if (dir)
|
|
54015
|
+
if (dir) mkdirSync20(dir, { recursive: true });
|
|
53672
54016
|
return;
|
|
53673
54017
|
}
|
|
53674
54018
|
case "0":
|
|
@@ -53676,7 +54020,7 @@ var init_runtimes = __esm({
|
|
|
53676
54020
|
case "7": {
|
|
53677
54021
|
const file = safeEntryPath(this.dest, name);
|
|
53678
54022
|
if (!file) return;
|
|
53679
|
-
|
|
54023
|
+
mkdirSync20(dirname20(file), { recursive: true });
|
|
53680
54024
|
this.fd = openSync17(file, "w", octal(header, 100, 8) & 511 || 420);
|
|
53681
54025
|
this.written.push(file);
|
|
53682
54026
|
return;
|
|
@@ -54248,18 +54592,18 @@ var init_legacy_project_db = __esm({
|
|
|
54248
54592
|
});
|
|
54249
54593
|
|
|
54250
54594
|
// packages/server/src/frizz-db.ts
|
|
54251
|
-
import { existsSync as
|
|
54252
|
-
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";
|
|
54253
54597
|
function frizzDatabaseLocation(options) {
|
|
54254
54598
|
if (options.stateDir !== void 0) {
|
|
54255
|
-
const projectsDir =
|
|
54599
|
+
const projectsDir = dirname21(options.stateDir);
|
|
54256
54600
|
if (basename13(projectsDir) === "projects") {
|
|
54257
|
-
return { path: options.path ??
|
|
54601
|
+
return { path: options.path ?? join43(dirname21(projectsDir), "ui.db"), projectsDir };
|
|
54258
54602
|
}
|
|
54259
|
-
return { path: options.path ??
|
|
54603
|
+
return { path: options.path ?? join43(options.stateDir, "ui.db"), projectsDir: void 0 };
|
|
54260
54604
|
}
|
|
54261
54605
|
const data = options.home ? frizzPaths({ home: options.home }).data : frizzRoots().data;
|
|
54262
|
-
return { path: options.path ??
|
|
54606
|
+
return { path: options.path ?? join43(data, "ui.db"), projectsDir: join43(data, "projects") };
|
|
54263
54607
|
}
|
|
54264
54608
|
function ensureFrizzSchema(db) {
|
|
54265
54609
|
db.exec(`
|
|
@@ -54278,7 +54622,7 @@ function ensureFrizzSchema(db) {
|
|
|
54278
54622
|
}
|
|
54279
54623
|
function openFrizzDatabase(options = {}) {
|
|
54280
54624
|
const { path: path3, projectsDir } = frizzDatabaseLocation(options);
|
|
54281
|
-
|
|
54625
|
+
mkdirSync21(dirname21(path3), { recursive: true });
|
|
54282
54626
|
const db = new sqlite_default(path3);
|
|
54283
54627
|
db.pragma("busy_timeout = 5000");
|
|
54284
54628
|
db.pragma("journal_mode = WAL");
|
|
@@ -54290,10 +54634,10 @@ function openFrizzDatabase(options = {}) {
|
|
|
54290
54634
|
);
|
|
54291
54635
|
for (const projectId of retiredLegacyProjectIds(projectsDir)) {
|
|
54292
54636
|
if (alreadyImported.has(projectId)) continue;
|
|
54293
|
-
const dir =
|
|
54637
|
+
const dir = join43(projectsDir, projectId);
|
|
54294
54638
|
try {
|
|
54295
|
-
renameSync12(
|
|
54296
|
-
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());
|
|
54297
54641
|
alreadyImported.add(projectId);
|
|
54298
54642
|
log.info("frizz-db", `${projectId}: restored ui.db.imported to ui.db and recorded it as imported`);
|
|
54299
54643
|
} catch (error) {
|
|
@@ -54303,7 +54647,7 @@ function openFrizzDatabase(options = {}) {
|
|
|
54303
54647
|
}
|
|
54304
54648
|
for (const projectId of legacyProjectIds(projectsDir)) {
|
|
54305
54649
|
if (alreadyImported.has(projectId)) continue;
|
|
54306
|
-
const legacyPath =
|
|
54650
|
+
const legacyPath = join43(projectsDir, projectId, "ui.db");
|
|
54307
54651
|
try {
|
|
54308
54652
|
const rows = importLegacyProject(db, projectId, legacyPath);
|
|
54309
54653
|
imported.push({ projectId, rows });
|
|
@@ -54333,10 +54677,10 @@ function openFrizzDatabase(options = {}) {
|
|
|
54333
54677
|
};
|
|
54334
54678
|
}
|
|
54335
54679
|
function projectIdsWithFile(projectsDir, file) {
|
|
54336
|
-
if (!
|
|
54337
|
-
return
|
|
54680
|
+
if (!existsSync16(projectsDir)) return [];
|
|
54681
|
+
return readdirSync14(projectsDir).filter((name) => {
|
|
54338
54682
|
try {
|
|
54339
|
-
return statSync23(
|
|
54683
|
+
return statSync23(join43(projectsDir, name, file)).isFile();
|
|
54340
54684
|
} catch {
|
|
54341
54685
|
return false;
|
|
54342
54686
|
}
|
|
@@ -54346,7 +54690,7 @@ function legacyProjectIds(projectsDir) {
|
|
|
54346
54690
|
return projectIdsWithFile(projectsDir, "ui.db");
|
|
54347
54691
|
}
|
|
54348
54692
|
function retiredLegacyProjectIds(projectsDir) {
|
|
54349
|
-
return projectIdsWithFile(projectsDir, "ui.db.imported").filter((id) => !
|
|
54693
|
+
return projectIdsWithFile(projectsDir, "ui.db.imported").filter((id) => !existsSync16(join43(projectsDir, id, "ui.db")));
|
|
54350
54694
|
}
|
|
54351
54695
|
function tableColumns(db, schema, table) {
|
|
54352
54696
|
return db.prepare(`PRAGMA ${schema}.table_info(${table})`).all().map((c) => c.name);
|
|
@@ -54502,7 +54846,7 @@ var init_tenant_prime = __esm({
|
|
|
54502
54846
|
// packages/server/src/project-teardown.ts
|
|
54503
54847
|
import { rmSync as rmSync13 } from "node:fs";
|
|
54504
54848
|
import { homedir as homedir19 } from "node:os";
|
|
54505
|
-
import { dirname as
|
|
54849
|
+
import { dirname as dirname22, resolve as resolve10 } from "node:path";
|
|
54506
54850
|
async function stopProjectWorkers(ctx) {
|
|
54507
54851
|
let stopped = 0;
|
|
54508
54852
|
for (const row of ctx.storage.allSessions()) {
|
|
@@ -54522,7 +54866,7 @@ function deleteProjectState(projectId, home = homedir19()) {
|
|
|
54522
54866
|
if (!/^[\w.-]+$/u.test(projectId) || projectId === "." || projectId === "..") {
|
|
54523
54867
|
throw new Error(`Refusing to delete state for a malformed project id: ${projectId}`);
|
|
54524
54868
|
}
|
|
54525
|
-
if (
|
|
54869
|
+
if (dirname22(resolve10(target)) !== resolve10(dirname22(projectStateDir("x", home)))) {
|
|
54526
54870
|
throw new Error(`Refusing to delete ${target} \u2014 it is not a project state directory`);
|
|
54527
54871
|
}
|
|
54528
54872
|
rmSync13(target, { recursive: true, force: true });
|
|
@@ -54551,11 +54895,11 @@ __export(index_exports, {
|
|
|
54551
54895
|
unknownProjectPage: () => unknownProjectPage
|
|
54552
54896
|
});
|
|
54553
54897
|
import { createServer } from "node:http";
|
|
54554
|
-
import { readFileSync as
|
|
54555
|
-
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";
|
|
54556
54900
|
function readServerAddressHolder(path3) {
|
|
54557
54901
|
try {
|
|
54558
|
-
const value = JSON.parse(
|
|
54902
|
+
const value = JSON.parse(readFileSync31(path3, "utf8"));
|
|
54559
54903
|
if (typeof value?.pid !== "number") return void 0;
|
|
54560
54904
|
return { pid: value.pid, port: typeof value.port === "number" ? value.port : -1 };
|
|
54561
54905
|
} catch {
|
|
@@ -54680,12 +55024,12 @@ function staticIsFresh(req, etag, mtimeMs) {
|
|
|
54680
55024
|
}
|
|
54681
55025
|
function serveStatic(distDir, req, res) {
|
|
54682
55026
|
const rel = normalize2((req.url ?? "/").split("?")[0]).replace(/^(\.\.[/\\])+/, "");
|
|
54683
|
-
let file =
|
|
54684
|
-
if (!file.startsWith(distDir)) file =
|
|
54685
|
-
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");
|
|
54686
55030
|
try {
|
|
54687
55031
|
const stats = statSync24(file);
|
|
54688
|
-
const cacheControl = file.startsWith(
|
|
55032
|
+
const cacheControl = file.startsWith(join44(distDir, "assets") + sep6) ? STATIC_CACHE_IMMUTABLE : STATIC_CACHE_REVALIDATE;
|
|
54689
55033
|
const etag = `"${stats.size.toString(16)}-${Math.trunc(stats.mtimeMs).toString(16)}"`;
|
|
54690
55034
|
const headers = {
|
|
54691
55035
|
"content-type": MIME[extname4(file)] ?? "application/octet-stream",
|
|
@@ -54701,7 +55045,7 @@ function serveStatic(distDir, req, res) {
|
|
|
54701
55045
|
res.end();
|
|
54702
55046
|
return;
|
|
54703
55047
|
}
|
|
54704
|
-
let body =
|
|
55048
|
+
let body = readFileSync31(file);
|
|
54705
55049
|
const accept = req.headers["accept-encoding"];
|
|
54706
55050
|
const encoding = negotiateEncoding(Array.isArray(accept) ? accept.join(",") : accept);
|
|
54707
55051
|
if (encoding && shouldCompress(new Headers({ "content-type": headers["content-type"] }), body.byteLength)) {
|
|
@@ -54963,7 +55307,7 @@ async function startServer(opts = {}) {
|
|
|
54963
55307
|
if (statusPath && statusIdentity) runtime.removeStatus(statusPath, statusIdentity);
|
|
54964
55308
|
if (statusPath && statusIdentity) {
|
|
54965
55309
|
try {
|
|
54966
|
-
runtime.removeStatus(serverAddressPathForStateDir(
|
|
55310
|
+
runtime.removeStatus(serverAddressPathForStateDir(dirname23(statusPath)), statusIdentity);
|
|
54967
55311
|
} catch {
|
|
54968
55312
|
}
|
|
54969
55313
|
}
|
|
@@ -55101,7 +55445,7 @@ async function startServer(opts = {}) {
|
|
|
55101
55445
|
}
|
|
55102
55446
|
statusPath = serverLockPathFor(ctx.project);
|
|
55103
55447
|
const webRoot = resolve11(import.meta.dirname, "..", "..", "web");
|
|
55104
|
-
const distDir = opts.webDistDir ? resolve11(opts.webDistDir) :
|
|
55448
|
+
const distDir = opts.webDistDir ? resolve11(opts.webDistDir) : join44(webRoot, "dist");
|
|
55105
55449
|
startupPhase = "Vite";
|
|
55106
55450
|
if (opts.dev) {
|
|
55107
55451
|
try {
|
|
@@ -55177,7 +55521,7 @@ async function startServer(opts = {}) {
|
|
|
55177
55521
|
if (vite) {
|
|
55178
55522
|
vite.middlewares(req, res, () => {
|
|
55179
55523
|
try {
|
|
55180
|
-
const html =
|
|
55524
|
+
const html = readFileSync31(join44(webRoot, "index.html"), "utf8");
|
|
55181
55525
|
void vite.transformIndexHtml(url, html).then((out) => {
|
|
55182
55526
|
res.writeHead(200, { "content-type": "text/html" });
|
|
55183
55527
|
res.end(out);
|
|
@@ -55189,7 +55533,7 @@ async function startServer(opts = {}) {
|
|
|
55189
55533
|
});
|
|
55190
55534
|
return;
|
|
55191
55535
|
}
|
|
55192
|
-
if (
|
|
55536
|
+
if (existsSync17(distDir)) {
|
|
55193
55537
|
serveStatic(distDir, req, res);
|
|
55194
55538
|
return;
|
|
55195
55539
|
}
|
|
@@ -55387,7 +55731,7 @@ var init_index = __esm({
|
|
|
55387
55731
|
}
|
|
55388
55732
|
};
|
|
55389
55733
|
isApiUrl = (url) => url === FRIZZ_ROUTE_PREFIX || url.startsWith(`${FRIZZ_ROUTE_PREFIX}/`);
|
|
55390
|
-
serverLockPathFor = (project) =>
|
|
55734
|
+
serverLockPathFor = (project) => join44(project.stateDir, "server.lock");
|
|
55391
55735
|
MIME = {
|
|
55392
55736
|
".html": "text/html",
|
|
55393
55737
|
".js": "text/javascript",
|
|
@@ -55410,8 +55754,8 @@ init_project();
|
|
|
55410
55754
|
init_project_launch();
|
|
55411
55755
|
init_shutdown();
|
|
55412
55756
|
init_logging();
|
|
55413
|
-
import { existsSync as
|
|
55414
|
-
import { join as
|
|
55757
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
55758
|
+
import { join as join45 } from "node:path";
|
|
55415
55759
|
process.on("uncaughtException", (error) => {
|
|
55416
55760
|
log.error("dev-child", `uncaught exception: ${error instanceof Error ? error.stack ?? error.message : error}`);
|
|
55417
55761
|
process.exit(1);
|
|
@@ -55449,9 +55793,9 @@ try {
|
|
|
55449
55793
|
["FRIZZ_SCRIPTS_DIR", process.env.FRIZZ_SCRIPTS_DIR, "index.mjs"],
|
|
55450
55794
|
["FRIZZ_WORKER_PLUGIN_DIR", process.env.FRIZZ_WORKER_PLUGIN_DIR, ".claude-plugin/plugin.json"]
|
|
55451
55795
|
];
|
|
55452
|
-
if (!
|
|
55796
|
+
if (!existsSync18(stableWebDist)) throw new Error("stable artifact launch is missing its verified web directory");
|
|
55453
55797
|
for (const [name, directory, requiredFile] of required) {
|
|
55454
|
-
if (!directory || !
|
|
55798
|
+
if (!directory || !existsSync18(join45(directory, requiredFile)))
|
|
55455
55799
|
throw new Error(`stable artifact launch is missing verified ${name}`);
|
|
55456
55800
|
}
|
|
55457
55801
|
}
|