frizz-server 0.15.16 → 0.15.17

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.
Files changed (99) hide show
  1. package/dist/dev-child.js +1254 -779
  2. package/package.json +1 -1
  3. package/runtime/cc-worker/bin/frizz-mcp.mjs +66 -1
  4. package/web-dist/assets/{abnfDiagram-VRR7QNED-DjpPWj1n.js → abnfDiagram-VRR7QNED-BCWz80uN.js} +1 -1
  5. package/web-dist/assets/{arc-GGQPeqIn.js → arc-DDtkTWyk.js} +1 -1
  6. package/web-dist/assets/architecture-TIHT7OUA-BSM-tgTt.js +1 -0
  7. package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-i9N18wLs.js → architectureDiagram-ZJ3FMSHR-BpRbm_s5.js} +1 -1
  8. package/web-dist/assets/{blockDiagram-677ZJIJ3-CIc5kmW3.js → blockDiagram-677ZJIJ3-_kGtJSW2.js} +1 -1
  9. package/web-dist/assets/{c4Diagram-LMCZKHZV-DjUgY_rv.js → c4Diagram-LMCZKHZV-D8XwDoiY.js} +1 -1
  10. package/web-dist/assets/channel-BwwaRyUv.js +1 -0
  11. package/web-dist/assets/{chunk-32BRIVSS-DdVPbS2L.js → chunk-32BRIVSS-BUGbBNz_.js} +1 -1
  12. package/web-dist/assets/{chunk-52WLFC77-k-avutEL.js → chunk-52WLFC77-Dc0eyYJe.js} +1 -1
  13. package/web-dist/assets/{chunk-C7G6YPKG-jMdA6WRB.js → chunk-C7G6YPKG-CNP8apQ_.js} +1 -1
  14. package/web-dist/assets/{chunk-EX3LRPZG-DPQFUeFc.js → chunk-EX3LRPZG-m5klG9uB.js} +1 -1
  15. package/web-dist/assets/{chunk-FWX5IMBZ-CnOUb3RH.js → chunk-FWX5IMBZ-CHO58JFl.js} +2 -2
  16. package/web-dist/assets/{chunk-HOUHSVGY-YdnK1w2S.js → chunk-HOUHSVGY-DjH-r82r.js} +1 -1
  17. package/web-dist/assets/{chunk-ICXQ74PX-hdfmNc2d.js → chunk-ICXQ74PX-DkYjEd46.js} +1 -1
  18. package/web-dist/assets/{chunk-MOJQB5TN-CsGFUAEU.js → chunk-MOJQB5TN-D89rLIxX.js} +1 -1
  19. package/web-dist/assets/{chunk-OGEWGWER-CzQY8gM0.js → chunk-OGEWGWER-Db2MBETv.js} +1 -1
  20. package/web-dist/assets/{chunk-PUDLZKDR-CquKZy9Z.js → chunk-PUDLZKDR-Dtdx_z8j.js} +1 -1
  21. package/web-dist/assets/{chunk-Q4XR5HBZ-C_1V073n.js → chunk-Q4XR5HBZ-XYvD_xYq.js} +1 -1
  22. package/web-dist/assets/{chunk-RYQCIY6F-B2Y6QBP5.js → chunk-RYQCIY6F-CZ7RTprX.js} +1 -1
  23. package/web-dist/assets/{chunk-V7JOEXUC-_NMzZcnP.js → chunk-V7JOEXUC-CoAVJiNJ.js} +1 -1
  24. package/web-dist/assets/{chunk-VAUOI2AC-D8ojVgWd.js → chunk-VAUOI2AC-DbjEHErZ.js} +1 -1
  25. package/web-dist/assets/{chunk-VR4S4FIN-CgTzyBot.js → chunk-VR4S4FIN-4BB6eLCK.js} +1 -1
  26. package/web-dist/assets/{chunk-WYO6CB5R-D0qL-eZe.js → chunk-WYO6CB5R-Cuvm_fLi.js} +1 -1
  27. package/web-dist/assets/{chunk-XXDRQBXY-CqoZQ1Er.js → chunk-XXDRQBXY-CvLzx99l.js} +1 -1
  28. package/web-dist/assets/{chunk-ZGVPDNZ5-CY3MtA1p.js → chunk-ZGVPDNZ5-BccJcRbi.js} +1 -1
  29. package/web-dist/assets/classDiagram-OUVF2IWQ-DTgWbehh.js +1 -0
  30. package/web-dist/assets/classDiagram-v2-EOCWNBFH-DTgWbehh.js +1 -0
  31. package/web-dist/assets/{cose-bilkent-JH36ORCC-CdwbTfJj.js → cose-bilkent-JH36ORCC-BfwT-16i.js} +1 -1
  32. package/web-dist/assets/{cynefin-VYW2F7L2-CpVXg7NY.js → cynefin-VYW2F7L2-DbZ1V36t.js} +1 -1
  33. package/web-dist/assets/{cynefinDiagram-TSTJHNR4-Bq8xdMaL.js → cynefinDiagram-TSTJHNR4-mFI_mDt-.js} +1 -1
  34. package/web-dist/assets/{dagre-VKFMJZFB-3LmR7haE.js → dagre-VKFMJZFB-BldEgHyl.js} +1 -1
  35. package/web-dist/assets/{diagram-FQU43EPY-Bl3VhSKJ.js → diagram-FQU43EPY-CWSdOHjN.js} +1 -1
  36. package/web-dist/assets/{diagram-G47NLZAW-Dx8wicI9.js → diagram-G47NLZAW-CohHPpmC.js} +1 -1
  37. package/web-dist/assets/{diagram-NH7WQ7WH-D-ac7oKf.js → diagram-NH7WQ7WH-CY9SIr04.js} +1 -1
  38. package/web-dist/assets/{diagram-OA4YK3LP-C3n9muDh.js → diagram-OA4YK3LP-D1ChaJcq.js} +1 -1
  39. package/web-dist/assets/{diagram-WEI45ONY-zhWZ_XKT.js → diagram-WEI45ONY-Bng85j-O.js} +1 -1
  40. package/web-dist/assets/{dist-C2WuhXSR.js → dist-Dn2m7SMF.js} +1 -1
  41. package/web-dist/assets/{ebnfDiagram-CCIWWBDH-BYXQgDLw.js → ebnfDiagram-CCIWWBDH-CcHfTwsR.js} +1 -1
  42. package/web-dist/assets/{erDiagram-Q63AITRT-DSTBG9Mp.js → erDiagram-Q63AITRT-D9XptUTi.js} +1 -1
  43. package/web-dist/assets/eventmodeling-45OFAUF4-vqzohKbi.js +1 -0
  44. package/web-dist/assets/flowDiagram-23GEKE2U-CYPLykok.js +1 -0
  45. package/web-dist/assets/{ganttDiagram-NO4QXBWP-C9RStO67.js → ganttDiagram-NO4QXBWP-CpDcHWNC.js} +1 -1
  46. package/web-dist/assets/{gitGraph-TEB2WS4Q-JFtHkb0B.js → gitGraph-TEB2WS4Q-dskxWshP.js} +1 -1
  47. package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-uVA8Zt2w.js → gitGraphDiagram-IHSO6WYX-Gm-g6rXY.js} +1 -1
  48. package/web-dist/assets/index-Bi4vNYho.css +2 -0
  49. package/web-dist/assets/index-C5sCt0eh.js +334 -0
  50. package/web-dist/assets/{info-DKCQHKI2-hrkiQZrg.js → info-DKCQHKI2-DfBWPig9.js} +1 -1
  51. package/web-dist/assets/{infoDiagram-FWYZ7A6U-BhdOdJlu.js → infoDiagram-FWYZ7A6U-RA1gm_5G.js} +1 -1
  52. package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-zdLsCb3B.js → ishikawaDiagram-FXEZZL3T-DMO4tlB7.js} +1 -1
  53. package/web-dist/assets/{journeyDiagram-5HDEW3XC-C_2hQwBD.js → journeyDiagram-5HDEW3XC-CGn0Vfft.js} +1 -1
  54. package/web-dist/assets/{kanban-definition-HUTT4EX6-o0jEXUku.js → kanban-definition-HUTT4EX6-qRxs3pxC.js} +1 -1
  55. package/web-dist/assets/{line-BI9UTuIR.js → line-BihkNjKV.js} +1 -1
  56. package/web-dist/assets/{linear-Rr0EbNoq.js → linear-CbcYjraG.js} +1 -1
  57. package/web-dist/assets/{mermaid-parser.core-yhmLALkv.js → mermaid-parser.core-CstJtBOd.js} +3 -3
  58. package/web-dist/assets/{mermaid.core-BRyxVBzn.js → mermaid.core-CAoFTj5o.js} +3 -3
  59. package/web-dist/assets/{mindmap-definition-LN4V7U3C-BA9ji-1w.js → mindmap-definition-LN4V7U3C-Dobyf2TY.js} +1 -1
  60. package/web-dist/assets/{packet-7NZHBO7P-DBhL0KIK.js → packet-7NZHBO7P-BV-_zRVl.js} +1 -1
  61. package/web-dist/assets/{pegDiagram-2B236MQR-CPxXVeZH.js → pegDiagram-2B236MQR-CoWfyvfk.js} +1 -1
  62. package/web-dist/assets/{pie-RZYD4A2V-ByCiaDbD.js → pie-RZYD4A2V-ptQFpYwJ.js} +1 -1
  63. package/web-dist/assets/{pieDiagram-ENE6RG2P-Bw8GvNiv.js → pieDiagram-ENE6RG2P-DCYSn0kJ.js} +1 -1
  64. package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-CwL8u1x5.js → quadrantDiagram-ABIIQ3AL-D-IhKJdt.js} +1 -1
  65. package/web-dist/assets/{radar-I7S5WNFK-Ds0-Pw3X.js → radar-I7S5WNFK-CqtSeYcU.js} +1 -1
  66. package/web-dist/assets/{railroad-3IZDKUUU-xwnxXT5n.js → railroad-3IZDKUUU-CejeX1m0.js} +1 -1
  67. package/web-dist/assets/railroad-abnf-AHOZXSZD-D858Ks1V.js +1 -0
  68. package/web-dist/assets/railroad-ebnf-EBAXGLYW-CnKN0qs5.js +1 -0
  69. package/web-dist/assets/railroad-peg-LSFZ7HO6-CG_oVFtv.js +1 -0
  70. package/web-dist/assets/{railroadDiagram-RFXS5EU6-B1rEgDrn.js → railroadDiagram-RFXS5EU6-CLMVsbkb.js} +1 -1
  71. package/web-dist/assets/{requirementDiagram-TGXJPOKE-CdLF-_L5.js → requirementDiagram-TGXJPOKE-J6ovU2nZ.js} +1 -1
  72. package/web-dist/assets/{sankeyDiagram-HTMAVEWB-DTmdqI7H.js → sankeyDiagram-HTMAVEWB-BN1Wcnxg.js} +1 -1
  73. package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-CKtz0A1H.js → sequenceDiagram-DBY2YBRQ-CnDSUjeE.js} +1 -1
  74. package/web-dist/assets/{src-BqbE4HyW.js → src-ie67lQl7.js} +1 -1
  75. package/web-dist/assets/{stateDiagram-2N3HPSRC-GYGYAkK2.js → stateDiagram-2N3HPSRC-CDvDw5S6.js} +1 -1
  76. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-CWmRITC6.js +1 -0
  77. package/web-dist/assets/{swimlanes-5IMT3BWC-DAi3tBaQ.js → swimlanes-5IMT3BWC-BmljTUhI.js} +1 -1
  78. package/web-dist/assets/swimlanesDiagram-G3AALYLV-BTxJqUkH.js +8 -0
  79. package/web-dist/assets/{timeline-definition-FHXFAJF6-O4KNojxn.js → timeline-definition-FHXFAJF6-CjA-qR6O.js} +1 -1
  80. package/web-dist/assets/{treeView-QDETBFTQ-BbAhfX9e.js → treeView-QDETBFTQ-CHKGsZbS.js} +1 -1
  81. package/web-dist/assets/{treemap-6X3UGDF4-D3XVXTNg.js → treemap-6X3UGDF4-CqU-nL1w.js} +1 -1
  82. package/web-dist/assets/{vennDiagram-L72KCM5P-BjsVc4st.js → vennDiagram-L72KCM5P-BwQcxcel.js} +1 -1
  83. package/web-dist/assets/{wardley-OPB4EBWU-CcWQmwG4.js → wardley-OPB4EBWU-Bo8e8N-h.js} +1 -1
  84. package/web-dist/assets/{wardleyDiagram-EHGQE667-Cz-aojN7.js → wardleyDiagram-EHGQE667-ByioZC4m.js} +1 -1
  85. package/web-dist/assets/{xychartDiagram-FW5EYKEG-CASxN8z7.js → xychartDiagram-FW5EYKEG-B48Vy_EL.js} +1 -1
  86. package/web-dist/index.html +2 -2
  87. package/web-dist/assets/architecture-TIHT7OUA-qF4uSd6w.js +0 -1
  88. package/web-dist/assets/channel-KKo0nJfj.js +0 -1
  89. package/web-dist/assets/classDiagram-OUVF2IWQ-B4WEPxqA.js +0 -1
  90. package/web-dist/assets/classDiagram-v2-EOCWNBFH-B4WEPxqA.js +0 -1
  91. package/web-dist/assets/eventmodeling-45OFAUF4-Dfi1SiqN.js +0 -1
  92. package/web-dist/assets/flowDiagram-23GEKE2U-DrZ_4EiE.js +0 -1
  93. package/web-dist/assets/index-DdA4AFB7.js +0 -334
  94. package/web-dist/assets/index-J1N8yjnp.css +0 -2
  95. package/web-dist/assets/railroad-abnf-AHOZXSZD-BMLoaNxy.js +0 -1
  96. package/web-dist/assets/railroad-ebnf-EBAXGLYW-BRk3kvdr.js +0 -1
  97. package/web-dist/assets/railroad-peg-LSFZ7HO6-h9Wo00HF.js +0 -1
  98. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-BmiBzOjo.js +0 -1
  99. package/web-dist/assets/swimlanesDiagram-G3AALYLV-BvIghLXt.js +0 -8
package/dist/dev-child.js CHANGED
@@ -760,10 +760,10 @@ function discoverProjectRoot(cwd = process.cwd(), home = homedir3()) {
760
760
  } catch {
761
761
  return resolve3(cwd);
762
762
  }
763
- const stop = resolve3(home);
763
+ const stop2 = resolve3(home);
764
764
  const filesystemRoot = parse(dir).root;
765
765
  for (let at2 = dir; ; at2 = dirname3(at2)) {
766
- if (at2 === stop || at2 === filesystemRoot) break;
766
+ if (at2 === stop2 || at2 === filesystemRoot) break;
767
767
  if (existsSync2(projectIdPath(at2))) return at2;
768
768
  if (hasAny(at2, REPO_MARKERS)) return at2;
769
769
  if (hasAny(at2, PROJECT_MARKERS)) return at2;
@@ -13731,9 +13731,10 @@ function signoffNudgeText(needsInput) {
13731
13731
  " `mcp__frizz__timer`; `mcp__frizz__activity` reads back everything you have running, with its id.",
13732
13732
  "- `` ```awaiting `` with `steps:` \u2014 the human must PERFORM something you cannot: sign in, approve,",
13733
13733
  " merge, press a button you may not. List each step as a `- ` line under `steps:`, written to be",
13734
- " followed cold; frizz reads them verbatim. Steps name the HUMAN as the wait, so the fence needs no",
13735
- " other name and no `for:`, and the thread goes into their queue. Their Done comes back to you as",
13736
- " their reply; anything else they need to say comes as a message of their own.",
13734
+ " followed cold: a real Markdown link to every page and file it names, every command in a code span,",
13735
+ " every value the act needs written in. Frizz reads them verbatim. Steps name the HUMAN as the wait,",
13736
+ " so the fence needs no other name and no `for:`, and the thread goes into their queue. Their Done",
13737
+ " comes back to you as their reply; anything else they need to say comes as a message of their own.",
13737
13738
  "- `` ```awaiting `` with `questions:` \u2014 a question you registered at an EARLIER rest is still open and",
13738
13739
  " you still need its answer. Name every such question (`questions: [qst_\u2026]`) and withdraw the rest with",
13739
13740
  " `mcp__frizz__unask`: a fence that leaves an open question out is refused. A named card is drawn at",
@@ -13854,6 +13855,8 @@ function askedQuestionFaults(q2) {
13854
13855
  const faults = [];
13855
13856
  const walk = (node, path3) => {
13856
13857
  const options = node.options ?? [];
13858
+ if (node.secret && options.length > 0) faults.push(`${path3}: a secret request takes no options \u2014 it is one masked box`);
13859
+ if (node.secret && path3 !== "question") faults.push(`${path3}: a secret request cannot be a follow-up \u2014 register it on its own`);
13857
13860
  if (node.kind === "multi" && options.length === 0) faults.push(`${path3}: \`kind: "multi"\` needs options \u2014 a question with none is free text`);
13858
13861
  if (options.filter((o) => o.recommended).length > 1) faults.push(`${path3}: only ONE option may be \`recommended\` \u2014 a recommendation on two of three choices says nothing`);
13859
13862
  for (const [i, option] of options.entries()) {
@@ -13870,6 +13873,12 @@ function askedQuestionFaults(q2) {
13870
13873
  }
13871
13874
  return faults;
13872
13875
  }
13876
+ function secretAnswerText(path3) {
13877
+ return `(secret ready at ${quotePath(path3)} \u2014 it can be read ONCE, within ${SECRET_TTL_MS / 6e4}m; never print it)`;
13878
+ }
13879
+ function quotePath(value) {
13880
+ return `'${value.replace(/'/g, `'\\''`)}'`;
13881
+ }
13873
13882
  function questionAnswerMessage(answers, dismissed = []) {
13874
13883
  if (answers.length === 0) return questionsCancelledWakeMessage(dismissed.length);
13875
13884
  const rows = [];
@@ -14118,7 +14127,7 @@ function parseGithubWakeSteer(text2) {
14118
14127
  function frizzRoute(path3) {
14119
14128
  return `${FRIZZ_ROUTE_PREFIX}${path3.startsWith("/") ? path3 : `/${path3}`}`;
14120
14129
  }
14121
- var import_yaml, ATTACHMENT_IMAGE_EXTENSIONS, ATTACHMENT_TEXT_EXTENSIONS, ATTACHMENT_OFFICE_EXTENSIONS, ATTACHMENT_DATA_EXTENSIONS, ATTACHMENT_ARCHIVE_EXTENSIONS, ATTACHMENT_DOC_EXTENSIONS, ATTACHMENT_EXTENSIONS, ATTACHMENT_MAX_BASE64_CHARS, ATTACHMENT_MAX_BYTES, ATTACHMENT_EXT_SET, ATTACHMENT_ACCEPT, FrizzStatus, BlockMechanism, RuntimeState, Backend, CodexModel, ClaudeModel, CODEX_MODELS_FALLBACK, AcpAgent, ACP_MODEL_PREFIX, AcpAgentModel, AcpAgentModels, AcpAgentModelsInput, ThreadProfileOption, ThreadAgent, SubAgentView, BgShellView, CompletionHoldOp, CompletionHold, AskOption, AskQuestion, PendingAsk, AwaitingHint, RETIRED_AWAITING_KINDS, RETIRED_LINE_RE, RETIRED_AWAITING_REPLACEMENT, AWAITING_KEY_RE, AWAITING_YAML_KEYS, AWAITING_SEQUENCE_KEYS, AWAITING_HINT_MAX, AWAITING_HINT_VALUE_MAX, AWAITING_SCALAR_KINDS, AWAITING_STEPS_MAX, AWAITING_STEP_VALUE_MAX, AWAITING_QUESTIONS_MAX, AWAITING_TITLE_MAX, AWAITING_STATUSES, AWAITING_ITEM_KINDS, AWAITING_DURATION_RE, DURATION_UNIT_MS, AWAITING_FOR_MAX_MS, SnoozeUntil, SNOOZE_PROMPT_MAX, SnoozePrompt, RECURRING_PROMPT_MAX, RECURRING_MIN_INTERVAL_SECONDS, RECURRING_MAX_INTERVAL_SECONDS, RecurringPromptText, RecurringIntervalSeconds, ThreadRecurringPrompt, INTERRUPT_MARKERS, ALLDONE_SENTINEL, OPT_OUT_NOTE, OVER_QUESTION_NOTE, TIMER_PROMPT_MAX, TIMER_MAX_DELAY_SECONDS, TIMER_MAX_ARMED, TimerPromptText, PR_WATCH_SPENT_TRAILER, PR_WATCH_ARMED_TRAILER, SHELL_DONE_TRAILER, ISSUE_WATCH_SPENT_TRAILER, ISSUE_WATCH_ARMED_TRAILER, INTERRUPT_ENDED_LEAD, SIGNOFF_NUDGE_MARKER, SIGNOFF_NUDGE_MESSAGE, SIGNOFF_NUDGE_MESSAGE_NEEDS_INPUT, PARK_CORRECTION_NAMES_LEAD, PARK_CORRECTION_RETIRED_LEAD, PARK_CORRECTION_QUESTION_LEAD, PARK_CORRECTION_NEEDS_INPUT_LEAD, ThreadWatchKind, GithubChecksState, GithubMergeState, GithubWatchStatus, GithubIssueStatus, ThreadWatchView, PR_WATCH_FOR_MAX_MS, PR_WATCH_DEFAULT_FOR_MS, PR_WATCH_MAX_ARMED, PrWatchView, AddOwnPrWatchInput, AddOwnPrWatchResult, DropOwnPrWatchInput, DropOwnPrWatchResult, OwnWatchKind, AddOwnWatchInput, OwnWatchView, AddOwnWatchResult, DropOwnWatchInput, DropOwnWatchResult, OWN_WATCH_MAX_ARMED, QUESTION_FENCE_RETIRED_AT, NEEDS_INPUT_REQUIRED_AT, AskQuestionKind, ASK_MAX_DEPTH, AskedOptionSchema, AskedQuestionSchema, AskInput, RegisteredQuestionView, AskResult, UnaskInput, UnaskResult, QuestionAnswerSchema, AnswerQuestionsInput, AnswerQuestionsResult, DismissQuestionsInput, DismissQuestionsResult, SettledQuestionView, ThreadSettledQuestionsResult, BURIED_ANSWERS_HEADER, ANSWER_FOLLOW_UP_MARKER, ANSWER_CONTINUATION_INDENT, indentAnswerContinuation, DISMISSED_ANSWER, MarkOwnDoneInput, MarkOwnDoneResult, ListOwnPrWatchesInput, OwnPrWatchesResult, ThreadTimerView, ThreadFence, LimitWindow, LimitPause, ProviderError, ThreadLinkView, UpsertOwnLinkInput, UpsertOwnLinkResult, DropOwnLinkInput, DropOwnLinkResult, LiveTool, ThreadView, BoardErrorItem, BoardSnapshot, QuotaWindow, ProviderQuota, QuotaSnapshot, ProviderAuth, AccountEmails, AuthSnapshot, AccountBackend, AccountLogoutInput, AccountLogoutResult, PermissionMode, LocalFileOpener, Settings, DispatchProviderPreferences, DispatchPreferences, DispatchProfileSnapshotShape, DispatchProfileSnapshot, SetDispatchPreferenceInput, DispatchInput, ADOPT_THREAD_MESSAGE_MAX_CHARS, AdoptThreadInput, AdoptThreadResult, AdoptSessionInput, FollowUpInput, DismissFailedFollowUpInput, DismissFailedFollowUpResult, UnqueueFollowUpInput, UnqueueFollowUpResult, DeliverQueuedNowInput, DeliverQueuedNowResult, CompactThreadInput, SetThreadSnoozeInput, SetThreadPinnedInput, SetThreadRecurringPromptInput, SetOwnThreadRecurringPromptInput, SetOwnThreadRecurringPromptResult, GetOwnThreadRecurringPromptInput, OwnThreadRecurringPromptResult, SetOwnThreadTimerInput, CancelOwnThreadTimerInput, ListOwnThreadTimersInput, OwnThreadTimersResult, ThreadActivityItem, ListOwnThreadActivityInput, OwnThreadActivityResult, SetOwnThreadTimerResult, CancelOwnThreadTimerResult, SetOwnThreadStopHookInput, SetOwnThreadHeartbeatInput, ThreadPluginReloadResult, RenameThreadInput, AiRenameThreadInput, AiRenameThreadResult, SetOwnThreadTitleInput, SetOwnThreadTitleResult, SetThreadPermissionInput, SetThreadPermissionResult, ThreadProfileOptionsInput, ThreadProfileOptionsResult, ThreadSkillSource, ThreadSkill, ThreadSkillsInput, ThreadSkillsResult, SetThreadProfileInput, SetThreadProfileResult, UpgradeThreadModelInput, UpgradeThreadModelResult, DISPATCH_TASK_BANNER, DISPATCH_TASK_BANNER_MARKER, GITHUB_DISPATCH_UI_BOUNDARY, WAKE_TIME_HEADER_TAIL, WAKE_TRAILERS, HUMAN_GAP_FLOOR_MS, HUMAN_GAP_NOTE_TAIL, WAKE_DELIVERY_TOKEN_TAIL, WAKE_DELIVERY_TOKEN_LINE, NOISE_PREFIXES, AGENT_MESSAGE_WRAPPER, GithubWakeItem, GithubWakeSteer, WAKE_SCOPE, WAKE_REVIEW_LEAD, WAKE_BACKLOG_TAIL, WAKE_REF, WAKE_SINGLE, WAKE_MULTI_HEAD, WAKE_ITEM, WAKE_MORE, PR_WATCH_FINISHED, PR_WATCH_CI_PASSED, PR_WATCH_CI_GATED, PR_WATCH_STATE, PR_WATCH_CI_FAILED, GithubStatus, GithubRefCard, GithubRefPreviewInput, GithubRefPreviewResult, GithubItem, GithubListInput, GithubListResult, GithubBatchInput, GithubBatchResult, BoardMeta, ServerEvent, TranscriptEdit, TranscriptTodo, TranscriptToolCall, TranscriptPart, TranscriptMessage, TranscriptPageCursor, EditedFile, TranscriptPage, TranscriptEarlierInput, SocketTranscriptSlug, SocketFilePath, SocketTranscriptClientMsg, SocketFileClientMsg, SocketClientMsg, ProjectCard, ProjectRailCounts, PROJECT_ICON_EXTENSIONS, PROJECT_ICON_MAX_BASE64_CHARS, DirectoryPickResult, ThreadLocation, FRIZZ_ROUTE_PREFIX, DEFAULT_PORT, threadIdentityName;
14130
+ var import_yaml, ATTACHMENT_IMAGE_EXTENSIONS, ATTACHMENT_TEXT_EXTENSIONS, ATTACHMENT_OFFICE_EXTENSIONS, ATTACHMENT_DATA_EXTENSIONS, ATTACHMENT_ARCHIVE_EXTENSIONS, ATTACHMENT_DOC_EXTENSIONS, ATTACHMENT_EXTENSIONS, ATTACHMENT_MAX_BASE64_CHARS, ATTACHMENT_MAX_BYTES, ATTACHMENT_EXT_SET, ATTACHMENT_ACCEPT, FrizzStatus, BlockMechanism, RuntimeState, Backend, CodexModel, ClaudeModel, CODEX_MODELS_FALLBACK, AcpAgent, ACP_MODEL_PREFIX, AcpAgentModel, AcpAgentModels, AcpAgentModelsInput, ThreadProfileOption, ThreadAgent, SubAgentView, BgShellView, CompletionHoldOp, CompletionHold, AskOption, AskQuestion, PendingAsk, AwaitingHint, RETIRED_AWAITING_KINDS, RETIRED_LINE_RE, RETIRED_AWAITING_REPLACEMENT, AWAITING_KEY_RE, AWAITING_YAML_KEYS, AWAITING_SEQUENCE_KEYS, AWAITING_HINT_MAX, AWAITING_HINT_VALUE_MAX, AWAITING_SCALAR_KINDS, AWAITING_STEPS_MAX, AWAITING_STEP_VALUE_MAX, AWAITING_QUESTIONS_MAX, AWAITING_TITLE_MAX, AWAITING_STATUSES, AWAITING_ITEM_KINDS, AWAITING_DURATION_RE, DURATION_UNIT_MS, AWAITING_FOR_MAX_MS, SnoozeUntil, SNOOZE_PROMPT_MAX, SnoozePrompt, RECURRING_PROMPT_MAX, RECURRING_MIN_INTERVAL_SECONDS, RECURRING_MAX_INTERVAL_SECONDS, RecurringPromptText, RecurringIntervalSeconds, ThreadRecurringPrompt, INTERRUPT_MARKERS, ALLDONE_SENTINEL, OPT_OUT_NOTE, OVER_QUESTION_NOTE, TIMER_PROMPT_MAX, TIMER_MAX_DELAY_SECONDS, TIMER_MAX_ARMED, TimerPromptText, PR_WATCH_SPENT_TRAILER, PR_WATCH_ARMED_TRAILER, SHELL_DONE_TRAILER, ISSUE_WATCH_SPENT_TRAILER, ISSUE_WATCH_ARMED_TRAILER, INTERRUPT_ENDED_LEAD, SIGNOFF_NUDGE_MARKER, SIGNOFF_NUDGE_MESSAGE, SIGNOFF_NUDGE_MESSAGE_NEEDS_INPUT, PARK_CORRECTION_NAMES_LEAD, PARK_CORRECTION_RETIRED_LEAD, PARK_CORRECTION_QUESTION_LEAD, PARK_CORRECTION_NEEDS_INPUT_LEAD, ThreadWatchKind, GithubChecksState, GithubMergeState, GithubWatchStatus, GithubIssueStatus, ThreadWatchView, PR_WATCH_FOR_MAX_MS, PR_WATCH_DEFAULT_FOR_MS, PR_WATCH_MAX_ARMED, PrWatchView, AddOwnPrWatchInput, AddOwnPrWatchResult, DropOwnPrWatchInput, DropOwnPrWatchResult, OwnWatchKind, AddOwnWatchInput, OwnWatchView, AddOwnWatchResult, DropOwnWatchInput, DropOwnWatchResult, OWN_WATCH_MAX_ARMED, QUESTION_FENCE_RETIRED_AT, NEEDS_INPUT_REQUIRED_AT, AskQuestionKind, ASK_MAX_DEPTH, AskedOptionSchema, AskedQuestionSchema, AskInput, RegisteredQuestionView, SECRET_TTL_MS, AskResult, UnaskInput, UnaskResult, QuestionAnswerSchema, AnswerQuestionsInput, AnswerQuestionsResult, DismissQuestionsInput, DismissQuestionsResult, SettledQuestionView, ThreadSettledQuestionsResult, BURIED_ANSWERS_HEADER, ANSWER_FOLLOW_UP_MARKER, ANSWER_CONTINUATION_INDENT, indentAnswerContinuation, DISMISSED_ANSWER, MarkOwnDoneInput, MarkOwnDoneResult, ListOwnPrWatchesInput, OwnPrWatchesResult, ThreadTimerView, ThreadFence, LimitWindow, LimitPause, ProviderError, ThreadLinkView, UpsertOwnLinkInput, UpsertOwnLinkResult, DropOwnLinkInput, DropOwnLinkResult, LiveTool, ThreadView, BoardErrorItem, BoardSnapshot, QuotaWindow, ProviderQuota, QuotaSnapshot, ProviderAuth, AccountEmails, AuthSnapshot, AccountBackend, AccountLogoutInput, AccountLogoutResult, PermissionMode, LocalFileOpener, Settings, DispatchProviderPreferences, DispatchPreferences, DispatchProfileSnapshotShape, DispatchProfileSnapshot, SetDispatchPreferenceInput, DispatchInput, ADOPT_THREAD_MESSAGE_MAX_CHARS, AdoptThreadInput, AdoptThreadResult, AdoptSessionInput, FollowUpInput, DismissFailedFollowUpInput, DismissFailedFollowUpResult, UnqueueFollowUpInput, UnqueueFollowUpResult, DeliverQueuedNowInput, DeliverQueuedNowResult, CompactThreadInput, SetThreadSnoozeInput, SetThreadPinnedInput, SetThreadRecurringPromptInput, SetOwnThreadRecurringPromptInput, SetOwnThreadRecurringPromptResult, GetOwnThreadRecurringPromptInput, OwnThreadRecurringPromptResult, SetOwnThreadTimerInput, CancelOwnThreadTimerInput, ListOwnThreadTimersInput, OwnThreadTimersResult, ThreadActivityItem, ListOwnThreadActivityInput, OwnThreadActivityResult, SetOwnThreadTimerResult, CancelOwnThreadTimerResult, SetOwnThreadStopHookInput, SetOwnThreadHeartbeatInput, ThreadPluginReloadResult, RenameThreadInput, AiRenameThreadInput, AiRenameThreadResult, SetOwnThreadTitleInput, SetOwnThreadTitleResult, SetThreadPermissionInput, SetThreadPermissionResult, ThreadProfileOptionsInput, ThreadProfileOptionsResult, ThreadSkillSource, ThreadSkill, ThreadSkillsInput, ThreadSkillsResult, SetThreadProfileInput, SetThreadProfileResult, UpgradeThreadModelInput, UpgradeThreadModelResult, DISPATCH_TASK_BANNER, DISPATCH_TASK_BANNER_MARKER, GITHUB_DISPATCH_UI_BOUNDARY, WAKE_TIME_HEADER_TAIL, WAKE_TRAILERS, HUMAN_GAP_FLOOR_MS, HUMAN_GAP_NOTE_TAIL, WAKE_DELIVERY_TOKEN_TAIL, WAKE_DELIVERY_TOKEN_LINE, NOISE_PREFIXES, AGENT_MESSAGE_WRAPPER, GithubWakeItem, GithubWakeSteer, WAKE_SCOPE, WAKE_REVIEW_LEAD, WAKE_BACKLOG_TAIL, WAKE_REF, WAKE_SINGLE, WAKE_MULTI_HEAD, WAKE_ITEM, WAKE_MORE, PR_WATCH_FINISHED, PR_WATCH_CI_PASSED, PR_WATCH_CI_GATED, PR_WATCH_STATE, PR_WATCH_CI_FAILED, GithubStatus, GithubRefCard, GithubRefPreviewInput, GithubRefPreviewResult, GithubItem, GithubListInput, GithubListResult, GithubBatchInput, GithubBatchResult, BoardMeta, ServerEvent, TranscriptEdit, TranscriptTodo, TranscriptToolCall, TranscriptPart, TranscriptMessage, TranscriptPageCursor, EditedFile, TranscriptPage, TranscriptEarlierInput, SocketTranscriptSlug, SocketFilePath, SocketTranscriptClientMsg, SocketFileClientMsg, SocketClientMsg, ProjectCard, ProjectRailCounts, PROJECT_ICON_EXTENSIONS, PROJECT_ICON_MAX_BASE64_CHARS, DirectoryPickResult, ThreadLocation, FRIZZ_ROUTE_PREFIX, DEFAULT_PORT, threadIdentityName;
14122
14131
  var init_src = __esm({
14123
14132
  "packages/shared/src/index.ts"() {
14124
14133
  "use strict";
@@ -14794,6 +14803,7 @@ var init_src = __esm({
14794
14803
  header: external_exports.string().trim().max(24).optional(),
14795
14804
  kind: AskQuestionKind,
14796
14805
  danger: external_exports.boolean().optional(),
14806
+ secret: external_exports.boolean().optional(),
14797
14807
  // UNBOUNDED, deliberately. This carried `.max(8)` from launch until 2026-09-03, when the maintainer
14798
14808
  // asked for the cap to go ("allow arbitrary numbers of options"): a `multi` over a long list — which
14799
14809
  // gates to run, which of twenty findings to act on — is a real shape, and the card numbers past 9
@@ -14811,8 +14821,12 @@ var init_src = __esm({
14811
14821
  * an id alone cannot be correlated back to what was asked. */
14812
14822
  id: external_exports.string(),
14813
14823
  spec: AskedQuestionSchema,
14814
- askedAt: external_exports.string()
14824
+ askedAt: external_exports.string(),
14825
+ /** A `secret` question only: the path its value will be served at. Known at registration, so the
14826
+ * worker can prepare the command that reads it before the human has answered. */
14827
+ secretPath: external_exports.string().optional()
14815
14828
  }).strict();
14829
+ SECRET_TTL_MS = 15 * 6e4;
14816
14830
  AskResult = external_exports.object({
14817
14831
  registered: external_exports.array(RegisteredQuestionView),
14818
14832
  /** Everything still open on this thread afterwards, so a worker never needs a second call. */
@@ -18087,6 +18101,229 @@ var init_logging = __esm({
18087
18101
  }
18088
18102
  });
18089
18103
 
18104
+ // packages/server/src/local-origin.ts
18105
+ import { isIP } from "node:net";
18106
+ function publicAuthority(policy) {
18107
+ const raw2 = policy?.publicOrigin;
18108
+ if (!raw2) return null;
18109
+ let url;
18110
+ try {
18111
+ url = new URL(raw2);
18112
+ } catch {
18113
+ return null;
18114
+ }
18115
+ if (url.origin !== raw2) return null;
18116
+ return {
18117
+ hostname: normalizedHostname(url.hostname),
18118
+ port: explicitPort(url),
18119
+ authority: url.host.toLowerCase(),
18120
+ scheme: url.protocol === "https:" ? "https" : "http"
18121
+ };
18122
+ }
18123
+ function acceptsHostname(hostname, policy) {
18124
+ if (LOCAL_HOSTNAMES.has(hostname)) return true;
18125
+ if (!policy?.exposed) return false;
18126
+ if (isIP(hostname) !== 0) return true;
18127
+ return (policy.allowedHosts ?? []).some((allowed) => allowed === "*" || allowed.toLowerCase() === hostname);
18128
+ }
18129
+ function oneHeader(value) {
18130
+ return typeof value === "string" && value.length > 0 ? value : void 0;
18131
+ }
18132
+ function normalizedHostname(hostname) {
18133
+ const lower = hostname.toLowerCase();
18134
+ return lower.startsWith("[") && lower.endsWith("]") ? lower.slice(1, -1) : lower;
18135
+ }
18136
+ function explicitPort(url) {
18137
+ if (url.port) return Number(url.port);
18138
+ return url.protocol === "https:" ? 443 : 80;
18139
+ }
18140
+ function validExpectedPort(port2) {
18141
+ return Number.isInteger(port2) && port2 >= 1 && port2 <= 65535;
18142
+ }
18143
+ function parseLocalHttpOrigin(value, expectedPort, policy) {
18144
+ const raw2 = oneHeader(value);
18145
+ if (!raw2 || !validExpectedPort(expectedPort) || raw2 !== raw2.trim()) return null;
18146
+ const declared = publicAuthority(policy);
18147
+ if (declared && raw2 === policy?.publicOrigin) return declared;
18148
+ let url;
18149
+ try {
18150
+ url = new URL(raw2);
18151
+ } catch {
18152
+ return null;
18153
+ }
18154
+ if (url.protocol !== "http:" || url.origin !== raw2) return null;
18155
+ const hostname = normalizedHostname(url.hostname);
18156
+ if (!acceptsHostname(hostname, policy) || explicitPort(url) !== expectedPort) return null;
18157
+ return { hostname, port: expectedPort, authority: url.host, scheme: "http" };
18158
+ }
18159
+ function parseLocalHost(value, expectedPort, policy) {
18160
+ const raw2 = oneHeader(value);
18161
+ if (!raw2 || !validExpectedPort(expectedPort) || raw2 !== raw2.trim() || raw2.includes(",")) return null;
18162
+ let url;
18163
+ try {
18164
+ url = new URL(`http://${raw2}`);
18165
+ } catch {
18166
+ return null;
18167
+ }
18168
+ if (url.username || url.password || url.pathname !== "/" || url.search || url.hash) return null;
18169
+ if (url.host.toLowerCase() !== raw2.toLowerCase()) return null;
18170
+ const hostname = normalizedHostname(url.hostname);
18171
+ const declared = publicAuthority(policy);
18172
+ if (declared && hostname === declared.hostname) {
18173
+ return url.port === "" || Number(url.port) === declared.port ? declared : null;
18174
+ }
18175
+ if (!acceptsHostname(hostname, policy) || explicitPort(url) !== expectedPort) return null;
18176
+ return { hostname, port: expectedPort, authority: url.host.toLowerCase(), scheme: "http" };
18177
+ }
18178
+ function hasForwardedAuthority(headers) {
18179
+ return FORWARDED_HEADERS.some((name) => headers[name] !== void 0);
18180
+ }
18181
+ function forwardedAuthorityAllowed(headers, host, policy) {
18182
+ if (!hasForwardedAuthority(headers)) return true;
18183
+ const declared = publicAuthority(policy);
18184
+ return !!declared && declared.hostname === host.hostname;
18185
+ }
18186
+ function isTrustedLocalHttpRequest(headers, expectedPort, allowMissingOrigin = false, policy) {
18187
+ const host = parseLocalHost(headers.host, expectedPort, policy);
18188
+ if (!host) return false;
18189
+ if (!forwardedAuthorityAllowed(headers, host, policy)) return false;
18190
+ if (headers.origin === void 0) return allowMissingOrigin;
18191
+ const origin = parseLocalHttpOrigin(headers.origin, expectedPort, policy);
18192
+ return !!origin && host.hostname === origin.hostname && host.port === origin.port;
18193
+ }
18194
+ function allowedLocalCorsOrigin(origin, expectedPort, policy) {
18195
+ return parseLocalHttpOrigin(origin, expectedPort, policy) ? origin : void 0;
18196
+ }
18197
+ function isTrustedLocalWebSocketRequest(req, expectedPort = req.socket.localPort, policy) {
18198
+ if (!validExpectedPort(expectedPort)) return false;
18199
+ const headers = req.headers;
18200
+ const host = parseLocalHost(headers.host, expectedPort, policy);
18201
+ if (!host || !forwardedAuthorityAllowed(headers, host, policy)) return false;
18202
+ const origin = parseLocalHttpOrigin(headers.origin, expectedPort, policy);
18203
+ return !!origin && host.hostname === origin.hostname && host.port === origin.port;
18204
+ }
18205
+ function rejectWebSocketUpgrade(socket, status = 403, reason = "Forbidden") {
18206
+ const body = `${reason}
18207
+ `;
18208
+ const response = [
18209
+ `HTTP/1.1 ${status} ${reason}`,
18210
+ "Connection: close",
18211
+ "Content-Type: text/plain; charset=utf-8",
18212
+ `Content-Length: ${Buffer.byteLength(body)}`,
18213
+ "",
18214
+ body
18215
+ ].join("\r\n");
18216
+ try {
18217
+ socket.end(response);
18218
+ } catch {
18219
+ try {
18220
+ socket.destroy();
18221
+ } catch {
18222
+ }
18223
+ }
18224
+ }
18225
+ var LOCAL_HOSTNAMES, FORWARDED_HEADERS;
18226
+ var init_local_origin = __esm({
18227
+ "packages/server/src/local-origin.ts"() {
18228
+ "use strict";
18229
+ LOCAL_HOSTNAMES = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1"]);
18230
+ FORWARDED_HEADERS = [
18231
+ "forwarded",
18232
+ "x-forwarded-for",
18233
+ "x-forwarded-host",
18234
+ "x-forwarded-port",
18235
+ "x-forwarded-proto"
18236
+ ];
18237
+ }
18238
+ });
18239
+
18240
+ // packages/server/src/local-path.ts
18241
+ function normalizeLocalPath(path3, platform3 = process.platform) {
18242
+ return platform3 === "win32" ? path3.replace(/^\/([a-zA-Z]:[\\/])/, "$1") : path3;
18243
+ }
18244
+ var init_local_path = __esm({
18245
+ "packages/server/src/local-path.ts"() {
18246
+ "use strict";
18247
+ }
18248
+ });
18249
+
18250
+ // packages/server/src/local-image.ts
18251
+ import { createReadStream, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
18252
+ import { extname, isAbsolute as isAbsolute3 } from "node:path";
18253
+ function resolveLocalImage(rawPath, range) {
18254
+ if (rawPath) rawPath = normalizeLocalPath(rawPath);
18255
+ if (!rawPath || !isAbsolute3(rawPath)) return { status: 400 };
18256
+ const contentType = CONTENT_TYPE[extname(rawPath).toLowerCase()];
18257
+ if (!contentType) return { status: 400 };
18258
+ let real;
18259
+ try {
18260
+ real = realpathSync5(rawPath);
18261
+ } catch {
18262
+ return { status: 404 };
18263
+ }
18264
+ let size;
18265
+ try {
18266
+ const stat2 = statSync4(real);
18267
+ if (!stat2.isFile()) return { status: 404 };
18268
+ size = stat2.size;
18269
+ } catch {
18270
+ return { status: 404 };
18271
+ }
18272
+ const span = range ? byteRange(range, size) : null;
18273
+ if (span === "unsatisfiable") return { status: 416, size };
18274
+ if (span) return { status: 206, contentType, file: real, size, start: span.start, end: span.end };
18275
+ return { status: 200, contentType, file: real, size, start: 0, end: size - 1 };
18276
+ }
18277
+ function byteRange(header, size) {
18278
+ const match2 = /^bytes=(\d*)-(\d*)$/.exec(header.trim());
18279
+ if (!match2) return null;
18280
+ const [, first, last] = match2;
18281
+ if (first === "" && last === "") return null;
18282
+ if (first === "") {
18283
+ const suffix = Number(last);
18284
+ if (suffix === 0 || size === 0) return "unsatisfiable";
18285
+ return { start: Math.max(size - suffix, 0), end: size - 1 };
18286
+ }
18287
+ const start = Number(first);
18288
+ if (last !== "" && Number(last) < start) return null;
18289
+ if (start >= size) return "unsatisfiable";
18290
+ return { start, end: last === "" ? size - 1 : Math.min(Number(last), size - 1) };
18291
+ }
18292
+ function localImageHeaders(result) {
18293
+ return {
18294
+ "content-type": result.contentType,
18295
+ "content-length": String(result.end - result.start + 1),
18296
+ "accept-ranges": "bytes",
18297
+ "cache-control": "private, max-age=60",
18298
+ ...result.status === 206 ? { "content-range": `bytes ${result.start}-${result.end}/${result.size}` } : {}
18299
+ };
18300
+ }
18301
+ function localImageStream(result) {
18302
+ if (result.end < result.start) return null;
18303
+ return createReadStream(result.file, { start: result.start, end: result.end });
18304
+ }
18305
+ var IMAGE_CONTENT_TYPE, VIDEO_CONTENT_TYPE, CONTENT_TYPE;
18306
+ var init_local_image = __esm({
18307
+ "packages/server/src/local-image.ts"() {
18308
+ "use strict";
18309
+ init_local_path();
18310
+ IMAGE_CONTENT_TYPE = {
18311
+ ".png": "image/png",
18312
+ ".jpg": "image/jpeg",
18313
+ ".jpeg": "image/jpeg",
18314
+ ".gif": "image/gif",
18315
+ ".webp": "image/webp"
18316
+ };
18317
+ VIDEO_CONTENT_TYPE = {
18318
+ ".mp4": "video/mp4",
18319
+ ".m4v": "video/mp4",
18320
+ ".webm": "video/webm",
18321
+ ".mov": "video/quicktime"
18322
+ };
18323
+ CONTENT_TYPE = { ...IMAGE_CONTENT_TYPE, ...VIDEO_CONTENT_TYPE };
18324
+ }
18325
+ });
18326
+
18090
18327
  // packages/server/src/bus.ts
18091
18328
  var Bus, Emitter;
18092
18329
  var init_bus = __esm({
@@ -21229,16 +21466,122 @@ var init_storage = __esm({
21229
21466
  }
21230
21467
  });
21231
21468
 
21469
+ // packages/server/src/secret-files.ts
21470
+ import { execFileSync as execFileSync4 } from "node:child_process";
21471
+ import { chmodSync as chmodSync2, closeSync as closeSync5, constants, existsSync as existsSync5, lstatSync, mkdirSync as mkdirSync8, openSync as openSync6, readdirSync as readdirSync3, rmdirSync, rmSync as rmSync6, writeFileSync as writeFileSync7, writeSync as writeSync2 } from "node:fs";
21472
+ import { dirname as dirname7, join as join11 } from "node:path";
21473
+ function secretsRoot(stateDir) {
21474
+ return join11(stateDir, "secrets");
21475
+ }
21476
+ function secretFilePath(stateDir, slug, questionId) {
21477
+ return join11(secretsRoot(stateDir), slug, questionId);
21478
+ }
21479
+ function stop(path3) {
21480
+ const entry = served.get(path3);
21481
+ if (entry) clearInterval(entry.timer);
21482
+ served.delete(path3);
21483
+ rmSync6(path3, { force: true });
21484
+ try {
21485
+ rmdirSync(dirname7(path3));
21486
+ } catch {
21487
+ }
21488
+ }
21489
+ function serveSecret(stateDir, slug, questionId, value, opts = {}) {
21490
+ const now = opts.now ?? Date.now;
21491
+ const expiresAt = now() + (opts.ttlMs ?? SECRET_TTL_MS);
21492
+ const root = secretsRoot(stateDir);
21493
+ const dir = join11(root, slug);
21494
+ const path3 = secretFilePath(stateDir, slug, questionId);
21495
+ stop(path3);
21496
+ mkdirSync8(dir, { recursive: true, mode: 448 });
21497
+ chmodSync2(root, 448);
21498
+ chmodSync2(dir, 448);
21499
+ if ((opts.platform ?? process.platform) === "win32") {
21500
+ writeFileSync7(path3, value, { mode: 384 });
21501
+ const timer2 = setInterval(() => {
21502
+ if (now() >= expiresAt || !existsSync5(path3)) stop(path3);
21503
+ }, 1e3);
21504
+ timer2.unref();
21505
+ served.set(path3, { timer: timer2 });
21506
+ return path3;
21507
+ }
21508
+ execFileSync4("mkfifo", ["-m", "600", path3]);
21509
+ const bytes = Buffer.from(value, "utf8");
21510
+ const timer = setInterval(() => {
21511
+ if (now() >= expiresAt || !existsSync5(path3)) return stop(path3);
21512
+ let fd2;
21513
+ try {
21514
+ fd2 = openSync6(path3, constants.O_WRONLY | constants.O_NONBLOCK);
21515
+ } catch {
21516
+ return;
21517
+ }
21518
+ let delivered = false;
21519
+ try {
21520
+ delivered = writeSync2(fd2, bytes) === bytes.length;
21521
+ } catch {
21522
+ } finally {
21523
+ closeSync5(fd2);
21524
+ }
21525
+ if (delivered) stop(path3);
21526
+ }, POLL_MS2);
21527
+ timer.unref();
21528
+ served.set(path3, { timer });
21529
+ return path3;
21530
+ }
21531
+ function clearSecrets(stateDir) {
21532
+ const root = secretsRoot(stateDir);
21533
+ let removed = 0;
21534
+ let threads;
21535
+ try {
21536
+ threads = readdirSync3(root);
21537
+ } catch {
21538
+ return 0;
21539
+ }
21540
+ for (const thread of threads) {
21541
+ const dir = join11(root, thread);
21542
+ let entries2;
21543
+ try {
21544
+ if (!lstatSync(dir).isDirectory()) {
21545
+ rmSync6(dir, { force: true });
21546
+ continue;
21547
+ }
21548
+ entries2 = readdirSync3(dir);
21549
+ } catch {
21550
+ continue;
21551
+ }
21552
+ for (const entry of entries2) {
21553
+ const path3 = join11(dir, entry);
21554
+ if (served.has(path3)) continue;
21555
+ rmSync6(path3, { force: true });
21556
+ removed++;
21557
+ }
21558
+ try {
21559
+ if (readdirSync3(dir).length === 0) rmSync6(dir, { recursive: true, force: true });
21560
+ } catch {
21561
+ }
21562
+ }
21563
+ return removed;
21564
+ }
21565
+ var POLL_MS2, served;
21566
+ var init_secret_files = __esm({
21567
+ "packages/server/src/secret-files.ts"() {
21568
+ "use strict";
21569
+ init_src();
21570
+ POLL_MS2 = 100;
21571
+ served = /* @__PURE__ */ new Map();
21572
+ }
21573
+ });
21574
+
21232
21575
  // packages/server/src/machine-config.ts
21233
- import { closeSync as closeSync5, fsyncSync as fsyncSync5, mkdirSync as mkdirSync7, openSync as openSync6, readFileSync as readFileSync6, renameSync as renameSync5, rmSync as rmSync6, writeFileSync as writeFileSync6 } from "node:fs";
21234
- import { dirname as dirname6, join as join9 } from "node:path";
21576
+ import { closeSync as closeSync6, fsyncSync as fsyncSync5, mkdirSync as mkdirSync9, openSync as openSync7, readFileSync as readFileSync8, renameSync as renameSync5, rmSync as rmSync7, writeFileSync as writeFileSync8 } from "node:fs";
21577
+ import { dirname as dirname8, join as join12 } from "node:path";
21235
21578
  function machineConfigPath(home) {
21236
- return join9(frizzPaths({ home }).data, "config.json");
21579
+ return join12(frizzPaths({ home }).data, "config.json");
21237
21580
  }
21238
21581
  function readAll(home) {
21239
21582
  let raw2;
21240
21583
  try {
21241
- raw2 = JSON.parse(readFileSync6(machineConfigPath(home), "utf8"));
21584
+ raw2 = JSON.parse(readFileSync8(machineConfigPath(home), "utf8"));
21242
21585
  } catch {
21243
21586
  return {};
21244
21587
  }
@@ -21246,24 +21589,24 @@ function readAll(home) {
21246
21589
  }
21247
21590
  function writeAll(home, all) {
21248
21591
  const path3 = machineConfigPath(home);
21249
- mkdirSync7(dirname6(path3), { recursive: true });
21592
+ mkdirSync9(dirname8(path3), { recursive: true });
21250
21593
  const temp = `${path3}.${process.pid}.tmp`;
21251
21594
  let fd2;
21252
21595
  try {
21253
- fd2 = openSync6(temp, "w", 384);
21254
- writeFileSync6(fd2, `${JSON.stringify(all, null, 2)}
21596
+ fd2 = openSync7(temp, "w", 384);
21597
+ writeFileSync8(fd2, `${JSON.stringify(all, null, 2)}
21255
21598
  `, "utf8");
21256
21599
  fsyncSync5(fd2);
21257
- closeSync5(fd2);
21600
+ closeSync6(fd2);
21258
21601
  fd2 = void 0;
21259
21602
  renameSync5(temp, path3);
21260
21603
  } catch {
21261
21604
  if (fd2 !== void 0) try {
21262
- closeSync5(fd2);
21605
+ closeSync6(fd2);
21263
21606
  } catch {
21264
21607
  }
21265
21608
  try {
21266
- rmSync6(temp, { force: true });
21609
+ rmSync7(temp, { force: true });
21267
21610
  } catch {
21268
21611
  }
21269
21612
  }
@@ -21291,10 +21634,10 @@ var init_machine_config = __esm({
21291
21634
  });
21292
21635
 
21293
21636
  // packages/server/src/settings.ts
21294
- import { readFileSync as readFileSync7, rmSync as rmSync7 } from "node:fs";
21295
- import { join as join10 } from "node:path";
21637
+ import { readFileSync as readFileSync9, rmSync as rmSync8 } from "node:fs";
21638
+ import { join as join13 } from "node:path";
21296
21639
  function legacyMachineSettingsPath(home) {
21297
- return join10(frizzPaths({ home }).data, "settings.json");
21640
+ return join13(frizzPaths({ home }).data, "settings.json");
21298
21641
  }
21299
21642
  function pickMachine(settings) {
21300
21643
  return Object.fromEntries(MACHINE_KEYS.map((key) => [key, settings[key]]));
@@ -21304,7 +21647,7 @@ function readMachineSettings(home) {
21304
21647
  if (stored) return pickPresent(stored);
21305
21648
  let raw2;
21306
21649
  try {
21307
- raw2 = JSON.parse(readFileSync7(legacyMachineSettingsPath(home), "utf8"));
21650
+ raw2 = JSON.parse(readFileSync9(legacyMachineSettingsPath(home), "utf8"));
21308
21651
  } catch {
21309
21652
  return {};
21310
21653
  }
@@ -21335,7 +21678,7 @@ function resetSettings(storage, home) {
21335
21678
  storage.deleteSetting(SETTINGS_KEY);
21336
21679
  deleteMachineConfig(home, SETTINGS_KEY);
21337
21680
  try {
21338
- rmSync7(legacyMachineSettingsPath(home), { force: true });
21681
+ rmSync8(legacyMachineSettingsPath(home), { force: true });
21339
21682
  } catch {
21340
21683
  }
21341
21684
  return defaultSettings();
@@ -21635,15 +21978,15 @@ var init_codex_error = __esm({
21635
21978
  });
21636
21979
 
21637
21980
  // packages/server/src/discover.ts
21638
- import { readdirSync as readdirSync3, statSync as statSync4, openSync as openSync7, readSync, closeSync as closeSync6 } from "node:fs";
21639
- import { dirname as dirname7, join as join11 } from "node:path";
21981
+ import { readdirSync as readdirSync4, statSync as statSync5, openSync as openSync8, readSync, closeSync as closeSync7 } from "node:fs";
21982
+ import { dirname as dirname9, join as join14 } from "node:path";
21640
21983
  function sentinelFor(sessionId) {
21641
21984
  return `threads/${sessionId}/`;
21642
21985
  }
21643
21986
  function readHead(path3) {
21644
21987
  let fd2;
21645
21988
  try {
21646
- fd2 = openSync7(path3, "r");
21989
+ fd2 = openSync8(path3, "r");
21647
21990
  const buf = Buffer.allocUnsafe(HEAD_BYTES);
21648
21991
  const n = readSync(fd2, buf, 0, HEAD_BYTES, 0);
21649
21992
  return buf.toString("utf8", 0, n);
@@ -21652,7 +21995,7 @@ function readHead(path3) {
21652
21995
  } finally {
21653
21996
  if (fd2 !== void 0) {
21654
21997
  try {
21655
- closeSync6(fd2);
21998
+ closeSync7(fd2);
21656
21999
  } catch {
21657
22000
  }
21658
22001
  }
@@ -21664,7 +22007,7 @@ function discoverTranscriptId(logDir, sessionId, opts = {}) {
21664
22007
  const sentinel = sentinelFor(sessionId);
21665
22008
  let names;
21666
22009
  try {
21667
- names = readdirSync3(logDir);
22010
+ names = readdirSync4(logDir);
21668
22011
  } catch {
21669
22012
  return void 0;
21670
22013
  }
@@ -21673,10 +22016,10 @@ function discoverTranscriptId(logDir, sessionId, opts = {}) {
21673
22016
  if (name.startsWith(".") || !name.endsWith(".jsonl")) continue;
21674
22017
  const id2 = name.slice(0, -".jsonl".length);
21675
22018
  if (!id2 || id2 === sessionId || exclude?.has(id2)) continue;
21676
- const path3 = join11(logDir, name);
22019
+ const path3 = join14(logDir, name);
21677
22020
  let mtime;
21678
22021
  try {
21679
- mtime = statSync4(path3).mtimeMs;
22022
+ mtime = statSync5(path3).mtimeMs;
21680
22023
  } catch {
21681
22024
  continue;
21682
22025
  }
@@ -21691,7 +22034,7 @@ function discoverTranscriptId(logDir, sessionId, opts = {}) {
21691
22034
  }
21692
22035
  function mtimeOfNonEmpty(path3) {
21693
22036
  try {
21694
- const st2 = statSync4(path3, { throwIfNoEntry: false });
22037
+ const st2 = statSync5(path3, { throwIfNoEntry: false });
21695
22038
  return st2 && st2.size > 0 ? st2.mtimeMs : void 0;
21696
22039
  } catch {
21697
22040
  return void 0;
@@ -21701,7 +22044,7 @@ function discoverTranscriptDir(logDir, sessionId, memo3 = strandedLogDirs) {
21701
22044
  const name = `${sessionId}.jsonl`;
21702
22045
  const better = (best2, dir) => {
21703
22046
  if (dir === logDir) return best2;
21704
- const at2 = mtimeOfNonEmpty(join11(dir, name));
22047
+ const at2 = mtimeOfNonEmpty(join14(dir, name));
21705
22048
  if (at2 === void 0) return best2;
21706
22049
  return !best2 || at2 > best2.mtimeMs ? { dir, mtimeMs: at2 } : best2;
21707
22050
  };
@@ -21710,11 +22053,11 @@ function discoverTranscriptDir(logDir, sessionId, memo3 = strandedLogDirs) {
21710
22053
  if (best) return best.dir;
21711
22054
  let entries2;
21712
22055
  try {
21713
- entries2 = readdirSync3(dirname7(logDir), { withFileTypes: true }).filter((e14) => e14.isDirectory()).map((e14) => e14.name);
22056
+ entries2 = readdirSync4(dirname9(logDir), { withFileTypes: true }).filter((e14) => e14.isDirectory()).map((e14) => e14.name);
21714
22057
  } catch {
21715
22058
  return void 0;
21716
22059
  }
21717
- for (const entry of entries2) best = better(best, join11(dirname7(logDir), entry));
22060
+ for (const entry of entries2) best = better(best, join14(dirname9(logDir), entry));
21718
22061
  if (!best) return void 0;
21719
22062
  memo3.add(best.dir);
21720
22063
  return best.dir;
@@ -21800,27 +22143,27 @@ var init_types2 = __esm({
21800
22143
  });
21801
22144
 
21802
22145
  // packages/server/src/session-files.ts
21803
- import { chmodSync, lstatSync, mkdirSync as mkdirSync8, rmSync as rmSync8, writeFileSync as writeFileSync7 } from "node:fs";
21804
- import { join as join12 } from "node:path";
22146
+ import { chmodSync as chmodSync3, lstatSync as lstatSync2, mkdirSync as mkdirSync10, rmSync as rmSync9, writeFileSync as writeFileSync9 } from "node:fs";
22147
+ import { join as join15 } from "node:path";
21805
22148
  function systemPromptPath(sessionId) {
21806
22149
  if (!SESSION_ID_RE.test(sessionId)) throw new Error("invalid session id");
21807
- return join12(SYSTEM_PROMPT_DIR, `${sessionId}.md`);
22150
+ return join15(SYSTEM_PROMPT_DIR, `${sessionId}.md`);
21808
22151
  }
21809
22152
  function mcpConfigPath(sessionId) {
21810
22153
  if (!SESSION_ID_RE.test(sessionId)) throw new Error("invalid session id");
21811
- return join12(MCP_CONFIG_DIR, `${sessionId}.json`);
22154
+ return join15(MCP_CONFIG_DIR, `${sessionId}.json`);
21812
22155
  }
21813
22156
  function writeMcpConfigFile(sessionId, mcpServers) {
21814
22157
  const path3 = mcpConfigPath(sessionId);
21815
- mkdirSync8(MCP_CONFIG_DIR, { recursive: true, mode: 448 });
21816
- chmodSync(MCP_CONFIG_DIR, 448);
21817
- writeFileSync7(path3, JSON.stringify({ mcpServers }), { mode: 384 });
21818
- chmodSync(path3, 384);
22158
+ mkdirSync10(MCP_CONFIG_DIR, { recursive: true, mode: 448 });
22159
+ chmodSync3(MCP_CONFIG_DIR, 448);
22160
+ writeFileSync9(path3, JSON.stringify({ mcpServers }), { mode: 384 });
22161
+ chmodSync3(path3, 384);
21819
22162
  return path3;
21820
22163
  }
21821
22164
  function isDirectDirectory(path3) {
21822
22165
  try {
21823
- const stat2 = lstatSync(path3);
22166
+ const stat2 = lstatSync2(path3);
21824
22167
  return stat2.isDirectory() && !stat2.isSymbolicLink();
21825
22168
  } catch {
21826
22169
  return false;
@@ -21828,7 +22171,7 @@ function isDirectDirectory(path3) {
21828
22171
  }
21829
22172
  function pathAbsent(path3) {
21830
22173
  try {
21831
- lstatSync(path3);
22174
+ lstatSync2(path3);
21832
22175
  return false;
21833
22176
  } catch (error) {
21834
22177
  return error.code === "ENOENT";
@@ -21836,9 +22179,9 @@ function pathAbsent(path3) {
21836
22179
  }
21837
22180
  function unlinkDirectChild(parent, filename) {
21838
22181
  if (!isDirectDirectory(parent)) return pathAbsent(parent);
21839
- const child = join12(parent, filename);
22182
+ const child = join15(parent, filename);
21840
22183
  try {
21841
- rmSync8(child, { force: true });
22184
+ rmSync9(child, { force: true });
21842
22185
  } catch {
21843
22186
  return false;
21844
22187
  }
@@ -21846,14 +22189,14 @@ function unlinkDirectChild(parent, filename) {
21846
22189
  }
21847
22190
  function cleanupAdoptionSessionFiles(projectDir, sessionId) {
21848
22191
  if (!SESSION_ID_RE.test(sessionId)) return false;
21849
- const frizzDir = join12(projectDir, ".frizz");
22192
+ const frizzDir = join15(projectDir, ".frizz");
21850
22193
  let clean = true;
21851
22194
  if (isDirectDirectory(frizzDir)) {
21852
- const threads = join12(frizzDir, "threads");
22195
+ const threads = join15(frizzDir, "threads");
21853
22196
  if (isDirectDirectory(threads)) {
21854
- const child = join12(threads, sessionId);
22197
+ const child = join15(threads, sessionId);
21855
22198
  try {
21856
- rmSync8(child, { recursive: true, force: true });
22199
+ rmSync9(child, { recursive: true, force: true });
21857
22200
  } catch {
21858
22201
  clean = false;
21859
22202
  }
@@ -22105,10 +22448,10 @@ var init_adoption_recovery = __esm({
22105
22448
  });
22106
22449
 
22107
22450
  // packages/server/src/backend/codex-models.ts
22108
- import { join as join13 } from "node:path";
22109
- import { readFileSync as readFileSync8 } from "node:fs";
22451
+ import { join as join16 } from "node:path";
22452
+ import { readFileSync as readFileSync10 } from "node:fs";
22110
22453
  function cachePath(codexHome) {
22111
- return join13(codexHome, "models_cache.json");
22454
+ return join16(codexHome, "models_cache.json");
22112
22455
  }
22113
22456
  function toCodexModel(raw2) {
22114
22457
  if (!raw2 || typeof raw2 !== "object") return void 0;
@@ -22162,7 +22505,7 @@ function readCodexModels(codexHome = defaultCodexHome(), expectedClientVersion,
22162
22505
  if (hit && nowMs - hit.at < TTL_MS) return hit.models;
22163
22506
  let models;
22164
22507
  try {
22165
- const raw2 = readFileSync8(path3, "utf8");
22508
+ const raw2 = readFileSync10(path3, "utf8");
22166
22509
  models = parseCodexModelsCache(raw2, expectedClientVersion, trusted.get(key));
22167
22510
  let writer;
22168
22511
  try {
@@ -22839,10 +23182,10 @@ var init_claude_agent_sdk_protocol = __esm({
22839
23182
  });
22840
23183
 
22841
23184
  // packages/server/src/backend/claude-broker-diagnostics.ts
22842
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync9, readFileSync as readFileSync9, renameSync as renameSync6, statSync as statSync5 } from "node:fs";
22843
- import { join as join14 } from "node:path";
23185
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync11, readFileSync as readFileSync11, renameSync as renameSync6, statSync as statSync6 } from "node:fs";
23186
+ import { join as join17 } from "node:path";
22844
23187
  function claudeBrokerDiagnosticLogPath(stateDir, sessionId) {
22845
- return join14(stateDir, "claude-broker", `${sessionId}.diagnostics.log`);
23188
+ return join17(stateDir, "claude-broker", `${sessionId}.diagnostics.log`);
22846
23189
  }
22847
23190
  function readClaudeBrokerExit(stateDir, sessionId, generation) {
22848
23191
  if (!generation) return null;
@@ -22850,7 +23193,7 @@ function readClaudeBrokerExit(stateDir, sessionId, generation) {
22850
23193
  for (const path3 of [`${claudeBrokerDiagnosticLogPath(stateDir, sessionId)}.1`, claudeBrokerDiagnosticLogPath(stateDir, sessionId)]) {
22851
23194
  let text2;
22852
23195
  try {
22853
- text2 = readFileSync9(path3, "utf8");
23196
+ text2 = readFileSync11(path3, "utf8");
22854
23197
  } catch {
22855
23198
  continue;
22856
23199
  }
@@ -22903,11 +23246,11 @@ var init_claude_broker_diagnostics = __esm({
22903
23246
  });
22904
23247
 
22905
23248
  // packages/server/src/detached-daemons.ts
22906
- import { existsSync as existsSync4 } from "node:fs";
23249
+ import { existsSync as existsSync6 } from "node:fs";
22907
23250
  import { fileURLToPath } from "node:url";
22908
23251
  function resolveDetachedDaemonEntry(moduleUrl, basename14) {
22909
23252
  const candidates = [`./${basename14}.js`, `./${basename14}.ts`].map((rel) => fileURLToPath(new URL(rel, moduleUrl)));
22910
- const found = candidates.find((path3) => existsSync4(path3));
23253
+ const found = candidates.find((path3) => existsSync6(path3));
22911
23254
  if (!found) throw new Error(`frizz is missing the ${basename14} entry \u2014 looked for ${candidates.join(" and ")}`);
22912
23255
  return found;
22913
23256
  }
@@ -22947,10 +23290,10 @@ var init_daemon_tree = __esm({
22947
23290
  });
22948
23291
 
22949
23292
  // packages/server/src/backend/ipc-path.ts
22950
- import { join as join15 } from "node:path";
23293
+ import { join as join18 } from "node:path";
22951
23294
  function frizzIpcPath(name) {
22952
23295
  if (process.platform === "win32") return `\\\\.\\pipe\\${name}`;
22953
- return join15(process.env.TMPDIR ?? "/tmp", `${name}.sock`);
23296
+ return join18(process.env.TMPDIR ?? "/tmp", `${name}.sock`);
22954
23297
  }
22955
23298
  var init_ipc_path = __esm({
22956
23299
  "packages/server/src/backend/ipc-path.ts"() {
@@ -22961,18 +23304,18 @@ var init_ipc_path = __esm({
22961
23304
  // packages/server/src/backend/claude-broker-host.ts
22962
23305
  import { spawn } from "node:child_process";
22963
23306
  import { createHash as createHash5, randomUUID as randomUUID8 } from "node:crypto";
22964
- import { accessSync, constants as fsConstants, mkdirSync as mkdirSync10, readFileSync as readFileSync10, readdirSync as readdirSync4, unlinkSync, writeFileSync as writeFileSync8 } from "node:fs";
22965
- import { delimiter, dirname as dirname8, isAbsolute as isAbsolute3, join as join16 } from "node:path";
23307
+ import { accessSync, constants as fsConstants, mkdirSync as mkdirSync12, readFileSync as readFileSync12, readdirSync as readdirSync5, unlinkSync, writeFileSync as writeFileSync10 } from "node:fs";
23308
+ import { delimiter, dirname as dirname10, isAbsolute as isAbsolute4, join as join19 } from "node:path";
22966
23309
  function windowsShimTarget(shimPath) {
22967
23310
  let body;
22968
23311
  try {
22969
- body = readFileSync10(shimPath, "utf8");
23312
+ body = readFileSync12(shimPath, "utf8");
22970
23313
  } catch {
22971
23314
  return void 0;
22972
23315
  }
22973
23316
  const target = WINDOWS_SHIM_TARGET.exec(body)?.[1];
22974
23317
  if (!target) return void 0;
22975
- const full = join16(dirname8(shimPath), target);
23318
+ const full = join19(dirname10(shimPath), target);
22976
23319
  try {
22977
23320
  accessSync(full, fsConstants.F_OK);
22978
23321
  return full;
@@ -22988,22 +23331,22 @@ function searchPath(env) {
22988
23331
  }
22989
23332
  function resolveClaudeExecutableAbsolute(bin, env = process.env) {
22990
23333
  const candidate = bin && bin.length > 0 ? bin : "claude";
22991
- if (isAbsolute3(candidate)) return candidate;
23334
+ if (isAbsolute4(candidate)) return candidate;
22992
23335
  const windows = process.platform === "win32";
22993
23336
  for (const dir of searchPath(env).split(delimiter)) {
22994
23337
  if (!dir) continue;
22995
23338
  if (windows) {
22996
- const exe2 = join16(dir, `${candidate}.exe`);
23339
+ const exe2 = join19(dir, `${candidate}.exe`);
22997
23340
  try {
22998
23341
  accessSync(exe2, fsConstants.F_OK);
22999
23342
  return exe2;
23000
23343
  } catch {
23001
23344
  }
23002
- const viaShim = windowsShimTarget(join16(dir, `${candidate}.cmd`));
23345
+ const viaShim = windowsShimTarget(join19(dir, `${candidate}.cmd`));
23003
23346
  if (viaShim) return viaShim;
23004
23347
  continue;
23005
23348
  }
23006
- const full = join16(dir, candidate);
23349
+ const full = join19(dir, candidate);
23007
23350
  try {
23008
23351
  accessSync(full, fsConstants.X_OK);
23009
23352
  return full;
@@ -23018,18 +23361,18 @@ function claudeBrokerSocketPath(stateDir, sessionId) {
23018
23361
  }
23019
23362
  function claudeBrokerRecordPath(stateDir, sessionId) {
23020
23363
  const key = createHash5("sha256").update(sessionId).digest("hex").slice(0, 16);
23021
- return join16(stateDir, "claude-broker", `${key}.json`);
23364
+ return join19(stateDir, "claude-broker", `${key}.json`);
23022
23365
  }
23023
23366
  function claudeBrokerRetirementPath(stateDir, sessionId) {
23024
23367
  const key = createHash5("sha256").update(sessionId).digest("hex").slice(0, 16);
23025
- return join16(stateDir, "claude-broker", `${key}.retired`);
23368
+ return join19(stateDir, "claude-broker", `${key}.retired`);
23026
23369
  }
23027
23370
  function markBrokerRetired(stateDir, sessionId, reason, generation) {
23028
23371
  const mark = { at: (/* @__PURE__ */ new Date()).toISOString(), generation, reason };
23029
23372
  try {
23030
23373
  const path3 = claudeBrokerRetirementPath(stateDir, sessionId);
23031
- mkdirSync10(dirname8(path3), { recursive: true });
23032
- writeFileSync8(path3, JSON.stringify(mark));
23374
+ mkdirSync12(dirname10(path3), { recursive: true });
23375
+ writeFileSync10(path3, JSON.stringify(mark));
23033
23376
  } catch {
23034
23377
  }
23035
23378
  }
@@ -23037,7 +23380,7 @@ function takeBrokerRetirement(stateDir, sessionId) {
23037
23380
  const path3 = claudeBrokerRetirementPath(stateDir, sessionId);
23038
23381
  let mark = null;
23039
23382
  try {
23040
- const parsed = JSON.parse(readFileSync10(path3, "utf8"));
23383
+ const parsed = JSON.parse(readFileSync12(path3, "utf8"));
23041
23384
  if (typeof parsed?.at === "string" && typeof parsed.generation === "string" && typeof parsed.reason === "string") {
23042
23385
  mark = { at: parsed.at, generation: parsed.generation, reason: parsed.reason };
23043
23386
  }
@@ -23059,7 +23402,7 @@ function pidAlive(pid) {
23059
23402
  }
23060
23403
  function readBrokerRecord(recordPath2) {
23061
23404
  try {
23062
- return JSON.parse(readFileSync10(recordPath2, "utf8"));
23405
+ return JSON.parse(readFileSync12(recordPath2, "utf8"));
23063
23406
  } catch {
23064
23407
  return null;
23065
23408
  }
@@ -23072,7 +23415,7 @@ function lastKnownBrokerDaemon(stateDir, sessionId) {
23072
23415
  }
23073
23416
  function rememberBrokerIdentity(recordPath2, record) {
23074
23417
  try {
23075
- writeFileSync8(brokerLastKnownPath(recordPath2), JSON.stringify(record));
23418
+ writeFileSync10(brokerLastKnownPath(recordPath2), JSON.stringify(record));
23076
23419
  } catch {
23077
23420
  }
23078
23421
  }
@@ -23089,17 +23432,17 @@ function liveBrokerRecord(recordPath2) {
23089
23432
  return null;
23090
23433
  }
23091
23434
  function liveBrokerRecords(stateDir) {
23092
- const dir = join16(stateDir, "claude-broker");
23435
+ const dir = join19(stateDir, "claude-broker");
23093
23436
  let names;
23094
23437
  try {
23095
- names = readdirSync4(dir);
23438
+ names = readdirSync5(dir);
23096
23439
  } catch {
23097
23440
  return [];
23098
23441
  }
23099
23442
  const out = [];
23100
23443
  for (const name of names) {
23101
23444
  if (!name.endsWith(".json")) continue;
23102
- const record = liveBrokerRecord(join16(dir, name));
23445
+ const record = liveBrokerRecord(join19(dir, name));
23103
23446
  if (record) out.push(record);
23104
23447
  }
23105
23448
  return out;
@@ -23107,7 +23450,7 @@ function liveBrokerRecords(stateDir) {
23107
23450
  function forkBroker(options) {
23108
23451
  const socketPath = claudeBrokerSocketPath(options.stateDir, options.sessionId);
23109
23452
  const recordPath2 = claudeBrokerRecordPath(options.stateDir, options.sessionId);
23110
- mkdirSync10(dirname8(recordPath2), { recursive: true });
23453
+ mkdirSync12(dirname10(recordPath2), { recursive: true });
23111
23454
  const generation = randomUUID8();
23112
23455
  const config = {
23113
23456
  socketPath,
@@ -23717,7 +24060,7 @@ var init_delivery_ledger = __esm({
23717
24060
  });
23718
24061
 
23719
24062
  // packages/server/src/codex-subagents.ts
23720
- import { closeSync as closeSync7, openSync as openSync8, readSync as readSync2, statSync as statSync6 } from "node:fs";
24063
+ import { closeSync as closeSync8, openSync as openSync9, readSync as readSync2, statSync as statSync7 } from "node:fs";
23721
24064
  function createCodexSubAgentTracker(deps) {
23722
24065
  const findRollouts = deps.findRollouts ?? ((ids) => findRolloutsByIds(ids, deps.codexHome));
23723
24066
  const readAppended = deps.readAppended ?? defaultReadAppended;
@@ -23909,7 +24252,7 @@ function agentLabel(path3) {
23909
24252
  function defaultReadAppended(path3, offset) {
23910
24253
  let size;
23911
24254
  try {
23912
- size = statSync6(path3).size;
24255
+ size = statSync7(path3).size;
23913
24256
  } catch {
23914
24257
  return void 0;
23915
24258
  }
@@ -23917,7 +24260,7 @@ function defaultReadAppended(path3, offset) {
23917
24260
  const from = restarted ? 0 : offset;
23918
24261
  if (size <= from) return { text: "", offset: from, restarted };
23919
24262
  try {
23920
- const fd2 = openSync8(path3, "r");
24263
+ const fd2 = openSync9(path3, "r");
23921
24264
  try {
23922
24265
  const want = Math.min(ROLLOUT_READ_WINDOW, size - from);
23923
24266
  const buf = Buffer.allocUnsafe(want);
@@ -23926,7 +24269,7 @@ function defaultReadAppended(path3, offset) {
23926
24269
  const end = read < size - from && lastNl >= 0 ? lastNl + 1 : read;
23927
24270
  return { text: buf.toString("utf8", 0, end), offset: from + end, restarted };
23928
24271
  } finally {
23929
- closeSync7(fd2);
24272
+ closeSync8(fd2);
23930
24273
  }
23931
24274
  } catch {
23932
24275
  return void 0;
@@ -24051,15 +24394,15 @@ var init_completion_relay = __esm({
24051
24394
 
24052
24395
  // packages/server/src/tail-cache.ts
24053
24396
  import { createHash as createHash6 } from "node:crypto";
24054
- import { closeSync as closeSync8, openSync as openSync9, readFileSync as readFileSync11, readSync as readSync3, statSync as statSync7 } from "node:fs";
24055
- import { join as join17 } from "node:path";
24397
+ import { closeSync as closeSync9, openSync as openSync10, readFileSync as readFileSync13, readSync as readSync3, statSync as statSync8 } from "node:fs";
24398
+ import { join as join20 } from "node:path";
24056
24399
  function foldSchemaDigest(dir = import.meta.dirname) {
24057
24400
  if (foldSchemaMemo) return foldSchemaMemo;
24058
24401
  const hash = createHash6("sha256").update("frizz-tail-state-v1\0");
24059
24402
  let read = 0;
24060
24403
  for (const name of FOLD_SOURCES) {
24061
24404
  try {
24062
- hash.update(name).update("\0").update(readFileSync11(join17(dir, name)));
24405
+ hash.update(name).update("\0").update(readFileSync13(join20(dir, name)));
24063
24406
  read++;
24064
24407
  } catch {
24065
24408
  hash.update(name).update("\0missing\0");
@@ -24089,9 +24432,9 @@ function measureFence(path3, offset) {
24089
24432
  if (!Number.isSafeInteger(offset) || offset <= 0) return null;
24090
24433
  let fd2;
24091
24434
  try {
24092
- const stat2 = statSync7(path3);
24435
+ const stat2 = statSync8(path3);
24093
24436
  if (stat2.size < offset) return null;
24094
- fd2 = openSync9(path3, "r");
24437
+ fd2 = openSync10(path3, "r");
24095
24438
  const window = Math.min(SAMPLE_BYTES, offset);
24096
24439
  const head = Buffer.allocUnsafe(window);
24097
24440
  const headRead = readSync3(fd2, head, 0, window, 0);
@@ -24111,7 +24454,7 @@ function measureFence(path3, offset) {
24111
24454
  } finally {
24112
24455
  if (fd2 !== void 0) {
24113
24456
  try {
24114
- closeSync8(fd2);
24457
+ closeSync9(fd2);
24115
24458
  } catch {
24116
24459
  }
24117
24460
  }
@@ -24262,11 +24605,11 @@ var init_tail_cache = __esm({
24262
24605
  });
24263
24606
 
24264
24607
  // packages/server/src/tailer.ts
24265
- import { statSync as statSync8, openSync as openSync10, readSync as readSync4, closeSync as closeSync9, readdirSync as readdirSync5, realpathSync as realpathSync5, mkdirSync as mkdirSync11, writeFileSync as writeFileSync9, readFileSync as readFileSync12, existsSync as existsSync5 } from "node:fs";
24608
+ import { statSync as statSync9, openSync as openSync11, readSync as readSync4, closeSync as closeSync10, readdirSync as readdirSync6, realpathSync as realpathSync6, mkdirSync as mkdirSync13, writeFileSync as writeFileSync11, readFileSync as readFileSync14, existsSync as existsSync7 } from "node:fs";
24266
24609
  import { execFile as execFile2 } from "node:child_process";
24267
24610
  import { createHash as createHash7 } from "node:crypto";
24268
24611
  import { promisify as promisify2 } from "node:util";
24269
- import { basename as basename4, join as join18, win32 } from "node:path";
24612
+ import { basename as basename4, join as join21, win32 } from "node:path";
24270
24613
  import { homedir as homedir7 } from "node:os";
24271
24614
  function pendingCallDeadline(tail) {
24272
24615
  const resolved2 = /* @__PURE__ */ new Set();
@@ -24313,7 +24656,7 @@ function readTranscriptTail(path3, size, window) {
24313
24656
  const length = Math.min(size, window);
24314
24657
  let fd2;
24315
24658
  try {
24316
- fd2 = openSync10(path3, "r");
24659
+ fd2 = openSync11(path3, "r");
24317
24660
  const buffer = Buffer.alloc(length);
24318
24661
  const read = readSync4(fd2, buffer, 0, length, size - length);
24319
24662
  const text2 = buffer.toString("utf8", 0, read);
@@ -24323,7 +24666,7 @@ function readTranscriptTail(path3, size, window) {
24323
24666
  } finally {
24324
24667
  if (fd2 !== void 0) {
24325
24668
  try {
24326
- closeSync9(fd2);
24669
+ closeSync10(fd2);
24327
24670
  } catch {
24328
24671
  }
24329
24672
  }
@@ -24337,7 +24680,7 @@ async function probeShellsAlive(shells, opts = {}) {
24337
24680
  const verdicts = /* @__PURE__ */ new Map();
24338
24681
  if (platform3 === "win32") {
24339
24682
  const present = outputFiles.filter((file) => {
24340
- if (existsSync5(file)) return true;
24683
+ if (existsSync7(file)) return true;
24341
24684
  verdicts.set(file, void 0);
24342
24685
  return false;
24343
24686
  });
@@ -24355,12 +24698,12 @@ async function probeShellsAlive(shells, opts = {}) {
24355
24698
  }
24356
24699
  const live = [];
24357
24700
  for (const file of outputFiles) {
24358
- if (!existsSync5(file)) {
24701
+ if (!existsSync7(file)) {
24359
24702
  verdicts.set(file, void 0);
24360
24703
  continue;
24361
24704
  }
24362
24705
  try {
24363
- live.push({ requested: file, real: realpathSync5(file) });
24706
+ live.push({ requested: file, real: realpathSync6(file) });
24364
24707
  } catch {
24365
24708
  verdicts.set(file, void 0);
24366
24709
  }
@@ -24793,7 +25136,7 @@ function launchTaskId(text2) {
24793
25136
  function readDescendantSidecars(sessionDir, mtimeMs) {
24794
25137
  let names;
24795
25138
  try {
24796
- names = readdirSync5(join18(sessionDir, "subagents"));
25139
+ names = readdirSync6(join21(sessionDir, "subagents"));
24797
25140
  } catch {
24798
25141
  return [];
24799
25142
  }
@@ -24804,7 +25147,7 @@ function readDescendantSidecars(sessionDir, mtimeMs) {
24804
25147
  if (!agentId) continue;
24805
25148
  let parsed;
24806
25149
  try {
24807
- parsed = JSON.parse(readFileSync12(join18(sessionDir, "subagents", name), "utf8"));
25150
+ parsed = JSON.parse(readFileSync14(join21(sessionDir, "subagents", name), "utf8"));
24808
25151
  } catch {
24809
25152
  continue;
24810
25153
  }
@@ -24818,7 +25161,7 @@ function readDescendantSidecars(sessionDir, mtimeMs) {
24818
25161
  agentType: text2(meta.agentType),
24819
25162
  parentAgentId: text2(meta.parentAgentId),
24820
25163
  spawnDepth: typeof meta.spawnDepth === "number" && Number.isFinite(meta.spawnDepth) ? meta.spawnDepth : void 0,
24821
- spawnedAtMs: mtimeMs(join18(sessionDir, "subagents", name))
25164
+ spawnedAtMs: mtimeMs(join21(sessionDir, "subagents", name))
24822
25165
  });
24823
25166
  }
24824
25167
  return out;
@@ -25307,19 +25650,19 @@ function isPermMarker(v) {
25307
25650
  }
25308
25651
  function defaultMtimeMs(path3) {
25309
25652
  try {
25310
- return statSync8(path3).mtimeMs;
25653
+ return statSync9(path3).mtimeMs;
25311
25654
  } catch {
25312
25655
  return void 0;
25313
25656
  }
25314
25657
  }
25315
25658
  function defaultLogDir(project) {
25316
- return join18(homedir7(), ".claude", "projects", project.cwdSlug);
25659
+ return join21(homedir7(), ".claude", "projects", project.cwdSlug);
25317
25660
  }
25318
25661
  function defaultReadPermMarker(project) {
25319
25662
  if (!project.stateDir) return () => void 0;
25320
25663
  return (slug) => {
25321
25664
  try {
25322
- const parsed = JSON.parse(readFileSync12(permMarkerPath(project, slug), "utf8"));
25665
+ const parsed = JSON.parse(readFileSync14(permMarkerPath(project, slug), "utf8"));
25323
25666
  return isPermMarker(parsed) ? parsed : void 0;
25324
25667
  } catch {
25325
25668
  return void 0;
@@ -25337,7 +25680,7 @@ function defaultBrokerDaemonAlive(project, now) {
25337
25680
  try {
25338
25681
  const path3 = claudeBrokerRecordPath(project.stateDir, sessionId);
25339
25682
  const record = readBrokerRecord(path3);
25340
- if (!record) alive = existsSync5(path3);
25683
+ if (!record) alive = existsSync7(path3);
25341
25684
  else if (typeof record.daemonPid !== "number") alive = true;
25342
25685
  else {
25343
25686
  try {
@@ -25445,7 +25788,7 @@ function createTailer(deps) {
25445
25788
  return paneDead(row.slug);
25446
25789
  }
25447
25790
  const defaultBackend = {
25448
- transcriptPath: (sessionId) => join18(logDir, `${sessionId}.jsonl`),
25791
+ transcriptPath: (sessionId) => join21(logDir, `${sessionId}.jsonl`),
25449
25792
  foldLine: (state, line) => {
25450
25793
  const rec = parseLine(line);
25451
25794
  if (rec) applyRecord(state, rec);
@@ -25487,7 +25830,7 @@ function createTailer(deps) {
25487
25830
  function blockedUntil(path3, m) {
25488
25831
  let size;
25489
25832
  try {
25490
- size = statSync8(path3).size;
25833
+ size = statSync9(path3).size;
25491
25834
  } catch {
25492
25835
  return void 0;
25493
25836
  }
@@ -25613,7 +25956,7 @@ ${ask}`;
25613
25956
  return state.path.replace(/\.jsonl$/, "");
25614
25957
  }
25615
25958
  function descendantSidecars(state) {
25616
- const at2 = mtimeMs(join18(sessionDirOf(state), "subagents"));
25959
+ const at2 = mtimeMs(join21(sessionDirOf(state), "subagents"));
25617
25960
  const cached2 = descendantIndex.get(state.slug);
25618
25961
  if (cached2 && cached2.at === at2) return cached2.all;
25619
25962
  const all = readDescendantSidecars(sessionDirOf(state), mtimeMs);
@@ -25627,7 +25970,7 @@ ${ask}`;
25627
25970
  return descendantIndex.get(state.slug)?.byToolUse.get(id2);
25628
25971
  }
25629
25972
  function descendantTranscript(state, meta) {
25630
- return join18(sessionDirOf(state), "subagents", `agent-${meta.agentId}.jsonl`);
25973
+ return join21(sessionDirOf(state), "subagents", `agent-${meta.agentId}.jsonl`);
25631
25974
  }
25632
25975
  function subAgentDescendantTasks(slug, id2) {
25633
25976
  const state = states.get(slug);
@@ -25947,7 +26290,7 @@ ${ask}`;
25947
26290
  if (!deps.project.dir) return [];
25948
26291
  const cwds = /* @__PURE__ */ new Set([deps.project.dir]);
25949
26292
  try {
25950
- cwds.add(realpathSync5(deps.project.dir));
26293
+ cwds.add(realpathSync6(deps.project.dir));
25951
26294
  } catch {
25952
26295
  }
25953
26296
  try {
@@ -25965,7 +26308,7 @@ ${ask}`;
25965
26308
  function scanForeign(nowMs) {
25966
26309
  let names;
25967
26310
  try {
25968
- names = readdirSync5(logDir);
26311
+ names = readdirSync6(logDir);
25969
26312
  } catch {
25970
26313
  return [];
25971
26314
  }
@@ -25975,10 +26318,10 @@ ${ask}`;
25975
26318
  if (name.startsWith(".") || !name.endsWith(".jsonl")) continue;
25976
26319
  const id2 = name.slice(0, -".jsonl".length);
25977
26320
  if (!id2 || registered.has(id2)) continue;
25978
- const path3 = join18(logDir, name);
26321
+ const path3 = join21(logDir, name);
25979
26322
  let mtime;
25980
26323
  try {
25981
- mtime = statSync8(path3).mtimeMs;
26324
+ mtime = statSync9(path3).mtimeMs;
25982
26325
  } catch {
25983
26326
  continue;
25984
26327
  }
@@ -26131,7 +26474,7 @@ ${ask}`;
26131
26474
  if (entry.path !== state.path) {
26132
26475
  let derivedSize = 0;
26133
26476
  try {
26134
- derivedSize = statSync8(state.path).size;
26477
+ derivedSize = statSync9(state.path).size;
26135
26478
  } catch {
26136
26479
  derivedSize = 0;
26137
26480
  }
@@ -26188,7 +26531,7 @@ ${ask}`;
26188
26531
  function consume(state, backend, onLine) {
26189
26532
  let size;
26190
26533
  try {
26191
- size = statSync8(state.path).size;
26534
+ size = statSync9(state.path).size;
26192
26535
  } catch {
26193
26536
  return;
26194
26537
  }
@@ -26199,7 +26542,7 @@ ${ask}`;
26199
26542
  if (size <= state.offset) return;
26200
26543
  let carry = state.partial ? Buffer.from(state.partial, "utf8") : EMPTY_BUFFER;
26201
26544
  try {
26202
- const fd2 = openSync10(state.path, "r");
26545
+ const fd2 = openSync11(state.path, "r");
26203
26546
  try {
26204
26547
  const buf = Buffer.allocUnsafe(Math.min(TRANSCRIPT_READ_WINDOW, size - state.offset));
26205
26548
  while (state.offset < size) {
@@ -26219,7 +26562,7 @@ ${ask}`;
26219
26562
  carry = start < view.length ? Buffer.from(view.subarray(start)) : EMPTY_BUFFER;
26220
26563
  }
26221
26564
  } finally {
26222
- closeSync9(fd2);
26565
+ closeSync10(fd2);
26223
26566
  }
26224
26567
  } catch {
26225
26568
  state.partial = carry.toString("utf8");
@@ -26246,8 +26589,8 @@ ${ask}`;
26246
26589
  `thread ${row.slug} (session ${row.session_id}): no transcript ${DISCOVERY_GRACE_MS / 1e3}s after dispatch \u2014 likely a boot failure. ${detail2.slice(0, 4e3)}`
26247
26590
  );
26248
26591
  try {
26249
- mkdirSync11(stallLogDir, { recursive: true });
26250
- writeFileSync9(join18(stallLogDir, `${row.slug}.stall.log`), `session_id: ${row.session_id}
26592
+ mkdirSync13(stallLogDir, { recursive: true });
26593
+ writeFileSync11(join21(stallLogDir, `${row.slug}.stall.log`), `session_id: ${row.session_id}
26251
26594
  captured_at: ${new Date(now()).toISOString()}
26252
26595
 
26253
26596
  ${detail2}
@@ -26257,10 +26600,10 @@ ${detail2}
26257
26600
  }
26258
26601
  function relocatedTranscript(state) {
26259
26602
  const name = `${state.nativeSessionId}.jsonl`;
26260
- const home = join18(logDir, name);
26603
+ const home = join21(logDir, name);
26261
26604
  const homeAt = home === state.path ? void 0 : mtimeOfNonEmpty(home);
26262
26605
  const dir = discoverTranscriptDir(logDir, state.nativeSessionId);
26263
- const sibling = dir ? join18(dir, name) : void 0;
26606
+ const sibling = dir ? join21(dir, name) : void 0;
26264
26607
  const siblingAt = sibling && sibling !== state.path ? mtimeOfNonEmpty(sibling) : void 0;
26265
26608
  if (homeAt === void 0) return siblingAt === void 0 ? void 0 : sibling;
26266
26609
  if (siblingAt === void 0) return home;
@@ -26268,7 +26611,7 @@ ${detail2}
26268
26611
  }
26269
26612
  function resolveTranscript(state, row, nowMs) {
26270
26613
  if (state.offset > 0) {
26271
- if (existsSync5(state.path)) {
26614
+ if (existsSync7(state.path)) {
26272
26615
  state.discoverMisses = 0;
26273
26616
  state.nextDiscoverMs = 0;
26274
26617
  return true;
@@ -26295,7 +26638,7 @@ ${detail2}
26295
26638
  }
26296
26639
  let size = 0;
26297
26640
  try {
26298
- size = statSync8(state.path).size;
26641
+ size = statSync9(state.path).size;
26299
26642
  } catch {
26300
26643
  size = 0;
26301
26644
  }
@@ -26312,7 +26655,7 @@ ${detail2}
26312
26655
  state.nextDiscoverMs = nowMs + DISCOVER_RETRY_MS;
26313
26656
  const strandedDir = discoverTranscriptDir(logDir, row.session_id);
26314
26657
  if (strandedDir) {
26315
- state.path = join18(strandedDir, `${row.session_id}.jsonl`);
26658
+ state.path = join21(strandedDir, `${row.session_id}.jsonl`);
26316
26659
  state.offset = 0;
26317
26660
  state.partial = "";
26318
26661
  state.primed = false;
@@ -26336,7 +26679,7 @@ ${detail2}
26336
26679
  committed = false;
26337
26680
  }
26338
26681
  if (!committed) return false;
26339
- state.path = join18(logDir, `${found}.jsonl`);
26682
+ state.path = join21(logDir, `${found}.jsonl`);
26340
26683
  state.offset = 0;
26341
26684
  state.partial = "";
26342
26685
  state.primed = false;
@@ -26396,7 +26739,7 @@ ${detail2}
26396
26739
  continue;
26397
26740
  }
26398
26741
  if (!state) {
26399
- const path3 = backend.transcriptPath(nativeId) ?? join18(logDir, `${nativeId}.jsonl`);
26742
+ const path3 = backend.transcriptPath(nativeId) ?? join21(logDir, `${nativeId}.jsonl`);
26400
26743
  state = newTailState(row.slug, row.session_id, path3, false, nativeId, runtimeGeneration);
26401
26744
  state.dismissedOps = deps.storage.retiredOps(row.slug, row.session_id);
26402
26745
  hydrateFromCache(state, row, nativeId);
@@ -26631,12 +26974,12 @@ ${detail2}
26631
26974
  const elapsed = monotonicNow() - started;
26632
26975
  lastTickMs = elapsed;
26633
26976
  lastTickEndedAtMs = now();
26634
- if (elapsed > POLL_MS2) {
26977
+ if (elapsed > POLL_MS3) {
26635
26978
  overBudgetTicks++;
26636
26979
  if (overBudgetTicks === 1 || overBudgetTicks % 30 === 0) {
26637
26980
  log.warn(
26638
26981
  "tailer",
26639
- `tick took ${Math.round(elapsed)}ms (poll ${POLL_MS2}ms, ${states.size} sessions) \u2014 the event loop is blocked for that long, so RPCs and board pushes are delayed (occurrence ${overBudgetTicks})`
26982
+ `tick took ${Math.round(elapsed)}ms (poll ${POLL_MS3}ms, ${states.size} sessions) \u2014 the event loop is blocked for that long, so RPCs and board pushes are delayed (occurrence ${overBudgetTicks})`
26640
26983
  );
26641
26984
  }
26642
26985
  }
@@ -26650,7 +26993,7 @@ ${detail2}
26650
26993
  }
26651
26994
  }
26652
26995
  function scheduleTick() {
26653
- const delay2 = primeIncomplete ? 1 : Math.min(MAX_POLL_MS, Math.max(POLL_MS2, Math.round(lastTickMs)));
26996
+ const delay2 = primeIncomplete ? 1 : Math.min(MAX_POLL_MS, Math.max(POLL_MS3, Math.round(lastTickMs)));
26654
26997
  timer = setTimeout(() => {
26655
26998
  timer = null;
26656
26999
  try {
@@ -26754,7 +27097,7 @@ function landsAfterRead(eventAt, lastReadAt) {
26754
27097
  if (!Number.isFinite(e14) || !Number.isFinite(r)) return true;
26755
27098
  return e14 > r;
26756
27099
  }
26757
- var IDLE_BACKSTOP_MS, RUNTIME_CHASE_MAX, POLL_MS2, MAX_PRIME_ROWS_PER_TICK, PRIME_BUDGET_MS, TRANSCRIPT_READ_WINDOW, EMPTY_BUFFER, MAX_POLL_MS, SUBAGENT_STALE_MS, BASH_TIMEOUT_CEILING_MS, PENDING_CALL_TAIL_BYTES, SHELL_PROBE_TTL_MS, SHELL_PROBE_GRACE_MS, execFileAsync, FOREIGN_FRESH_MS, FOREIGN_MAX, FOREIGN_SCAN_EVERY, CACHE_FLUSH_MS, PRIME_PROGRESS_EVERY, DISCOVER_RETRY_MS, DISCOVER_RETRY_MAX_MS, RETAINED_SUBAGENTS_MAX, RETAINED_SHELLS_MAX, DESCENDANT_TERMINALS_MAX, PENDING_RESUMES_MAX, PENDING_SHELLS_MAX, LIVE_TOOLS_MAX, RESUME_REPLAY_SLACK_MS, FIRST_USER_TEXT_MAX, ASSISTANT_LINE_MAX, QUESTION_BLOCK_RE, SIGNAL_FENCE_RE, FENCE_BODY_MAX, LOCAL_COMMAND_RECEIPT, LAUNCH_ACK_RE, AUTO_BACKGROUND_ACK_RE, FOLDED_TERMINALS_MAX, DESCENDANT_SIDECAR_MAX, DESCENDANT_NOTIFY_GRACE_MS, MAX_OWNED_TOOL_USE_IDS, BROKER_LIVENESS_TTL_MS, UNRESTORED_TAIL_FIELDS;
27100
+ var IDLE_BACKSTOP_MS, RUNTIME_CHASE_MAX, POLL_MS3, MAX_PRIME_ROWS_PER_TICK, PRIME_BUDGET_MS, TRANSCRIPT_READ_WINDOW, EMPTY_BUFFER, MAX_POLL_MS, SUBAGENT_STALE_MS, BASH_TIMEOUT_CEILING_MS, PENDING_CALL_TAIL_BYTES, SHELL_PROBE_TTL_MS, SHELL_PROBE_GRACE_MS, execFileAsync, FOREIGN_FRESH_MS, FOREIGN_MAX, FOREIGN_SCAN_EVERY, CACHE_FLUSH_MS, PRIME_PROGRESS_EVERY, DISCOVER_RETRY_MS, DISCOVER_RETRY_MAX_MS, RETAINED_SUBAGENTS_MAX, RETAINED_SHELLS_MAX, DESCENDANT_TERMINALS_MAX, PENDING_RESUMES_MAX, PENDING_SHELLS_MAX, LIVE_TOOLS_MAX, RESUME_REPLAY_SLACK_MS, FIRST_USER_TEXT_MAX, ASSISTANT_LINE_MAX, QUESTION_BLOCK_RE, SIGNAL_FENCE_RE, FENCE_BODY_MAX, LOCAL_COMMAND_RECEIPT, LAUNCH_ACK_RE, AUTO_BACKGROUND_ACK_RE, FOLDED_TERMINALS_MAX, DESCENDANT_SIDECAR_MAX, DESCENDANT_NOTIFY_GRACE_MS, MAX_OWNED_TOOL_USE_IDS, BROKER_LIVENESS_TTL_MS, UNRESTORED_TAIL_FIELDS;
26758
27101
  var init_tailer = __esm({
26759
27102
  "packages/server/src/tailer.ts"() {
26760
27103
  "use strict";
@@ -26780,7 +27123,7 @@ var init_tailer = __esm({
26780
27123
  init_credential_redaction();
26781
27124
  IDLE_BACKSTOP_MS = 5e3;
26782
27125
  RUNTIME_CHASE_MAX = 20;
26783
- POLL_MS2 = 1e3;
27126
+ POLL_MS3 = 1e3;
26784
27127
  MAX_PRIME_ROWS_PER_TICK = 25;
26785
27128
  PRIME_BUDGET_MS = 200;
26786
27129
  TRANSCRIPT_READ_WINDOW = 16 * 1024 * 1024;
@@ -26864,14 +27207,14 @@ var init_tailer = __esm({
26864
27207
  });
26865
27208
 
26866
27209
  // packages/server/src/backend/codex.ts
26867
- import { join as join19 } from "node:path";
27210
+ import { join as join22 } from "node:path";
26868
27211
  import { homedir as homedir8 } from "node:os";
26869
- import { readdirSync as readdirSync6, statSync as statSync9, readFileSync as readFileSync13, openSync as openSync11, readSync as readSync5, closeSync as closeSync10 } from "node:fs";
27212
+ import { readdirSync as readdirSync7, statSync as statSync10, readFileSync as readFileSync15, openSync as openSync12, readSync as readSync5, closeSync as closeSync11 } from "node:fs";
26870
27213
  function defaultCodexHome() {
26871
- return process.env.CODEX_HOME && process.env.CODEX_HOME.trim() ? process.env.CODEX_HOME : join19(homedir8(), ".codex");
27214
+ return process.env.CODEX_HOME && process.env.CODEX_HOME.trim() ? process.env.CODEX_HOME : join22(homedir8(), ".codex");
26872
27215
  }
26873
27216
  function sessionsDir(codexHome) {
26874
- return join19(codexHome, "sessions");
27217
+ return join22(codexHome, "sessions");
26875
27218
  }
26876
27219
  function codexSandbox(mode) {
26877
27220
  switch (mode) {
@@ -27317,23 +27660,23 @@ function collectRollouts(dir, out, budget) {
27317
27660
  const files = entries2.filter((e14) => e14.isFile() && e14.name.startsWith("rollout-") && e14.name.endsWith(".jsonl")).sort(descByName);
27318
27661
  for (const d of dirs) {
27319
27662
  if (budget.n <= 0) return;
27320
- collectRollouts(join19(dir, d.name), out, budget);
27663
+ collectRollouts(join22(dir, d.name), out, budget);
27321
27664
  }
27322
27665
  for (const f of files) {
27323
27666
  if (budget.n <= 0) return;
27324
27667
  let mtimeMs;
27325
27668
  try {
27326
- mtimeMs = statSync9(join19(dir, f.name)).mtimeMs;
27669
+ mtimeMs = statSync10(join22(dir, f.name)).mtimeMs;
27327
27670
  } catch {
27328
27671
  continue;
27329
27672
  }
27330
- out.push({ path: join19(dir, f.name), mtimeMs });
27673
+ out.push({ path: join22(dir, f.name), mtimeMs });
27331
27674
  budget.n--;
27332
27675
  }
27333
27676
  }
27334
27677
  function safeReaddir(dir) {
27335
27678
  try {
27336
- return readdirSync6(dir, { withFileTypes: true });
27679
+ return readdirSync7(dir, { withFileTypes: true });
27337
27680
  } catch {
27338
27681
  return [];
27339
27682
  }
@@ -27371,9 +27714,9 @@ function readCodexThreadNames(codexHome = defaultCodexHome()) {
27371
27714
  const out = /* @__PURE__ */ new Map();
27372
27715
  let raw2;
27373
27716
  try {
27374
- const path3 = join19(codexHome, "session_index.jsonl");
27375
- if (statSync9(path3).size > SESSION_INDEX_MAX_BYTES) return out;
27376
- raw2 = readFileSync13(path3, "utf8");
27717
+ const path3 = join22(codexHome, "session_index.jsonl");
27718
+ if (statSync10(path3).size > SESSION_INDEX_MAX_BYTES) return out;
27719
+ raw2 = readFileSync15(path3, "utf8");
27377
27720
  } catch {
27378
27721
  return out;
27379
27722
  }
@@ -27413,7 +27756,7 @@ function rolloutIdOf(path3) {
27413
27756
  function readSessionMeta(path3) {
27414
27757
  let fd2;
27415
27758
  try {
27416
- fd2 = openSync11(path3, "r");
27759
+ fd2 = openSync12(path3, "r");
27417
27760
  const buf = Buffer.allocUnsafe(FOREIGN_ROLLOUT_HEAD_BYTES);
27418
27761
  const n = readSync5(fd2, buf, 0, FOREIGN_ROLLOUT_HEAD_BYTES, 0);
27419
27762
  const line = buf.toString("utf8", 0, n).split("\n", 1)[0];
@@ -27430,7 +27773,7 @@ function readSessionMeta(path3) {
27430
27773
  } finally {
27431
27774
  if (fd2 !== void 0) {
27432
27775
  try {
27433
- closeSync10(fd2);
27776
+ closeSync11(fd2);
27434
27777
  } catch {
27435
27778
  }
27436
27779
  }
@@ -27549,7 +27892,7 @@ var init_codex = __esm({
27549
27892
  });
27550
27893
 
27551
27894
  // packages/server/src/backend/codex-executable.ts
27552
- import { accessSync as accessSync2, constants as fsConstants2, readFileSync as readFileSync14 } from "node:fs";
27895
+ import { accessSync as accessSync2, constants as fsConstants2, readFileSync as readFileSync16 } from "node:fs";
27553
27896
  import { posix, win32 as win322 } from "node:path";
27554
27897
  function defaultAccess(path3, mode) {
27555
27898
  try {
@@ -27561,7 +27904,7 @@ function defaultAccess(path3, mode) {
27561
27904
  }
27562
27905
  function defaultReadFile(path3) {
27563
27906
  try {
27564
- return readFileSync14(path3, "utf8");
27907
+ return readFileSync16(path3, "utf8");
27565
27908
  } catch {
27566
27909
  return void 0;
27567
27910
  }
@@ -27575,19 +27918,19 @@ function searchPath2(env) {
27575
27918
  function vendoredNativeBeside(launcherJs, arch, access) {
27576
27919
  const triple = WINDOWS_TRIPLE[arch];
27577
27920
  if (!triple) return void 0;
27578
- const { dirname: dirname27, join: join51 } = win322;
27579
- const pkgRoot = dirname27(dirname27(launcherJs));
27921
+ const { dirname: dirname29, join: join54 } = win322;
27922
+ const pkgRoot = dirname29(dirname29(launcherJs));
27580
27923
  const platformPkg = `codex-win32-${arch}`;
27581
27924
  const vendorRoots = [
27582
- join51(pkgRoot, "node_modules", "@openai", platformPkg, "vendor"),
27925
+ join54(pkgRoot, "node_modules", "@openai", platformPkg, "vendor"),
27583
27926
  // nested under the package
27584
- join51(dirname27(pkgRoot), platformPkg, "vendor"),
27927
+ join54(dirname29(pkgRoot), platformPkg, "vendor"),
27585
27928
  // hoisted beside it: <prefix>\node_modules\@openai\<pkg>
27586
- join51(pkgRoot, "vendor")
27929
+ join54(pkgRoot, "vendor")
27587
27930
  // the pre-platform-package layout, binaries inside @openai/codex itself
27588
27931
  ];
27589
27932
  for (const root of vendorRoots) {
27590
- const exe2 = join51(root, triple, "bin", "codex.exe");
27933
+ const exe2 = join54(root, triple, "bin", "codex.exe");
27591
27934
  if (access(exe2, "exists")) return exe2;
27592
27935
  }
27593
27936
  return void 0;
@@ -29911,7 +30254,7 @@ var require_websocket = __commonJS({
29911
30254
  var http = __require("http");
29912
30255
  var net2 = __require("net");
29913
30256
  var tls = __require("tls");
29914
- var { randomBytes, createHash: createHash18 } = __require("crypto");
30257
+ var { randomBytes: randomBytes2, createHash: createHash18 } = __require("crypto");
29915
30258
  var { Duplex, Readable: Readable3 } = __require("stream");
29916
30259
  var { URL: URL2 } = __require("url");
29917
30260
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -30449,7 +30792,7 @@ var require_websocket = __commonJS({
30449
30792
  }
30450
30793
  }
30451
30794
  const defaultPort = isSecure ? 443 : 80;
30452
- const key = randomBytes(16).toString("base64");
30795
+ const key = randomBytes2(16).toString("base64");
30453
30796
  const request = isSecure ? https.request : http.request;
30454
30797
  const protocolSet = /* @__PURE__ */ new Set();
30455
30798
  let perMessageDeflate;
@@ -31419,15 +31762,15 @@ import { spawn as spawn2 } from "node:child_process";
31419
31762
  import { connect } from "node:net";
31420
31763
  import { Agent as HttpAgent } from "node:http";
31421
31764
  import { createHash as createHash8, randomUUID as randomUUID9 } from "node:crypto";
31422
- import { existsSync as existsSync6, mkdirSync as mkdirSync12, readFileSync as readFileSync15, unlinkSync as unlinkSync2, writeFileSync as writeFileSync10 } from "node:fs";
31423
- import { join as join20 } from "node:path";
31765
+ import { existsSync as existsSync8, mkdirSync as mkdirSync14, readFileSync as readFileSync17, unlinkSync as unlinkSync2, writeFileSync as writeFileSync12 } from "node:fs";
31766
+ import { join as join23 } from "node:path";
31424
31767
  import { PassThrough, Writable } from "node:stream";
31425
31768
  import { StringDecoder } from "node:string_decoder";
31426
31769
  function nativeDir(stateDir) {
31427
- return join20(stateDir, "codex-app-server-native");
31770
+ return join23(stateDir, "codex-app-server-native");
31428
31771
  }
31429
31772
  function nativeRecordPath(stateDir, projectId) {
31430
- return join20(nativeDir(stateDir), `${projectId}.json`);
31773
+ return join23(nativeDir(stateDir), `${projectId}.json`);
31431
31774
  }
31432
31775
  function nativeListenSocketPath(stateDir, projectId) {
31433
31776
  const key = createHash8("sha256").update(stateDir).update("\0").update(projectId).digest("hex").slice(0, 16);
@@ -31443,7 +31786,7 @@ function pidAlive2(pid) {
31443
31786
  }
31444
31787
  function readNativeRecord(stateDir, projectId) {
31445
31788
  try {
31446
- const value = JSON.parse(readFileSync15(nativeRecordPath(stateDir, projectId), "utf8"));
31789
+ const value = JSON.parse(readFileSync17(nativeRecordPath(stateDir, projectId), "utf8"));
31447
31790
  if (typeof value.listenerPid !== "number" || typeof value.socketPath !== "string" || typeof value.generation !== "string") return null;
31448
31791
  return {
31449
31792
  projectId,
@@ -31460,7 +31803,7 @@ function readNativeRecord(stateDir, projectId) {
31460
31803
  function liveNativeRecord(stateDir, projectId) {
31461
31804
  const record = readNativeRecord(stateDir, projectId);
31462
31805
  if (!record) return null;
31463
- if (pidAlive2(record.listenerPid) && existsSync6(record.socketPath)) return record;
31806
+ if (pidAlive2(record.listenerPid) && existsSync8(record.socketPath)) return record;
31464
31807
  try {
31465
31808
  unlinkSync2(nativeRecordPath(stateDir, projectId));
31466
31809
  } catch {
@@ -31600,9 +31943,9 @@ function attach(record, timeoutMs) {
31600
31943
  }
31601
31944
  async function startListener(options) {
31602
31945
  const { stateDir, projectId } = options;
31603
- mkdirSync12(nativeDir(stateDir), { recursive: true });
31946
+ mkdirSync14(nativeDir(stateDir), { recursive: true });
31604
31947
  const socketPath = nativeListenSocketPath(stateDir, projectId);
31605
- if (existsSync6(socketPath) && !await socketAccepting(socketPath)) {
31948
+ if (existsSync8(socketPath) && !await socketAccepting(socketPath)) {
31606
31949
  try {
31607
31950
  unlinkSync2(socketPath);
31608
31951
  } catch {
@@ -31627,10 +31970,10 @@ async function startListener(options) {
31627
31970
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
31628
31971
  ...options.authAccountId ? { authAccountId: options.authAccountId } : {}
31629
31972
  };
31630
- writeFileSync10(nativeRecordPath(stateDir, projectId), JSON.stringify(record));
31973
+ writeFileSync12(nativeRecordPath(stateDir, projectId), JSON.stringify(record));
31631
31974
  const deadline = Date.now() + (options.timeoutMs ?? 3e4);
31632
31975
  for (; ; ) {
31633
- if (existsSync6(socketPath) && await socketAccepting(socketPath)) return record;
31976
+ if (existsSync8(socketPath) && await socketAccepting(socketPath)) return record;
31634
31977
  if (!pidAlive2(record.listenerPid)) throw new Error("codex app-server listener exited before it became ready");
31635
31978
  if (Date.now() > deadline) throw new Error("codex app-server listener did not become ready");
31636
31979
  await new Promise((resolve13) => setTimeout(resolve13, 50));
@@ -31699,15 +32042,15 @@ var init_codex_app_server_native = __esm({
31699
32042
  import { spawn as spawn3 } from "node:child_process";
31700
32043
  import { createConnection } from "node:net";
31701
32044
  import { createHash as createHash9, randomUUID as randomUUID10 } from "node:crypto";
31702
- import { existsSync as existsSync7, mkdirSync as mkdirSync13, readFileSync as readFileSync16, unlinkSync as unlinkSync3 } from "node:fs";
31703
- import { join as join21 } from "node:path";
32045
+ import { existsSync as existsSync9, mkdirSync as mkdirSync15, readFileSync as readFileSync18, unlinkSync as unlinkSync3 } from "node:fs";
32046
+ import { join as join24 } from "node:path";
31704
32047
  import { PassThrough as PassThrough2, Writable as Writable2 } from "node:stream";
31705
32048
  import { StringDecoder as StringDecoder2 } from "node:string_decoder";
31706
32049
  function daemonDir(stateDir) {
31707
- return join21(stateDir, "codex-app-server");
32050
+ return join24(stateDir, "codex-app-server");
31708
32051
  }
31709
32052
  function recordPath(stateDir, projectId) {
31710
- return join21(daemonDir(stateDir), `${projectId}.json`);
32053
+ return join24(daemonDir(stateDir), `${projectId}.json`);
31711
32054
  }
31712
32055
  function codexAppServerSocketPath(stateDir, projectId) {
31713
32056
  const key = createHash9("sha256").update(stateDir).update("\0").update(projectId).digest("hex").slice(0, 16);
@@ -31723,7 +32066,7 @@ function pidAlive3(pid) {
31723
32066
  }
31724
32067
  function readDaemonRecord(stateDir, projectId) {
31725
32068
  try {
31726
- const value = JSON.parse(readFileSync16(recordPath(stateDir, projectId), "utf8"));
32069
+ const value = JSON.parse(readFileSync18(recordPath(stateDir, projectId), "utf8"));
31727
32070
  if (typeof value.daemonPid !== "number" || typeof value.socketPath !== "string" || typeof value.generation !== "string") return null;
31728
32071
  return {
31729
32072
  projectId,
@@ -31740,7 +32083,7 @@ function readDaemonRecord(stateDir, projectId) {
31740
32083
  }
31741
32084
  function readDaemonExitBreadcrumb(stateDir, projectId) {
31742
32085
  try {
31743
- const value = JSON.parse(readFileSync16(`${recordPath(stateDir, projectId)}.exit`, "utf8"));
32086
+ const value = JSON.parse(readFileSync18(`${recordPath(stateDir, projectId)}.exit`, "utf8"));
31744
32087
  if (typeof value.generation !== "string" || typeof value.reason !== "string") return null;
31745
32088
  return {
31746
32089
  generation: value.generation,
@@ -31790,7 +32133,7 @@ async function stopCodexAppServerDaemon(stateDir, projectId, timeoutMs = 1e4) {
31790
32133
  }
31791
32134
  function forkDaemon(options) {
31792
32135
  const { stateDir, projectId } = options;
31793
- mkdirSync13(daemonDir(stateDir), { recursive: true });
32136
+ mkdirSync15(daemonDir(stateDir), { recursive: true });
31794
32137
  const record = recordPath(stateDir, projectId);
31795
32138
  try {
31796
32139
  unlinkSync3(record);
@@ -31985,7 +32328,7 @@ var init_codex_app_server_host = __esm({
31985
32328
  }
31986
32329
  if (process.platform !== "win32") {
31987
32330
  const stale = codexAppServerSocketPath(options.stateDir, options.projectId);
31988
- if (existsSync7(stale) && !liveDaemonRecord(options.stateDir, options.projectId)) {
32331
+ if (existsSync9(stale) && !liveDaemonRecord(options.stateDir, options.projectId)) {
31989
32332
  try {
31990
32333
  unlinkSync3(stale);
31991
32334
  } catch {
@@ -32005,7 +32348,7 @@ var init_codex_app_server_host = __esm({
32005
32348
  });
32006
32349
 
32007
32350
  // packages/server/src/backend/claude-quota.ts
32008
- import { join as join22 } from "node:path";
32351
+ import { join as join25 } from "node:path";
32009
32352
  import { homedir as homedir9, platform } from "node:os";
32010
32353
  import { createHash as createHash10 } from "node:crypto";
32011
32354
  import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
@@ -32013,7 +32356,7 @@ import { execFile as execFile3 } from "node:child_process";
32013
32356
  import { promisify as promisify3 } from "node:util";
32014
32357
  function claudeConfigDir() {
32015
32358
  const override = process.env.CLAUDE_CONFIG_DIR;
32016
- return override && override.trim() ? override : join22(homedir9(), ".claude");
32359
+ return override && override.trim() ? override : join25(homedir9(), ".claude");
32017
32360
  }
32018
32361
  function tokenFromCredentialsJson(raw2) {
32019
32362
  let doc;
@@ -32042,7 +32385,7 @@ async function readKeychainToken() {
32042
32385
  }
32043
32386
  async function readAccessToken(configDir) {
32044
32387
  try {
32045
- const fromFile = tokenFromCredentialsJson(await readFile(join22(configDir, ".credentials.json"), "utf8"));
32388
+ const fromFile = tokenFromCredentialsJson(await readFile(join25(configDir, ".credentials.json"), "utf8"));
32046
32389
  if (fromFile) return fromFile;
32047
32390
  } catch {
32048
32391
  }
@@ -32116,8 +32459,8 @@ function retryAtFrom(res, now) {
32116
32459
  function cachePaths(cacheDir, configDir) {
32117
32460
  const profile = createHash10("sha256").update(configDir).digest("hex").slice(0, 12);
32118
32461
  return {
32119
- data: join22(cacheDir, `claude-${profile}.json`),
32120
- lock: join22(cacheDir, `claude-${profile}.lock`)
32462
+ data: join25(cacheDir, `claude-${profile}.json`),
32463
+ lock: join25(cacheDir, `claude-${profile}.lock`)
32121
32464
  };
32122
32465
  }
32123
32466
  async function readShared(path3) {
@@ -32329,7 +32672,7 @@ function refreshSharedInBackground(paths, claudeBin, deps, now) {
32329
32672
  async function refreshClaudeQuotaInBackground(claudeBin = "claude", deps = {}) {
32330
32673
  const now = (deps.now ?? Date.now)();
32331
32674
  const configDir = claudeConfigDir();
32332
- const cacheDir = deps.cacheDir ?? join22(frizzRoots().cache, "quota-cache");
32675
+ const cacheDir = deps.cacheDir ?? join25(frizzRoots().cache, "quota-cache");
32333
32676
  try {
32334
32677
  await mkdir(cacheDir, { recursive: true, mode: 448 });
32335
32678
  } catch {
@@ -32343,7 +32686,7 @@ async function refreshClaudeQuotaInBackground(claudeBin = "claude", deps = {}) {
32343
32686
  async function readClaudeQuota(claudeBin = "claude", deps = {}, options = {}) {
32344
32687
  const now = (deps.now ?? Date.now)();
32345
32688
  const configDir = claudeConfigDir();
32346
- const cacheDir = deps.cacheDir ?? join22(frizzRoots().cache, "quota-cache");
32689
+ const cacheDir = deps.cacheDir ?? join25(frizzRoots().cache, "quota-cache");
32347
32690
  const paths = cachePaths(cacheDir, configDir);
32348
32691
  try {
32349
32692
  await mkdir(cacheDir, { recursive: true, mode: 448 });
@@ -32450,19 +32793,19 @@ var init_claude_quota = __esm({
32450
32793
  });
32451
32794
 
32452
32795
  // packages/server/src/backend/auth-status.ts
32453
- import { join as join23 } from "node:path";
32796
+ import { join as join26 } from "node:path";
32454
32797
  import { homedir as homedir10, platform as platform2 } from "node:os";
32455
- import { readFileSync as readFileSync17, statSync as statSync10 } from "node:fs";
32798
+ import { readFileSync as readFileSync19, statSync as statSync11 } from "node:fs";
32456
32799
  import { execFile as execFile4 } from "node:child_process";
32457
32800
  import { promisify as promisify4 } from "node:util";
32458
32801
  function claudeConfigDir2() {
32459
32802
  const override = process.env.CLAUDE_CONFIG_DIR;
32460
- return override && override.trim() ? override : join23(homedir10(), ".claude");
32803
+ return override && override.trim() ? override : join26(homedir10(), ".claude");
32461
32804
  }
32462
32805
  function claudeFileState(configDir) {
32463
32806
  let raw2;
32464
32807
  try {
32465
- raw2 = readFileSync17(join23(configDir, ".credentials.json"), "utf8");
32808
+ raw2 = readFileSync19(join26(configDir, ".credentials.json"), "utf8");
32466
32809
  } catch (err) {
32467
32810
  return err.code === "ENOENT" ? "absent" : "error";
32468
32811
  }
@@ -32495,7 +32838,7 @@ function readCodexAuthState(codexHome = defaultCodexHome()) {
32495
32838
  if (process.env.OPENAI_API_KEY || process.env.CODEX_API_KEY || process.env.CODEX_ACCESS_TOKEN) return "authed";
32496
32839
  let raw2;
32497
32840
  try {
32498
- raw2 = readFileSync17(join23(codexHome, "auth.json"), "utf8");
32841
+ raw2 = readFileSync19(join26(codexHome, "auth.json"), "utf8");
32499
32842
  } catch (err) {
32500
32843
  return err.code === "ENOENT" ? "signed-out" : "unknown";
32501
32844
  }
@@ -32515,7 +32858,7 @@ function readCodexAuthState(codexHome = defaultCodexHome()) {
32515
32858
  function readCodexAccountId(codexHome = defaultCodexHome()) {
32516
32859
  if (process.env.OPENAI_API_KEY || process.env.CODEX_API_KEY || process.env.CODEX_ACCESS_TOKEN) return void 0;
32517
32860
  try {
32518
- const doc = JSON.parse(readFileSync17(join23(codexHome, "auth.json"), "utf8"));
32861
+ const doc = JSON.parse(readFileSync19(join26(codexHome, "auth.json"), "utf8"));
32519
32862
  if (!doc || typeof doc !== "object") return void 0;
32520
32863
  const tokens = doc.tokens;
32521
32864
  if (!tokens || typeof tokens !== "object") return void 0;
@@ -32574,12 +32917,12 @@ function asEmail(value) {
32574
32917
  }
32575
32918
  function claudeAccountFile() {
32576
32919
  const override = process.env.CLAUDE_CONFIG_DIR;
32577
- return override && override.trim() ? join23(override, ".claude.json") : join23(homedir10(), ".claude.json");
32920
+ return override && override.trim() ? join26(override, ".claude.json") : join26(homedir10(), ".claude.json");
32578
32921
  }
32579
32922
  function readClaudeAccountEmail(path3 = claudeAccountFile()) {
32580
32923
  let stat2;
32581
32924
  try {
32582
- stat2 = statSync10(path3);
32925
+ stat2 = statSync11(path3);
32583
32926
  } catch {
32584
32927
  return void 0;
32585
32928
  }
@@ -32587,7 +32930,7 @@ function readClaudeAccountEmail(path3 = claudeAccountFile()) {
32587
32930
  if (memo3 && memo3.path === path3 && memo3.mtimeMs === stat2.mtimeMs && memo3.size === stat2.size) return memo3.email;
32588
32931
  let email;
32589
32932
  try {
32590
- const doc = JSON.parse(readFileSync17(path3, "utf8"));
32933
+ const doc = JSON.parse(readFileSync19(path3, "utf8"));
32591
32934
  email = asEmail(doc?.oauthAccount?.emailAddress);
32592
32935
  } catch {
32593
32936
  email = void 0;
@@ -32598,7 +32941,7 @@ function readClaudeAccountEmail(path3 = claudeAccountFile()) {
32598
32941
  function readCodexAccountEmail(codexHome = defaultCodexHome()) {
32599
32942
  let doc;
32600
32943
  try {
32601
- doc = JSON.parse(readFileSync17(join23(codexHome, "auth.json"), "utf8"));
32944
+ doc = JSON.parse(readFileSync19(join26(codexHome, "auth.json"), "utf8"));
32602
32945
  } catch {
32603
32946
  return void 0;
32604
32947
  }
@@ -32724,7 +33067,7 @@ var init_codex_execution_health = __esm({
32724
33067
 
32725
33068
  // packages/server/src/backend/codex-app-server.ts
32726
33069
  import { createHash as createHash11, randomUUID as randomUUID11 } from "node:crypto";
32727
- import { existsSync as existsSync8 } from "node:fs";
33070
+ import { existsSync as existsSync10 } from "node:fs";
32728
33071
  import { StringDecoder as StringDecoder3 } from "node:string_decoder";
32729
33072
  function selectCodexHostKind(flagValue, platform3, hasSpawn) {
32730
33073
  if (hasSpawn) return "direct";
@@ -35174,7 +35517,7 @@ var init_codex_app_server = __esm({
35174
35517
  * external rollout may legitimately live somewhere else.
35175
35518
  */
35176
35519
  resumeCwdOverride(row) {
35177
- if (existsSync8(row.cwd)) return {};
35520
+ if (existsSync10(row.cwd)) return {};
35178
35521
  return { cwd: this.options.projectDir };
35179
35522
  }
35180
35523
  recordResumedCwd(row, override) {
@@ -35996,17 +36339,17 @@ var init_codex_app_server = __esm({
35996
36339
  });
35997
36340
 
35998
36341
  // packages/server/src/backend/codex-quota.ts
35999
- import { join as join24 } from "node:path";
36000
- import { readdirSync as readdirSync7, statSync as statSync11, openSync as openSync12, readSync as readSync6, fstatSync, closeSync as closeSync11 } from "node:fs";
36342
+ import { join as join27 } from "node:path";
36343
+ import { readdirSync as readdirSync8, statSync as statSync12, openSync as openSync13, readSync as readSync6, fstatSync, closeSync as closeSync12 } from "node:fs";
36001
36344
  import { spawn as spawn4 } from "node:child_process";
36002
36345
  function sessionsDir2(codexHome) {
36003
- return join24(codexHome, "sessions");
36346
+ return join27(codexHome, "sessions");
36004
36347
  }
36005
36348
  function newestRollouts(dir, out, budget) {
36006
36349
  if (budget.n <= 0) return;
36007
36350
  let entries2;
36008
36351
  try {
36009
- entries2 = readdirSync7(dir, { withFileTypes: true });
36352
+ entries2 = readdirSync8(dir, { withFileTypes: true });
36010
36353
  } catch {
36011
36354
  return;
36012
36355
  }
@@ -36014,18 +36357,18 @@ function newestRollouts(dir, out, budget) {
36014
36357
  const files = entries2.filter((e14) => e14.isFile() && e14.name.startsWith("rollout-") && e14.name.endsWith(".jsonl")).map((e14) => e14.name).sort(descByName2);
36015
36358
  for (const d of dirs) {
36016
36359
  if (budget.n <= 0) return;
36017
- newestRollouts(join24(dir, d), out, budget);
36360
+ newestRollouts(join27(dir, d), out, budget);
36018
36361
  }
36019
36362
  for (const f of files) {
36020
36363
  if (budget.n <= 0) return;
36021
- out.push(join24(dir, f));
36364
+ out.push(join27(dir, f));
36022
36365
  budget.n--;
36023
36366
  }
36024
36367
  }
36025
36368
  function readTail(path3) {
36026
36369
  let fd2;
36027
36370
  try {
36028
- fd2 = openSync12(path3, "r");
36371
+ fd2 = openSync13(path3, "r");
36029
36372
  const size = fstatSync(fd2).size;
36030
36373
  const start = Math.max(0, size - TAIL_BYTES);
36031
36374
  const len = size - start;
@@ -36042,7 +36385,7 @@ function readTail(path3) {
36042
36385
  } finally {
36043
36386
  if (fd2 !== void 0) {
36044
36387
  try {
36045
- closeSync11(fd2);
36388
+ closeSync12(fd2);
36046
36389
  } catch {
36047
36390
  }
36048
36391
  }
@@ -36090,7 +36433,7 @@ function readCodexQuotaFromRollouts(codexHome = defaultCodexHome()) {
36090
36433
  newestRollouts(sessionsDir2(codexHome), rollouts, { n: 8 });
36091
36434
  const byMtime = rollouts.map((path3) => {
36092
36435
  try {
36093
- return { path: path3, mtimeMs: statSync11(path3).mtimeMs };
36436
+ return { path: path3, mtimeMs: statSync12(path3).mtimeMs };
36094
36437
  } catch {
36095
36438
  return void 0;
36096
36439
  }
@@ -36289,25 +36632,15 @@ var init_quota = __esm({
36289
36632
  }
36290
36633
  });
36291
36634
 
36292
- // packages/server/src/local-path.ts
36293
- function normalizeLocalPath(path3, platform3 = process.platform) {
36294
- return platform3 === "win32" ? path3.replace(/^\/([a-zA-Z]:[\\/])/, "$1") : path3;
36295
- }
36296
- var init_local_path = __esm({
36297
- "packages/server/src/local-path.ts"() {
36298
- "use strict";
36299
- }
36300
- });
36301
-
36302
36635
  // packages/server/src/local-file.ts
36303
36636
  import { spawn as spawn5 } from "node:child_process";
36304
- import { existsSync as existsSync9, readFileSync as readFileSync18, realpathSync as realpathSync6, statSync as statSync12 } from "node:fs";
36637
+ import { existsSync as existsSync11, readFileSync as readFileSync20, realpathSync as realpathSync7, statSync as statSync13 } from "node:fs";
36305
36638
  import { homedir as homedir11 } from "node:os";
36306
- import { dirname as dirname9, isAbsolute as isAbsolute4, join as join25, resolve as resolve5, sep as sep2 } from "node:path";
36639
+ import { dirname as dirname11, isAbsolute as isAbsolute5, join as join28, resolve as resolve5, sep as sep2 } from "node:path";
36307
36640
  function isUnder(real, root) {
36308
36641
  let rootReal;
36309
36642
  try {
36310
- rootReal = realpathSync6(root);
36643
+ rootReal = realpathSync7(root);
36311
36644
  } catch {
36312
36645
  return false;
36313
36646
  }
@@ -36315,12 +36648,12 @@ function isUnder(real, root) {
36315
36648
  return real === rootReal || real.startsWith(rootReal.endsWith(sep2) ? rootReal : rootReal + sep2);
36316
36649
  }
36317
36650
  try {
36318
- const trusted2 = statSync12(rootReal, { bigint: true });
36651
+ const trusted2 = statSync13(rootReal, { bigint: true });
36319
36652
  if (!trusted2.isDirectory() || trusted2.ino === 0n) return false;
36320
36653
  for (let ancestor = real; ; ) {
36321
- const actual = statSync12(ancestor, { bigint: true });
36654
+ const actual = statSync13(ancestor, { bigint: true });
36322
36655
  if (actual.dev === trusted2.dev && actual.ino === trusted2.ino) return true;
36323
- const parent = dirname9(ancestor);
36656
+ const parent = dirname11(ancestor);
36324
36657
  if (parent === ancestor) return false;
36325
36658
  ancestor = parent;
36326
36659
  }
@@ -36330,16 +36663,16 @@ function isUnder(real, root) {
36330
36663
  }
36331
36664
  function resolveLocalFile(rawPath, roots) {
36332
36665
  rawPath = normalizeLocalPath(rawPath);
36333
- if (!isAbsolute4(rawPath)) throw new Error("Local path must be absolute");
36666
+ if (!isAbsolute5(rawPath)) throw new Error("Local path must be absolute");
36334
36667
  let real;
36335
36668
  try {
36336
- real = realpathSync6(rawPath);
36669
+ real = realpathSync7(rawPath);
36337
36670
  } catch {
36338
36671
  throw new Error("Local file was not found");
36339
36672
  }
36340
36673
  if (!roots.some((root) => isUnder(real, root))) throw new Error("Local file is outside Frizz's trusted roots");
36341
36674
  try {
36342
- if (!statSync12(real).isFile()) throw new Error("Local path is not a regular file");
36675
+ if (!statSync13(real).isFile()) throw new Error("Local path is not a regular file");
36343
36676
  } catch (error) {
36344
36677
  if (error instanceof Error && error.message === "Local path is not a regular file") throw error;
36345
36678
  throw new Error("Local file was not found");
@@ -36349,7 +36682,7 @@ function resolveLocalFile(rawPath, roots) {
36349
36682
  function resolveOpenableFile(raw2, projectDir, roots, home = homedir11()) {
36350
36683
  const trimmed = raw2.trim().replace(/:\d+(?::\d+)?$/, "");
36351
36684
  if (!trimmed) return null;
36352
- const abs = trimmed === "~" ? home : /^~[\/\\]/.test(trimmed) ? join25(home, trimmed.slice(2)) : isAbsolute4(trimmed) ? trimmed : resolve5(projectDir, trimmed);
36685
+ const abs = trimmed === "~" ? home : /^~[\/\\]/.test(trimmed) ? join28(home, trimmed.slice(2)) : isAbsolute5(trimmed) ? trimmed : resolve5(projectDir, trimmed);
36353
36686
  try {
36354
36687
  return resolveLocalFile(abs, roots);
36355
36688
  } catch {
@@ -36358,7 +36691,7 @@ function resolveOpenableFile(raw2, projectDir, roots, home = homedir11()) {
36358
36691
  }
36359
36692
  function readLocalTextFile(rawPath, roots) {
36360
36693
  const path3 = resolveLocalFile(rawPath, roots);
36361
- const bytes = readFileSync18(path3);
36694
+ const bytes = readFileSync20(path3);
36362
36695
  if (bytes.subarray(0, 8192).includes(0)) throw new Error("Local file is not a text file");
36363
36696
  if (bytes.length <= MARKDOWN_READ_LIMIT) return { path: path3, text: bytes.toString("utf8"), truncated: false };
36364
36697
  const head = bytes.subarray(0, MARKDOWN_READ_LIMIT);
@@ -36369,7 +36702,7 @@ function readLocalMarkdown(rawPath, roots) {
36369
36702
  if (!MARKDOWN_FILE_EXT.test(rawPath.trim())) throw new Error("Local file is not a Markdown file");
36370
36703
  const path3 = resolveLocalFile(rawPath, roots);
36371
36704
  if (!MARKDOWN_FILE_EXT.test(path3)) throw new Error("Local file is not a Markdown file");
36372
- const bytes = readFileSync18(path3);
36705
+ const bytes = readFileSync20(path3);
36373
36706
  if (bytes.length <= MARKDOWN_READ_LIMIT) return { path: path3, markdown: bytes.toString("utf8"), truncated: false };
36374
36707
  const head = bytes.subarray(0, MARKDOWN_READ_LIMIT);
36375
36708
  const lastBreak = head.lastIndexOf(10);
@@ -36404,10 +36737,10 @@ function localFileOpenCommand(path3, selected, options = {}) {
36404
36737
  if (selected === "finder") return { command: "explorer.exe", args: [`/select,${path3}`] };
36405
36738
  const editor = WINDOWS_EDITOR_EXE[selected];
36406
36739
  const env = options.env ?? process.env;
36407
- const exists = options.exists ?? existsSync9;
36740
+ const exists = options.exists ?? existsSync11;
36408
36741
  const localAppData = env.LOCALAPPDATA;
36409
36742
  if (localAppData) {
36410
- const exe2 = join25(localAppData, ...editor.exe);
36743
+ const exe2 = join28(localAppData, ...editor.exe);
36411
36744
  if (exists(exe2)) return { command: exe2, args: [path3] };
36412
36745
  }
36413
36746
  if (/["%\r\n]/u.test(path3)) throw new Error(`cannot hand ${path3} to the ${editor.shim} shim through cmd.exe`);
@@ -36445,7 +36778,7 @@ var init_local_file = __esm({
36445
36778
  });
36446
36779
 
36447
36780
  // packages/server/src/thread-links.ts
36448
- import { isAbsolute as isAbsolute5 } from "node:path";
36781
+ import { isAbsolute as isAbsolute6 } from "node:path";
36449
36782
  import { fileURLToPath as fileURLToPath2 } from "node:url";
36450
36783
  function threadLinkView(row) {
36451
36784
  return { id: row.id, kind: row.kind, label: row.label, target: row.target };
@@ -36461,7 +36794,7 @@ function resolveThreadLink(target, projectDir, roots) {
36461
36794
  const url = new URL(target);
36462
36795
  if (url.search || url.hash) throw new Error("File links must not contain a query or fragment");
36463
36796
  path3 = fileURLToPath2(url);
36464
- } else if (!isAbsolute5(target) && /^[a-z][a-z\d+.-]*:/i.test(target)) {
36797
+ } else if (!isAbsolute6(target) && /^[a-z][a-z\d+.-]*:/i.test(target)) {
36465
36798
  throw new Error("Register an HTTP(S) URL or a local file");
36466
36799
  }
36467
36800
  const resolved2 = resolveOpenableFile(path3, projectDir, roots);
@@ -36672,8 +37005,8 @@ var init_claude_model_upgrade = __esm({
36672
37005
 
36673
37006
  // packages/server/src/frizz.ts
36674
37007
  import { execFile as execFile6 } from "node:child_process";
36675
- import { lstatSync as lstatSync2, realpathSync as realpathSync7 } from "node:fs";
36676
- import { basename as basename5, dirname as dirname10, join as join26, resolve as resolve6 } from "node:path";
37008
+ import { lstatSync as lstatSync3, realpathSync as realpathSync8 } from "node:fs";
37009
+ import { basename as basename5, dirname as dirname12, join as join29, resolve as resolve6 } from "node:path";
36677
37010
  import { promisify as promisify5 } from "node:util";
36678
37011
  function frizzScriptsDir() {
36679
37012
  if (process.env.FRIZZ_SCRIPTS_DIR) return process.env.FRIZZ_SCRIPTS_DIR;
@@ -36681,12 +37014,12 @@ function frizzScriptsDir() {
36681
37014
  }
36682
37015
  function directFrizzRoot(projectDir) {
36683
37016
  try {
36684
- const projectRoot = realpathSync7(projectDir);
36685
- const path3 = join26(projectRoot, ".frizz");
36686
- const stat2 = lstatSync2(path3);
37017
+ const projectRoot = realpathSync8(projectDir);
37018
+ const path3 = join29(projectRoot, ".frizz");
37019
+ const stat2 = lstatSync3(path3);
36687
37020
  if (!stat2.isDirectory() || stat2.isSymbolicLink()) return null;
36688
- const real = realpathSync7(path3);
36689
- return dirname10(real) === projectRoot && basename5(real) === ".frizz" ? real : null;
37021
+ const real = realpathSync8(path3);
37022
+ return dirname12(real) === projectRoot && basename5(real) === ".frizz" ? real : null;
36690
37023
  } catch {
36691
37024
  return null;
36692
37025
  }
@@ -36696,7 +37029,7 @@ function frizzDirExists(projectDir) {
36696
37029
  }
36697
37030
  async function readBoard(projectDir, scriptsDir = frizzScriptsDir()) {
36698
37031
  if (!directFrizzRoot(projectDir)) throw new Error("unsafe or missing .frizz directory");
36699
- const { stdout } = await execFileP("node", [join26(scriptsDir, "index.mjs"), "--json"], {
37032
+ const { stdout } = await execFileP("node", [join29(scriptsDir, "index.mjs"), "--json"], {
36700
37033
  cwd: projectDir,
36701
37034
  env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir },
36702
37035
  maxBuffer: 32 * 1024 * 1024
@@ -36721,7 +37054,7 @@ async function readBoard(projectDir, scriptsDir = frizzScriptsDir()) {
36721
37054
  };
36722
37055
  }
36723
37056
  async function runThreadUpdate(projectDir, slug, args, scriptsDir = frizzScriptsDir()) {
36724
- await execFileP("node", [join26(scriptsDir, "thread-update.mjs"), slug, ...args], {
37057
+ await execFileP("node", [join29(scriptsDir, "thread-update.mjs"), slug, ...args], {
36725
37058
  cwd: projectDir,
36726
37059
  env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir }
36727
37060
  });
@@ -36855,12 +37188,12 @@ var init_awaiting = __esm({
36855
37188
  });
36856
37189
 
36857
37190
  // packages/server/src/backend/project-mcp-servers.ts
36858
- import { readFileSync as readFileSync19 } from "node:fs";
37191
+ import { readFileSync as readFileSync21 } from "node:fs";
36859
37192
  import { homedir as homedir12 } from "node:os";
36860
- import { join as join27 } from "node:path";
37193
+ import { join as join30 } from "node:path";
36861
37194
  function readJsonObject(path3) {
36862
37195
  try {
36863
- const parsed = JSON.parse(readFileSync19(path3, "utf8"));
37196
+ const parsed = JSON.parse(readFileSync21(path3, "utf8"));
36864
37197
  return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
36865
37198
  } catch {
36866
37199
  return void 0;
@@ -36953,15 +37286,15 @@ function projectMcpServers(cwd, options = {}) {
36953
37286
  const env = options.env ?? process.env;
36954
37287
  const home = options.home ?? homedir12();
36955
37288
  const configOverride = options.claudeConfigDir ?? (env.CLAUDE_CONFIG_DIR?.trim() ? env.CLAUDE_CONFIG_DIR.trim() : void 0);
36956
- const accountFile = configOverride ? join27(configOverride, ".claude.json") : join27(home, ".claude.json");
36957
- const userSettingsFile = join27(configOverride ?? join27(home, ".claude"), "settings.json");
37289
+ const accountFile = configOverride ? join30(configOverride, ".claude.json") : join30(home, ".claude.json");
37290
+ const userSettingsFile = join30(configOverride ?? join30(home, ".claude"), "settings.json");
36958
37291
  const account = readJsonObject(accountFile);
36959
37292
  const out = userScopeRemoteServers(account, cwd, env);
36960
- const declared = objectField(readJsonObject(join27(cwd, ".mcp.json")), "mcpServers");
37293
+ const declared = objectField(readJsonObject(join30(cwd, ".mcp.json")), "mcpServers");
36961
37294
  if (!declared) return out;
36962
37295
  const approval = collectApproval([
36963
- readJsonObject(join27(cwd, ".claude", "settings.json")),
36964
- readJsonObject(join27(cwd, ".claude", "settings.local.json")),
37296
+ readJsonObject(join30(cwd, ".claude", "settings.json")),
37297
+ readJsonObject(join30(cwd, ".claude", "settings.local.json")),
36965
37298
  readJsonObject(userSettingsFile),
36966
37299
  objectField(objectField(account, "projects"), cwd)
36967
37300
  ]);
@@ -36985,18 +37318,18 @@ var init_project_mcp_servers = __esm({
36985
37318
  });
36986
37319
 
36987
37320
  // packages/server/src/worker-plugin-dir.ts
36988
- import { existsSync as existsSync10 } from "node:fs";
36989
- import { dirname as dirname11, join as join28 } from "node:path";
37321
+ import { existsSync as existsSync12 } from "node:fs";
37322
+ import { dirname as dirname13, join as join31 } from "node:path";
36990
37323
  import { fileURLToPath as fileURLToPath3 } from "node:url";
36991
37324
  function resolveWorkerPluginDir(moduleUrl = import.meta.url, env = process.env) {
36992
37325
  const override = env.FRIZZ_WORKER_PLUGIN_DIR;
36993
- if (override && existsSync10(join28(override, ".claude-plugin", "plugin.json")))
37326
+ if (override && existsSync12(join31(override, ".claude-plugin", "plugin.json")))
36994
37327
  return override;
36995
- let current = dirname11(fileURLToPath3(moduleUrl));
37328
+ let current = dirname13(fileURLToPath3(moduleUrl));
36996
37329
  for (; ; ) {
36997
- const candidate = join28(current, "cc-worker");
36998
- if (existsSync10(join28(candidate, ".claude-plugin", "plugin.json"))) return candidate;
36999
- const parent = dirname11(current);
37330
+ const candidate = join31(current, "cc-worker");
37331
+ if (existsSync12(join31(candidate, ".claude-plugin", "plugin.json"))) return candidate;
37332
+ const parent = dirname13(current);
37000
37333
  if (parent === current) return void 0;
37001
37334
  current = parent;
37002
37335
  }
@@ -37144,9 +37477,9 @@ reasoning around the ask, never a copy of it (see Questions for the human).
37144
37477
  **AT EVERY LATER REST, SAY WHERE EACH OLD QUESTION STANDS.** A question still open from an EARLIER rest
37145
37478
  is not your new rest's sign-off, and frizz does NOT redraw its card under your new handoff \u2014 it stays
37146
37479
  where you asked it. So a later rest either NAMES each one you still need under \`questions:\` in an
37147
- \` \`\`\`awaiting \` fence \u2014 its card is then drawn at this rest, under your fence \u2014 or WITHDRAWS it with
37148
- \`unask\`. A rest that does neither is bumped, and so is any \` \`\`\`awaiting \` fence that leaves an open
37149
- question out, at whichever rest it lands.
37480
+ \` \`\`\`awaiting \` fence \u2014 its card is then drawn at this rest, under your fence's prose \u2014 or WITHDRAWS
37481
+ it with \`unask\`. A rest that does neither is bumped, and so is any \` \`\`\`awaiting \` fence that leaves
37482
+ an open question out, at whichever rest it lands.
37150
37483
 
37151
37484
  Use at most ONE fenced signal block, at the very END (a question's PLACEMENT marker is not a signal
37152
37485
  block \u2014 see Questions for the human). The fence language is the state; the body is the card the human
@@ -37267,7 +37600,7 @@ exactly ONE of them.
37267
37600
  title: Sign in to npm so the release can publish
37268
37601
  steps:
37269
37602
  - Run \`npm login --auth-type=web\` in a terminal on this machine.
37270
- - Approve the browser prompt with the maintainer account.
37603
+ - Approve the browser prompt with the maintainer account; if no prompt opens, sign in at [npmjs.com/login](https://www.npmjs.com/login) and run the command again.
37271
37604
  ---
37272
37605
  The publish step runs as the maintainer, and no token for that account is available to this thread.
37273
37606
  \`\`\`
@@ -37352,12 +37685,34 @@ exactly ONE of them.
37352
37685
  \`Done\`, the same as anything they type; anything else they need to tell you \u2014 a step that failed,
37353
37686
  the account they used \u2014 comes as a message of their own. An act is not a decision: never ask
37354
37687
  WHETHER they will do it, and never call \`done\` while it is still owed.
37688
+ **EVERY STEP IS CLICKABLE AND COMPLETE \u2014 A STEP THAT MAKES THE HUMAN GO LOOKING IS A BROKEN STEP.**
37689
+ The steps are the most actionable thing you hand over, so write each one to be DONE, not
37690
+ researched: every page it names is a real Markdown link to that exact page (the settings screen,
37691
+ the audit log, the PR, the release run \u2014 never "in the dashboard" or "on GitHub"); every file is a
37692
+ real link; every command is a code span ready to paste; and every value the act needs \u2014 the account,
37693
+ the date range, the token or secret name, the exact button \u2014 is written into the step. Steps render
37694
+ as Markdown, so links click. Bad: \`Open the Cloudflare dashboard and check the audit log for the
37695
+ upload.\` Good: \`Open the [Frizz account audit log](https://dash.cloudflare.com/<account-id>/audit-log),
37696
+ filter to 2026-10-05 18:00\u201319:00 UTC, and note the actor and IP on the frizz-relay upload.\`
37697
+ Fill in every id you hold; when you cannot know a URL, link the nearest page you can and say what to
37698
+ click there. A step is cut at 500 characters, so keep each link inside that.
37699
+ (Maintainer 2026-10-08, after a security handoff listed seven to-dos with no link in any of them:
37700
+ *"Anytime you stop with a to-do block for the user, it needs to include clickable links. It needs to
37701
+ be as actionable as possible."*)
37702
+ **A VALUE ONLY THE HUMAN HOLDS IS NOT A STEP** \u2014 a 2FA code, a token, a password a command needs.
37703
+ Ask for it with \`mcp__frizz__secret\`: the human pastes it into a masked card, from any device, and
37704
+ it is served from memory through a private pipe whose path the tool returns. The path reads ONCE:
37705
+ use it inside the command (\`--otp "$(cat '<path>')"\`) and never print it. It is a registered
37706
+ question: name it under \`questions:\` at later rests.
37355
37707
  - \`questions:\` \u2014 your registered questions you are STILL waiting on, by id: \`questions: [qst_ab12cd34]\`.
37356
37708
  A fence beside open questions names EVERY one of them \u2014 withdraw any you no longer need with
37357
37709
  \`mcp__frizz__unask\` first \u2014 or frizz refuses the park and lists what it left out. Each named card is
37358
37710
  drawn at THIS rest, under your fence; to set it inside your prose instead, add its placement marker
37359
- (see Questions for the human). Like \`steps:\`, questions name the human as the wait: no other name
37360
- and no \`for:\` needed, and the thread stays in their queue.
37711
+ (see Questions for the human). A fence that names questions draws NO awaiting card of its own: the
37712
+ question cards are the rest's ending, its prose under \`---\` reads as plain handoff text, and the
37713
+ work it also names is listed beside the human's prompt box (a fence with \`steps:\` keeps its card).
37714
+ Like \`steps:\`, questions name the human as the wait: no other name and no \`for:\` needed, and the
37715
+ thread stays in their queue.
37361
37716
  - **REGISTERING IS NOT PARKING, AND PARKING IS NOT REGISTERING.** Your shells, sub-agents, timers
37362
37717
  and PR watchers are watched AUTOMATICALLY, fence or no fence \u2014 frizz wakes you when one finishes,
37363
37718
  every time. The fence only declares that you have STOPPED, names which of them you stopped for,
@@ -38108,26 +38463,26 @@ checks. Depth scales with blast radius and yields to the project's conventions.`
38108
38463
  });
38109
38464
 
38110
38465
  // packages/server/src/backend/acp-agents.ts
38111
- import { accessSync as accessSync3, constants, statSync as statSync13 } from "node:fs";
38112
- import { delimiter as delimiter2, isAbsolute as isAbsolute6, join as join29 } from "node:path";
38466
+ import { accessSync as accessSync3, constants as constants2, statSync as statSync14 } from "node:fs";
38467
+ import { delimiter as delimiter2, isAbsolute as isAbsolute7, join as join32 } from "node:path";
38113
38468
  function isExecutableFile(path3) {
38114
38469
  try {
38115
- if (!statSync13(path3).isFile()) return false;
38116
- if (process.platform !== "win32") accessSync3(path3, constants.X_OK);
38470
+ if (!statSync14(path3).isFile()) return false;
38471
+ if (process.platform !== "win32") accessSync3(path3, constants2.X_OK);
38117
38472
  return true;
38118
38473
  } catch {
38119
38474
  return false;
38120
38475
  }
38121
38476
  }
38122
38477
  function findOnPath(command, env = process.env) {
38123
- if (isAbsolute6(command)) return isExecutableFile(command) ? command : void 0;
38478
+ if (isAbsolute7(command)) return isExecutableFile(command) ? command : void 0;
38124
38479
  const dirs = (env.PATH ?? env.Path ?? "").split(delimiter2).filter(Boolean);
38125
38480
  const exts = process.platform === "win32" ? ["", ...(env.PATHEXT ?? ".EXE;.CMD;.BAT").split(";")] : [""];
38126
38481
  for (const dir of dirs) {
38127
38482
  for (const ext of exts) {
38128
- const candidate = join29(dir, command + ext.toLowerCase());
38483
+ const candidate = join32(dir, command + ext.toLowerCase());
38129
38484
  if (isExecutableFile(candidate)) return candidate;
38130
- if (ext && isExecutableFile(join29(dir, command + ext))) return join29(dir, command + ext);
38485
+ if (ext && isExecutableFile(join32(dir, command + ext))) return join32(dir, command + ext);
38131
38486
  }
38132
38487
  }
38133
38488
  return void 0;
@@ -39144,8 +39499,8 @@ var init_claude_agent_broker_bridge = __esm({
39144
39499
  });
39145
39500
 
39146
39501
  // packages/server/src/dispatch.ts
39147
- import { closeSync as closeSync12, constants as constants2, existsSync as existsSync11, fstatSync as fstatSync2, lstatSync as lstatSync3, openSync as openSync13, readFileSync as readFileSync20, realpathSync as realpathSync8, statSync as statSync14, writeFileSync as writeFileSync11, mkdirSync as mkdirSync14, rmSync as rmSync9 } from "node:fs";
39148
- import { basename as basename6, join as join30, dirname as dirname12 } from "node:path";
39502
+ import { closeSync as closeSync13, constants as constants3, existsSync as existsSync13, fstatSync as fstatSync2, lstatSync as lstatSync4, openSync as openSync14, readFileSync as readFileSync22, realpathSync as realpathSync9, statSync as statSync15, writeFileSync as writeFileSync13, mkdirSync as mkdirSync16, rmSync as rmSync10 } from "node:fs";
39503
+ import { basename as basename6, join as join33, dirname as dirname14 } from "node:path";
39149
39504
  import { createHash as createHash12, randomUUID as randomUUID13 } from "node:crypto";
39150
39505
  function fallbackTitle(prompt) {
39151
39506
  const firstLine2 = prompt.trim().split("\n", 1)[0].trim();
@@ -39164,7 +39519,7 @@ function fallbackTitle(prompt) {
39164
39519
  }
39165
39520
  function resolveSlug(frizzDir, base, taken) {
39166
39521
  base = ThreadSlug.parse(base);
39167
- const isTaken = (slug) => existsSync11(join30(frizzDir, `${slug}.md`)) || (taken?.(slug) ?? false);
39522
+ const isTaken = (slug) => existsSync13(join33(frizzDir, `${slug}.md`)) || (taken?.(slug) ?? false);
39168
39523
  if (!isTaken(base)) return base;
39169
39524
  for (let n = 2; ; n++) {
39170
39525
  const suffix = `-${n}`;
@@ -39180,29 +39535,29 @@ function resolveLegacyThreadFile(projectDir, value) {
39180
39535
  const parsed = ThreadSlug.safeParse(value);
39181
39536
  if (!parsed.success) return null;
39182
39537
  try {
39183
- const projectRoot = realpathSync8(projectDir);
39184
- const frizzPath = join30(projectRoot, ".frizz");
39185
- const frizzStat = lstatSync3(frizzPath);
39538
+ const projectRoot = realpathSync9(projectDir);
39539
+ const frizzPath = join33(projectRoot, ".frizz");
39540
+ const frizzStat = lstatSync4(frizzPath);
39186
39541
  if (!frizzStat.isDirectory() || frizzStat.isSymbolicLink()) return null;
39187
- const realFrizz = realpathSync8(frizzPath);
39188
- if (dirname12(realFrizz) !== projectRoot || basename6(realFrizz) !== ".frizz") return null;
39189
- const path3 = join30(realFrizz, `${parsed.data}.md`);
39190
- const before = lstatSync3(path3);
39542
+ const realFrizz = realpathSync9(frizzPath);
39543
+ if (dirname14(realFrizz) !== projectRoot || basename6(realFrizz) !== ".frizz") return null;
39544
+ const path3 = join33(realFrizz, `${parsed.data}.md`);
39545
+ const before = lstatSync4(path3);
39191
39546
  if (!before.isFile() || before.isSymbolicLink()) return null;
39192
- const realPath = realpathSync8(path3);
39193
- if (dirname12(realPath) !== realFrizz || basename6(realPath) !== `${parsed.data}.md`) return null;
39547
+ const realPath = realpathSync9(path3);
39548
+ if (dirname14(realPath) !== realFrizz || basename6(realPath) !== `${parsed.data}.md`) return null;
39194
39549
  let contents;
39195
39550
  let openedBefore;
39196
39551
  let openedAfter;
39197
- const fd2 = openSync13(path3, constants2.O_RDONLY | constants2.O_NOFOLLOW);
39552
+ const fd2 = openSync14(path3, constants3.O_RDONLY | constants3.O_NOFOLLOW);
39198
39553
  try {
39199
39554
  openedBefore = fstatSync2(fd2);
39200
- contents = readFileSync20(fd2);
39555
+ contents = readFileSync22(fd2);
39201
39556
  openedAfter = fstatSync2(fd2);
39202
39557
  } finally {
39203
- closeSync12(fd2);
39558
+ closeSync13(fd2);
39204
39559
  }
39205
- const after = lstatSync3(path3);
39560
+ const after = lstatSync4(path3);
39206
39561
  if (before.dev !== openedBefore.dev || before.ino !== openedBefore.ino || openedBefore.dev !== openedAfter.dev || openedBefore.ino !== openedAfter.ino || openedBefore.size !== openedAfter.size || openedBefore.mtimeMs !== openedAfter.mtimeMs || openedBefore.ctimeMs !== openedAfter.ctimeMs || after.dev !== openedAfter.dev || after.ino !== openedAfter.ino || after.size !== openedAfter.size || after.mtimeMs !== openedAfter.mtimeMs || after.ctimeMs !== openedAfter.ctimeMs || !openedAfter.isFile() || !after.isFile() || after.isSymbolicLink()) {
39207
39562
  return null;
39208
39563
  }
@@ -39230,17 +39585,17 @@ function boardAuthorizesAdoption(board, slug) {
39230
39585
  return !board.errorItems.some((item) => item.file === `${slug}.md`);
39231
39586
  }
39232
39587
  function ensureSafeDirectDirectory(parent, name) {
39233
- const path3 = join30(parent, name);
39588
+ const path3 = join33(parent, name);
39234
39589
  try {
39235
- mkdirSync14(path3);
39590
+ mkdirSync16(path3);
39236
39591
  } catch (error) {
39237
39592
  const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
39238
39593
  if (code !== "EEXIST") throw error;
39239
39594
  }
39240
- const stat2 = lstatSync3(path3);
39595
+ const stat2 = lstatSync4(path3);
39241
39596
  if (!stat2.isDirectory() || stat2.isSymbolicLink()) throw new Error("unsafe project directory");
39242
- const real = realpathSync8(path3);
39243
- if (dirname12(real) !== parent || basename6(real) !== name) throw new Error("unsafe project directory");
39597
+ const real = realpathSync9(path3);
39598
+ if (dirname14(real) !== parent || basename6(real) !== name) throw new Error("unsafe project directory");
39244
39599
  return real;
39245
39600
  }
39246
39601
  function scratchDirRelPath(sessionId) {
@@ -39248,7 +39603,7 @@ function scratchDirRelPath(sessionId) {
39248
39603
  }
39249
39604
  function writeScratchDir(projectDir, sessionId) {
39250
39605
  if (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/.test(sessionId)) throw new Error("invalid session id");
39251
- const projectRoot = realpathSync8(projectDir);
39606
+ const projectRoot = realpathSync9(projectDir);
39252
39607
  const frizzDir = ensureSafeDirectDirectory(projectRoot, ".frizz");
39253
39608
  const threadsDir = ensureSafeDirectDirectory(frizzDir, "threads");
39254
39609
  ensureSafeDirectDirectory(threadsDir, sessionId);
@@ -39260,8 +39615,8 @@ function loadWorkerPrompt(kind = "claude") {
39260
39615
  function monitorScriptsDir() {
39261
39616
  const plugin = workerPluginDir();
39262
39617
  if (!plugin) return void 0;
39263
- const dir = join30(plugin, "skills", "gh", "scripts");
39264
- return existsSync11(join30(dir, "ci-watch.mjs")) ? dir : void 0;
39618
+ const dir = join33(plugin, "skills", "gh", "scripts");
39619
+ return existsSync13(join33(dir, "ci-watch.mjs")) ? dir : void 0;
39265
39620
  }
39266
39621
  function codexScratchpadHookConfig(hookScript, sessionId) {
39267
39622
  if (!hookScript || !sessionId) return {};
@@ -39273,7 +39628,7 @@ function codexScratchpadHookConfig(hookScript, sessionId) {
39273
39628
  }
39274
39629
  ]
39275
39630
  });
39276
- const bashBackgroundHook = join30(dirname12(hookScript), "bash-background.mjs");
39631
+ const bashBackgroundHook = join33(dirname14(hookScript), "bash-background.mjs");
39277
39632
  return {
39278
39633
  bypass_hook_trust: true,
39279
39634
  hooks: {
@@ -39299,7 +39654,7 @@ function codexScratchpadHookConfig(hookScript, sessionId) {
39299
39654
  }
39300
39655
  function scratchpadHookScript() {
39301
39656
  const plugin = workerPluginDir();
39302
- return plugin ? join30(plugin, "hooks", "scratchpad.mjs") : void 0;
39657
+ return plugin ? join33(plugin, "hooks", "scratchpad.mjs") : void 0;
39303
39658
  }
39304
39659
  function composePrompt(sessionId, prompt, kind = "claude") {
39305
39660
  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.";
@@ -39315,12 +39670,12 @@ function scratchpadOrientation(sessionId, kind = "claude") {
39315
39670
  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.`;
39316
39671
  }
39317
39672
  function frizzConfigBlock(projectDir) {
39318
- const path3 = join30(projectDir, "FRIZZ.md");
39673
+ const path3 = join33(projectDir, "FRIZZ.md");
39319
39674
  let body;
39320
39675
  try {
39321
- const st2 = statSync14(path3);
39676
+ const st2 = statSync15(path3);
39322
39677
  if (!st2.isFile() || st2.size > FRIZZ_MD_MAX_BYTES) return "";
39323
- body = readFileSync20(path3, "utf8").trim();
39678
+ body = readFileSync22(path3, "utf8").trim();
39324
39679
  } catch {
39325
39680
  return "";
39326
39681
  }
@@ -39350,17 +39705,17 @@ function effectivePermissionMode(kind, mode) {
39350
39705
  }
39351
39706
  function systemPromptFlags(sessionId, system) {
39352
39707
  if (!system) return [];
39353
- mkdirSync14(SYSTEM_PROMPT_DIR, { recursive: true });
39708
+ mkdirSync16(SYSTEM_PROMPT_DIR, { recursive: true });
39354
39709
  const path3 = systemPromptPath(sessionId);
39355
- writeFileSync11(path3, system);
39710
+ writeFileSync13(path3, system);
39356
39711
  return ["--append-system-prompt-file", path3];
39357
39712
  }
39358
39713
  function resolveFrizzMcp(target, moduleUrl = import.meta.url, env = process.env, slug) {
39359
39714
  const { stateDir, serverLock, projectId } = typeof target === "string" ? { stateDir: target } : target;
39360
39715
  const pluginDir = resolveWorkerPluginDir(moduleUrl, env);
39361
39716
  if (!pluginDir) return void 0;
39362
- const scriptPath = join30(pluginDir, "bin", FRIZZ_MCP.script);
39363
- if (!existsSync11(scriptPath)) return void 0;
39717
+ const scriptPath = join33(pluginDir, "bin", FRIZZ_MCP.script);
39718
+ if (!existsSync13(scriptPath)) return void 0;
39364
39719
  return {
39365
39720
  scriptPath,
39366
39721
  stateDir,
@@ -39441,12 +39796,12 @@ function buildClaudeResumeCommand(opts) {
39441
39796
  }
39442
39797
  function createDispatcher(deps) {
39443
39798
  const readBoardSource = deps.readBoard ?? readBoard;
39444
- const frizzDir = join30(deps.project.dir, ".frizz");
39799
+ const frizzDir = join33(deps.project.dir, ".frizz");
39445
39800
  const adoptionRuntime = deps.adoptionRuntime ?? productionRuntime;
39446
39801
  function cleanupPrewrites(built) {
39447
39802
  for (const path3 of new Set(built.prewrite.map((file) => file.path))) {
39448
39803
  try {
39449
- rmSync9(path3, { force: true });
39804
+ rmSync10(path3, { force: true });
39450
39805
  } catch {
39451
39806
  }
39452
39807
  }
@@ -39454,7 +39809,7 @@ function createDispatcher(deps) {
39454
39809
  function cleanupDispatchFiles(scratchRel, built, sessionId) {
39455
39810
  cleanupPrewrites(built);
39456
39811
  try {
39457
- rmSync9(join30(deps.project.dir, scratchRel), { force: true, recursive: true });
39812
+ rmSync10(join33(deps.project.dir, scratchRel), { force: true, recursive: true });
39458
39813
  } catch {
39459
39814
  }
39460
39815
  cleanupAdoptionSessionFiles(deps.project.dir, sessionId);
@@ -39943,11 +40298,11 @@ var init_dispatch = __esm({
39943
40298
 
39944
40299
  // packages/server/src/board.ts
39945
40300
  import {
39946
- realpathSync as realpathSync9,
40301
+ realpathSync as realpathSync10,
39947
40302
  watch as fsWatch
39948
40303
  } from "node:fs";
39949
40304
  import { homedir as homedir14 } from "node:os";
39950
- import { dirname as dirname13, join as join31 } from "node:path";
40305
+ import { dirname as dirname15, join as join34 } from "node:path";
39951
40306
  import watcher from "@parcel/watcher";
39952
40307
  function appServerTurnStalled(liveness, lastActivityAt, nowMs) {
39953
40308
  if (!liveness) return false;
@@ -39996,7 +40351,7 @@ function registeredLegacyFileIsTerminal(projectDir, slug) {
39996
40351
  return status === "done" || status === "dismissed";
39997
40352
  }
39998
40353
  function isBoardRelevantFrizzPath(roots, path3) {
39999
- return path3.endsWith(".md") && roots.has(dirname13(path3));
40354
+ return path3.endsWith(".md") && roots.has(dirname15(path3));
40000
40355
  }
40001
40356
  function futureSnooze(row, nowMs) {
40002
40357
  const parsed = SnoozeUntil.safeParse(row.snoozed_until);
@@ -40856,10 +41211,10 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
40856
41211
  if (parcelSub || stopped) return Promise.resolve();
40857
41212
  if (watchSetup) return watchSetup;
40858
41213
  const setup = (async () => {
40859
- const dir = join31(project.dir, ".frizz");
41214
+ const dir = join34(project.dir, ".frizz");
40860
41215
  const roots = /* @__PURE__ */ new Set([dir]);
40861
41216
  try {
40862
- roots.add(realpathSync9(dir));
41217
+ roots.add(realpathSync10(dir));
40863
41218
  } catch {
40864
41219
  }
40865
41220
  const next = await subscribe(
@@ -40871,7 +41226,7 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
40871
41226
  }
40872
41227
  if (events.some((event) => isBoardRelevantFrizzPath(roots, event.path))) scheduleRebuild();
40873
41228
  },
40874
- { ignore: FRIZZ_WATCH_IGNORED_DIRS.map((name) => join31(dir, name)) }
41229
+ { ignore: FRIZZ_WATCH_IGNORED_DIRS.map((name) => join34(dir, name)) }
40875
41230
  );
40876
41231
  if (stopped) {
40877
41232
  await next.unsubscribe();
@@ -43988,7 +44343,7 @@ var init_resume = __esm({
43988
44343
  });
43989
44344
 
43990
44345
  // packages/server/src/backend/claude.ts
43991
- import { join as join32 } from "node:path";
44346
+ import { join as join35 } from "node:path";
43992
44347
  function toolResultText2(content) {
43993
44348
  if (typeof content === "string") return content;
43994
44349
  if (!Array.isArray(content)) return "";
@@ -44007,7 +44362,7 @@ function parseClaudeLine(line) {
44007
44362
  const at2 = typeof rec.timestamp === "string" ? rec.timestamp : void 0;
44008
44363
  const out = [];
44009
44364
  if (rec.type === "assistant") {
44010
- const stop = typeof rec.message?.stop_reason === "string" ? rec.message.stop_reason : void 0;
44365
+ const stop2 = typeof rec.message?.stop_reason === "string" ? rec.message.stop_reason : void 0;
44011
44366
  const content = rec.message?.content;
44012
44367
  let lastText;
44013
44368
  if (Array.isArray(content)) {
@@ -44016,13 +44371,13 @@ function parseClaudeLine(line) {
44016
44371
  const b = block;
44017
44372
  if (b.type === "text" && typeof b.text === "string") {
44018
44373
  lastText = b.text;
44019
- out.push({ kind: "assistant-text", at: at2, text: b.text, final: stop === "end_turn" });
44374
+ out.push({ kind: "assistant-text", at: at2, text: b.text, final: stop2 === "end_turn" });
44020
44375
  } else if (b.type === "tool_use") {
44021
44376
  out.push({ kind: "tool-call", at: at2, id: typeof b.id === "string" ? b.id : "", name: typeof b.name === "string" ? b.name : "", input: b.input });
44022
44377
  }
44023
44378
  }
44024
44379
  }
44025
- if (stop === "end_turn") out.push({ kind: "turn-end", at: at2, finalText: lastText });
44380
+ if (stop2 === "end_turn") out.push({ kind: "turn-end", at: at2, finalText: lastText });
44026
44381
  return out;
44027
44382
  }
44028
44383
  if (rec.type === "user" && rec.isMeta !== true) {
@@ -44079,7 +44434,7 @@ function createClaudeBackend(opts) {
44079
44434
  return { argv, env: claudeWorkerEnvironment(), prewrite: [] };
44080
44435
  },
44081
44436
  transcriptPath(sessionId) {
44082
- return join32(opts.logDir, `${sessionId}.jsonl`);
44437
+ return join35(opts.logDir, `${sessionId}.jsonl`);
44083
44438
  },
44084
44439
  parseLine(line) {
44085
44440
  return parseClaudeLine(line);
@@ -44104,10 +44459,10 @@ var init_claude = __esm({
44104
44459
  });
44105
44460
 
44106
44461
  // packages/server/src/backend/acp-transcript.ts
44107
- import { appendFileSync as appendFileSync3, existsSync as existsSync13, mkdirSync as mkdirSync15, readFileSync as readFileSync21 } from "node:fs";
44108
- import { dirname as dirname14, join as join33 } from "node:path";
44462
+ import { appendFileSync as appendFileSync3, existsSync as existsSync15, mkdirSync as mkdirSync17, readFileSync as readFileSync23 } from "node:fs";
44463
+ import { dirname as dirname16, join as join36 } from "node:path";
44109
44464
  function acpTranscriptPath(stateDir, sessionId) {
44110
- return join33(stateDir, ACP_TRANSCRIPT_DIR, `${sessionId}.jsonl`);
44465
+ return join36(stateDir, ACP_TRANSCRIPT_DIR, `${sessionId}.jsonl`);
44111
44466
  }
44112
44467
  function parseAcpRecord(line) {
44113
44468
  if (!line.trim()) return void 0;
@@ -44308,8 +44663,8 @@ var init_acp_transcript = __esm({
44308
44663
  AcpTranscriptWriter = class {
44309
44664
  constructor(path3) {
44310
44665
  this.path = path3;
44311
- mkdirSync15(dirname14(path3), { recursive: true });
44312
- if (!existsSync13(path3)) appendFileSync3(path3, "");
44666
+ mkdirSync17(dirname16(path3), { recursive: true });
44667
+ if (!existsSync15(path3)) appendFileSync3(path3, "");
44313
44668
  }
44314
44669
  append(record) {
44315
44670
  appendFileSync3(this.path, JSON.stringify(record) + "\n");
@@ -44696,15 +45051,15 @@ var init_acp_rpc = __esm({
44696
45051
  import { spawn as spawn7 } from "node:child_process";
44697
45052
  import { createConnection as createConnection2 } from "node:net";
44698
45053
  import { createHash as createHash14, randomUUID as randomUUID15 } from "node:crypto";
44699
- import { existsSync as existsSync14, mkdirSync as mkdirSync16, readFileSync as readFileSync22, readdirSync as readdirSync8, unlinkSync as unlinkSync4 } from "node:fs";
44700
- import { join as join34 } from "node:path";
45054
+ import { existsSync as existsSync16, mkdirSync as mkdirSync18, readFileSync as readFileSync24, readdirSync as readdirSync9, unlinkSync as unlinkSync4 } from "node:fs";
45055
+ import { join as join37 } from "node:path";
44701
45056
  import { PassThrough as PassThrough3, Writable as Writable3 } from "node:stream";
44702
45057
  import { StringDecoder as StringDecoder5 } from "node:string_decoder";
44703
45058
  function daemonDir2(stateDir) {
44704
- return join34(stateDir, "acp-daemon");
45059
+ return join37(stateDir, "acp-daemon");
44705
45060
  }
44706
45061
  function acpDaemonRecordPath(stateDir, sessionId) {
44707
- return join34(daemonDir2(stateDir), `${sessionId}.json`);
45062
+ return join37(daemonDir2(stateDir), `${sessionId}.json`);
44708
45063
  }
44709
45064
  function acpDaemonSocketPath(stateDir, sessionId) {
44710
45065
  const key = createHash14("sha256").update(stateDir).update("\0").update(sessionId).digest("hex").slice(0, 16);
@@ -44720,7 +45075,7 @@ function pidAlive4(pid) {
44720
45075
  }
44721
45076
  function readAcpDaemonRecord(stateDir, sessionId) {
44722
45077
  try {
44723
- const value = JSON.parse(readFileSync22(acpDaemonRecordPath(stateDir, sessionId), "utf8"));
45078
+ const value = JSON.parse(readFileSync24(acpDaemonRecordPath(stateDir, sessionId), "utf8"));
44724
45079
  if (typeof value.daemonPid !== "number" || typeof value.socketPath !== "string" || typeof value.generation !== "string") return null;
44725
45080
  return {
44726
45081
  threadSlug: typeof value.threadSlug === "string" ? value.threadSlug : "",
@@ -44766,7 +45121,7 @@ async function stopAcpDaemon(stateDir, sessionId, timeoutMs = 1e4) {
44766
45121
  }
44767
45122
  function forkDaemon2(options) {
44768
45123
  const { stateDir, sessionId } = options;
44769
- mkdirSync16(daemonDir2(stateDir), { recursive: true });
45124
+ mkdirSync18(daemonDir2(stateDir), { recursive: true });
44770
45125
  const record = acpDaemonRecordPath(stateDir, sessionId);
44771
45126
  try {
44772
45127
  unlinkSync4(record);
@@ -44962,7 +45317,7 @@ var init_acp_host = __esm({
44962
45317
  }
44963
45318
  if (process.platform !== "win32") {
44964
45319
  const stale = acpDaemonSocketPath(stateDir, sessionId);
44965
- if (existsSync14(stale) && !liveAcpDaemonRecord(stateDir, sessionId)) {
45320
+ if (existsSync16(stale) && !liveAcpDaemonRecord(stateDir, sessionId)) {
44966
45321
  try {
44967
45322
  unlinkSync4(stale);
44968
45323
  } catch {
@@ -71654,7 +72009,7 @@ var init_claude_context_window = __esm({
71654
72009
  });
71655
72010
 
71656
72011
  // packages/server/src/backend/claude-agent-sdk.ts
71657
- import { delimiter as delimiter3, isAbsolute as isAbsolute8 } from "node:path";
72012
+ import { delimiter as delimiter3, isAbsolute as isAbsolute9 } from "node:path";
71658
72013
  function sanitizeProviderChildEnvironment(environment) {
71659
72014
  const sanitized = { ...environment };
71660
72015
  for (const key of Object.keys(sanitized)) {
@@ -71796,24 +72151,24 @@ var init_claude_models = __esm({
71796
72151
  });
71797
72152
 
71798
72153
  // packages/server/src/backend/codex-app-server-diagnostics.ts
71799
- import { appendFileSync as appendFileSync5, mkdirSync as mkdirSync18, renameSync as renameSync9, statSync as statSync16 } from "node:fs";
71800
- import { join as join36 } from "node:path";
72154
+ import { appendFileSync as appendFileSync5, mkdirSync as mkdirSync20, renameSync as renameSync9, statSync as statSync17 } from "node:fs";
72155
+ import { join as join39 } from "node:path";
71801
72156
  function codexDiagnosticLogPath(stateDir, projectId) {
71802
- return join36(stateDir, "codex-app-server", `${projectId}.diagnostics.log`);
72157
+ return join39(stateDir, "codex-app-server", `${projectId}.diagnostics.log`);
71803
72158
  }
71804
72159
  function createCodexDiagnosticSink(stateDir, projectId, now = () => /* @__PURE__ */ new Date()) {
71805
- const dir = join36(stateDir, "codex-app-server");
72160
+ const dir = join39(stateDir, "codex-app-server");
71806
72161
  const path3 = codexDiagnosticLogPath(stateDir, projectId);
71807
72162
  let ensured = false;
71808
72163
  return (event) => {
71809
72164
  if (event.event === "stderr") return;
71810
72165
  try {
71811
72166
  if (!ensured) {
71812
- mkdirSync18(dir, { recursive: true });
72167
+ mkdirSync20(dir, { recursive: true });
71813
72168
  ensured = true;
71814
72169
  }
71815
72170
  try {
71816
- if (statSync16(path3).size > MAX_BYTES2) renameSync9(path3, `${path3}.1`);
72171
+ if (statSync17(path3).size > MAX_BYTES2) renameSync9(path3, `${path3}.1`);
71817
72172
  } catch {
71818
72173
  }
71819
72174
  appendFileSync5(path3, `${JSON.stringify({ at: now().toISOString(), ...event })}
@@ -71832,9 +72187,9 @@ var init_codex_app_server_diagnostics = __esm({
71832
72187
 
71833
72188
  // packages/server/src/backend/stale-socket-sweep.ts
71834
72189
  import { execFile as execFile9 } from "node:child_process";
71835
- import { readdirSync as readdirSync10, unlinkSync as unlinkSync6 } from "node:fs";
72190
+ import { readdirSync as readdirSync11, unlinkSync as unlinkSync6 } from "node:fs";
71836
72191
  import { connect as connectSocket } from "node:net";
71837
- import { join as join37 } from "node:path";
72192
+ import { join as join40 } from "node:path";
71838
72193
  function parseLsofSocketNames(stdout) {
71839
72194
  const referenced = /* @__PURE__ */ new Set();
71840
72195
  for (const line of stdout.split("\n")) {
@@ -71851,7 +72206,7 @@ function sweepStaleSockets(options, deps = {}) {
71851
72206
  const keep = new Set(options.keep ?? []);
71852
72207
  let candidates;
71853
72208
  try {
71854
- candidates = (deps.readdir ?? readdirSync10)(options.dir).filter((name) => name.startsWith(options.prefix) && name.endsWith(".sock")).map((name) => join37(options.dir, name)).filter((path3) => !keep.has(path3));
72209
+ candidates = (deps.readdir ?? readdirSync11)(options.dir).filter((name) => name.startsWith(options.prefix) && name.endsWith(".sock")).map((name) => join40(options.dir, name)).filter((path3) => !keep.has(path3));
71855
72210
  } catch {
71856
72211
  return;
71857
72212
  }
@@ -71901,8 +72256,8 @@ var init_stale_socket_sweep = __esm({
71901
72256
 
71902
72257
  // packages/server/src/orphan-reaper.ts
71903
72258
  import { execFile as execFile10 } from "node:child_process";
71904
- import { readFileSync as readFileSync24 } from "node:fs";
71905
- import { dirname as dirname16 } from "node:path";
72259
+ import { readFileSync as readFileSync26 } from "node:fs";
72260
+ import { dirname as dirname18 } from "node:path";
71906
72261
  import { promisify as promisify8 } from "node:util";
71907
72262
  function firstTokenBasename(command) {
71908
72263
  const first = command.trimStart().split(/\s+/, 1)[0] ?? "";
@@ -72131,7 +72486,7 @@ async function sweepOrphansOnce(deps = {}) {
72131
72486
  }
72132
72487
  function sweepStaleBrokerSockets() {
72133
72488
  try {
72134
- sweepStaleSockets({ dir: dirname16(claudeBrokerSocketPath("", "")), prefix: CLAUDE_BROKER_SOCKET_PREFIX });
72489
+ sweepStaleSockets({ dir: dirname18(claudeBrokerSocketPath("", "")), prefix: CLAUDE_BROKER_SOCKET_PREFIX });
72135
72490
  } catch {
72136
72491
  }
72137
72492
  }
@@ -72208,7 +72563,7 @@ var init_orphan_reaper = __esm({
72208
72563
  defaultExec = async (file, args) => (await execFileAsync6(file, args, { encoding: "utf8", maxBuffer: 16 * 1024 * 1024, timeout: 1e4 })).stdout;
72209
72564
  defaultReadEnv = (pid) => {
72210
72565
  try {
72211
- return readFileSync24(`/proc/${pid}/environ`, "utf8");
72566
+ return readFileSync26(`/proc/${pid}/environ`, "utf8");
72212
72567
  } catch {
72213
72568
  return null;
72214
72569
  }
@@ -72228,7 +72583,7 @@ var init_orphan_reaper = __esm({
72228
72583
  });
72229
72584
 
72230
72585
  // packages/server/src/context.ts
72231
- import { join as join38 } from "node:path";
72586
+ import { join as join41 } from "node:path";
72232
72587
  import { randomUUID as randomUUID16 } from "node:crypto";
72233
72588
  import { homedir as homedir15 } from "node:os";
72234
72589
  function reconcileSessions(storage) {
@@ -72380,8 +72735,9 @@ async function createContext(opts = {}) {
72380
72735
  function createContextUnchecked(opts, resources) {
72381
72736
  const home = opts.home ?? homedir15();
72382
72737
  const project = opts.project ?? resolveProject();
72383
- const storage = createStorage(opts.database ?? join38(project.stateDir, "ui.db"), project.id);
72738
+ const storage = createStorage(opts.database ?? join41(project.stateDir, "ui.db"), project.id);
72384
72739
  resources.storage = storage;
72740
+ clearSecrets(project.stateDir);
72385
72741
  const bus = new Bus();
72386
72742
  const transcriptChange = new Emitter();
72387
72743
  const bootId = randomUUID16();
@@ -72797,6 +73153,7 @@ var init_context = __esm({
72797
73153
  init_bus();
72798
73154
  init_project();
72799
73155
  init_storage();
73156
+ init_secret_files();
72800
73157
  init_settings();
72801
73158
  init_dispatch_preferences();
72802
73159
  init_quota();
@@ -75492,8 +75849,8 @@ var init_server = __esm({
75492
75849
  });
75493
75850
 
75494
75851
  // packages/server/src/repair.ts
75495
- import { existsSync as existsSync16, readFileSync as readFileSync25, writeFileSync as writeFileSync12 } from "node:fs";
75496
- import { basename as basename7, dirname as dirname17, resolve as resolve9 } from "node:path";
75852
+ import { existsSync as existsSync18, readFileSync as readFileSync27, writeFileSync as writeFileSync14 } from "node:fs";
75853
+ import { basename as basename7, dirname as dirname19, resolve as resolve9 } from "node:path";
75497
75854
  function quoteValue(v) {
75498
75855
  if (/^[\w./#:+-]+$/.test(v)) return v;
75499
75856
  return `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
@@ -75505,10 +75862,10 @@ function deriveTitle(body, slug) {
75505
75862
  function repairThreadFile(frizzDir, file) {
75506
75863
  const root = resolve9(frizzDir);
75507
75864
  const abs = resolve9(root, file);
75508
- if (dirname17(abs) !== root) throw new RepairError(`refusing to repair "${file}": not directly under .frizz/`);
75865
+ if (dirname19(abs) !== root) throw new RepairError(`refusing to repair "${file}": not directly under .frizz/`);
75509
75866
  if (!abs.endsWith(".md")) throw new RepairError(`refusing to repair "${file}": not a .md thread file`);
75510
- if (!existsSync16(abs)) throw new RepairError(`no thread file to repair: ${basename7(abs)}`);
75511
- const content = readFileSync25(abs, "utf8");
75867
+ if (!existsSync18(abs)) throw new RepairError(`no thread file to repair: ${basename7(abs)}`);
75868
+ const content = readFileSync27(abs, "utf8");
75512
75869
  const firstLine2 = content.replace(/^/, "").split(/\r?\n/).find((l) => l.trim() !== "");
75513
75870
  if (firstLine2?.trim() === "---") {
75514
75871
  throw new RepairError(`${basename7(abs)} already opens with a "---" block \u2014 repair only heals a MISSING frontmatter block`);
@@ -75523,7 +75880,7 @@ function repairThreadFile(frizzDir, file) {
75523
75880
  "---",
75524
75881
  ""
75525
75882
  ].join("\n");
75526
- writeFileSync12(abs, frontmatter + content);
75883
+ writeFileSync14(abs, frontmatter + content);
75527
75884
  return { slug };
75528
75885
  }
75529
75886
  var RepairError, REPAIR_STATUS_TEXT;
@@ -75665,10 +76022,10 @@ var init_edited_files = __esm({
75665
76022
  });
75666
76023
 
75667
76024
  // packages/server/src/repo-files.ts
75668
- import { execFileSync as execFileSync4 } from "node:child_process";
76025
+ import { execFileSync as execFileSync5 } from "node:child_process";
75669
76026
  import path2 from "node:path";
75670
76027
  function git(args, cwd) {
75671
- return execFileSync4("git", args, {
76028
+ return execFileSync5("git", args, {
75672
76029
  cwd,
75673
76030
  encoding: "utf8",
75674
76031
  env: { ...process.env, LC_ALL: "C" },
@@ -75709,7 +76066,7 @@ function probeIgnored(projectDir, inside) {
75709
76066
  return /* @__PURE__ */ new Set();
75710
76067
  }
75711
76068
  try {
75712
- const out = execFileSync4("git", ["check-ignore", "-z", "--stdin"], {
76069
+ const out = execFileSync5("git", ["check-ignore", "-z", "--stdin"], {
75713
76070
  cwd: projectDir,
75714
76071
  encoding: "utf8",
75715
76072
  env: { ...process.env, LC_ALL: "C" },
@@ -75736,7 +76093,7 @@ var init_repo_files = __esm({
75736
76093
  });
75737
76094
 
75738
76095
  // cc-worker/hooks/bash-background.mjs
75739
- import { readFileSync as readFileSync26, realpathSync as realpathSync11 } from "node:fs";
76096
+ import { readFileSync as readFileSync28, realpathSync as realpathSync12 } from "node:fs";
75740
76097
  import { basename as basename8 } from "node:path";
75741
76098
  import { fileURLToPath as fileURLToPath4, pathToFileURL } from "node:url";
75742
76099
  function emit(obj) {
@@ -75874,7 +76231,7 @@ function evaluateBashBackgroundHook(input, env = process.env) {
75874
76231
  }
75875
76232
  };
75876
76233
  }
75877
- function isDirectHookExecution(argv1, moduleUrl, realpath = realpathSync11) {
76234
+ function isDirectHookExecution(argv1, moduleUrl, realpath = realpathSync12) {
75878
76235
  if (typeof argv1 !== "string" || basename8(argv1) !== "bash-background.mjs") return false;
75879
76236
  if (pathToFileURL(argv1).href === moduleUrl) return true;
75880
76237
  try {
@@ -75891,7 +76248,7 @@ var init_bash_background = __esm({
75891
76248
  if (isDirectHookExecution(process.argv[1], import.meta.url)) {
75892
76249
  try {
75893
76250
  const env = process.argv.includes("--frizz-thread") ? { ...process.env, FRIZZ_THREAD: process.env.FRIZZ_THREAD || "codex-worker" } : process.env;
75894
- emit(evaluateBashBackgroundHook(JSON.parse(readFileSync26(0, "utf8")), env));
76251
+ emit(evaluateBashBackgroundHook(JSON.parse(readFileSync28(0, "utf8")), env));
75895
76252
  } catch {
75896
76253
  emit({});
75897
76254
  }
@@ -75900,10 +76257,10 @@ var init_bash_background = __esm({
75900
76257
  });
75901
76258
 
75902
76259
  // packages/server/src/transcript.ts
75903
- import { closeSync as closeSync14, existsSync as existsSync17, fstatSync as fstatSync3, mkdirSync as mkdirSync19, openSync as openSync15, readdirSync as readdirSync11, readFileSync as readFileSync27, readSync as readSync8, renameSync as renameSync10, statSync as statSync17, unlinkSync as unlinkSync7, writeFileSync as writeFileSync13 } from "node:fs";
76260
+ import { closeSync as closeSync15, existsSync as existsSync19, fstatSync as fstatSync3, mkdirSync as mkdirSync21, openSync as openSync16, readdirSync as readdirSync12, readFileSync as readFileSync29, readSync as readSync8, renameSync as renameSync10, statSync as statSync18, unlinkSync as unlinkSync7, writeFileSync as writeFileSync15 } from "node:fs";
75904
76261
  import { createHash as createHash15 } from "node:crypto";
75905
76262
  import { StringDecoder as StringDecoder6 } from "node:string_decoder";
75906
- import { join as join39 } from "node:path";
76263
+ import { join as join42 } from "node:path";
75907
76264
  import { homedir as homedir16 } from "node:os";
75908
76265
  function formatTokens(n) {
75909
76266
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
@@ -76507,18 +76864,18 @@ function looksLikeImage(buf, ext) {
76507
76864
  }
76508
76865
  function pruneScreenshotCache() {
76509
76866
  try {
76510
- const entries2 = readdirSync11(SCREENSHOT_CACHE_DIR).filter((n) => !n.startsWith("."));
76867
+ const entries2 = readdirSync12(SCREENSHOT_CACHE_DIR).filter((n) => !n.startsWith("."));
76511
76868
  if (entries2.length <= SCREENSHOT_CACHE_MAX) return;
76512
76869
  const byMtime = entries2.map((n) => {
76513
76870
  try {
76514
- return { n, m: statSync17(join39(SCREENSHOT_CACHE_DIR, n)).mtimeMs };
76871
+ return { n, m: statSync18(join42(SCREENSHOT_CACHE_DIR, n)).mtimeMs };
76515
76872
  } catch {
76516
76873
  return { n, m: 0 };
76517
76874
  }
76518
76875
  }).sort((a, b) => b.m - a.m);
76519
76876
  for (const { n } of byMtime.slice(SCREENSHOT_CACHE_MAX)) {
76520
76877
  try {
76521
- unlinkSync7(join39(SCREENSHOT_CACHE_DIR, n));
76878
+ unlinkSync7(join42(SCREENSHOT_CACHE_DIR, n));
76522
76879
  } catch {
76523
76880
  }
76524
76881
  }
@@ -76548,15 +76905,15 @@ function persistBase64Image(mediaType, data, idKey) {
76548
76905
  const ext = IMAGE_MEDIA_EXT[typeof mediaType === "string" ? mediaType.toLowerCase() : ""];
76549
76906
  if (!ext || !data) return void 0;
76550
76907
  const name = createHash15("sha256").update(idKey).digest("hex").slice(0, 32);
76551
- const path3 = join39(SCREENSHOT_CACHE_DIR, `${name}.${ext}`);
76908
+ const path3 = join42(SCREENSHOT_CACHE_DIR, `${name}.${ext}`);
76552
76909
  try {
76553
- if (existsSync17(path3)) return path3;
76910
+ if (existsSync19(path3)) return path3;
76554
76911
  if (data.length > SCREENSHOT_MAX_BASE64) return void 0;
76555
76912
  const buf = Buffer.from(data, "base64");
76556
76913
  if (buf.length === 0 || !looksLikeImage(buf, ext)) return void 0;
76557
- mkdirSync19(SCREENSHOT_CACHE_DIR, { recursive: true });
76558
- const tmp = join39(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
76559
- writeFileSync13(tmp, buf);
76914
+ mkdirSync21(SCREENSHOT_CACHE_DIR, { recursive: true });
76915
+ const tmp = join42(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
76916
+ writeFileSync15(tmp, buf);
76560
76917
  renameSync10(tmp, path3);
76561
76918
  pruneScreenshotCache();
76562
76919
  return path3;
@@ -76570,15 +76927,15 @@ function persistSentFile(srcPath, idKey) {
76570
76927
  const outExt = ext === "jpeg" ? "jpg" : ext;
76571
76928
  try {
76572
76929
  const name = createHash15("sha256").update(idKey).digest("hex").slice(0, 32);
76573
- const dest = join39(SCREENSHOT_CACHE_DIR, `${name}.${outExt}`);
76574
- if (existsSync17(dest)) return dest;
76575
- const size = statSync17(srcPath).size;
76930
+ const dest = join42(SCREENSHOT_CACHE_DIR, `${name}.${outExt}`);
76931
+ if (existsSync19(dest)) return dest;
76932
+ const size = statSync18(srcPath).size;
76576
76933
  if (size === 0 || size > SENT_IMAGE_MAX_BYTES) return void 0;
76577
- const buf = readFileSync27(srcPath);
76934
+ const buf = readFileSync29(srcPath);
76578
76935
  if (!looksLikeImage(buf, outExt)) return void 0;
76579
- mkdirSync19(SCREENSHOT_CACHE_DIR, { recursive: true });
76580
- const tmp = join39(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
76581
- writeFileSync13(tmp, buf);
76936
+ mkdirSync21(SCREENSHOT_CACHE_DIR, { recursive: true });
76937
+ const tmp = join42(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
76938
+ writeFileSync15(tmp, buf);
76582
76939
  renameSync10(tmp, dest);
76583
76940
  pruneScreenshotCache();
76584
76941
  return dest;
@@ -76996,7 +77353,7 @@ function readTranscript(project, sessionId) {
76996
77353
  const identityPrefix = `claude:${sessionId}`;
76997
77354
  let fd2;
76998
77355
  try {
76999
- fd2 = openSync15(path3, "r");
77356
+ fd2 = openSync16(path3, "r");
77000
77357
  const st2 = fstatSync3(fd2);
77001
77358
  const size = st2.size;
77002
77359
  const fileId = `${st2.dev}:${st2.ino}:${Math.trunc(st2.birthtimeMs)}`;
@@ -77010,12 +77367,12 @@ function readTranscript(project, sessionId) {
77010
77367
  } catch {
77011
77368
  return [];
77012
77369
  } finally {
77013
- if (fd2 !== void 0) closeSync14(fd2);
77370
+ if (fd2 !== void 0) closeSync15(fd2);
77014
77371
  }
77015
77372
  }
77016
77373
  function verifyIncrementalParse(path3, identityPrefix, incremental) {
77017
77374
  try {
77018
- const fresh = parseTranscript(readFileSync27(path3, "utf8"), identityPrefix);
77375
+ const fresh = parseTranscript(readFileSync29(path3, "utf8"), identityPrefix);
77019
77376
  const a = JSON.stringify(incremental);
77020
77377
  const b = JSON.stringify(fresh);
77021
77378
  if (a !== b) {
@@ -77035,16 +77392,16 @@ function verifyIncrementalParse(path3, identityPrefix, incremental) {
77035
77392
  }
77036
77393
  }
77037
77394
  function logDirOf(project) {
77038
- return join39(homedir16(), ".claude", "projects", project.cwdSlug);
77395
+ return join42(homedir16(), ".claude", "projects", project.cwdSlug);
77039
77396
  }
77040
77397
  function resolveTranscriptPath(project, sessionId) {
77041
- const path3 = join39(logDirOf(project), `${sessionId}.jsonl`);
77398
+ const path3 = join42(logDirOf(project), `${sessionId}.jsonl`);
77042
77399
  try {
77043
- if (statSync17(path3).size > 0) return path3;
77400
+ if (statSync18(path3).size > 0) return path3;
77044
77401
  } catch {
77045
77402
  }
77046
77403
  const stranded = discoverTranscriptDir(logDirOf(project), sessionId);
77047
- return stranded ? join39(stranded, `${sessionId}.jsonl`) : path3;
77404
+ return stranded ? join42(stranded, `${sessionId}.jsonl`) : path3;
77048
77405
  }
77049
77406
  function projectCodexTranscript(raw2, identityPrefix = "codex") {
77050
77407
  const out = [];
@@ -78112,7 +78469,7 @@ function sourceForThread(project, storage, slug, backendFor) {
78112
78469
  }
78113
78470
  if (!FOREIGN_SESSION_ID_RE.test(slug)) return void 0;
78114
78471
  const claudePath = resolveTranscriptPath(project, slug);
78115
- if (existsSync17(claudePath)) {
78472
+ if (existsSync19(claudePath)) {
78116
78473
  return { slug, sessionId: slug, nativeId: slug, backend: "claude", runtimeGeneration: 0, path: claudePath };
78117
78474
  }
78118
78475
  const rollout = (backendFor?.("codex") ?? defaultCodexBackend()).transcriptPath(slug);
@@ -78148,7 +78505,7 @@ function discoveredClaudeSource(project, storage, slug, expectedNativeId) {
78148
78505
  function fixedSnapshot(source) {
78149
78506
  let fd2;
78150
78507
  try {
78151
- fd2 = openSync15(source.path, "r");
78508
+ fd2 = openSync16(source.path, "r");
78152
78509
  const before = fstatSync3(fd2);
78153
78510
  if (!Number.isSafeInteger(before.size) || before.size < 0) throw new Error("transcript is too large to page safely");
78154
78511
  const after = fstatSync3(fd2);
@@ -78158,7 +78515,7 @@ function fixedSnapshot(source) {
78158
78515
  const size = before.size;
78159
78516
  const path3 = source.path;
78160
78517
  const readRange = (from, length) => {
78161
- const rfd = openSync15(path3, "r");
78518
+ const rfd = openSync16(path3, "r");
78162
78519
  try {
78163
78520
  const st2 = fstatSync3(rfd);
78164
78521
  if (st2.dev !== before.dev || st2.ino !== before.ino || st2.size < size) {
@@ -78174,7 +78531,7 @@ function fixedSnapshot(source) {
78174
78531
  }
78175
78532
  return filled === want ? buf : buf.subarray(0, filled);
78176
78533
  } finally {
78177
- closeSync14(rfd);
78534
+ closeSync15(rfd);
78178
78535
  }
78179
78536
  };
78180
78537
  let allBytes;
@@ -78200,7 +78557,7 @@ function fixedSnapshot(source) {
78200
78557
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") return void 0;
78201
78558
  throw error;
78202
78559
  } finally {
78203
- if (fd2 !== void 0) closeSync14(fd2);
78560
+ if (fd2 !== void 0) closeSync15(fd2);
78204
78561
  }
78205
78562
  }
78206
78563
  function projectSnapshot(snapshot) {
@@ -78384,7 +78741,7 @@ function readEarlierThreadTranscriptPage(project, storage, slug, cursor, backend
78384
78741
  }
78385
78742
  function readCodexTranscriptFile(absPath, nativeId = absPath) {
78386
78743
  try {
78387
- return parseCodexTranscript(readFileSync27(absPath, "utf8"), `codex:${nativeId}`);
78744
+ return parseCodexTranscript(readFileSync29(absPath, "utf8"), `codex:${nativeId}`);
78388
78745
  } catch {
78389
78746
  return [];
78390
78747
  }
@@ -78452,7 +78809,7 @@ function projectTranscriptPageAgentLifecycles(page, lookup, peerLookup) {
78452
78809
  function readTranscriptFile(absPath) {
78453
78810
  try {
78454
78811
  const pathKey = createHash15("sha256").update(absPath).digest("base64url").slice(0, 16);
78455
- return parseTranscript(readFileSync27(absPath, "utf8"), `claude-file:${pathKey}`);
78812
+ return parseTranscript(readFileSync29(absPath, "utf8"), `claude-file:${pathKey}`);
78456
78813
  } catch {
78457
78814
  return [];
78458
78815
  }
@@ -78916,11 +79273,11 @@ var init_external_terminal = __esm({
78916
79273
  });
78917
79274
 
78918
79275
  // packages/server/src/background-shell-output.ts
78919
- import { closeSync as closeSync15, fstatSync as fstatSync4, openSync as openSync16, readSync as readSync9 } from "node:fs";
79276
+ import { closeSync as closeSync16, fstatSync as fstatSync4, openSync as openSync17, readSync as readSync9 } from "node:fs";
78920
79277
  function readBackgroundShellOutput(path3, maxBytes = OUTPUT_TAIL_BYTES) {
78921
79278
  let fd2;
78922
79279
  try {
78923
- fd2 = openSync16(path3, "r");
79280
+ fd2 = openSync17(path3, "r");
78924
79281
  const size = fstatSync4(fd2).size;
78925
79282
  const length = Math.min(size, maxBytes);
78926
79283
  const offset = Math.max(0, size - length);
@@ -78936,7 +79293,7 @@ function readBackgroundShellOutput(path3, maxBytes = OUTPUT_TAIL_BYTES) {
78936
79293
  } catch {
78937
79294
  return { output: "", truncated: false };
78938
79295
  } finally {
78939
- if (fd2 !== void 0) closeSync15(fd2);
79296
+ if (fd2 !== void 0) closeSync16(fd2);
78940
79297
  }
78941
79298
  }
78942
79299
  function readHead2(fd2, length) {
@@ -78953,7 +79310,7 @@ function readHead2(fd2, length) {
78953
79310
  function backgroundShellLineCount(path3) {
78954
79311
  let fd2;
78955
79312
  try {
78956
- fd2 = openSync16(path3, "r");
79313
+ fd2 = openSync17(path3, "r");
78957
79314
  const stat2 = fstatSync4(fd2);
78958
79315
  const size = stat2.size;
78959
79316
  let state = scans.get(path3);
@@ -79004,7 +79361,7 @@ function backgroundShellLineCount(path3) {
79004
79361
  } catch {
79005
79362
  return void 0;
79006
79363
  } finally {
79007
- if (fd2 !== void 0) closeSync15(fd2);
79364
+ if (fd2 !== void 0) closeSync16(fd2);
79008
79365
  }
79009
79366
  }
79010
79367
  var OUTPUT_TAIL_BYTES, SCAN_CHUNK_BYTES, SCAN_CEILING_BYTES, SCAN_CACHE_LIMIT, FINGERPRINT_BYTES, ANSI_ESCAPE_RE, scans;
@@ -79022,15 +79379,15 @@ var init_background_shell_output = __esm({
79022
79379
  });
79023
79380
 
79024
79381
  // packages/server/src/frizz-md.ts
79025
- import { execFileSync as execFileSync5 } from "node:child_process";
79026
- import { existsSync as existsSync18, writeFileSync as writeFileSync14 } from "node:fs";
79027
- import { join as join40 } from "node:path";
79382
+ import { execFileSync as execFileSync6 } from "node:child_process";
79383
+ import { existsSync as existsSync20, writeFileSync as writeFileSync16 } from "node:fs";
79384
+ import { join as join43 } from "node:path";
79028
79385
  function frizzMdPath(projectDir) {
79029
- return join40(projectDir, "FRIZZ.md");
79386
+ return join43(projectDir, "FRIZZ.md");
79030
79387
  }
79031
79388
  function git2(args, cwd) {
79032
79389
  try {
79033
- return execFileSync5("git", args, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 5e3 }).trim() || null;
79390
+ return execFileSync6("git", args, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 5e3 }).trim() || null;
79034
79391
  } catch {
79035
79392
  return null;
79036
79393
  }
@@ -79043,7 +79400,7 @@ function defaultBranch(projectDir) {
79043
79400
  }
79044
79401
  function frizzMdStatus(projectDir, storage) {
79045
79402
  return {
79046
- exists: existsSync18(frizzMdPath(projectDir)),
79403
+ exists: existsSync20(frizzMdPath(projectDir)),
79047
79404
  skipped: storage.getSetting(SKIP_SETTING) !== void 0,
79048
79405
  defaultBranch: defaultBranch(projectDir)
79049
79406
  };
@@ -79051,7 +79408,7 @@ function frizzMdStatus(projectDir, storage) {
79051
79408
  function createFrizzMd(projectDir, answers) {
79052
79409
  const path3 = frizzMdPath(projectDir);
79053
79410
  try {
79054
- writeFileSync14(path3, composeFrizzMd(answers, defaultBranch(projectDir)), { encoding: "utf8", flag: "wx" });
79411
+ writeFileSync16(path3, composeFrizzMd(answers, defaultBranch(projectDir)), { encoding: "utf8", flag: "wx" });
79055
79412
  } catch (error) {
79056
79413
  if (error.code === "EEXIST") throw new Error("This project already has a FRIZZ.md.");
79057
79414
  throw error;
@@ -79071,15 +79428,15 @@ var init_frizz_md2 = __esm({
79071
79428
  });
79072
79429
 
79073
79430
  // packages/server/src/image-header.ts
79074
- import { closeSync as closeSync16, openSync as openSync17, readSync as readSync10, statSync as statSync18 } from "node:fs";
79075
- import { extname } from "node:path";
79431
+ import { closeSync as closeSync17, openSync as openSync18, readSync as readSync10, statSync as statSync19 } from "node:fs";
79432
+ import { extname as extname2 } from "node:path";
79076
79433
  function readHead3(path3, budget) {
79077
79434
  let fd2;
79078
79435
  try {
79079
- const size = statSync18(path3).size;
79436
+ const size = statSync19(path3).size;
79080
79437
  if (size === 0) return void 0;
79081
79438
  const buffer = Buffer.alloc(Math.min(size, budget));
79082
- fd2 = openSync17(path3, "r");
79439
+ fd2 = openSync18(path3, "r");
79083
79440
  const read = readSync10(fd2, buffer, 0, buffer.length, 0);
79084
79441
  return read === buffer.length ? buffer : buffer.subarray(0, read);
79085
79442
  } catch {
@@ -79087,7 +79444,7 @@ function readHead3(path3, budget) {
79087
79444
  } finally {
79088
79445
  if (fd2 !== void 0) {
79089
79446
  try {
79090
- closeSync16(fd2);
79447
+ closeSync17(fd2);
79091
79448
  } catch {
79092
79449
  }
79093
79450
  }
@@ -79180,7 +79537,7 @@ function svg(head) {
79180
79537
  return void 0;
79181
79538
  }
79182
79539
  function svgDeclaresColour(path3) {
79183
- if (extname(path3).toLowerCase() !== ".svg") return void 0;
79540
+ if (extname2(path3).toLowerCase() !== ".svg") return void 0;
79184
79541
  const head = readHead3(path3, 512 * 1024);
79185
79542
  if (!head) return void 0;
79186
79543
  const source = head.toString("utf8");
@@ -79192,7 +79549,7 @@ function svgDeclaresColour(path3) {
79192
79549
  return false;
79193
79550
  }
79194
79551
  function imageDimensions(path3) {
79195
- const extension2 = extname(path3).toLowerCase();
79552
+ const extension2 = extname2(path3).toLowerCase();
79196
79553
  const budget = extension2 === ".jpg" || extension2 === ".jpeg" ? JPEG_SCAN_BYTES : HEAD_BYTES2;
79197
79554
  const head = readHead3(path3, budget);
79198
79555
  if (!head) return void 0;
@@ -79454,11 +79811,11 @@ function run(argv) {
79454
79811
  });
79455
79812
 
79456
79813
  // packages/server/src/router.ts
79457
- import { readFileSync as readFileSync28, statSync as statSync19 } from "node:fs";
79458
- import { join as join41, resolve as resolve10 } from "node:path";
79814
+ import { readFileSync as readFileSync30, statSync as statSync20 } from "node:fs";
79815
+ import { join as join44, resolve as resolve10 } from "node:path";
79459
79816
  import { randomUUID as randomUUID17 } from "node:crypto";
79460
- import { basename as basename9, dirname as dirname18 } from "node:path";
79461
- import { existsSync as existsSync19, mkdirSync as mkdirSync20, rmSync as rmSync11, writeFileSync as writeFileSync15 } from "node:fs";
79817
+ import { basename as basename9, dirname as dirname20 } from "node:path";
79818
+ import { existsSync as existsSync21, mkdirSync as mkdirSync22, rmSync as rmSync12, writeFileSync as writeFileSync17 } from "node:fs";
79462
79819
  import { homedir as homedir17 } from "node:os";
79463
79820
  function validateGithubDispatchProfile(input, codexModels) {
79464
79821
  if (input.backend === "acp") return;
@@ -79632,11 +79989,11 @@ function projectCard(entry, stale) {
79632
79989
  function addProjectAtPath(input, home = homedir17()) {
79633
79990
  const typed = input.trim();
79634
79991
  if (!typed) throw new Error("Enter a folder path.");
79635
- const expanded = typed === "~" || typed.startsWith("~/") ? join41(home, typed.slice(1)) : typed;
79992
+ const expanded = typed === "~" || typed.startsWith("~/") ? join44(home, typed.slice(1)) : typed;
79636
79993
  const absolute = resolve10(expanded);
79637
79994
  let stats;
79638
79995
  try {
79639
- stats = statSync19(absolute);
79996
+ stats = statSync20(absolute);
79640
79997
  } catch {
79641
79998
  throw new Error(`No folder at ${absolute}`);
79642
79999
  }
@@ -79661,15 +80018,15 @@ function storeProjectIcon(id2, name, bytes) {
79661
80018
  if (!entry) throw new Error("No such project.");
79662
80019
  if (bytes.length === 0) throw new Error("That file is empty.");
79663
80020
  const path3 = customIconPath(id2, `.${extension2}`);
79664
- mkdirSync20(dirname18(path3), { recursive: true });
79665
- writeFileSync15(path3, bytes);
80021
+ mkdirSync22(dirname20(path3), { recursive: true });
80022
+ writeFileSync17(path3, bytes);
79666
80023
  if (!imageDimensions(path3)) {
79667
- rmSync11(path3, { force: true });
80024
+ rmSync12(path3, { force: true });
79668
80025
  throw new Error("That file does not look like an image Frizz can draw.");
79669
80026
  }
79670
80027
  for (const stale of PROJECT_ICON_EXTENSIONS) {
79671
80028
  const other = customIconPath(id2, `.${stale}`);
79672
- if (other !== path3) rmSync11(other, { force: true });
80029
+ if (other !== path3) rmSync12(other, { force: true });
79673
80030
  }
79674
80031
  const updated = setProjectIcon(id2, path3);
79675
80032
  if (!updated) throw new Error("No such project.");
@@ -79683,7 +80040,7 @@ function iconPicker(id2) {
79683
80040
  function setProjectIconFromFile(id2, file) {
79684
80041
  let bytes;
79685
80042
  try {
79686
- bytes = readFileSync28(file);
80043
+ bytes = readFileSync30(file);
79687
80044
  } catch {
79688
80045
  throw new Error("That file could not be read.");
79689
80046
  }
@@ -79716,7 +80073,7 @@ function mergeSubAgentSteers(messages, steers) {
79716
80073
  return merged;
79717
80074
  }
79718
80075
  function createRouter(ctx) {
79719
- const frizzDir = join41(ctx.project.dir, ".frizz");
80076
+ const frizzDir = join44(ctx.project.dir, ".frizz");
79720
80077
  const openRoots = openableFileRoots(ctx.project);
79721
80078
  function isAutoTitledSession(slug) {
79722
80079
  return ctx.storage.getSession(slug)?.title_auto === 1;
@@ -79824,15 +80181,24 @@ function createRouter(ctx) {
79824
80181
  for (const q2 of ctx.storage.listThreadQuestions(slug, { openOnly: true })) {
79825
80182
  const spec = parseQuestionSpec(q2.spec);
79826
80183
  if (!spec) continue;
79827
- out.push({ id: q2.id, spec, askedAt: new Date(q2.asked_at).toISOString() });
80184
+ out.push(questionView(slug, q2.id, spec, q2.asked_at));
79828
80185
  }
79829
80186
  return out;
79830
80187
  }
80188
+ function questionView(slug, id2, spec, askedAtMs) {
80189
+ return {
80190
+ id: id2,
80191
+ spec,
80192
+ askedAt: new Date(askedAtMs).toISOString(),
80193
+ ...spec.secret ? { secretPath: secretFilePath(ctx.project.stateDir, slug, id2) } : {}
80194
+ };
80195
+ }
79831
80196
  function cancelQuestionsForAutonomy(slug) {
79832
80197
  const now = Date.now();
79833
80198
  let cancelled = 0;
79834
80199
  for (const q2 of ctx.storage.listThreadQuestions(slug, { openOnly: true })) {
79835
- if (parseQuestionSpec(q2.spec)?.danger) continue;
80200
+ const spec = parseQuestionSpec(q2.spec);
80201
+ if (spec?.danger || spec?.secret) continue;
79836
80202
  if (ctx.storage.dismissThreadQuestion(q2.id, now)) cancelled++;
79837
80203
  }
79838
80204
  return cancelled;
@@ -80170,14 +80536,14 @@ function createRouter(ctx) {
80170
80536
  ctx.storage.listSubAgentSteers(input.slug, input.id)
80171
80537
  );
80172
80538
  const steer = subAgentSteerable(input.slug, input.id);
80173
- const stop = subAgentStoppable(input.slug, input.id);
80539
+ const stop2 = subAgentStoppable(input.slug, input.id);
80174
80540
  return {
80175
80541
  messages,
80176
80542
  state: info.state,
80177
80543
  steerable: steer.sessionId !== null,
80178
80544
  steerNote: steer.sessionId === null ? steer.note : null,
80179
- stoppable: stop.sessionId !== null,
80180
- stopNote: stop.sessionId === null ? stop.note : null
80545
+ stoppable: stop2.sessionId !== null,
80546
+ stopNote: stop2.sessionId === null ? stop2.note : null
80181
80547
  };
80182
80548
  }
80183
80549
  }),
@@ -80255,13 +80621,13 @@ function createRouter(ctx) {
80255
80621
  const info = ctx.tailer.backgroundShell?.(input.slug, input.id);
80256
80622
  if (!info) return { command: null, output: "", truncated: false, state: "gone", stoppable: false, stopNote: null };
80257
80623
  const content = info.outputFile ? readBackgroundShellOutput(info.outputFile) : { output: "", truncated: false };
80258
- const stop = subAgentStoppable(input.slug, input.id);
80624
+ const stop2 = subAgentStoppable(input.slug, input.id);
80259
80625
  return {
80260
80626
  command: info.command ?? null,
80261
80627
  ...content,
80262
80628
  state: info.state,
80263
- stoppable: stop.sessionId !== null,
80264
- stopNote: stop.sessionId === null ? stop.note : null
80629
+ stoppable: stop2.sessionId !== null,
80630
+ stopNote: stop2.sessionId === null ? stop2.note : null
80265
80631
  };
80266
80632
  }
80267
80633
  }),
@@ -81295,7 +81661,7 @@ ${gapNote}` : input.message;
81295
81661
  throw new Error("Reopen this thread before asking a question on it");
81296
81662
  }
81297
81663
  const goal = autonomousGoal(row);
81298
- if (goal) {
81664
+ if (goal && !input.questions.every((q2) => q2.secret)) {
81299
81665
  throw new Error(
81300
81666
  `This thread is running autonomously \u2014 decide it yourself and proceed. Its standing instruction is:
81301
81667
 
@@ -81311,7 +81677,7 @@ Say which way you went and why in your write-up, so the human can course-correct
81311
81677
  const id2 = `qst_${randomUUID17().replace(/-/g, "").slice(0, 12)}`;
81312
81678
  ctx.storage.clearThreadDone(input.slug);
81313
81679
  ctx.storage.askThreadQuestion({ id: id2, slug: input.slug, spec: JSON.stringify(spec), askedAtMs: now });
81314
- return { id: id2, spec, askedAt: new Date(now).toISOString() };
81680
+ return questionView(input.slug, id2, spec, now);
81315
81681
  });
81316
81682
  ctx.board.refresh();
81317
81683
  return { registered, open: openQuestionViews(input.slug) };
@@ -81336,7 +81702,14 @@ Say which way you went and why in your write-up, so the human can course-correct
81336
81702
  for (const answer of input.answers) {
81337
81703
  const q2 = ctx.storage.getThreadQuestion(answer.questionId);
81338
81704
  if (!q2 || q2.thread_slug !== input.slug || q2.state !== "open") continue;
81339
- if (ctx.storage.answerThreadQuestion(answer.questionId, JSON.stringify(answer), now)) answered.push(answer.questionId);
81705
+ let stored = answer;
81706
+ if (parseQuestionSpec(q2.spec)?.secret) {
81707
+ const value = answer.text?.trim() ?? "";
81708
+ if (!value) continue;
81709
+ const path3 = serveSecret(ctx.project.stateDir, input.slug, q2.id, value);
81710
+ stored = { questionId: answer.questionId, question: answer.question, chosen: [], text: secretAnswerText(path3) };
81711
+ }
81712
+ if (ctx.storage.answerThreadQuestion(answer.questionId, JSON.stringify(stored), now)) answered.push(answer.questionId);
81340
81713
  }
81341
81714
  if (answered.length > 0) {
81342
81715
  ctx.board.refresh();
@@ -81930,11 +82303,11 @@ Say which way you went and why in your write-up, so the human can course-correct
81930
82303
  output: ProjectCard,
81931
82304
  handler: async ({ input }) => {
81932
82305
  for (const extension2 of PROJECT_ICON_EXTENSIONS) {
81933
- rmSync11(customIconPath(input.id, `.${extension2}`), { force: true });
82306
+ rmSync12(customIconPath(input.id, `.${extension2}`), { force: true });
81934
82307
  }
81935
82308
  const updated = clearProjectIcon(input.id);
81936
82309
  if (!updated) throw new Error("No such project.");
81937
- return projectCard(updated, !existsSync19(updated.path));
82310
+ return projectCard(updated, !existsSync21(updated.path));
81938
82311
  }
81939
82312
  }),
81940
82313
  /**
@@ -81975,7 +82348,7 @@ Say which way you went and why in your write-up, so the human can course-correct
81975
82348
  }
81976
82349
  const updated = renameProject(entry.id, { name: name === basename9(path3) ? null : name, slug: name });
81977
82350
  if (!updated) throw new Error("No such project.");
81978
- return projectCard(updated, !existsSync19(updated.path));
82351
+ return projectCard(updated, !existsSync21(updated.path));
81979
82352
  }
81980
82353
  }),
81981
82354
  /**
@@ -82179,6 +82552,7 @@ var init_router5 = __esm({
82179
82552
  init_server();
82180
82553
  init_src();
82181
82554
  init_context();
82555
+ init_secret_files();
82182
82556
  init_acp_agents();
82183
82557
  init_storage();
82184
82558
  init_usage_limit();
@@ -82235,144 +82609,8 @@ var init_router5 = __esm({
82235
82609
  }
82236
82610
  });
82237
82611
 
82238
- // packages/server/src/local-origin.ts
82239
- import { isIP } from "node:net";
82240
- function publicAuthority(policy) {
82241
- const raw2 = policy?.publicOrigin;
82242
- if (!raw2) return null;
82243
- let url;
82244
- try {
82245
- url = new URL(raw2);
82246
- } catch {
82247
- return null;
82248
- }
82249
- if (url.origin !== raw2) return null;
82250
- return {
82251
- hostname: normalizedHostname(url.hostname),
82252
- port: explicitPort(url),
82253
- authority: url.host.toLowerCase(),
82254
- scheme: url.protocol === "https:" ? "https" : "http"
82255
- };
82256
- }
82257
- function acceptsHostname(hostname, policy) {
82258
- if (LOCAL_HOSTNAMES.has(hostname)) return true;
82259
- if (!policy?.exposed) return false;
82260
- if (isIP(hostname) !== 0) return true;
82261
- return (policy.allowedHosts ?? []).some((allowed) => allowed === "*" || allowed.toLowerCase() === hostname);
82262
- }
82263
- function oneHeader(value) {
82264
- return typeof value === "string" && value.length > 0 ? value : void 0;
82265
- }
82266
- function normalizedHostname(hostname) {
82267
- const lower = hostname.toLowerCase();
82268
- return lower.startsWith("[") && lower.endsWith("]") ? lower.slice(1, -1) : lower;
82269
- }
82270
- function explicitPort(url) {
82271
- if (url.port) return Number(url.port);
82272
- return url.protocol === "https:" ? 443 : 80;
82273
- }
82274
- function validExpectedPort(port2) {
82275
- return Number.isInteger(port2) && port2 >= 1 && port2 <= 65535;
82276
- }
82277
- function parseLocalHttpOrigin(value, expectedPort, policy) {
82278
- const raw2 = oneHeader(value);
82279
- if (!raw2 || !validExpectedPort(expectedPort) || raw2 !== raw2.trim()) return null;
82280
- const declared = publicAuthority(policy);
82281
- if (declared && raw2 === policy?.publicOrigin) return declared;
82282
- let url;
82283
- try {
82284
- url = new URL(raw2);
82285
- } catch {
82286
- return null;
82287
- }
82288
- if (url.protocol !== "http:" || url.origin !== raw2) return null;
82289
- const hostname = normalizedHostname(url.hostname);
82290
- if (!acceptsHostname(hostname, policy) || explicitPort(url) !== expectedPort) return null;
82291
- return { hostname, port: expectedPort, authority: url.host, scheme: "http" };
82292
- }
82293
- function parseLocalHost(value, expectedPort, policy) {
82294
- const raw2 = oneHeader(value);
82295
- if (!raw2 || !validExpectedPort(expectedPort) || raw2 !== raw2.trim() || raw2.includes(",")) return null;
82296
- let url;
82297
- try {
82298
- url = new URL(`http://${raw2}`);
82299
- } catch {
82300
- return null;
82301
- }
82302
- if (url.username || url.password || url.pathname !== "/" || url.search || url.hash) return null;
82303
- if (url.host.toLowerCase() !== raw2.toLowerCase()) return null;
82304
- const hostname = normalizedHostname(url.hostname);
82305
- const declared = publicAuthority(policy);
82306
- if (declared && hostname === declared.hostname) {
82307
- return url.port === "" || Number(url.port) === declared.port ? declared : null;
82308
- }
82309
- if (!acceptsHostname(hostname, policy) || explicitPort(url) !== expectedPort) return null;
82310
- return { hostname, port: expectedPort, authority: url.host.toLowerCase(), scheme: "http" };
82311
- }
82312
- function hasForwardedAuthority(headers) {
82313
- return FORWARDED_HEADERS.some((name) => headers[name] !== void 0);
82314
- }
82315
- function forwardedAuthorityAllowed(headers, host, policy) {
82316
- if (!hasForwardedAuthority(headers)) return true;
82317
- const declared = publicAuthority(policy);
82318
- return !!declared && declared.hostname === host.hostname;
82319
- }
82320
- function isTrustedLocalHttpRequest(headers, expectedPort, allowMissingOrigin = false, policy) {
82321
- const host = parseLocalHost(headers.host, expectedPort, policy);
82322
- if (!host) return false;
82323
- if (!forwardedAuthorityAllowed(headers, host, policy)) return false;
82324
- if (headers.origin === void 0) return allowMissingOrigin;
82325
- const origin = parseLocalHttpOrigin(headers.origin, expectedPort, policy);
82326
- return !!origin && host.hostname === origin.hostname && host.port === origin.port;
82327
- }
82328
- function allowedLocalCorsOrigin(origin, expectedPort, policy) {
82329
- return parseLocalHttpOrigin(origin, expectedPort, policy) ? origin : void 0;
82330
- }
82331
- function isTrustedLocalWebSocketRequest(req, expectedPort = req.socket.localPort, policy) {
82332
- if (!validExpectedPort(expectedPort)) return false;
82333
- const headers = req.headers;
82334
- const host = parseLocalHost(headers.host, expectedPort, policy);
82335
- if (!host || !forwardedAuthorityAllowed(headers, host, policy)) return false;
82336
- const origin = parseLocalHttpOrigin(headers.origin, expectedPort, policy);
82337
- return !!origin && host.hostname === origin.hostname && host.port === origin.port;
82338
- }
82339
- function rejectWebSocketUpgrade(socket, status = 403, reason = "Forbidden") {
82340
- const body = `${reason}
82341
- `;
82342
- const response = [
82343
- `HTTP/1.1 ${status} ${reason}`,
82344
- "Connection: close",
82345
- "Content-Type: text/plain; charset=utf-8",
82346
- `Content-Length: ${Buffer.byteLength(body)}`,
82347
- "",
82348
- body
82349
- ].join("\r\n");
82350
- try {
82351
- socket.end(response);
82352
- } catch {
82353
- try {
82354
- socket.destroy();
82355
- } catch {
82356
- }
82357
- }
82358
- }
82359
- var LOCAL_HOSTNAMES, FORWARDED_HEADERS;
82360
- var init_local_origin = __esm({
82361
- "packages/server/src/local-origin.ts"() {
82362
- "use strict";
82363
- LOCAL_HOSTNAMES = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1"]);
82364
- FORWARDED_HEADERS = [
82365
- "forwarded",
82366
- "x-forwarded-for",
82367
- "x-forwarded-host",
82368
- "x-forwarded-port",
82369
- "x-forwarded-proto"
82370
- ];
82371
- }
82372
- });
82373
-
82374
82612
  // packages/server/src/compression.ts
82375
- import { brotliCompressSync, gzipSync, constants as constants4 } from "node:zlib";
82613
+ import { brotliCompressSync, gzipSync, constants as constants5 } from "node:zlib";
82376
82614
  function negotiateEncoding(acceptEncoding) {
82377
82615
  if (!acceptEncoding) return null;
82378
82616
  const offers = /* @__PURE__ */ new Map();
@@ -82395,9 +82633,9 @@ function negotiateEncoding(acceptEncoding) {
82395
82633
  function compress(body, encoding) {
82396
82634
  const out = encoding === "br" ? brotliCompressSync(body, {
82397
82635
  params: {
82398
- [constants4.BROTLI_PARAM_QUALITY]: 4,
82636
+ [constants5.BROTLI_PARAM_QUALITY]: 4,
82399
82637
  // Telling brotli the input size lets it size its window instead of guessing.
82400
- [constants4.BROTLI_PARAM_SIZE_HINT]: body.byteLength
82638
+ [constants5.BROTLI_PARAM_SIZE_HINT]: body.byteLength
82401
82639
  }
82402
82640
  }) : gzipSync(body, { level: 6 });
82403
82641
  return Uint8Array.from(out);
@@ -82417,87 +82655,10 @@ var init_compression = __esm({
82417
82655
  }
82418
82656
  });
82419
82657
 
82420
- // packages/server/src/local-image.ts
82421
- import { createReadStream, realpathSync as realpathSync12, statSync as statSync20 } from "node:fs";
82422
- import { extname as extname2, isAbsolute as isAbsolute9 } from "node:path";
82423
- function resolveLocalImage(rawPath, range) {
82424
- if (rawPath) rawPath = normalizeLocalPath(rawPath);
82425
- if (!rawPath || !isAbsolute9(rawPath)) return { status: 400 };
82426
- const contentType = CONTENT_TYPE[extname2(rawPath).toLowerCase()];
82427
- if (!contentType) return { status: 400 };
82428
- let real;
82429
- try {
82430
- real = realpathSync12(rawPath);
82431
- } catch {
82432
- return { status: 404 };
82433
- }
82434
- let size;
82435
- try {
82436
- const stat2 = statSync20(real);
82437
- if (!stat2.isFile()) return { status: 404 };
82438
- size = stat2.size;
82439
- } catch {
82440
- return { status: 404 };
82441
- }
82442
- const span = range ? byteRange(range, size) : null;
82443
- if (span === "unsatisfiable") return { status: 416, size };
82444
- if (span) return { status: 206, contentType, file: real, size, start: span.start, end: span.end };
82445
- return { status: 200, contentType, file: real, size, start: 0, end: size - 1 };
82446
- }
82447
- function byteRange(header, size) {
82448
- const match2 = /^bytes=(\d*)-(\d*)$/.exec(header.trim());
82449
- if (!match2) return null;
82450
- const [, first, last] = match2;
82451
- if (first === "" && last === "") return null;
82452
- if (first === "") {
82453
- const suffix = Number(last);
82454
- if (suffix === 0 || size === 0) return "unsatisfiable";
82455
- return { start: Math.max(size - suffix, 0), end: size - 1 };
82456
- }
82457
- const start = Number(first);
82458
- if (last !== "" && Number(last) < start) return null;
82459
- if (start >= size) return "unsatisfiable";
82460
- return { start, end: last === "" ? size - 1 : Math.min(Number(last), size - 1) };
82461
- }
82462
- function localImageHeaders(result) {
82463
- return {
82464
- "content-type": result.contentType,
82465
- "content-length": String(result.end - result.start + 1),
82466
- "accept-ranges": "bytes",
82467
- "cache-control": "private, max-age=60",
82468
- ...result.status === 206 ? { "content-range": `bytes ${result.start}-${result.end}/${result.size}` } : {}
82469
- };
82470
- }
82471
- function localImageStream(result) {
82472
- if (result.end < result.start) return null;
82473
- return createReadStream(result.file, { start: result.start, end: result.end });
82474
- }
82475
- var IMAGE_CONTENT_TYPE, VIDEO_CONTENT_TYPE, CONTENT_TYPE;
82476
- var init_local_image = __esm({
82477
- "packages/server/src/local-image.ts"() {
82478
- "use strict";
82479
- init_local_path();
82480
- IMAGE_CONTENT_TYPE = {
82481
- ".png": "image/png",
82482
- ".jpg": "image/jpeg",
82483
- ".jpeg": "image/jpeg",
82484
- ".gif": "image/gif",
82485
- ".webp": "image/webp"
82486
- };
82487
- VIDEO_CONTENT_TYPE = {
82488
- ".mp4": "video/mp4",
82489
- ".m4v": "video/mp4",
82490
- ".webm": "video/webm",
82491
- ".mov": "video/quicktime"
82492
- };
82493
- CONTENT_TYPE = { ...IMAGE_CONTENT_TYPE, ...VIDEO_CONTENT_TYPE };
82494
- }
82495
- });
82496
-
82497
82658
  // packages/server/src/project-icon.ts
82498
- import { readFileSync as readFileSync29, readdirSync as readdirSync12, realpathSync as realpathSync13, statSync as statSync21 } from "node:fs";
82659
+ import { readFileSync as readFileSync31, readdirSync as readdirSync13, realpathSync as realpathSync13, statSync as statSync21 } from "node:fs";
82499
82660
  import { homedir as homedir18 } from "node:os";
82500
- import { basename as basename10, dirname as dirname19, extname as extname3, join as join42, relative as relative2, sep as sep4 } from "node:path";
82661
+ import { basename as basename10, dirname as dirname21, extname as extname3, join as join45, relative as relative2, sep as sep4 } from "node:path";
82501
82662
  function normalizeStem(stem) {
82502
82663
  const sized = stem.toLowerCase().replace(/[@-]\d+(\.\d+)?x(\d+)?$/u, "").replace(/[-_]\d{2,4}$/u, "");
82503
82664
  const normalized = sized.replace(VARIANT_SUFFIX, "");
@@ -82515,11 +82676,11 @@ function sizeScore(dimensions) {
82515
82676
  return Math.max(0, Math.min(40, Math.round(Math.log2(edge / 24) * 8)));
82516
82677
  }
82517
82678
  function under(root, relativeDirectory) {
82518
- return relativeDirectory ? join42(root, relativeDirectory) : root;
82679
+ return relativeDirectory ? join45(root, relativeDirectory) : root;
82519
82680
  }
82520
82681
  function listFiles(directory) {
82521
82682
  try {
82522
- return readdirSync12(directory, { withFileTypes: true }).filter((entry) => entry.isFile() || entry.isSymbolicLink()).map((entry) => entry.name);
82683
+ return readdirSync13(directory, { withFileTypes: true }).filter((entry) => entry.isFile() || entry.isSymbolicLink()).map((entry) => entry.name);
82523
82684
  } catch {
82524
82685
  return [];
82525
82686
  }
@@ -82528,7 +82689,7 @@ function iconDirectories(root) {
82528
82689
  let children2;
82529
82690
  try {
82530
82691
  children2 = new Set(
82531
- readdirSync12(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name)
82692
+ readdirSync13(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name)
82532
82693
  );
82533
82694
  } catch {
82534
82695
  return [root];
@@ -82537,19 +82698,19 @@ function iconDirectories(root) {
82537
82698
  for (const asset of ASSET_DIRECTORIES) directories.push(under(root, asset));
82538
82699
  for (const host of HOST_DIRECTORIES) {
82539
82700
  if (!children2.has(host)) continue;
82540
- for (const asset of ASSET_DIRECTORIES) directories.push(under(join42(root, host), asset));
82701
+ for (const asset of ASSET_DIRECTORIES) directories.push(under(join45(root, host), asset));
82541
82702
  }
82542
82703
  for (const extra of EXTRA_DIRECTORIES) directories.push(under(root, extra));
82543
82704
  for (const container of WORKSPACE_CONTAINERS) {
82544
82705
  if (!children2.has(container)) continue;
82545
82706
  let members;
82546
82707
  try {
82547
- members = readdirSync12(join42(root, container), { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
82708
+ members = readdirSync13(join45(root, container), { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
82548
82709
  } catch {
82549
82710
  continue;
82550
82711
  }
82551
82712
  for (const member of members) {
82552
- for (const asset of ASSET_DIRECTORIES) directories.push(under(join42(root, container, member), asset));
82713
+ for (const asset of ASSET_DIRECTORIES) directories.push(under(join45(root, container, member), asset));
82553
82714
  }
82554
82715
  }
82555
82716
  return [...new Set(directories)];
@@ -82557,13 +82718,13 @@ function iconDirectories(root) {
82557
82718
  function manifestIcons(manifestPath) {
82558
82719
  let parsed;
82559
82720
  try {
82560
- parsed = JSON.parse(readFileSync29(manifestPath, "utf8"));
82721
+ parsed = JSON.parse(readFileSync31(manifestPath, "utf8"));
82561
82722
  } catch {
82562
82723
  return [];
82563
82724
  }
82564
82725
  if (!Array.isArray(parsed?.icons)) return [];
82565
- const directory = dirname19(manifestPath);
82566
- return parsed.icons.map((icon) => typeof icon?.src === "string" ? icon.src : void 0).filter((src) => !!src && !/^(https?:)?\/\//u.test(src) && !src.startsWith("data:")).map((src) => join42(directory, src.replace(/[?#].*$/u, "").replace(/^\//u, "")));
82726
+ const directory = dirname21(manifestPath);
82727
+ return parsed.icons.map((icon) => typeof icon?.src === "string" ? icon.src : void 0).filter((src) => !!src && !/^(https?:)?\/\//u.test(src) && !src.startsWith("data:")).map((src) => join45(directory, src.replace(/[?#].*$/u, "").replace(/^\//u, "")));
82567
82728
  }
82568
82729
  function projectIconCandidates(root) {
82569
82730
  const projectStem = normalizeStem(basename10(root)).normalized;
@@ -82582,10 +82743,10 @@ function projectIconCandidates(root) {
82582
82743
  for (const name of listFiles(directory)) {
82583
82744
  const extension2 = extname3(name).toLowerCase();
82584
82745
  if (MANIFEST_NAMES.includes(name.toLowerCase())) {
82585
- for (const icon of manifestIcons(join42(directory, name))) {
82746
+ for (const icon of manifestIcons(join45(directory, name))) {
82586
82747
  if (MEASURABLE_IMAGE_EXTENSIONS.has(extname3(icon).toLowerCase())) {
82587
82748
  fromManifest.add(icon);
82588
- files.push({ path: icon, directory: dirname19(icon) });
82749
+ files.push({ path: icon, directory: dirname21(icon) });
82589
82750
  }
82590
82751
  }
82591
82752
  continue;
@@ -82593,7 +82754,7 @@ function projectIconCandidates(root) {
82593
82754
  if (!MEASURABLE_IMAGE_EXTENSIONS.has(extension2)) continue;
82594
82755
  const stem = name.slice(0, name.length - extension2.length);
82595
82756
  if (normalizeStem(stem).normalized === "favicon") iconHomes.add(directory);
82596
- files.push({ path: join42(directory, name), directory });
82757
+ files.push({ path: join45(directory, name), directory });
82597
82758
  if (files.length >= MAX_CANDIDATES) break;
82598
82759
  }
82599
82760
  }
@@ -82658,7 +82819,7 @@ function resolveProjectIconResponse(id2, options = {}) {
82658
82819
  });
82659
82820
  if (!roots.some((root) => real === root || real.startsWith(root + sep4))) return { status: 404 };
82660
82821
  try {
82661
- return { status: 200, contentType, body: readFileSync29(real) };
82822
+ return { status: 200, contentType, body: readFileSync31(real) };
82662
82823
  } catch {
82663
82824
  return { status: 404 };
82664
82825
  }
@@ -82770,11 +82931,11 @@ var init_project_icon = __esm({
82770
82931
  });
82771
82932
 
82772
82933
  // packages/server/src/local-visualization.ts
82773
- import { readdirSync as readdirSync13, readFileSync as readFileSync30, realpathSync as realpathSync14, statSync as statSync22 } from "node:fs";
82774
- import { join as join43, sep as sep5 } from "node:path";
82934
+ import { readdirSync as readdirSync14, readFileSync as readFileSync32, realpathSync as realpathSync14, statSync as statSync22 } from "node:fs";
82935
+ import { join as join46, sep as sep5 } from "node:path";
82775
82936
  function children(path3, pattern) {
82776
82937
  try {
82777
- return readdirSync13(path3, { withFileTypes: true }).filter((entry) => entry.isDirectory() && pattern.test(entry.name)).map((entry) => entry.name).sort().reverse();
82938
+ return readdirSync14(path3, { withFileTypes: true }).filter((entry) => entry.isDirectory() && pattern.test(entry.name)).map((entry) => entry.name).sort().reverse();
82778
82939
  } catch {
82779
82940
  return [];
82780
82941
  }
@@ -82783,7 +82944,7 @@ function isUnder2(path3, root) {
82783
82944
  return path3 === root || path3.startsWith(root.endsWith(sep5) ? root : root + sep5);
82784
82945
  }
82785
82946
  function resolveFragment(projectDir, sessionId, file) {
82786
- const base = join43(projectDir, ".codex", "visualizations");
82947
+ const base = join46(projectDir, ".codex", "visualizations");
82787
82948
  let projectReal;
82788
82949
  let baseReal;
82789
82950
  try {
@@ -82794,12 +82955,12 @@ function resolveFragment(projectDir, sessionId, file) {
82794
82955
  }
82795
82956
  if (!isUnder2(baseReal, projectReal)) return null;
82796
82957
  for (const year of children(base, YEAR_PART)) {
82797
- const yearDir = join43(base, year);
82958
+ const yearDir = join46(base, year);
82798
82959
  for (const month of children(yearDir, DATE_PART)) {
82799
- const monthDir = join43(yearDir, month);
82960
+ const monthDir = join46(yearDir, month);
82800
82961
  for (const day of children(monthDir, DATE_PART)) {
82801
- const sessionRoot = join43(baseReal, year, month, day, sessionId);
82802
- const candidate = join43(monthDir, day, sessionId, file);
82962
+ const sessionRoot = join46(baseReal, year, month, day, sessionId);
82963
+ const candidate = join46(monthDir, day, sessionId, file);
82803
82964
  try {
82804
82965
  const real = realpathSync14(candidate);
82805
82966
  if (isUnder2(real, sessionRoot) && statSync22(real).isFile()) return real;
@@ -82889,7 +83050,7 @@ function resolveLocalVisualization(projectDir, sessionId, file) {
82889
83050
  try {
82890
83051
  const size = statSync22(path3).size;
82891
83052
  if (size > MAX_FRAGMENT_BYTES) return { status: 413 };
82892
- fragment = readFileSync30(path3, "utf8");
83053
+ fragment = readFileSync32(path3, "utf8");
82893
83054
  } catch {
82894
83055
  return { status: 404 };
82895
83056
  }
@@ -82931,9 +83092,9 @@ var init_local_visualization = __esm({
82931
83092
  });
82932
83093
 
82933
83094
  // packages/server/src/app.ts
82934
- import { mkdirSync as mkdirSync21, writeFileSync as writeFileSync16 } from "node:fs";
83095
+ import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync18 } from "node:fs";
82935
83096
  import { Readable } from "node:stream";
82936
- import { join as join44 } from "node:path";
83097
+ import { join as join47 } from "node:path";
82937
83098
  import { randomUUID as randomUUID18 } from "node:crypto";
82938
83099
  function createApp(ctx, options = {}) {
82939
83100
  const app = new Hono2();
@@ -82994,8 +83155,8 @@ function createApp(ctx, options = {}) {
82994
83155
  const supplied = c.req.header("x-frizz-launch-token");
82995
83156
  if (!options.controlToken || !supplied || supplied !== options.controlToken) return c.text("Forbidden", 403);
82996
83157
  if (!options.requestOwnerStop) return c.text("Owner control unavailable", 503);
82997
- const stop = setTimeout(options.requestOwnerStop, 25);
82998
- stop.unref();
83158
+ const stop2 = setTimeout(options.requestOwnerStop, 25);
83159
+ stop2.unref();
82999
83160
  return c.json({ accepted: true }, 202);
83000
83161
  });
83001
83162
  app.get(frizzRoute("/local-image"), (c) => {
@@ -83040,11 +83201,11 @@ function createApp(ctx, options = {}) {
83040
83201
  if (typeof body.data !== "string" || body.data.length > ATTACHMENT_MAX_BASE64_CHARS) return c.json({ error: "bad payload" }, 400);
83041
83202
  const ext = `.${attachmentExtension(name)}`;
83042
83203
  const buf = Buffer.from(body.data, "base64");
83043
- const dir = join44(ctx.project.stateDir, "attachments");
83044
- mkdirSync21(dir, { recursive: true });
83204
+ const dir = join47(ctx.project.stateDir, "attachments");
83205
+ mkdirSync23(dir, { recursive: true });
83045
83206
  const base = name.replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]+/g, "-").slice(0, 40) || "file";
83046
- const path3 = join44(dir, `${Date.now()}-${randomUUID18().slice(0, 8)}-${base}${ext}`);
83047
- writeFileSync16(path3, buf);
83207
+ const path3 = join47(dir, `${Date.now()}-${randomUUID18().slice(0, 8)}-${base}${ext}`);
83208
+ writeFileSync18(path3, buf);
83048
83209
  return c.json({ path: path3 });
83049
83210
  });
83050
83211
  app.get(
@@ -83964,7 +84125,7 @@ var init_app_socket = __esm({
83964
84125
 
83965
84126
  // packages/server/src/local-file-watch.ts
83966
84127
  import { statSync as statSync23, watch } from "node:fs";
83967
- import { basename as basename11, dirname as dirname20 } from "node:path";
84128
+ import { basename as basename11, dirname as dirname22 } from "node:path";
83968
84129
  function stampOf(path3) {
83969
84130
  try {
83970
84131
  const s = statSync23(path3, { bigint: true });
@@ -83987,7 +84148,7 @@ function watchLocalFile(path3, onChange) {
83987
84148
  let entry = entries.get(path3);
83988
84149
  if (!entry) {
83989
84150
  const name = basename11(path3);
83990
- const watcher2 = watch(dirname20(path3), { persistent: false }, (_event, changed) => {
84151
+ const watcher2 = watch(dirname22(path3), { persistent: false }, (_event, changed) => {
83991
84152
  if (changed !== null && changed !== void 0 && changed.toString() !== name) return;
83992
84153
  const current = entries.get(path3);
83993
84154
  if (!current) return;
@@ -84023,10 +84184,10 @@ var init_local_file_watch = __esm({
84023
84184
  });
84024
84185
 
84025
84186
  // packages/server/src/boot-progress.ts
84026
- import { mkdirSync as mkdirSync22, readFileSync as readFileSync31, renameSync as renameSync11, rmSync as rmSync12, writeFileSync as writeFileSync17 } from "node:fs";
84027
- import { basename as basename12, dirname as dirname21, join as join45 } from "node:path";
84187
+ import { mkdirSync as mkdirSync24, readFileSync as readFileSync33, renameSync as renameSync11, rmSync as rmSync13, writeFileSync as writeFileSync19 } from "node:fs";
84188
+ import { basename as basename12, dirname as dirname23, join as join48 } from "node:path";
84028
84189
  function bootProgressPath(stateDir) {
84029
- return join45(stateDir, BOOT_PROGRESS_NAME);
84190
+ return join48(stateDir, BOOT_PROGRESS_NAME);
84030
84191
  }
84031
84192
  function createBootProgressPublisher(stateDir, minIntervalMs = 200) {
84032
84193
  if (!stateDir) {
@@ -84046,9 +84207,9 @@ function createBootProgressPublisher(stateDir, minIntervalMs = 200) {
84046
84207
  lastAt = now;
84047
84208
  step++;
84048
84209
  try {
84049
- mkdirSync22(dirname21(path3), { recursive: true, mode: 448 });
84050
- const temp = join45(dirname21(path3), `.${basename12(path3)}.${process.pid}.tmp`);
84051
- writeFileSync17(temp, `${JSON.stringify({ pid: process.pid, step, phase, at: new Date(now).toISOString() })}
84210
+ mkdirSync24(dirname23(path3), { recursive: true, mode: 448 });
84211
+ const temp = join48(dirname23(path3), `.${basename12(path3)}.${process.pid}.tmp`);
84212
+ writeFileSync19(temp, `${JSON.stringify({ pid: process.pid, step, phase, at: new Date(now).toISOString() })}
84052
84213
  `, "utf8");
84053
84214
  renameSync11(temp, path3);
84054
84215
  } catch {
@@ -84057,7 +84218,7 @@ function createBootProgressPublisher(stateDir, minIntervalMs = 200) {
84057
84218
  return Object.assign(write, {
84058
84219
  done: () => {
84059
84220
  try {
84060
- rmSync12(path3, { force: true });
84221
+ rmSync13(path3, { force: true });
84061
84222
  } catch {
84062
84223
  }
84063
84224
  }
@@ -84073,13 +84234,13 @@ var init_boot_progress = __esm({
84073
84234
  });
84074
84235
 
84075
84236
  // packages/server/src/runtime-lease.ts
84076
- import { existsSync as existsSync20, mkdirSync as mkdirSync23, readdirSync as readdirSync14, readFileSync as readFileSync32, unlinkSync as unlinkSync8, writeFileSync as writeFileSync18 } from "node:fs";
84077
- import { dirname as dirname22, join as join46 } from "node:path";
84237
+ import { existsSync as existsSync22, mkdirSync as mkdirSync25, readdirSync as readdirSync15, readFileSync as readFileSync34, unlinkSync as unlinkSync8, writeFileSync as writeFileSync20 } from "node:fs";
84238
+ import { dirname as dirname24, join as join49 } from "node:path";
84078
84239
  function runtimeVersionDir(bin) {
84079
- let dir = dirname22(bin);
84240
+ let dir = dirname24(bin);
84080
84241
  for (let step = 0; step < MAX_ASCENT; step++) {
84081
- if (existsSync20(join46(dir, PROVISIONED_MARKER))) return dir;
84082
- const parent = dirname22(dir);
84242
+ if (existsSync22(join49(dir, PROVISIONED_MARKER))) return dir;
84243
+ const parent = dirname24(dir);
84083
84244
  if (parent === dir) return void 0;
84084
84245
  dir = parent;
84085
84246
  }
@@ -84097,11 +84258,11 @@ function leaseRuntime(bin, role) {
84097
84258
  const versionDir = runtimeVersionDir(bin);
84098
84259
  if (!versionDir) return () => {
84099
84260
  };
84100
- const path3 = join46(versionDir, LEASES_DIR, `${process.pid}.json`);
84261
+ const path3 = join49(versionDir, LEASES_DIR, `${process.pid}.json`);
84101
84262
  try {
84102
- mkdirSync23(dirname22(path3), { recursive: true });
84263
+ mkdirSync25(dirname24(path3), { recursive: true });
84103
84264
  const lease = { pid: process.pid, role, bin, at: (/* @__PURE__ */ new Date()).toISOString() };
84104
- writeFileSync18(path3, JSON.stringify(lease));
84265
+ writeFileSync20(path3, JSON.stringify(lease));
84105
84266
  } catch {
84106
84267
  return () => {
84107
84268
  };
@@ -84114,20 +84275,20 @@ function leaseRuntime(bin, role) {
84114
84275
  };
84115
84276
  }
84116
84277
  function liveRuntimeLeases(versionDir) {
84117
- const dir = join46(versionDir, LEASES_DIR);
84278
+ const dir = join49(versionDir, LEASES_DIR);
84118
84279
  let names;
84119
84280
  try {
84120
- names = readdirSync14(dir);
84281
+ names = readdirSync15(dir);
84121
84282
  } catch {
84122
84283
  return [];
84123
84284
  }
84124
84285
  const live = [];
84125
84286
  for (const name of names) {
84126
84287
  if (!name.endsWith(".json")) continue;
84127
- const path3 = join46(dir, name);
84288
+ const path3 = join49(dir, name);
84128
84289
  let lease;
84129
84290
  try {
84130
- lease = JSON.parse(readFileSync32(path3, "utf8"));
84291
+ lease = JSON.parse(readFileSync34(path3, "utf8"));
84131
84292
  } catch {
84132
84293
  continue;
84133
84294
  }
@@ -84156,27 +84317,27 @@ var init_runtime_lease = __esm({
84156
84317
  // packages/server/src/runtimes.ts
84157
84318
  import { createHash as createHash17 } from "node:crypto";
84158
84319
  import {
84159
- chmodSync as chmodSync2,
84160
- closeSync as closeSync17,
84161
- existsSync as existsSync21,
84162
- mkdirSync as mkdirSync24,
84163
- openSync as openSync18,
84164
- readFileSync as readFileSync33,
84165
- readdirSync as readdirSync15,
84320
+ chmodSync as chmodSync4,
84321
+ closeSync as closeSync18,
84322
+ existsSync as existsSync23,
84323
+ mkdirSync as mkdirSync26,
84324
+ openSync as openSync19,
84325
+ readFileSync as readFileSync35,
84326
+ readdirSync as readdirSync16,
84166
84327
  renameSync as renameSync12,
84167
- rmSync as rmSync13,
84328
+ rmSync as rmSync14,
84168
84329
  statSync as statSync24,
84169
- writeFileSync as writeFileSync19,
84170
- writeSync as writeSync2
84330
+ writeFileSync as writeFileSync21,
84331
+ writeSync as writeSync3
84171
84332
  } from "node:fs";
84172
- import { dirname as dirname23, isAbsolute as isAbsolute10, join as join47, normalize, relative as relative3, sep as sep6 } from "node:path";
84333
+ import { dirname as dirname25, isAbsolute as isAbsolute10, join as join50, normalize, relative as relative3, sep as sep6 } from "node:path";
84173
84334
  import { Readable as Readable2, Transform, Writable as Writable4 } from "node:stream";
84174
84335
  import { pipeline } from "node:stream/promises";
84175
84336
  import { createGunzip } from "node:zlib";
84176
84337
  function runtimesRoot(env = process.env) {
84177
84338
  const override = env[RUNTIMES_DIR_ENV];
84178
84339
  if (override && isAbsolute10(override)) return override;
84179
- return join47(frizzRoots().cache, "runtimes");
84340
+ return join50(frizzRoots().cache, "runtimes");
84180
84341
  }
84181
84342
  function isMusl() {
84182
84343
  if (process.platform !== "linux") return false;
@@ -84193,16 +84354,16 @@ function runtimeCoordinates(backend, platform3 = process.platform, arch = proces
84193
84354
  return { pkg: "@openai/codex", packageVersion: `${CODEX_VERSION}-${platform3}-${arch}`, label: CODEX_VERSION, binary: `codex${exe2}` };
84194
84355
  }
84195
84356
  function provisionedBinary(backend, root, label) {
84196
- const dir = join47(root, backend, label);
84357
+ const dir = join50(root, backend, label);
84197
84358
  let marker;
84198
84359
  try {
84199
- marker = JSON.parse(readFileSync33(join47(dir, MARKER), "utf8"));
84360
+ marker = JSON.parse(readFileSync35(join50(dir, MARKER), "utf8"));
84200
84361
  } catch {
84201
84362
  return void 0;
84202
84363
  }
84203
84364
  if (typeof marker.binary !== "string" || marker.label !== label) return void 0;
84204
- const bin = join47(dir, marker.binary);
84205
- return existsSync21(bin) ? bin : void 0;
84365
+ const bin = join50(dir, marker.binary);
84366
+ return existsSync23(bin) ? bin : void 0;
84206
84367
  }
84207
84368
  function octal(buffer, offset, length) {
84208
84369
  const text2 = buffer.toString("latin1", offset, offset + length).replace(/\0.*$/su, "").trim();
@@ -84216,26 +84377,26 @@ function safeEntryPath(dest, name) {
84216
84377
  if (parts.length < 2) return void 0;
84217
84378
  const rel = normalize(parts.slice(1).join(sep6));
84218
84379
  if (isAbsolute10(rel) || rel === ".." || rel.startsWith(`..${sep6}`)) return void 0;
84219
- const full = join47(dest, rel);
84380
+ const full = join50(dest, rel);
84220
84381
  const back = relative3(dest, full);
84221
84382
  if (back.startsWith("..") || isAbsolute10(back)) return void 0;
84222
84383
  return full;
84223
84384
  }
84224
84385
  function locateBinary(dir, backend, binary) {
84225
84386
  if (backend === "claude") {
84226
- const direct = join47(dir, binary);
84227
- return existsSync21(direct) ? direct : void 0;
84387
+ const direct = join50(dir, binary);
84388
+ return existsSync23(direct) ? direct : void 0;
84228
84389
  }
84229
- const vendor = join47(dir, "vendor");
84390
+ const vendor = join50(dir, "vendor");
84230
84391
  let triples;
84231
84392
  try {
84232
- triples = readdirSync15(vendor);
84393
+ triples = readdirSync16(vendor);
84233
84394
  } catch {
84234
84395
  return void 0;
84235
84396
  }
84236
84397
  for (const triple of triples) {
84237
- const candidate = join47(vendor, triple, "bin", binary);
84238
- if (existsSync21(candidate)) return candidate;
84398
+ const candidate = join50(vendor, triple, "bin", binary);
84399
+ if (existsSync23(candidate)) return candidate;
84239
84400
  }
84240
84401
  return void 0;
84241
84402
  }
@@ -84250,12 +84411,12 @@ async function provisionRuntime(backend, options) {
84250
84411
  const registry = options.registry ?? REGISTRY;
84251
84412
  const progress = options.onProgress ?? (() => {
84252
84413
  });
84253
- const backendDir = join47(root, backend);
84254
- const finalDir = join47(backendDir, coordinates.label);
84255
- const partial = join47(backendDir, `.partial-${coordinates.label}-${process.pid}`);
84256
- mkdirSync24(backendDir, { recursive: true });
84257
- rmSync13(partial, { recursive: true, force: true });
84258
- mkdirSync24(partial);
84414
+ const backendDir = join50(root, backend);
84415
+ const finalDir = join50(backendDir, coordinates.label);
84416
+ const partial = join50(backendDir, `.partial-${coordinates.label}-${process.pid}`);
84417
+ mkdirSync26(backendDir, { recursive: true });
84418
+ rmSync14(partial, { recursive: true, force: true });
84419
+ mkdirSync26(partial);
84259
84420
  try {
84260
84421
  const manifestUrl = `${registry}/${coordinates.pkg.replace("/", "%2F")}/${coordinates.packageVersion}`;
84261
84422
  progress(`resolving ${coordinates.pkg}@${coordinates.packageVersion}`);
@@ -84289,7 +84450,7 @@ async function provisionRuntime(backend, options) {
84289
84450
  if (digest !== integrity) throw new Error(`integrity mismatch for ${tarball}: expected ${integrity}, got ${digest}`);
84290
84451
  const bin = locateBinary(partial, backend, coordinates.binary);
84291
84452
  if (!bin) throw new Error(`${coordinates.pkg}@${coordinates.packageVersion} unpacked without a ${coordinates.binary} binary`);
84292
- if (process.platform !== "win32") chmodSync2(bin, 493);
84453
+ if (process.platform !== "win32") chmodSync4(bin, 493);
84293
84454
  const marker = {
84294
84455
  backend,
84295
84456
  label: coordinates.label,
@@ -84299,7 +84460,7 @@ async function provisionRuntime(backend, options) {
84299
84460
  binary: relative3(partial, bin),
84300
84461
  at: (/* @__PURE__ */ new Date()).toISOString()
84301
84462
  };
84302
- writeFileSync19(join47(partial, MARKER), `${JSON.stringify(marker, null, 2)}
84463
+ writeFileSync21(join50(partial, MARKER), `${JSON.stringify(marker, null, 2)}
84303
84464
  `, "utf8");
84304
84465
  const rename2 = options.rename ?? renameSync12;
84305
84466
  try {
@@ -84308,36 +84469,36 @@ async function provisionRuntime(backend, options) {
84308
84469
  rename2(partial, finalDir);
84309
84470
  break;
84310
84471
  } catch (err) {
84311
- if (attempt >= RENAME_ATTEMPTS || !TRANSIENT_HANDLE_CODES.has(errorCode4(err) ?? "") || existsSync21(finalDir)) throw err;
84472
+ if (attempt >= RENAME_ATTEMPTS || !TRANSIENT_HANDLE_CODES.has(errorCode4(err) ?? "") || existsSync23(finalDir)) throw err;
84312
84473
  await new Promise((resolve13) => setTimeout(resolve13, options.retryDelayMs ?? RENAME_RETRY_DELAY_MS));
84313
84474
  }
84314
84475
  }
84315
84476
  } catch (err) {
84316
84477
  const theirs = provisionedBinary(backend, root, coordinates.label);
84317
84478
  if (!theirs) throw err;
84318
- rmSync13(partial, { recursive: true, force: true });
84479
+ rmSync14(partial, { recursive: true, force: true });
84319
84480
  return { bin: theirs, label: coordinates.label, fetched: false };
84320
84481
  }
84321
84482
  progress("ready");
84322
- return { bin: join47(finalDir, marker.binary), label: coordinates.label, fetched: true };
84483
+ return { bin: join50(finalDir, marker.binary), label: coordinates.label, fetched: true };
84323
84484
  } catch (err) {
84324
- rmSync13(partial, { recursive: true, force: true });
84485
+ rmSync14(partial, { recursive: true, force: true });
84325
84486
  throw err;
84326
84487
  }
84327
84488
  }
84328
84489
  function sweepRuntimes(backend, root, keepLabel, now = Date.now(), deps = {}) {
84329
84490
  const rm2 = deps.rm ?? defaultSweepRm;
84330
- const backendDir = join47(root, backend);
84491
+ const backendDir = join50(root, backend);
84331
84492
  let entries2;
84332
84493
  try {
84333
- entries2 = readdirSync15(backendDir);
84494
+ entries2 = readdirSync16(backendDir);
84334
84495
  } catch {
84335
84496
  return { removed: [], kept: [] };
84336
84497
  }
84337
84498
  const sweep = { removed: [], kept: [] };
84338
84499
  for (const entry of entries2) {
84339
84500
  if (entry === keepLabel) continue;
84340
- const full = join47(backendDir, entry);
84501
+ const full = join50(backendDir, entry);
84341
84502
  if (entry.startsWith(".partial-")) {
84342
84503
  try {
84343
84504
  if (now - statSync24(full).mtimeMs < 24 * 60 * 60 * 1e3) continue;
@@ -84463,7 +84624,7 @@ var init_runtimes = __esm({
84463
84624
  }
84464
84625
  }
84465
84626
  _final(callback) {
84466
- if (this.fd !== void 0) closeSync17(this.fd);
84627
+ if (this.fd !== void 0) closeSync18(this.fd);
84467
84628
  this.fd = void 0;
84468
84629
  callback(this.remaining > 0 ? new Error("tarball ended inside a file entry") : null);
84469
84630
  }
@@ -84520,7 +84681,7 @@ var init_runtimes = __esm({
84520
84681
  return;
84521
84682
  case "5": {
84522
84683
  const dir = safeEntryPath(this.dest, name);
84523
- if (dir) mkdirSync24(dir, { recursive: true });
84684
+ if (dir) mkdirSync26(dir, { recursive: true });
84524
84685
  return;
84525
84686
  }
84526
84687
  case "0":
@@ -84528,8 +84689,8 @@ var init_runtimes = __esm({
84528
84689
  case "7": {
84529
84690
  const file = safeEntryPath(this.dest, name);
84530
84691
  if (!file) return;
84531
- mkdirSync24(dirname23(file), { recursive: true });
84532
- this.fd = openSync18(file, "w", octal(header, 100, 8) & 511 || 420);
84692
+ mkdirSync26(dirname25(file), { recursive: true });
84693
+ this.fd = openSync19(file, "w", octal(header, 100, 8) & 511 || 420);
84533
84694
  this.written.push(file);
84534
84695
  return;
84535
84696
  }
@@ -84538,13 +84699,13 @@ var init_runtimes = __esm({
84538
84699
  }
84539
84700
  }
84540
84701
  sink(bytes) {
84541
- if (this.fd !== void 0) writeSync2(this.fd, bytes);
84702
+ if (this.fd !== void 0) writeSync3(this.fd, bytes);
84542
84703
  else if (this.nameBuffer) this.nameBuffer.push(Buffer.from(bytes));
84543
84704
  else if (this.paxBuffer) this.paxBuffer.push(Buffer.from(bytes));
84544
84705
  }
84545
84706
  finishEntry() {
84546
84707
  if (this.fd !== void 0) {
84547
- closeSync17(this.fd);
84708
+ closeSync18(this.fd);
84548
84709
  this.fd = void 0;
84549
84710
  }
84550
84711
  if (this.nameBuffer) {
@@ -84572,7 +84733,7 @@ var init_runtimes = __esm({
84572
84733
  RENAME_RETRY_DELAY_MS = 200;
84573
84734
  TRANSIENT_HANDLE_CODES = /* @__PURE__ */ new Set(["EPERM", "EBUSY", "EACCES", "ENOTEMPTY"]);
84574
84735
  errorCode4 = (err) => err?.code;
84575
- defaultSweepRm = (path3) => rmSync13(path3, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
84736
+ defaultSweepRm = (path3) => rmSync14(path3, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
84576
84737
  }
84577
84738
  });
84578
84739
 
@@ -85108,18 +85269,18 @@ var init_legacy_project_db = __esm({
85108
85269
  });
85109
85270
 
85110
85271
  // packages/server/src/frizz-db.ts
85111
- import { existsSync as existsSync22, mkdirSync as mkdirSync25, readdirSync as readdirSync16, renameSync as renameSync13, statSync as statSync25 } from "node:fs";
85112
- import { basename as basename13, dirname as dirname24, join as join48 } from "node:path";
85272
+ import { existsSync as existsSync24, mkdirSync as mkdirSync27, readdirSync as readdirSync17, renameSync as renameSync13, statSync as statSync25 } from "node:fs";
85273
+ import { basename as basename13, dirname as dirname26, join as join51 } from "node:path";
85113
85274
  function frizzDatabaseLocation(options) {
85114
85275
  if (options.stateDir !== void 0) {
85115
- const projectsDir = dirname24(options.stateDir);
85276
+ const projectsDir = dirname26(options.stateDir);
85116
85277
  if (basename13(projectsDir) === "projects") {
85117
- return { path: options.path ?? join48(dirname24(projectsDir), "ui.db"), projectsDir };
85278
+ return { path: options.path ?? join51(dirname26(projectsDir), "ui.db"), projectsDir };
85118
85279
  }
85119
- return { path: options.path ?? join48(options.stateDir, "ui.db"), projectsDir: void 0 };
85280
+ return { path: options.path ?? join51(options.stateDir, "ui.db"), projectsDir: void 0 };
85120
85281
  }
85121
85282
  const data = options.home ? frizzPaths({ home: options.home }).data : frizzRoots().data;
85122
- return { path: options.path ?? join48(data, "ui.db"), projectsDir: join48(data, "projects") };
85283
+ return { path: options.path ?? join51(data, "ui.db"), projectsDir: join51(data, "projects") };
85123
85284
  }
85124
85285
  function ensureFrizzSchema(db2) {
85125
85286
  db2.exec(`
@@ -85138,7 +85299,7 @@ function ensureFrizzSchema(db2) {
85138
85299
  }
85139
85300
  function openFrizzDatabase(options = {}) {
85140
85301
  const { path: path3, projectsDir } = frizzDatabaseLocation(options);
85141
- mkdirSync25(dirname24(path3), { recursive: true });
85302
+ mkdirSync27(dirname26(path3), { recursive: true });
85142
85303
  const db2 = new sqlite_default(path3);
85143
85304
  db2.pragma("busy_timeout = 5000");
85144
85305
  db2.pragma("journal_mode = WAL");
@@ -85150,10 +85311,10 @@ function openFrizzDatabase(options = {}) {
85150
85311
  );
85151
85312
  for (const projectId of retiredLegacyProjectIds(projectsDir)) {
85152
85313
  if (alreadyImported.has(projectId)) continue;
85153
- const dir = join48(projectsDir, projectId);
85314
+ const dir = join51(projectsDir, projectId);
85154
85315
  try {
85155
- renameSync13(join48(dir, "ui.db.imported"), join48(dir, "ui.db"));
85156
- db2.prepare("INSERT INTO imported_project (project_id, source, rows, imported_at) VALUES (?, ?, 0, ?)").run(projectId, join48(dir, "ui.db"), (/* @__PURE__ */ new Date()).toISOString());
85316
+ renameSync13(join51(dir, "ui.db.imported"), join51(dir, "ui.db"));
85317
+ db2.prepare("INSERT INTO imported_project (project_id, source, rows, imported_at) VALUES (?, ?, 0, ?)").run(projectId, join51(dir, "ui.db"), (/* @__PURE__ */ new Date()).toISOString());
85157
85318
  alreadyImported.add(projectId);
85158
85319
  log.info("frizz-db", `${projectId}: restored ui.db.imported to ui.db and recorded it as imported`);
85159
85320
  } catch (error) {
@@ -85163,7 +85324,7 @@ function openFrizzDatabase(options = {}) {
85163
85324
  }
85164
85325
  for (const projectId of legacyProjectIds(projectsDir)) {
85165
85326
  if (alreadyImported.has(projectId)) continue;
85166
- const legacyPath = join48(projectsDir, projectId, "ui.db");
85327
+ const legacyPath = join51(projectsDir, projectId, "ui.db");
85167
85328
  try {
85168
85329
  const rows = importLegacyProject(db2, projectId, legacyPath);
85169
85330
  imported.push({ projectId, rows });
@@ -85193,10 +85354,10 @@ function openFrizzDatabase(options = {}) {
85193
85354
  };
85194
85355
  }
85195
85356
  function projectIdsWithFile(projectsDir, file) {
85196
- if (!existsSync22(projectsDir)) return [];
85197
- return readdirSync16(projectsDir).filter((name) => {
85357
+ if (!existsSync24(projectsDir)) return [];
85358
+ return readdirSync17(projectsDir).filter((name) => {
85198
85359
  try {
85199
- return statSync25(join48(projectsDir, name, file)).isFile();
85360
+ return statSync25(join51(projectsDir, name, file)).isFile();
85200
85361
  } catch {
85201
85362
  return false;
85202
85363
  }
@@ -85206,7 +85367,7 @@ function legacyProjectIds(projectsDir) {
85206
85367
  return projectIdsWithFile(projectsDir, "ui.db");
85207
85368
  }
85208
85369
  function retiredLegacyProjectIds(projectsDir) {
85209
- return projectIdsWithFile(projectsDir, "ui.db.imported").filter((id2) => !existsSync22(join48(projectsDir, id2, "ui.db")));
85370
+ return projectIdsWithFile(projectsDir, "ui.db.imported").filter((id2) => !existsSync24(join51(projectsDir, id2, "ui.db")));
85210
85371
  }
85211
85372
  function tableColumns(db2, schema, table) {
85212
85373
  return db2.prepare(`PRAGMA ${schema}.table_info(${table})`).all().map((c) => c.name);
@@ -85360,9 +85521,9 @@ var init_tenant_prime = __esm({
85360
85521
  });
85361
85522
 
85362
85523
  // packages/server/src/project-teardown.ts
85363
- import { rmSync as rmSync14 } from "node:fs";
85524
+ import { rmSync as rmSync15 } from "node:fs";
85364
85525
  import { homedir as homedir19 } from "node:os";
85365
- import { dirname as dirname25, resolve as resolve11 } from "node:path";
85526
+ import { dirname as dirname27, resolve as resolve11 } from "node:path";
85366
85527
  async function stopProjectWorkers(ctx) {
85367
85528
  let stopped = 0;
85368
85529
  for (const row of ctx.storage.allSessions()) {
@@ -85382,10 +85543,10 @@ function deleteProjectState(projectId, home = homedir19()) {
85382
85543
  if (!/^[\w.-]+$/u.test(projectId) || projectId === "." || projectId === "..") {
85383
85544
  throw new Error(`Refusing to delete state for a malformed project id: ${projectId}`);
85384
85545
  }
85385
- if (dirname25(resolve11(target)) !== resolve11(dirname25(projectStateDir("x", home)))) {
85546
+ if (dirname27(resolve11(target)) !== resolve11(dirname27(projectStateDir("x", home)))) {
85386
85547
  throw new Error(`Refusing to delete ${target} \u2014 it is not a project state directory`);
85387
85548
  }
85388
- rmSync14(target, { recursive: true, force: true });
85549
+ rmSync15(target, { recursive: true, force: true });
85389
85550
  }
85390
85551
  var init_project_teardown = __esm({
85391
85552
  "packages/server/src/project-teardown.ts"() {
@@ -85411,11 +85572,11 @@ __export(index_exports, {
85411
85572
  unknownProjectPage: () => unknownProjectPage
85412
85573
  });
85413
85574
  import { createServer } from "node:http";
85414
- import { readFileSync as readFileSync34, existsSync as existsSync23, statSync as statSync26 } from "node:fs";
85415
- import { dirname as dirname26, join as join49, resolve as resolve12, extname as extname4, posix as posix2, sep as sep7 } from "node:path";
85575
+ import { readFileSync as readFileSync36, existsSync as existsSync25, statSync as statSync26 } from "node:fs";
85576
+ import { dirname as dirname28, join as join52, resolve as resolve12, extname as extname4, posix as posix2, sep as sep7 } from "node:path";
85416
85577
  function readServerAddressHolder(path3) {
85417
85578
  try {
85418
- const value = JSON.parse(readFileSync34(path3, "utf8"));
85579
+ const value = JSON.parse(readFileSync36(path3, "utf8"));
85419
85580
  if (typeof value?.pid !== "number") return void 0;
85420
85581
  return { pid: value.pid, port: typeof value.port === "number" ? value.port : -1 };
85421
85582
  } catch {
@@ -85540,12 +85701,12 @@ function staticIsFresh(req, etag, mtimeMs) {
85540
85701
  }
85541
85702
  function serveStatic(distDir, req, res) {
85542
85703
  const rel = posix2.normalize((req.url ?? "/").split("?")[0].replace(/\\/g, "/")).replace(/^(\.\.[/\\])+/, "");
85543
- let file = join49(distDir, rel === "/" ? "index.html" : rel);
85544
- if (!file.startsWith(distDir + sep7)) file = join49(distDir, "index.html");
85545
- if (!existsSync23(file)) file = join49(distDir, "index.html");
85704
+ let file = join52(distDir, rel === "/" ? "index.html" : rel);
85705
+ if (!file.startsWith(distDir + sep7)) file = join52(distDir, "index.html");
85706
+ if (!existsSync25(file)) file = join52(distDir, "index.html");
85546
85707
  try {
85547
85708
  const stats = statSync26(file);
85548
- const cacheControl = file.startsWith(join49(distDir, "assets") + sep7) ? STATIC_CACHE_IMMUTABLE : STATIC_CACHE_REVALIDATE;
85709
+ const cacheControl = file.startsWith(join52(distDir, "assets") + sep7) ? STATIC_CACHE_IMMUTABLE : STATIC_CACHE_REVALIDATE;
85549
85710
  const etag = `"${stats.size.toString(16)}-${Math.trunc(stats.mtimeMs).toString(16)}"`;
85550
85711
  const headers = {
85551
85712
  "content-type": MIME[extname4(file)] ?? "application/octet-stream",
@@ -85561,7 +85722,7 @@ function serveStatic(distDir, req, res) {
85561
85722
  res.end();
85562
85723
  return;
85563
85724
  }
85564
- let body = readFileSync34(file);
85725
+ let body = readFileSync36(file);
85565
85726
  const accept = req.headers["accept-encoding"];
85566
85727
  const encoding = negotiateEncoding(Array.isArray(accept) ? accept.join(",") : accept);
85567
85728
  if (encoding && shouldCompress(new Headers({ "content-type": headers["content-type"] }), body.byteLength)) {
@@ -85818,7 +85979,7 @@ async function startServer(opts = {}) {
85818
85979
  if (statusPath && statusIdentity) runtime.removeStatus(statusPath, statusIdentity);
85819
85980
  if (statusPath && statusIdentity) {
85820
85981
  try {
85821
- runtime.removeStatus(serverAddressPathForStateDir(dirname26(statusPath)), statusIdentity);
85982
+ runtime.removeStatus(serverAddressPathForStateDir(dirname28(statusPath)), statusIdentity);
85822
85983
  } catch {
85823
85984
  }
85824
85985
  }
@@ -85950,7 +86111,7 @@ async function startServer(opts = {}) {
85950
86111
  }
85951
86112
  statusPath = serverLockPathFor(ctx.project);
85952
86113
  const webRoot = resolve12(import.meta.dirname, "..", "..", "web");
85953
- const distDir = opts.webDistDir ? resolve12(opts.webDistDir) : join49(webRoot, "dist");
86114
+ const distDir = opts.webDistDir ? resolve12(opts.webDistDir) : join52(webRoot, "dist");
85954
86115
  startupPhase = "Vite";
85955
86116
  if (opts.dev) {
85956
86117
  try {
@@ -86028,7 +86189,7 @@ async function startServer(opts = {}) {
86028
86189
  if (vite) {
86029
86190
  vite.middlewares(req, res, () => {
86030
86191
  try {
86031
- const html = readFileSync34(join49(webRoot, "index.html"), "utf8");
86192
+ const html = readFileSync36(join52(webRoot, "index.html"), "utf8");
86032
86193
  void vite.transformIndexHtml(url, html).then((out) => {
86033
86194
  res.writeHead(200, { "content-type": "text/html" });
86034
86195
  res.end(out);
@@ -86040,7 +86201,7 @@ async function startServer(opts = {}) {
86040
86201
  });
86041
86202
  return;
86042
86203
  }
86043
- if (existsSync23(distDir)) {
86204
+ if (existsSync25(distDir)) {
86044
86205
  serveStatic(distDir, req, res);
86045
86206
  return;
86046
86207
  }
@@ -86234,7 +86395,7 @@ var init_index = __esm({
86234
86395
  }
86235
86396
  };
86236
86397
  isApiUrl = (url) => url === FRIZZ_ROUTE_PREFIX || url.startsWith(`${FRIZZ_ROUTE_PREFIX}/`);
86237
- serverLockPathFor = (project) => join49(project.stateDir, "server.lock");
86398
+ serverLockPathFor = (project) => join52(project.stateDir, "server.lock");
86238
86399
  MIME = {
86239
86400
  ".html": "text/html",
86240
86401
  ".js": "text/javascript",
@@ -86257,8 +86418,316 @@ init_project();
86257
86418
  init_project_launch();
86258
86419
  init_shutdown();
86259
86420
  init_logging();
86260
- import { existsSync as existsSync24 } from "node:fs";
86261
- import { join as join50 } from "node:path";
86421
+ import { existsSync as existsSync26 } from "node:fs";
86422
+ import { join as join53 } from "node:path";
86423
+
86424
+ // packages/server/src/access-codes.ts
86425
+ import { randomBytes, timingSafeEqual, createHmac } from "node:crypto";
86426
+ import { chmodSync, existsSync as existsSync4, mkdirSync as mkdirSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
86427
+ import { dirname as dirname6, join as join9 } from "node:path";
86428
+ var DEFAULT_CODE_TTL_MS = 5 * 6e4;
86429
+ var DEFAULT_SESSION_TTL_MS = 30 * 24 * 60 * 6e4;
86430
+ var SESSION_EPOCH = 1;
86431
+ var SESSION_KEY_FILE = "session-key";
86432
+ var SESSION_EPOCH_FILE = "session-epoch";
86433
+ function writeSessionKey(path3, key) {
86434
+ mkdirSync7(dirname6(path3), { recursive: true });
86435
+ writeFileSync6(path3, key, { mode: 384 });
86436
+ try {
86437
+ chmodSync(path3, 384);
86438
+ } catch {
86439
+ }
86440
+ }
86441
+ function rotateSessionKey(stateDir) {
86442
+ const key = randomBytes(32);
86443
+ writeSessionKey(join9(stateDir, SESSION_KEY_FILE), key);
86444
+ return key;
86445
+ }
86446
+ function readSessionEpoch(stateDir) {
86447
+ try {
86448
+ const parsed = JSON.parse(readFileSync6(join9(stateDir, SESSION_EPOCH_FILE), "utf8"));
86449
+ return Number.isInteger(parsed?.epoch) && parsed.epoch >= 0 ? parsed.epoch : 0;
86450
+ } catch {
86451
+ return 0;
86452
+ }
86453
+ }
86454
+ function advanceSessionEpoch(stateDir, epoch = SESSION_EPOCH) {
86455
+ const from = readSessionEpoch(stateDir);
86456
+ if (from >= epoch) return { advanced: false, epoch: from };
86457
+ const keyPath = join9(stateDir, SESSION_KEY_FILE);
86458
+ const rotatedKey = existsSync4(keyPath);
86459
+ if (rotatedKey) rotateSessionKey(stateDir);
86460
+ mkdirSync7(stateDir, { recursive: true });
86461
+ writeFileSync6(
86462
+ join9(stateDir, SESSION_EPOCH_FILE),
86463
+ JSON.stringify({ epoch, advancedAt: (/* @__PURE__ */ new Date()).toISOString() }),
86464
+ { mode: 384 }
86465
+ );
86466
+ return { advanced: true, from, to: epoch, rotatedKey };
86467
+ }
86468
+ function sessionEpochLogLine(advance, signedOut) {
86469
+ if (!advance.advanced || !advance.rotatedKey) return null;
86470
+ const count = signedOut === null ? "an unknown number of" : String(signedOut);
86471
+ return `session epoch ${advance.from} -> ${advance.to}: rotated the session key and signed out ${count} recorded remote device(s); every older remote session is refused`;
86472
+ }
86473
+
86474
+ // packages/server/src/session-epoch-child.ts
86475
+ import { readFileSync as readFileSync7 } from "node:fs";
86476
+ import { join as join10 } from "node:path";
86477
+
86478
+ // packages/server/src/restart-supervisor.ts
86479
+ init_local_origin();
86480
+ init_local_image();
86481
+
86482
+ // packages/server/src/supervisor-pages.ts
86483
+ var BASE_STYLE = `
86484
+ *,*::before,*::after{box-sizing:border-box}
86485
+ :root{
86486
+ color-scheme:dark;
86487
+ --bg:#0d0e10;--panel:#131519;--panel-2:#181b20;
86488
+ --border:#26282d;--border-strong:#33363c;--control-border:#26282d;--control-strong:#33363c;
86489
+ --fg:#e6e7e9;--muted:#8b8f96;--accent:#e8b923;--danger:#fca5a5;
86490
+ --focus-border:color-mix(in srgb,var(--accent) 55%,transparent);--focus-ring:color-mix(in srgb,var(--accent) 22%,transparent);
86491
+ --sans:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
86492
+ --mono:ui-monospace,"JetBrains Mono","SF Mono","Cascadia Mono",Menlo,Consolas,monospace;
86493
+ --ease:cubic-bezier(0,0,.2,1);
86494
+ }
86495
+ :root[data-theme=light]{
86496
+ color-scheme:light;
86497
+ --bg:#f7f7f7;--panel:#fff;--panel-2:#fafafa;
86498
+ --border:#dedede;--border-strong:#cecece;--control-border:#858585;--control-strong:#7d7d7d;
86499
+ --fg:#292929;--muted:#606060;--accent:#416896;--danger:#cf222e;
86500
+ --focus-border:#416896;--focus-ring:#416896;
86501
+ }
86502
+ @media(prefers-color-scheme:light){
86503
+ :root:not([data-theme]){
86504
+ color-scheme:light;
86505
+ --bg:#f7f7f7;--panel:#fff;--panel-2:#fafafa;
86506
+ --border:#dedede;--border-strong:#cecece;--control-border:#858585;--control-strong:#7d7d7d;
86507
+ --fg:#292929;--muted:#606060;--accent:#416896;--danger:#cf222e;
86508
+ --focus-border:#416896;--focus-ring:#416896;
86509
+ }
86510
+ }
86511
+ html,body{background:var(--bg)}
86512
+ body{
86513
+ margin:0;min-height:100vh;min-height:100dvh;
86514
+ display:flex;align-items:center;justify-content:center;padding:24px;
86515
+ color:var(--fg);font-family:var(--sans);font-size:12.5px;line-height:1.55;
86516
+ -webkit-font-smoothing:antialiased;
86517
+ }
86518
+ main{width:100%;max-width:28rem;padding:18px;border:1px solid var(--border-strong);border-radius:12px;background:var(--panel-2)}
86519
+ h1{margin:0;display:flex;align-items:baseline;gap:7px;font-size:14px;font-weight:600;letter-spacing:-.01em;line-height:1.4}
86520
+ p{margin:0;text-wrap:pretty}
86521
+ .detail{margin-top:7px;color:color-mix(in srgb,var(--fg) 88%,transparent)}
86522
+ .note{margin-top:12px;padding-top:11px;border-top:1px solid var(--border);color:var(--muted);font-size:11.5px;line-height:1.6}
86523
+ code{font-family:var(--mono);font-size:.92em;padding:.1em .35em;border-radius:4px;background:var(--panel);border:1px solid var(--border);white-space:nowrap}
86524
+ [hidden]{display:none!important}
86525
+ `.trim();
86526
+ var RECOVERY_STYLE = `
86527
+ .actions{margin-top:14px;display:flex;flex-wrap:wrap;gap:8px}
86528
+ /* ErrorBoundary's ACTION_CLASS, one size up for a page that is alone in a viewport. */
86529
+ .btn{
86530
+ appearance:none;display:inline-flex;align-items:center;
86531
+ border:1px solid var(--control-border);border-radius:6px;background:transparent;
86532
+ padding:5px 10px;font:inherit;font-size:11.5px;color:color-mix(in srgb,var(--fg) 90%,transparent);
86533
+ cursor:pointer;text-decoration:none;
86534
+ transition:background-color 120ms var(--ease),border-color 120ms var(--ease),color 120ms var(--ease);
86535
+ }
86536
+ .btn:hover{background:var(--panel);border-color:var(--control-strong);color:var(--fg)}
86537
+ .btn:focus-visible{outline:none;border-color:var(--focus-border);box-shadow:0 0 0 2px var(--focus-ring)}
86538
+ .btn:disabled{opacity:.5;pointer-events:none}
86539
+ /* min-height holds the slot open while it is LIVE, so a changing status line never nudges the card;
86540
+ :empty collapses it when there is nothing live to say, so a halted card has no trailing gutter. */
86541
+ .probe{margin-top:12px;font-family:var(--mono);font-size:11px;line-height:1.5;color:var(--muted);min-height:1.5em}
86542
+ .probe:empty{margin-top:0;min-height:0}
86543
+ /* RestartFailureNotice's block, at this altitude: a supervisor \`message\` is raw build output, and it
86544
+ reads as what it is \u2014 a terminal excerpt \u2014 only inside a scrolling mono box. */
86545
+ .log{
86546
+ margin-top:10px;max-height:16rem;overflow:auto;white-space:pre-wrap;overflow-wrap:break-word;
86547
+ border:1px solid var(--border);border-radius:6px;background:var(--panel);padding:8px 10px;
86548
+ font-family:var(--mono);font-size:11px;line-height:1.6;color:color-mix(in srgb,var(--fg) 70%,transparent);
86549
+ }
86550
+
86551
+ /* THE LIVE DOT, and it is the app's own \`.frizz-live-dot\` \u2014 same 6px, same 28%/14% halo, same 1.25s
86552
+ cadence \u2014 because it means the same thing here that it means there: work is in flight.
86553
+
86554
+ Alignment is an INK problem. A baseline-aligned flex item with no text of its own contributes its
86555
+ BORDER-BOX BOTTOM as the baseline, so the dot's ink centre lands 3px above it while the cap band's
86556
+ centre sits 0.5cap above it. \`cap\` is the resolved font's own cap height, so the correction holds
86557
+ at any size, with nothing to re-measure when the type scale moves. The em spelling is the fallback for a browser without the unit (.35em ~= 0.5 x a
86558
+ 0.7em cap) and is overwritten wherever \`cap\` parses. */
86559
+ .dot{
86560
+ width:6px;height:6px;flex:0 0 auto;border-radius:9999px;background:var(--accent);
86561
+ box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 28%,transparent);
86562
+ animation:frizz-live-pulse 1.25s ease-in-out infinite;
86563
+ transform:translateY(calc(3px - .35em));
86564
+ transform:translateY(calc(3px - .5cap));
86565
+ }
86566
+ .dot[data-state=idle]{animation:none;background:var(--muted);box-shadow:none}
86567
+ .dot[data-state=bad]{animation:none;background:var(--danger);box-shadow:0 0 0 1px color-mix(in srgb,var(--danger) 28%,transparent)}
86568
+ @keyframes frizz-live-pulse{50%{opacity:.62;box-shadow:0 0 0 2px color-mix(in srgb,var(--accent) 14%,transparent)}}
86569
+ @media (prefers-reduced-motion:reduce){
86570
+ .dot{animation:none;background:transparent;border:2px solid var(--accent);box-shadow:none}
86571
+ .dot[data-state=idle]{border-color:var(--muted)}
86572
+ .dot[data-state=bad]{border-color:var(--danger);background:transparent}
86573
+ }
86574
+
86575
+ /* The app's \`.shimmer-text\`: a highlight sweeping muted text is how this product says "working", and
86576
+ the probe line is the only thing on the page that is. */
86577
+ .probe[data-live=yes]{
86578
+ color:transparent;
86579
+ background:linear-gradient(90deg,var(--muted) 0%,var(--muted) 35%,var(--fg) 50%,var(--muted) 65%,var(--muted) 100%) 0 0/200% 100%;
86580
+ -webkit-background-clip:text;background-clip:text;
86581
+ animation:frizz-shimmer 2.2s linear infinite;
86582
+ }
86583
+ @keyframes frizz-shimmer{from{background-position:200% 0}to{background-position:-200% 0}}
86584
+ @media (prefers-reduced-motion:reduce){
86585
+ .probe[data-live=yes]{animation:none;background:none;color:var(--muted)}
86586
+ }
86587
+ `.trim();
86588
+ var RECOVERY_SCRIPT = `
86589
+ (function(){
86590
+ var target=document.body.dataset.target||"/"
86591
+ var heading=document.getElementById("heading")
86592
+ var detail=document.getElementById("detail")
86593
+ var probe=document.getElementById("probe")
86594
+ var log=document.getElementById("log")
86595
+ var dot=document.getElementById("dot")
86596
+ var restart=document.getElementById("restart")
86597
+ var BUDGET=120000,MIN=600,MAX=4000,GROWTH=1.4
86598
+ var delay=MIN,deadline=Date.now()+BUDGET,timer=0,stopped=false,busy=false,told=""
86599
+
86600
+ function say(text,live){probe.textContent=text;probe.setAttribute("data-live",live?"yes":"no")}
86601
+ function halt(text,bad){stopped=true;clearTimeout(timer);dot.setAttribute("data-state",bad?"bad":"idle");say(text,false)}
86602
+ function showLog(message){if(message){log.textContent=message;log.hidden=false}else{log.hidden=true}}
86603
+ function resume(){stopped=false;busy=false;delay=MIN;deadline=Date.now()+BUDGET;dot.removeAttribute("data-state");clearTimeout(timer);timer=setTimeout(tick,0)}
86604
+
86605
+ // 503 is this proxy's own "no child". Every other answer \u2014 200, 404, even a 500 from the app \u2014 means
86606
+ // something is listening again, and the reader's own URL is the right thing to ask.
86607
+ function alive(){
86608
+ return fetch(target,{method:"HEAD",cache:"no-store",credentials:"same-origin"})
86609
+ .then(function(r){return r.status!==503}).catch(function(){return false})
86610
+ }
86611
+ function readStatus(){
86612
+ return fetch("/_frizz/control/status",{cache:"no-store",headers:{"cache-control":"no-store"}})
86613
+ .then(function(r){return r.ok?r.json():null})
86614
+ .then(function(b){return b&&b.protocol===1?b:null}).catch(function(){return null})
86615
+ }
86616
+
86617
+ // An unreachable launcher leaves the server-rendered copy alone: it is already right for the case
86618
+ // that rendered it, and guessing over it would be worse than saying nothing.
86619
+ function narrate(status){
86620
+ if(!status||status.state===told)return
86621
+ told=status.state
86622
+ if(status.state==="failed"){
86623
+ heading.textContent="Frizz did not restart"
86624
+ // Not a second copy of the note below it \u2014 a lead-in to the log, which is the next thing down.
86625
+ detail.textContent="The launcher could not bring the application server back, and reported this:"
86626
+ showLog(status.message||"The launcher gave no reason.")
86627
+ halt("",true)
86628
+ return
86629
+ }
86630
+ showLog("")
86631
+ if(status.state==="restarting"){
86632
+ heading.textContent="Frizz is restarting"
86633
+ detail.textContent="The application server is coming back up."
86634
+ }
86635
+ }
86636
+
86637
+ function tick(){
86638
+ if(stopped||busy)return
86639
+ // A hidden tab neither polls nor spends its budget; visibilitychange starts the loop again.
86640
+ if(document.hidden)return
86641
+ alive().then(function(up){
86642
+ if(up){say("Frizz is back. Reloading.",true);location.replace(target);return}
86643
+ return readStatus().then(function(status){
86644
+ narrate(status)
86645
+ if(stopped)return
86646
+ if(Date.now()>deadline){halt("No answer after 2m. This page stopped checking.",false);return}
86647
+ delay=Math.min(MAX,delay*GROWTH)
86648
+ say("Waiting for Frizz",true)
86649
+ timer=setTimeout(tick,delay)
86650
+ })
86651
+ })
86652
+ }
86653
+
86654
+ document.addEventListener("visibilitychange",function(){
86655
+ if(document.hidden||stopped||busy)return
86656
+ resume()
86657
+ })
86658
+
86659
+ restart.addEventListener("click",function(){
86660
+ if(busy)return
86661
+ busy=true;stopped=false;told="";clearTimeout(timer)
86662
+ restart.disabled=true;restart.textContent="Restarting"
86663
+ dot.removeAttribute("data-state");showLog("");say("Restarting Frizz",true)
86664
+ fetch("/_frizz/control/restart",{method:"POST",headers:{"cache-control":"no-store"}})
86665
+ .then(function(r){return r.json().catch(function(){return null}).then(function(b){return{ok:r.ok,status:r.status,body:b}})})
86666
+ .catch(function(){return{ok:false,status:0,body:null}})
86667
+ .then(function(r){
86668
+ restart.disabled=false;restart.textContent="Restart Frizz";busy=false
86669
+ if(!r.ok){
86670
+ heading.textContent="Frizz did not restart"
86671
+ detail.textContent="The launcher could not bring the application server back, and reported this:"
86672
+ showLog((r.body&&r.body.message)||("The launcher refused the restart ("+(r.status||"no response")+")."))
86673
+ halt("",true)
86674
+ return
86675
+ }
86676
+ // Accepted. The probe, not this response, decides whether the child is actually back.
86677
+ resume()
86678
+ })
86679
+ })
86680
+
86681
+ say("Waiting for Frizz",true)
86682
+ tick()
86683
+ })()
86684
+ `.trim();
86685
+
86686
+ // packages/server/src/restart-supervisor.ts
86687
+ init_src();
86688
+ var SUPERVISOR_CONTROL_PREFIX = "/_frizz/control";
86689
+ var SUPERVISOR_RESTART_PATH = `${SUPERVISOR_CONTROL_PREFIX}/restart`;
86690
+ var SUPERVISOR_UPDATE_RESTART_PATH = `${SUPERVISOR_CONTROL_PREFIX}/update-restart`;
86691
+ var SUPERVISOR_STATUS_PATH = `${SUPERVISOR_CONTROL_PREFIX}/status`;
86692
+ var SUPERVISOR_ACCESS_CODE_PATH = `${SUPERVISOR_CONTROL_PREFIX}/access-code`;
86693
+ var SUPERVISOR_SESSIONS_PATH = `${SUPERVISOR_CONTROL_PREFIX}/sessions`;
86694
+ var SUPERVISOR_SIGN_OUT_PATH = `${SUPERVISOR_CONTROL_PREFIX}/sign-out`;
86695
+ var LOCAL_IMAGE_PATH = new RegExp(`^${FRIZZ_ROUTE_PREFIX}(?:/[^/]+)?/local-image$`);
86696
+
86697
+ // packages/server/src/session-epoch-child.ts
86698
+ async function signOutOlderSessionEpoch(options) {
86699
+ const advance = advanceSessionEpoch(options.stateDir, options.epoch ?? SESSION_EPOCH);
86700
+ if (!advance.advanced || !advance.rotatedKey) return { advance, signedOut: 0 };
86701
+ const port2 = supervisorPort(options.stateDir, options.supervisorPid);
86702
+ if (port2 === void 0) return { advance, signedOut: null };
86703
+ try {
86704
+ const response = await (options.fetcher ?? fetch)(`http://127.0.0.1:${port2}${SUPERVISOR_SESSIONS_PATH}`, {
86705
+ method: "POST",
86706
+ // Node's fetch sends no Origin, and the control plane wants one on a POST: name the loopback
86707
+ // authority, as `frizz --sign-out` does.
86708
+ headers: { origin: `http://127.0.0.1:${port2}`, "content-type": "application/json" },
86709
+ body: JSON.stringify({ all: true }),
86710
+ signal: AbortSignal.timeout(5e3)
86711
+ });
86712
+ if (response.status === 409) return { advance, signedOut: 0 };
86713
+ if (!response.ok) return { advance, signedOut: null };
86714
+ const body = await response.json().catch(() => void 0);
86715
+ return { advance, signedOut: typeof body?.signedOut === "number" ? body.signedOut : null };
86716
+ } catch {
86717
+ return { advance, signedOut: null };
86718
+ }
86719
+ }
86720
+ function supervisorPort(stateDir, supervisorPid) {
86721
+ try {
86722
+ const status = JSON.parse(readFileSync7(join10(stateDir, "dev-supervisor.lock"), "utf8"));
86723
+ if (status.pid !== supervisorPid) return void 0;
86724
+ return Number.isInteger(status.port) && status.port > 0 && status.port <= 65535 ? status.port : void 0;
86725
+ } catch {
86726
+ return void 0;
86727
+ }
86728
+ }
86729
+
86730
+ // packages/server/src/dev-child.ts
86262
86731
  process.on("uncaughtException", (error) => {
86263
86732
  log.error("dev-child", `uncaught exception: ${error instanceof Error ? error.stack ?? error.message : error}`);
86264
86733
  process.exit(1);
@@ -86313,9 +86782,9 @@ try {
86313
86782
  ["FRIZZ_SCRIPTS_DIR", process.env.FRIZZ_SCRIPTS_DIR, "index.mjs"],
86314
86783
  ["FRIZZ_WORKER_PLUGIN_DIR", process.env.FRIZZ_WORKER_PLUGIN_DIR, ".claude-plugin/plugin.json"]
86315
86784
  ];
86316
- if (!existsSync24(stableWebDist)) throw new Error("stable artifact launch is missing its verified web directory");
86785
+ if (!existsSync26(stableWebDist)) throw new Error("stable artifact launch is missing its verified web directory");
86317
86786
  for (const [name, directory, requiredFile] of required) {
86318
- if (!directory || !existsSync24(join50(directory, requiredFile)))
86787
+ if (!directory || !existsSync26(join53(directory, requiredFile)))
86319
86788
  throw new Error(`stable artifact launch is missing verified ${name}`);
86320
86789
  }
86321
86790
  }
@@ -86335,8 +86804,14 @@ try {
86335
86804
  port: server.port,
86336
86805
  bootId: server.ctx.bootId
86337
86806
  });
86807
+ if (process.connected) {
86808
+ void signOutOlderSessionEpoch({ stateDir: target.stateDir, supervisorPid: process.ppid }).then(({ advance, signedOut }) => {
86809
+ const line = sessionEpochLogLine(advance, signedOut);
86810
+ if (line) log.warn("dev-child", `${line} (a launcher older than this release refuses the rest from its next start)`);
86811
+ }).catch((error) => log.warn("dev-child", `session epoch: ${error instanceof Error ? error.message : error}`));
86812
+ }
86338
86813
  let shuttingDown = false;
86339
- const stop = async () => {
86814
+ const stop2 = async () => {
86340
86815
  if (shuttingDown) return;
86341
86816
  shuttingDown = true;
86342
86817
  const force = setTimeout(() => process.exit(1), 15e3);
@@ -86359,9 +86834,9 @@ try {
86359
86834
  process.exit(1);
86360
86835
  }
86361
86836
  };
86362
- shutdown = stop;
86363
- process.on("SIGINT", () => void stop());
86364
- process.on("SIGTERM", () => void stop());
86837
+ shutdown = stop2;
86838
+ process.on("SIGINT", () => void stop2());
86839
+ process.on("SIGTERM", () => void stop2());
86365
86840
  } catch (err) {
86366
86841
  log.error("dev-child", `failed to start: ${err instanceof Error ? err.stack ?? err.message : err}`);
86367
86842
  process.exit(1);