frizz 0.12.4 → 0.12.7

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 (91) hide show
  1. package/dist/claude-agent-broker.js +1911 -1910
  2. package/dist/dev-child.js +329 -159
  3. package/dist/frizz.js +10 -1
  4. package/package.json +1 -1
  5. package/web-dist/assets/{TerminalPane-D5Tx2hu9.js → TerminalPane-CDk5zKv9.js} +1 -1
  6. package/web-dist/assets/{abnfDiagram-VRR7QNED-BO0tgRMu.js → abnfDiagram-VRR7QNED-DmkK2qjk.js} +1 -1
  7. package/web-dist/assets/architecture-TIHT7OUA-c0q2ebfx.js +1 -0
  8. package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-TCJFLj-i.js → architectureDiagram-ZJ3FMSHR-BFbA3OG6.js} +1 -1
  9. package/web-dist/assets/{blockDiagram-677ZJIJ3-BRd9xJTz.js → blockDiagram-677ZJIJ3-DTslTfq9.js} +1 -1
  10. package/web-dist/assets/{c4Diagram-LMCZKHZV-BxlNYwY8.js → c4Diagram-LMCZKHZV-Dmugni-f.js} +1 -1
  11. package/web-dist/assets/channel-CZ15urUA.js +1 -0
  12. package/web-dist/assets/{chunk-32BRIVSS-o0wtC3P5.js → chunk-32BRIVSS-DS7QIaUB.js} +1 -1
  13. package/web-dist/assets/{chunk-52WLFC77-C_bt24w7.js → chunk-52WLFC77-CnnFIjVe.js} +1 -1
  14. package/web-dist/assets/{chunk-C7G6YPKG-DlsBv-nI.js → chunk-C7G6YPKG-BZxNdEVe.js} +1 -1
  15. package/web-dist/assets/{chunk-EX3LRPZG-Y_Debiw-.js → chunk-EX3LRPZG-Zv7RLgbb.js} +1 -1
  16. package/web-dist/assets/{chunk-FWX5IMBZ-D_9nCJ43.js → chunk-FWX5IMBZ-6-Zb5eo-.js} +2 -2
  17. package/web-dist/assets/{chunk-HOUHSVGY-Bzhu2UoJ.js → chunk-HOUHSVGY-J5Ui6IxH.js} +1 -1
  18. package/web-dist/assets/{chunk-ICXQ74PX-CwJVbXqL.js → chunk-ICXQ74PX-DH6GE_Om.js} +1 -1
  19. package/web-dist/assets/{chunk-MOJQB5TN-DPm_X7tz.js → chunk-MOJQB5TN-Bjd1ChDq.js} +1 -1
  20. package/web-dist/assets/{chunk-OGEWGWER-1m3zk2ed.js → chunk-OGEWGWER-BNvzjYRM.js} +1 -1
  21. package/web-dist/assets/{chunk-PUDLZKDR-D2Bnu5zc.js → chunk-PUDLZKDR-CdtfylsO.js} +1 -1
  22. package/web-dist/assets/{chunk-Q4XR5HBZ-DJZtjVxI.js → chunk-Q4XR5HBZ-C7N3sKog.js} +1 -1
  23. package/web-dist/assets/{chunk-V7JOEXUC-BQVKbxnn.js → chunk-V7JOEXUC-vX-c4OzH.js} +1 -1
  24. package/web-dist/assets/{chunk-VAUOI2AC-TwOgVbMm.js → chunk-VAUOI2AC-DtbheJmZ.js} +1 -1
  25. package/web-dist/assets/{chunk-VR4S4FIN-DlG1lzSj.js → chunk-VR4S4FIN-BpE1AOJR.js} +1 -1
  26. package/web-dist/assets/{chunk-WYO6CB5R-Ckk8qoao.js → chunk-WYO6CB5R-BupZRR1a.js} +1 -1
  27. package/web-dist/assets/{chunk-ZGVPDNZ5-CZxmPZzT.js → chunk-ZGVPDNZ5-XoWDM-02.js} +1 -1
  28. package/web-dist/assets/classDiagram-OUVF2IWQ-DFxJiEZ1.js +1 -0
  29. package/web-dist/assets/classDiagram-v2-EOCWNBFH-DFxJiEZ1.js +1 -0
  30. package/web-dist/assets/{cynefin-VYW2F7L2-CioP0cgr.js → cynefin-VYW2F7L2-DOIzVENe.js} +1 -1
  31. package/web-dist/assets/{cynefinDiagram-TSTJHNR4-BJZpJw_3.js → cynefinDiagram-TSTJHNR4-DGq-kl_q.js} +1 -1
  32. package/web-dist/assets/{dagre-VKFMJZFB-BGv33WEE.js → dagre-VKFMJZFB-Brs6wxcd.js} +1 -1
  33. package/web-dist/assets/{diagram-FQU43EPY-CvhxVWTl.js → diagram-FQU43EPY-BrQd5FEw.js} +1 -1
  34. package/web-dist/assets/{diagram-G47NLZAW-DnrPOeE0.js → diagram-G47NLZAW-B-DN7aQk.js} +1 -1
  35. package/web-dist/assets/{diagram-NH7WQ7WH-CazuXXkX.js → diagram-NH7WQ7WH-DB-NFs3X.js} +1 -1
  36. package/web-dist/assets/{diagram-OA4YK3LP-DfbFhbQs.js → diagram-OA4YK3LP-DsrBhvMB.js} +1 -1
  37. package/web-dist/assets/{diagram-WEI45ONY-BESpc3Oj.js → diagram-WEI45ONY-DYctq6PN.js} +1 -1
  38. package/web-dist/assets/{ebnfDiagram-CCIWWBDH-C6h37W51.js → ebnfDiagram-CCIWWBDH-C6ghRrJP.js} +1 -1
  39. package/web-dist/assets/{erDiagram-Q63AITRT-vCxGREHo.js → erDiagram-Q63AITRT-C_iK-Ja6.js} +1 -1
  40. package/web-dist/assets/eventmodeling-45OFAUF4-BdXQ9Pv4.js +1 -0
  41. package/web-dist/assets/flowDiagram-23GEKE2U-rTXtf38R.js +1 -0
  42. package/web-dist/assets/{ganttDiagram-NO4QXBWP-B5l9XyZe.js → ganttDiagram-NO4QXBWP-Y9GZAgbA.js} +1 -1
  43. package/web-dist/assets/{gitGraph-TEB2WS4Q-CQpssLnk.js → gitGraph-TEB2WS4Q-BgqW4vt7.js} +1 -1
  44. package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-j95eUOjO.js → gitGraphDiagram-IHSO6WYX-eImStPZ8.js} +1 -1
  45. package/web-dist/assets/{index-Dzq6GPUo.js → index-BOACK0Xu.js} +92 -92
  46. package/web-dist/assets/{info-DKCQHKI2-CiW0hhEI.js → info-DKCQHKI2-BtbNWkY3.js} +1 -1
  47. package/web-dist/assets/{infoDiagram-FWYZ7A6U-BJwJPEq2.js → infoDiagram-FWYZ7A6U-DMIPEeRd.js} +1 -1
  48. package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-Ck4D0hT_.js → ishikawaDiagram-FXEZZL3T-08_raW8G.js} +1 -1
  49. package/web-dist/assets/{journeyDiagram-5HDEW3XC-Bz8PK7lM.js → journeyDiagram-5HDEW3XC-hPkkufFj.js} +1 -1
  50. package/web-dist/assets/{kanban-definition-HUTT4EX6-Kqt3cah4.js → kanban-definition-HUTT4EX6-CDBcUNEE.js} +1 -1
  51. package/web-dist/assets/{line-Dl7tIumR.js → line-Njg200Gq.js} +1 -1
  52. package/web-dist/assets/{mermaid-parser.core-C_aHybiE.js → mermaid-parser.core-1A-yH2Ql.js} +3 -3
  53. package/web-dist/assets/{mermaid.core-Dv6lgZxU.js → mermaid.core-D5Mvu4fo.js} +3 -3
  54. package/web-dist/assets/{mindmap-definition-LN4V7U3C-EkN_2bUd.js → mindmap-definition-LN4V7U3C-r-0LqhPG.js} +1 -1
  55. package/web-dist/assets/{packet-7NZHBO7P-LL-j9b42.js → packet-7NZHBO7P-Dj8tWs_Q.js} +1 -1
  56. package/web-dist/assets/{pegDiagram-2B236MQR-CrNUBIKh.js → pegDiagram-2B236MQR-BHoUQUjJ.js} +1 -1
  57. package/web-dist/assets/{pie-RZYD4A2V-8wZ8AyeT.js → pie-RZYD4A2V-GZmPkAjn.js} +1 -1
  58. package/web-dist/assets/{pieDiagram-ENE6RG2P-BSUUt2Vt.js → pieDiagram-ENE6RG2P-CL0ZHN1y.js} +1 -1
  59. package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-BmRRE-b9.js → quadrantDiagram-ABIIQ3AL-vZJzUcfC.js} +1 -1
  60. package/web-dist/assets/{radar-I7S5WNFK-BZ8i3wPh.js → radar-I7S5WNFK-D3x_tyhl.js} +1 -1
  61. package/web-dist/assets/{railroad-3IZDKUUU-Bvq-p3jW.js → railroad-3IZDKUUU-HVHtGCKZ.js} +1 -1
  62. package/web-dist/assets/railroad-abnf-AHOZXSZD-BD2umz4T.js +1 -0
  63. package/web-dist/assets/railroad-ebnf-EBAXGLYW-C1IGySZs.js +1 -0
  64. package/web-dist/assets/railroad-peg-LSFZ7HO6-BVCH7yeK.js +1 -0
  65. package/web-dist/assets/{railroadDiagram-RFXS5EU6-CH0DOBjJ.js → railroadDiagram-RFXS5EU6-Dfw0JONh.js} +1 -1
  66. package/web-dist/assets/{requirementDiagram-TGXJPOKE-ytS-raWw.js → requirementDiagram-TGXJPOKE-DLM4etHl.js} +1 -1
  67. package/web-dist/assets/{sankeyDiagram-HTMAVEWB-BU49ulmu.js → sankeyDiagram-HTMAVEWB-2nsrE-nL.js} +1 -1
  68. package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-C1edCLps.js → sequenceDiagram-DBY2YBRQ-VkpQVaPX.js} +1 -1
  69. package/web-dist/assets/{stateDiagram-2N3HPSRC-C049S4Yj.js → stateDiagram-2N3HPSRC-xvBH0825.js} +1 -1
  70. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-B3bLucl6.js +1 -0
  71. package/web-dist/assets/{swimlanes-5IMT3BWC-KNWNnFDx.js → swimlanes-5IMT3BWC-DA8H4qPO.js} +1 -1
  72. package/web-dist/assets/swimlanesDiagram-G3AALYLV-cYXAfa4Q.js +8 -0
  73. package/web-dist/assets/{timeline-definition-FHXFAJF6-D8Z-Q8JO.js → timeline-definition-FHXFAJF6-npL1KNyH.js} +1 -1
  74. package/web-dist/assets/{treeView-QDETBFTQ-CvyDkH5p.js → treeView-QDETBFTQ-Cea7MDUV.js} +1 -1
  75. package/web-dist/assets/{treemap-6X3UGDF4-COwCP95k.js → treemap-6X3UGDF4-CGHINewA.js} +1 -1
  76. package/web-dist/assets/{vennDiagram-L72KCM5P-DHKE_6N3.js → vennDiagram-L72KCM5P-D-RIigY2.js} +1 -1
  77. package/web-dist/assets/{wardley-OPB4EBWU-CYWcYdsx.js → wardley-OPB4EBWU-BXdXDctR.js} +1 -1
  78. package/web-dist/assets/{wardleyDiagram-EHGQE667-BS3OkOU_.js → wardleyDiagram-EHGQE667-tLo8yxD2.js} +1 -1
  79. package/web-dist/assets/{xychartDiagram-FW5EYKEG-Df4GdNEo.js → xychartDiagram-FW5EYKEG-I4H6c-9Q.js} +1 -1
  80. package/web-dist/index.html +1 -1
  81. package/web-dist/assets/architecture-TIHT7OUA-lCPPJORL.js +0 -1
  82. package/web-dist/assets/channel-tGE7Gbbs.js +0 -1
  83. package/web-dist/assets/classDiagram-OUVF2IWQ-CQo4x1hj.js +0 -1
  84. package/web-dist/assets/classDiagram-v2-EOCWNBFH-CQo4x1hj.js +0 -1
  85. package/web-dist/assets/eventmodeling-45OFAUF4-C517fJsQ.js +0 -1
  86. package/web-dist/assets/flowDiagram-23GEKE2U-IrjbjjxF.js +0 -1
  87. package/web-dist/assets/railroad-abnf-AHOZXSZD-DIZeZa-B.js +0 -1
  88. package/web-dist/assets/railroad-ebnf-EBAXGLYW-DVn3xHNX.js +0 -1
  89. package/web-dist/assets/railroad-peg-LSFZ7HO6-BvLcJu_d.js +0 -1
  90. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-D-Et-Cj1.js +0 -1
  91. package/web-dist/assets/swimlanesDiagram-G3AALYLV-DQNRnHXT.js +0 -8
package/dist/dev-child.js CHANGED
@@ -13671,7 +13671,7 @@ function parseGithubWakeSteer(text2) {
13671
13671
  function frizzRoute(path3) {
13672
13672
  return `${FRIZZ_ROUTE_PREFIX}${path3.startsWith("/") ? path3 : `/${path3}`}`;
13673
13673
  }
13674
- var import_yaml, ATTACHMENT_IMAGE_EXTENSIONS, ATTACHMENT_TEXT_EXTENSIONS, ATTACHMENT_OFFICE_EXTENSIONS, ATTACHMENT_DATA_EXTENSIONS, ATTACHMENT_ARCHIVE_EXTENSIONS, ATTACHMENT_DOC_EXTENSIONS, ATTACHMENT_EXTENSIONS, ATTACHMENT_MAX_BASE64_CHARS, ATTACHMENT_MAX_BYTES, ATTACHMENT_EXT_SET, ATTACHMENT_ACCEPT, FrizzStatus, BlockMechanism, RuntimeState, Backend, CodexModel, ThreadProfileOption, ThreadAgent, SubAgentView, BgShellView, CompletionHoldOp, CompletionHold, AskOption, AskQuestion, PendingAsk, AwaitingHint, RETIRED_AWAITING_KINDS, RETIRED_LINE_RE, RETIRED_AWAITING_REPLACEMENT, AWAITING_KEY_RE, AWAITING_YAML_KEYS, AWAITING_SEQUENCE_KEYS, AWAITING_HINT_MAX, AWAITING_HINT_VALUE_MAX, AWAITING_TITLE_MAX, AWAITING_ITEM_KINDS, AWAITING_DURATION_RE, DURATION_UNIT_MS, AWAITING_FOR_MAX_MS, SnoozeUntil, SNOOZE_PROMPT_MAX, SnoozePrompt, RECURRING_PROMPT_MAX, RECURRING_MIN_INTERVAL_SECONDS, RECURRING_MAX_INTERVAL_SECONDS, RecurringPromptText, RecurringIntervalSeconds, ThreadRecurringPrompt, INTERRUPT_MARKERS, ALLDONE_SENTINEL, OPT_OUT_NOTE, OVER_QUESTION_NOTE, TIMER_PROMPT_MAX, TIMER_MAX_DELAY_SECONDS, TIMER_MAX_ARMED, TimerPromptText, PR_WATCH_SPENT_TRAILER, PR_WATCH_ARMED_TRAILER, SHELL_DONE_TRAILER, SIGNOFF_NUDGE_MARKER, SIGNOFF_NUDGE_MESSAGE, PARK_CORRECTION_NAMES_LEAD, PARK_CORRECTION_RETIRED_LEAD, PARK_CORRECTION_QUESTION_LEAD, ThreadWatchKind, GithubChecksState, GithubMergeState, GithubWatchStatus, ThreadWatchView, PR_WATCH_FOR_MAX_MS, PR_WATCH_DEFAULT_FOR_MS, PR_WATCH_MAX_ARMED, PrWatchView, AddOwnPrWatchInput, AddOwnPrWatchResult, DropOwnPrWatchInput, DropOwnPrWatchResult, OwnWatchKind, AddOwnWatchInput, OwnWatchView, AddOwnWatchResult, DropOwnWatchInput, DropOwnWatchResult, OWN_WATCH_MAX_ARMED, AskQuestionKind, ASK_MAX_DEPTH, AskedOptionSchema, AskedQuestionSchema, AskInput, RegisteredQuestionView, AskResult, UnaskInput, UnaskResult, QuestionAnswerSchema, AnswerQuestionsInput, AnswerQuestionsResult, DismissQuestionsInput, DismissQuestionsResult, BURIED_ANSWERS_HEADER, ANSWER_FOLLOW_UP_MARKER, DISMISSED_ANSWER, MarkOwnDoneInput, MarkOwnDoneResult, ListOwnPrWatchesInput, OwnPrWatchesResult, ThreadTimerView, ThreadFence, LimitWindow, LimitPause, ThreadView, BoardErrorItem, BoardSnapshot, QuotaWindow, ProviderQuota, QuotaSnapshot, ProviderAuth, AccountEmails, AuthSnapshot, AccountLogoutInput, AccountLogoutResult, AccountLoginStartInput, AccountLoginStartResult, AccountLoginStatusInput, AccountLoginStatusResult, PermissionMode, LocalFileOpener, Settings, DispatchProviderPreferences, DispatchPreferences, DispatchProfileSnapshot, SetDispatchPreferenceInput, DispatchInput, ADOPT_THREAD_MESSAGE_MAX_CHARS, AdoptThreadInput, AdoptThreadResult, AdoptSessionInput, FollowUpInput, UnqueueFollowUpInput, UnqueueFollowUpResult, DeliverQueuedNowInput, DeliverQueuedNowResult, SetThreadSnoozeInput, SetThreadPinnedInput, SetThreadRecurringPromptInput, SetOwnThreadRecurringPromptInput, SetOwnThreadRecurringPromptResult, GetOwnThreadRecurringPromptInput, OwnThreadRecurringPromptResult, SetOwnThreadTimerInput, CancelOwnThreadTimerInput, ListOwnThreadTimersInput, OwnThreadTimersResult, ThreadActivityItem, ListOwnThreadActivityInput, OwnThreadActivityResult, SetOwnThreadTimerResult, CancelOwnThreadTimerResult, SetOwnThreadStopHookInput, SetOwnThreadHeartbeatInput, ThreadPluginReloadResult, RenameThreadInput, AiRenameThreadInput, AiRenameThreadResult, SetOwnThreadTitleInput, SetOwnThreadTitleResult, SetThreadPermissionInput, SetThreadPermissionResult, ThreadProfileOptionsInput, ThreadProfileOptionsResult, ThreadSkillSource, ThreadSkill, ThreadSkillsInput, ThreadSkillsResult, SetThreadProfileInput, SetThreadProfileResult, DISPATCH_TASK_BANNER, DISPATCH_TASK_BANNER_MARKER, GITHUB_DISPATCH_UI_BOUNDARY, WAKE_TIME_HEADER_TAIL, WAKE_TRAILERS, HUMAN_GAP_FLOOR_MS, HUMAN_GAP_NOTE_TAIL, WAKE_DELIVERY_TOKEN_TAIL, WAKE_DELIVERY_TOKEN_LINE, NOISE_PREFIXES, AGENT_MESSAGE_WRAPPER, GithubWakeItem, GithubWakeSteer, WAKE_SCOPE, WAKE_REVIEW_LEAD, WAKE_BACKLOG_TAIL, WAKE_REF, WAKE_SINGLE, WAKE_MULTI_HEAD, WAKE_ITEM, WAKE_MORE, PR_WATCH_FINISHED, PR_WATCH_CI_PASSED, PR_WATCH_CI_GATED, PR_WATCH_STATE, PR_WATCH_CI_FAILED, GithubStatus, GithubRefCard, GithubRefPreviewInput, GithubRefPreviewResult, GithubItem, GithubListInput, GithubListResult, GithubBatchInput, GithubBatchResult, BoardMeta, ServerEvent, TranscriptEdit, TranscriptTodo, TranscriptToolCall, TranscriptPart, TranscriptMessage, TranscriptPageCursor, EditedFile, TranscriptPage, TranscriptEarlierInput, SocketTranscriptSlug, SocketFilePath, SocketTranscriptClientMsg, SocketFileClientMsg, SocketClientMsg, ProjectCard, PROJECT_ICON_EXTENSIONS, PROJECT_ICON_MAX_BASE64_CHARS, DirectoryPickResult, ThreadLocation, FRIZZ_ROUTE_PREFIX, DEFAULT_PORT, threadIdentityName;
13674
+ var import_yaml, ATTACHMENT_IMAGE_EXTENSIONS, ATTACHMENT_TEXT_EXTENSIONS, ATTACHMENT_OFFICE_EXTENSIONS, ATTACHMENT_DATA_EXTENSIONS, ATTACHMENT_ARCHIVE_EXTENSIONS, ATTACHMENT_DOC_EXTENSIONS, ATTACHMENT_EXTENSIONS, ATTACHMENT_MAX_BASE64_CHARS, ATTACHMENT_MAX_BYTES, ATTACHMENT_EXT_SET, ATTACHMENT_ACCEPT, FrizzStatus, BlockMechanism, RuntimeState, Backend, CodexModel, ThreadProfileOption, ThreadAgent, SubAgentView, BgShellView, CompletionHoldOp, CompletionHold, AskOption, AskQuestion, PendingAsk, AwaitingHint, RETIRED_AWAITING_KINDS, RETIRED_LINE_RE, RETIRED_AWAITING_REPLACEMENT, AWAITING_KEY_RE, AWAITING_YAML_KEYS, AWAITING_SEQUENCE_KEYS, AWAITING_HINT_MAX, AWAITING_HINT_VALUE_MAX, AWAITING_TITLE_MAX, AWAITING_ITEM_KINDS, AWAITING_DURATION_RE, DURATION_UNIT_MS, AWAITING_FOR_MAX_MS, SnoozeUntil, SNOOZE_PROMPT_MAX, SnoozePrompt, RECURRING_PROMPT_MAX, RECURRING_MIN_INTERVAL_SECONDS, RECURRING_MAX_INTERVAL_SECONDS, RecurringPromptText, RecurringIntervalSeconds, ThreadRecurringPrompt, INTERRUPT_MARKERS, ALLDONE_SENTINEL, OPT_OUT_NOTE, OVER_QUESTION_NOTE, TIMER_PROMPT_MAX, TIMER_MAX_DELAY_SECONDS, TIMER_MAX_ARMED, TimerPromptText, PR_WATCH_SPENT_TRAILER, PR_WATCH_ARMED_TRAILER, SHELL_DONE_TRAILER, SIGNOFF_NUDGE_MARKER, SIGNOFF_NUDGE_MESSAGE, PARK_CORRECTION_NAMES_LEAD, PARK_CORRECTION_RETIRED_LEAD, PARK_CORRECTION_QUESTION_LEAD, ThreadWatchKind, GithubChecksState, GithubMergeState, GithubWatchStatus, ThreadWatchView, PR_WATCH_FOR_MAX_MS, PR_WATCH_DEFAULT_FOR_MS, PR_WATCH_MAX_ARMED, PrWatchView, AddOwnPrWatchInput, AddOwnPrWatchResult, DropOwnPrWatchInput, DropOwnPrWatchResult, OwnWatchKind, AddOwnWatchInput, OwnWatchView, AddOwnWatchResult, DropOwnWatchInput, DropOwnWatchResult, OWN_WATCH_MAX_ARMED, AskQuestionKind, ASK_MAX_DEPTH, AskedOptionSchema, AskedQuestionSchema, AskInput, RegisteredQuestionView, AskResult, UnaskInput, UnaskResult, QuestionAnswerSchema, AnswerQuestionsInput, AnswerQuestionsResult, DismissQuestionsInput, DismissQuestionsResult, BURIED_ANSWERS_HEADER, ANSWER_FOLLOW_UP_MARKER, DISMISSED_ANSWER, MarkOwnDoneInput, MarkOwnDoneResult, ListOwnPrWatchesInput, OwnPrWatchesResult, ThreadTimerView, ThreadFence, LimitWindow, LimitPause, ProviderError, ThreadView, BoardErrorItem, BoardSnapshot, QuotaWindow, ProviderQuota, QuotaSnapshot, ProviderAuth, AccountEmails, AuthSnapshot, AccountLogoutInput, AccountLogoutResult, AccountLoginStartInput, AccountLoginStartResult, AccountLoginStatusInput, AccountLoginStatusResult, PermissionMode, LocalFileOpener, Settings, DispatchProviderPreferences, DispatchPreferences, DispatchProfileSnapshot, SetDispatchPreferenceInput, DispatchInput, ADOPT_THREAD_MESSAGE_MAX_CHARS, AdoptThreadInput, AdoptThreadResult, AdoptSessionInput, FollowUpInput, UnqueueFollowUpInput, UnqueueFollowUpResult, DeliverQueuedNowInput, DeliverQueuedNowResult, SetThreadSnoozeInput, SetThreadPinnedInput, SetThreadRecurringPromptInput, SetOwnThreadRecurringPromptInput, SetOwnThreadRecurringPromptResult, GetOwnThreadRecurringPromptInput, OwnThreadRecurringPromptResult, SetOwnThreadTimerInput, CancelOwnThreadTimerInput, ListOwnThreadTimersInput, OwnThreadTimersResult, ThreadActivityItem, ListOwnThreadActivityInput, OwnThreadActivityResult, SetOwnThreadTimerResult, CancelOwnThreadTimerResult, SetOwnThreadStopHookInput, SetOwnThreadHeartbeatInput, ThreadPluginReloadResult, RenameThreadInput, AiRenameThreadInput, AiRenameThreadResult, SetOwnThreadTitleInput, SetOwnThreadTitleResult, SetThreadPermissionInput, SetThreadPermissionResult, ThreadProfileOptionsInput, ThreadProfileOptionsResult, ThreadSkillSource, ThreadSkill, ThreadSkillsInput, ThreadSkillsResult, SetThreadProfileInput, SetThreadProfileResult, DISPATCH_TASK_BANNER, DISPATCH_TASK_BANNER_MARKER, GITHUB_DISPATCH_UI_BOUNDARY, WAKE_TIME_HEADER_TAIL, WAKE_TRAILERS, HUMAN_GAP_FLOOR_MS, HUMAN_GAP_NOTE_TAIL, WAKE_DELIVERY_TOKEN_TAIL, WAKE_DELIVERY_TOKEN_LINE, NOISE_PREFIXES, AGENT_MESSAGE_WRAPPER, GithubWakeItem, GithubWakeSteer, WAKE_SCOPE, WAKE_REVIEW_LEAD, WAKE_BACKLOG_TAIL, WAKE_REF, WAKE_SINGLE, WAKE_MULTI_HEAD, WAKE_ITEM, WAKE_MORE, PR_WATCH_FINISHED, PR_WATCH_CI_PASSED, PR_WATCH_CI_GATED, PR_WATCH_STATE, PR_WATCH_CI_FAILED, GithubStatus, GithubRefCard, GithubRefPreviewInput, GithubRefPreviewResult, GithubItem, GithubListInput, GithubListResult, GithubBatchInput, GithubBatchResult, BoardMeta, ServerEvent, TranscriptEdit, TranscriptTodo, TranscriptToolCall, TranscriptPart, TranscriptMessage, TranscriptPageCursor, EditedFile, TranscriptPage, TranscriptEarlierInput, SocketTranscriptSlug, SocketFilePath, SocketTranscriptClientMsg, SocketFileClientMsg, SocketClientMsg, ProjectCard, PROJECT_ICON_EXTENSIONS, PROJECT_ICON_MAX_BASE64_CHARS, DirectoryPickResult, ThreadLocation, FRIZZ_ROUTE_PREFIX, DEFAULT_PORT, threadIdentityName;
13675
13675
  var init_src = __esm({
13676
13676
  "packages/shared/src/index.ts"() {
13677
13677
  "use strict";
@@ -14429,6 +14429,13 @@ var init_src = __esm({
14429
14429
  // setting is off, the instant is unresolvable, or the pause is too old to safely resume.
14430
14430
  autoResume: external_exports.boolean()
14431
14431
  });
14432
+ ProviderError = external_exports.object({
14433
+ message: external_exports.string(),
14434
+ code: external_exports.string().optional(),
14435
+ details: external_exports.string().optional(),
14436
+ retrying: external_exports.boolean().optional(),
14437
+ at: external_exports.string().optional()
14438
+ });
14432
14439
  ThreadView = external_exports.object({
14433
14440
  id: ThreadSlug,
14434
14441
  // slug; filename is <slug>.md
@@ -14539,6 +14546,7 @@ var init_src = __esm({
14539
14546
  // is to WAIT and continue — not to sign in. Same discipline as providerFault: only typed data
14540
14547
  // travels, never the provider's own error text. Optional so old snapshots/servers parse.
14541
14548
  limitPause: LimitPause.optional(),
14549
+ providerError: ProviderError.optional(),
14542
14550
  // ---- Session-first fields (ALL optional: absent ⇒ a legacy .frizz-file row / pre-restart server;
14543
14551
  // the client treats such rows as Legacy-shelf material). Deliberately not zod-defaulted so server
14544
14552
  // constructors that predate the model still typecheck and old snapshots parse unchanged. ----
@@ -15498,6 +15506,7 @@ ${DISPATCH_TASK_BANNER}
15498
15506
  // search, and transcript logic; shared chat surfaces use this compact form for generated prompts
15499
15507
  // whose machine-facing tail would otherwise dominate the first user bubble.
15500
15508
  displayText: external_exports.string().optional(),
15509
+ providerError: ProviderError.optional(),
15501
15510
  tools: external_exports.array(TranscriptToolCall),
15502
15511
  at: external_exports.string().optional(),
15503
15512
  // ISO8601
@@ -20752,6 +20761,180 @@ var init_dispatch_preferences = __esm({
20752
20761
  }
20753
20762
  });
20754
20763
 
20764
+ // packages/server/src/credential-redaction.ts
20765
+ function replacement(options, secretToken) {
20766
+ const configured = options.replacement ?? DEFAULT_REPLACEMENT;
20767
+ return typeof configured === "function" ? configured(secretToken) : configured;
20768
+ }
20769
+ function unquote(raw2) {
20770
+ return raw2.length >= 2 && (raw2[0] === '"' || raw2[0] === "'") && raw2.at(-1) === raw2[0] ? raw2.slice(1, -1) : raw2;
20771
+ }
20772
+ function userInfoParts(raw2) {
20773
+ const value = unquote(raw2);
20774
+ const literal = value.indexOf(":");
20775
+ const encodedMatch = /%3a/iu.exec(value);
20776
+ const encoded = encodedMatch?.index ?? -1;
20777
+ const index = literal === -1 ? encoded : encoded === -1 ? literal : Math.min(literal, encoded);
20778
+ if (index <= 0) return null;
20779
+ const delimiter2 = value.slice(index, index + (index === encoded ? 3 : 1));
20780
+ return { username: value.slice(0, index), delimiter: delimiter2, password: value.slice(index + delimiter2.length) };
20781
+ }
20782
+ function redactUserInfoToken(raw2, options) {
20783
+ const parts = userInfoParts(raw2);
20784
+ if (!parts) return null;
20785
+ return `${parts.username}${parts.delimiter}${replacement(options, parts.password)}`;
20786
+ }
20787
+ function hasCurlCommandContext(source, offset) {
20788
+ const bounded = source.slice(Math.max(0, offset - 1024), offset);
20789
+ const separator = Math.max(
20790
+ bounded.lastIndexOf("\n"),
20791
+ bounded.lastIndexOf("\r"),
20792
+ bounded.lastIndexOf(";"),
20793
+ bounded.lastIndexOf("&"),
20794
+ bounded.lastIndexOf("|")
20795
+ );
20796
+ const segment = bounded.slice(separator + 1);
20797
+ return segment.split(/[ \t]+/u).some((token) => CURL_EXECUTABLE_RE.test(unquote(token)));
20798
+ }
20799
+ function redactCredentialSyntax(raw2, options = {}) {
20800
+ let value = raw2;
20801
+ value = value.replace(
20802
+ URL_USERINFO_RE,
20803
+ (_whole, scheme, username, delimiter2, password) => `${scheme}${username}${delimiter2}${replacement(options, password)}@`
20804
+ );
20805
+ value = value.replace(
20806
+ URL_ENCODED_USERINFO_RE,
20807
+ (_whole, scheme, username, delimiter2, password) => `${scheme}${username}${delimiter2}${replacement(options, password)}@`
20808
+ );
20809
+ value = value.replace(
20810
+ USER_FLAG_RE,
20811
+ (whole, boundary, flag, separator, userInfo, offset, source) => {
20812
+ if (unquote(flag).toLowerCase() === "-u" && !hasCurlCommandContext(source, offset)) return whole;
20813
+ const safe = redactUserInfoToken(userInfo, options);
20814
+ return safe === null ? whole : `${boundary}${flag}${separator}${safe}`;
20815
+ }
20816
+ );
20817
+ value = value.replace(
20818
+ ATTACHED_USER_FLAG_RE,
20819
+ (whole, boundary, flag, userInfo, offset, source) => {
20820
+ if (!hasCurlCommandContext(source, offset)) return whole;
20821
+ const safe = redactUserInfoToken(userInfo, options);
20822
+ return safe === null ? whole : `${boundary}${flag}${safe}`;
20823
+ }
20824
+ );
20825
+ value = value.replace(
20826
+ LONG_FLAG_RE,
20827
+ (_whole, boundary, flag, separator, secret) => `${boundary}${flag}${separator}${replacement(options, secret)}`
20828
+ );
20829
+ return value;
20830
+ }
20831
+ function isCredentialFieldName(name) {
20832
+ const normalized = name.replace(new RegExp("([\\p{Ll}\\d])(\\p{Lu})", "gu"), "$1-$2");
20833
+ return EXACT_CREDENTIAL_NAME.test(normalized) || SUFFIX_CREDENTIAL_NAME.test(normalized);
20834
+ }
20835
+ function exactLongFlag(raw2) {
20836
+ return EXACT_LONG_FLAG_RE.test(unquote(raw2));
20837
+ }
20838
+ function redactArgv(argv, options) {
20839
+ const out = argv.map((part) => redactCredentialSyntax(part, options));
20840
+ for (let index = 0; index < argv.length; index++) {
20841
+ const flag = argv[index];
20842
+ if (exactLongFlag(flag) && index + 1 < argv.length) {
20843
+ out[index + 1] = replacement(options, argv[index + 1]);
20844
+ index++;
20845
+ continue;
20846
+ }
20847
+ const userFlag = unquote(flag).toLowerCase();
20848
+ const curlContext = argv.slice(0, index).some((part) => CURL_EXECUTABLE_RE.test(unquote(part)));
20849
+ if ((userFlag === "--user" || userFlag === "-u" && curlContext) && index + 1 < argv.length) {
20850
+ const safe = redactUserInfoToken(argv[index + 1], options);
20851
+ if (safe !== null) out[index + 1] = safe;
20852
+ index++;
20853
+ }
20854
+ }
20855
+ return out;
20856
+ }
20857
+ function redactCredentialStructure(input, options = {}) {
20858
+ const seen = /* @__PURE__ */ new WeakMap();
20859
+ const visit = (value, fieldName, credentialContext = false) => {
20860
+ const sensitive = credentialContext || fieldName !== void 0 && isCredentialFieldName(fieldName);
20861
+ if (typeof value === "string") {
20862
+ if (sensitive) return replacement(options, value);
20863
+ return redactCredentialSyntax(value, options);
20864
+ }
20865
+ if (!value || typeof value !== "object") return value;
20866
+ const prior = seen.get(value);
20867
+ if (prior) return prior;
20868
+ if (Array.isArray(value)) {
20869
+ const allStrings = value.every((entry) => typeof entry === "string");
20870
+ const target2 = [];
20871
+ seen.set(value, target2);
20872
+ const source = allStrings && (fieldName === void 0 || ARGV_FIELD_NAME.test(fieldName)) ? redactArgv(value, options) : value;
20873
+ for (const entry of source) target2.push(visit(entry, void 0, sensitive));
20874
+ return target2;
20875
+ }
20876
+ const target = {};
20877
+ seen.set(value, target);
20878
+ for (const [key, entry] of Object.entries(value)) target[key] = visit(entry, key, sensitive);
20879
+ return target;
20880
+ };
20881
+ return visit(input);
20882
+ }
20883
+ var DEFAULT_REPLACEMENT, FLAG_NAME, BOUNDARY, FLAG_TOKEN, FLAG_SEPARATOR, ESCAPED_SHELL_CHARACTER, QUOTED_OR_BARE_VALUE, LONG_FLAG_RE, USER_FLAG_RE, ATTACHED_USER_FLAG_RE, URL_USERINFO_RE, URL_ENCODED_USERINFO_RE, EXACT_CREDENTIAL_NAME, SUFFIX_CREDENTIAL_NAME, ARGV_FIELD_NAME, EXACT_LONG_FLAG_RE, CURL_EXECUTABLE_RE;
20884
+ var init_credential_redaction = __esm({
20885
+ "packages/server/src/credential-redaction.ts"() {
20886
+ "use strict";
20887
+ DEFAULT_REPLACEMENT = "[redacted]";
20888
+ FLAG_NAME = String.raw`(?:api[-_]?key|access[-_]?token|auth[-_]?token|client[-_]?secret|token|secret|password|passwd|credential|private[-_]?key)`;
20889
+ BOUNDARY = String.raw`(^|[\s;&|([{"'])`;
20890
+ FLAG_TOKEN = String.raw`(?:(?:"|')?--?${FLAG_NAME}(?:"|')?)`;
20891
+ FLAG_SEPARATOR = String.raw`(?:[ \t]*(?:=|:)[ \t]*|[ \t]*\\\r?\n[ \t]*|[ \t]+)`;
20892
+ ESCAPED_SHELL_CHARACTER = String.raw`\\(?:\r?\n|[^\r\n])`;
20893
+ QUOTED_OR_BARE_VALUE = String.raw`(?:"(?:${ESCAPED_SHELL_CHARACTER}|[^"\\]){0,4096}"|'[^']{0,4096}'|(?:${ESCAPED_SHELL_CHARACTER}|[^\\\s;&|"']){1,4096})`;
20894
+ LONG_FLAG_RE = new RegExp(`${BOUNDARY}(${FLAG_TOKEN})(${FLAG_SEPARATOR})(${QUOTED_OR_BARE_VALUE})`, "gimu");
20895
+ USER_FLAG_RE = new RegExp(
20896
+ `${BOUNDARY}((?:(?:"|')?(?:-u|--user)(?:"|')?))(${FLAG_SEPARATOR})(${QUOTED_OR_BARE_VALUE})`,
20897
+ "gimu"
20898
+ );
20899
+ ATTACHED_USER_FLAG_RE = new RegExp(`${BOUNDARY}(-u)(${QUOTED_OR_BARE_VALUE})`, "gimu");
20900
+ URL_USERINFO_RE = /\b([a-z][a-z0-9+.-]{0,31}:\/\/)([^\s/?#@"':]{1,512})(:)([^\s/?#@"']{0,4096})@/giu;
20901
+ URL_ENCODED_USERINFO_RE = /\b([a-z][a-z0-9+.-]{0,31}:\/\/)([^\s/?#@"']{1,512}?)(%3a)([^\s/?#@"']{0,4096})@/giu;
20902
+ EXACT_CREDENTIAL_NAME = /^(?:authorization|proxy[-_]?authorization|api[-_]?key|access[-_]?token|auth[-_]?token|client[-_]?secret|token|secret|password|passwd|credential|private[-_]?key|cookie)$/iu;
20903
+ SUFFIX_CREDENTIAL_NAME = /(?:^|[._-])(?:api[-_]?key|access[-_]?token|auth[-_]?token|client[-_]?secret|token|secret|password|passwd|credential|private[-_]?key)$/iu;
20904
+ ARGV_FIELD_NAME = /^(?:argv|args|arguments|command|cmd)$/iu;
20905
+ EXACT_LONG_FLAG_RE = new RegExp(`^--?${FLAG_NAME}$`, "iu");
20906
+ CURL_EXECUTABLE_RE = /(?:^|[\\/])curl(?:\.exe)?$/iu;
20907
+ }
20908
+ });
20909
+
20910
+ // packages/server/src/backend/codex-error.ts
20911
+ function errorText(text2) {
20912
+ const safe = redactCredentialSyntax(text2).replace(/\b((?:proxy-)?authorization\s*:\s*(?:bearer|basic)\s+)[^\s,;"']+/gi, "$1[redacted]").trim();
20913
+ return safe.length > 32e3 ? `${safe.slice(0, 32e3)}
20914
+ [truncated]` : safe;
20915
+ }
20916
+ function codexProviderError(raw2, at, retrying = false) {
20917
+ const error = raw2 && typeof raw2 === "object" ? raw2 : {};
20918
+ const info = error.codex_error_info ?? error.codexErrorInfo;
20919
+ const category = typeof info === "string" ? info : info && typeof info === "object" ? Object.keys(info)[0] : void 0;
20920
+ const code = category?.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase().slice(0, 128);
20921
+ const message = typeof raw2 === "string" ? raw2 : typeof error.message === "string" ? error.message : "";
20922
+ const details = error.additional_details ?? error.additionalDetails;
20923
+ return {
20924
+ message: errorText(message) || "Codex reported an error without a message.",
20925
+ ...code ? { code } : {},
20926
+ ...typeof details === "string" && details.trim() ? { details: errorText(details) } : {},
20927
+ ...retrying ? { retrying: true } : {},
20928
+ ...at ? { at } : {}
20929
+ };
20930
+ }
20931
+ var init_codex_error = __esm({
20932
+ "packages/server/src/backend/codex-error.ts"() {
20933
+ "use strict";
20934
+ init_credential_redaction();
20935
+ }
20936
+ });
20937
+
20755
20938
  // packages/server/src/discover.ts
20756
20939
  import { readdirSync as readdirSync3, statSync as statSync4, openSync as openSync7, readSync, closeSync as closeSync6 } from "node:fs";
20757
20940
  import { dirname as dirname7, join as join11 } from "node:path";
@@ -23754,6 +23937,18 @@ function applyFinalText(state, text2) {
23754
23937
  function applyEvent(state, ev) {
23755
23938
  if ("at" in ev && typeof ev.at === "string" && ev.kind !== "context-usage") state.lastActivityAt = ev.at;
23756
23939
  switch (ev.kind) {
23940
+ case "provider-error":
23941
+ state.sawRecords = true;
23942
+ if (ev.error.retrying) break;
23943
+ state.turn = "idle";
23944
+ state.apiFault = true;
23945
+ state.providerError = ev.error;
23946
+ state.lastAssistant = ev.error.message;
23947
+ state.lastFence = void 0;
23948
+ state.lastAssistantAllDone = false;
23949
+ state.lastAssistantHasQuestion = false;
23950
+ if (typeof ev.at === "string") state.lastAssistantAt = ev.at;
23951
+ break;
23757
23952
  case "turn-start":
23758
23953
  state.sawRecords = true;
23759
23954
  state.turn = "in-flight";
@@ -23762,10 +23957,16 @@ function applyEvent(state, ev) {
23762
23957
  state.sawRecords = true;
23763
23958
  state.turn = "idle";
23764
23959
  if (typeof ev.at === "string") state.lastAssistantAt = ev.at;
23960
+ if (ev.finalText !== void 0 || ev.successful) {
23961
+ state.apiFault = void 0;
23962
+ state.providerError = void 0;
23963
+ }
23765
23964
  if (ev.finalText !== void 0) applyFinalText(state, ev.finalText);
23766
23965
  break;
23767
23966
  case "assistant-text":
23768
23967
  state.sawRecords = true;
23968
+ state.apiFault = void 0;
23969
+ state.providerError = void 0;
23769
23970
  if (ev.final) {
23770
23971
  if (typeof ev.at === "string") state.lastAssistantAt = ev.at;
23771
23972
  applyFinalText(state, ev.text);
@@ -25203,7 +25404,7 @@ ${detail2}
25203
25404
  if (!s) return void 0;
25204
25405
  const pendingQuestion = s.lastAssistantHasQuestion;
25205
25406
  const nowMs = now();
25206
- return { turn: s.turn, permPrompt: s.permPrompt, permPolicy: s.permPolicy, permDenies: s.permDenies, model: s.model, effort: s.effort, profileAt: s.profileAt, profileRevision: s.profileRevision, permissionMode: s.permissionMode, permissionModeAt: s.permissionModeAt, permissionModeRevision: s.permissionModeRevision, lastActivityAt: s.lastActivityAt, lastAssistantAt: s.lastAssistantAt, lastAssistant: s.lastAssistant, aiTitle: s.aiTitle, customTitle: s.customTitle, customTitleRevision: s.customTitleRevision, subAgents: subAgentViews(s, nowMs), droppedReports: [...s.queuedReports.values()], bgShells: [...bgShellViews(s), ...codexBgShellViews(s)], retiredShells: retiredShellViews(s), pendingAsk: s.pendingAsk, pendingQuestion, lastAssistantAllDone: s.lastAssistantAllDone, lastUserAt: s.lastUserAt, lastUserText: s.lastUserText, firstUserText: s.firstUserText, lastFence: s.lastFence, noTranscript: s.noTranscript, authFault: s.authFault, apiFault: s.apiFault, limitFault: s.limitFault, contextTokens: s.contextTokens, contextWindow: s.contextWindow, lastCompactionAt: s.lastCompactionAt };
25407
+ return { turn: s.turn, permPrompt: s.permPrompt, permPolicy: s.permPolicy, permDenies: s.permDenies, model: s.model, effort: s.effort, profileAt: s.profileAt, profileRevision: s.profileRevision, permissionMode: s.permissionMode, permissionModeAt: s.permissionModeAt, permissionModeRevision: s.permissionModeRevision, lastActivityAt: s.lastActivityAt, lastAssistantAt: s.lastAssistantAt, lastAssistant: s.lastAssistant, aiTitle: s.aiTitle, customTitle: s.customTitle, customTitleRevision: s.customTitleRevision, subAgents: subAgentViews(s, nowMs), droppedReports: [...s.queuedReports.values()], bgShells: [...bgShellViews(s), ...codexBgShellViews(s)], retiredShells: retiredShellViews(s), pendingAsk: s.pendingAsk, pendingQuestion, lastAssistantAllDone: s.lastAssistantAllDone, lastUserAt: s.lastUserAt, lastUserText: s.lastUserText, firstUserText: s.firstUserText, lastFence: s.lastFence, noTranscript: s.noTranscript, authFault: s.authFault, apiFault: s.apiFault, providerError: s.providerError, limitFault: s.limitFault, contextTokens: s.contextTokens, contextWindow: s.contextWindow, lastCompactionAt: s.lastCompactionAt };
25207
25408
  },
25208
25409
  // The CURRENT fresh foreign session ids (mtime within FOREIGN_FRESH_MS, capped), mtime-desc. Kept
25209
25410
  // as the last scan's result — recomputed at most every FOREIGN_SCAN_EVERY ticks.
@@ -25536,8 +25737,15 @@ function parseCodexLine(line) {
25536
25737
  return [{ kind: "turn-start", at }];
25537
25738
  case "task_complete": {
25538
25739
  const finalText = typeof p.last_agent_message === "string" ? p.last_agent_message : void 0;
25539
- return [{ kind: "turn-end", at, finalText }];
25740
+ if (p.error != null) return [
25741
+ { kind: "provider-error", at, error: codexProviderError(p.error, at) },
25742
+ { kind: "turn-end", at }
25743
+ ];
25744
+ return [{ kind: "turn-end", at, finalText, ...p.error === null ? { successful: true } : {} }];
25540
25745
  }
25746
+ case "error":
25747
+ case "stream_error":
25748
+ return [{ kind: "provider-error", at, error: codexProviderError(p.error ?? p, at, pt === "stream_error" || p.will_retry === true || p.willRetry === true) }];
25541
25749
  // The OTHER closing bracket. An INTERRUPTED turn (`reason: "interrupted"` — what turn/interrupt
25542
25750
  // produces, now that stopping a Codex thread actually stops it) never reaches task_complete.
25543
25751
  // Without this the rollout's last word stays task_started, so the tailer holds the turn in-flight
@@ -26016,6 +26224,7 @@ var CODEX_FIRST_FINAL_TITLE_TRANSPORT, CODEX_FIRST_OUTPUT_TITLE_DEVELOPER_INSTRU
26016
26224
  var init_codex = __esm({
26017
26225
  "packages/server/src/backend/codex.ts"() {
26018
26226
  "use strict";
26227
+ init_codex_error();
26019
26228
  init_tailer();
26020
26229
  CODEX_FIRST_FINAL_TITLE_TRANSPORT = 'FRIZZ TITLE TRANSPORT (required): your very first assistant message must begin with one concise `<!-- frizz title="Concise thread title" -->` comment before any commentary, acknowledgement, or tool call. Frizz removes that comment from chat and uses only its quoted title as this thread\'s automatic title.';
26021
26230
  CODEX_FIRST_OUTPUT_TITLE_DEVELOPER_INSTRUCTIONS = 'FRIZZ UI metadata protocol (mandatory): the very first assistant message in this new session, before any commentary, acknowledgement, tool call, or other action, MUST begin on its first line with exactly one `<!-- frizz title="..." -->` HTML comment. Replace `...` with a concise human-readable 3-8 word title for the user\'s task. Put no text before the comment. You may continue the message normally after it. Emit this title comment exactly once. Do not explain the protocol. Frizz removes the comment before displaying the conversation.';
@@ -26054,152 +26263,6 @@ var init_worker_env = __esm({
26054
26263
  }
26055
26264
  });
26056
26265
 
26057
- // packages/server/src/credential-redaction.ts
26058
- function replacement(options, secretToken) {
26059
- const configured = options.replacement ?? DEFAULT_REPLACEMENT;
26060
- return typeof configured === "function" ? configured(secretToken) : configured;
26061
- }
26062
- function unquote(raw2) {
26063
- return raw2.length >= 2 && (raw2[0] === '"' || raw2[0] === "'") && raw2.at(-1) === raw2[0] ? raw2.slice(1, -1) : raw2;
26064
- }
26065
- function userInfoParts(raw2) {
26066
- const value = unquote(raw2);
26067
- const literal = value.indexOf(":");
26068
- const encodedMatch = /%3a/iu.exec(value);
26069
- const encoded = encodedMatch?.index ?? -1;
26070
- const index = literal === -1 ? encoded : encoded === -1 ? literal : Math.min(literal, encoded);
26071
- if (index <= 0) return null;
26072
- const delimiter2 = value.slice(index, index + (index === encoded ? 3 : 1));
26073
- return { username: value.slice(0, index), delimiter: delimiter2, password: value.slice(index + delimiter2.length) };
26074
- }
26075
- function redactUserInfoToken(raw2, options) {
26076
- const parts = userInfoParts(raw2);
26077
- if (!parts) return null;
26078
- return `${parts.username}${parts.delimiter}${replacement(options, parts.password)}`;
26079
- }
26080
- function hasCurlCommandContext(source, offset) {
26081
- const bounded = source.slice(Math.max(0, offset - 1024), offset);
26082
- const separator = Math.max(
26083
- bounded.lastIndexOf("\n"),
26084
- bounded.lastIndexOf("\r"),
26085
- bounded.lastIndexOf(";"),
26086
- bounded.lastIndexOf("&"),
26087
- bounded.lastIndexOf("|")
26088
- );
26089
- const segment = bounded.slice(separator + 1);
26090
- return segment.split(/[ \t]+/u).some((token) => CURL_EXECUTABLE_RE.test(unquote(token)));
26091
- }
26092
- function redactCredentialSyntax(raw2, options = {}) {
26093
- let value = raw2;
26094
- value = value.replace(
26095
- URL_USERINFO_RE,
26096
- (_whole, scheme, username, delimiter2, password) => `${scheme}${username}${delimiter2}${replacement(options, password)}@`
26097
- );
26098
- value = value.replace(
26099
- URL_ENCODED_USERINFO_RE,
26100
- (_whole, scheme, username, delimiter2, password) => `${scheme}${username}${delimiter2}${replacement(options, password)}@`
26101
- );
26102
- value = value.replace(
26103
- USER_FLAG_RE,
26104
- (whole, boundary, flag, separator, userInfo, offset, source) => {
26105
- if (unquote(flag).toLowerCase() === "-u" && !hasCurlCommandContext(source, offset)) return whole;
26106
- const safe = redactUserInfoToken(userInfo, options);
26107
- return safe === null ? whole : `${boundary}${flag}${separator}${safe}`;
26108
- }
26109
- );
26110
- value = value.replace(
26111
- ATTACHED_USER_FLAG_RE,
26112
- (whole, boundary, flag, userInfo, offset, source) => {
26113
- if (!hasCurlCommandContext(source, offset)) return whole;
26114
- const safe = redactUserInfoToken(userInfo, options);
26115
- return safe === null ? whole : `${boundary}${flag}${safe}`;
26116
- }
26117
- );
26118
- value = value.replace(
26119
- LONG_FLAG_RE,
26120
- (_whole, boundary, flag, separator, secret) => `${boundary}${flag}${separator}${replacement(options, secret)}`
26121
- );
26122
- return value;
26123
- }
26124
- function isCredentialFieldName(name) {
26125
- const normalized = name.replace(new RegExp("([\\p{Ll}\\d])(\\p{Lu})", "gu"), "$1-$2");
26126
- return EXACT_CREDENTIAL_NAME.test(normalized) || SUFFIX_CREDENTIAL_NAME.test(normalized);
26127
- }
26128
- function exactLongFlag(raw2) {
26129
- return EXACT_LONG_FLAG_RE.test(unquote(raw2));
26130
- }
26131
- function redactArgv(argv, options) {
26132
- const out = argv.map((part) => redactCredentialSyntax(part, options));
26133
- for (let index = 0; index < argv.length; index++) {
26134
- const flag = argv[index];
26135
- if (exactLongFlag(flag) && index + 1 < argv.length) {
26136
- out[index + 1] = replacement(options, argv[index + 1]);
26137
- index++;
26138
- continue;
26139
- }
26140
- const userFlag = unquote(flag).toLowerCase();
26141
- const curlContext = argv.slice(0, index).some((part) => CURL_EXECUTABLE_RE.test(unquote(part)));
26142
- if ((userFlag === "--user" || userFlag === "-u" && curlContext) && index + 1 < argv.length) {
26143
- const safe = redactUserInfoToken(argv[index + 1], options);
26144
- if (safe !== null) out[index + 1] = safe;
26145
- index++;
26146
- }
26147
- }
26148
- return out;
26149
- }
26150
- function redactCredentialStructure(input, options = {}) {
26151
- const seen = /* @__PURE__ */ new WeakMap();
26152
- const visit = (value, fieldName, credentialContext = false) => {
26153
- const sensitive = credentialContext || fieldName !== void 0 && isCredentialFieldName(fieldName);
26154
- if (typeof value === "string") {
26155
- if (sensitive) return replacement(options, value);
26156
- return redactCredentialSyntax(value, options);
26157
- }
26158
- if (!value || typeof value !== "object") return value;
26159
- const prior = seen.get(value);
26160
- if (prior) return prior;
26161
- if (Array.isArray(value)) {
26162
- const allStrings = value.every((entry) => typeof entry === "string");
26163
- const target2 = [];
26164
- seen.set(value, target2);
26165
- const source = allStrings && (fieldName === void 0 || ARGV_FIELD_NAME.test(fieldName)) ? redactArgv(value, options) : value;
26166
- for (const entry of source) target2.push(visit(entry, void 0, sensitive));
26167
- return target2;
26168
- }
26169
- const target = {};
26170
- seen.set(value, target);
26171
- for (const [key, entry] of Object.entries(value)) target[key] = visit(entry, key, sensitive);
26172
- return target;
26173
- };
26174
- return visit(input);
26175
- }
26176
- var DEFAULT_REPLACEMENT, FLAG_NAME, BOUNDARY, FLAG_TOKEN, FLAG_SEPARATOR, ESCAPED_SHELL_CHARACTER, QUOTED_OR_BARE_VALUE, LONG_FLAG_RE, USER_FLAG_RE, ATTACHED_USER_FLAG_RE, URL_USERINFO_RE, URL_ENCODED_USERINFO_RE, EXACT_CREDENTIAL_NAME, SUFFIX_CREDENTIAL_NAME, ARGV_FIELD_NAME, EXACT_LONG_FLAG_RE, CURL_EXECUTABLE_RE;
26177
- var init_credential_redaction = __esm({
26178
- "packages/server/src/credential-redaction.ts"() {
26179
- "use strict";
26180
- DEFAULT_REPLACEMENT = "[redacted]";
26181
- FLAG_NAME = String.raw`(?:api[-_]?key|access[-_]?token|auth[-_]?token|client[-_]?secret|token|secret|password|passwd|credential|private[-_]?key)`;
26182
- BOUNDARY = String.raw`(^|[\s;&|([{"'])`;
26183
- FLAG_TOKEN = String.raw`(?:(?:"|')?--?${FLAG_NAME}(?:"|')?)`;
26184
- FLAG_SEPARATOR = String.raw`(?:[ \t]*(?:=|:)[ \t]*|[ \t]*\\\r?\n[ \t]*|[ \t]+)`;
26185
- ESCAPED_SHELL_CHARACTER = String.raw`\\(?:\r?\n|[^\r\n])`;
26186
- QUOTED_OR_BARE_VALUE = String.raw`(?:"(?:${ESCAPED_SHELL_CHARACTER}|[^"\\]){0,4096}"|'[^']{0,4096}'|(?:${ESCAPED_SHELL_CHARACTER}|[^\\\s;&|"']){1,4096})`;
26187
- LONG_FLAG_RE = new RegExp(`${BOUNDARY}(${FLAG_TOKEN})(${FLAG_SEPARATOR})(${QUOTED_OR_BARE_VALUE})`, "gimu");
26188
- USER_FLAG_RE = new RegExp(
26189
- `${BOUNDARY}((?:(?:"|')?(?:-u|--user)(?:"|')?))(${FLAG_SEPARATOR})(${QUOTED_OR_BARE_VALUE})`,
26190
- "gimu"
26191
- );
26192
- ATTACHED_USER_FLAG_RE = new RegExp(`${BOUNDARY}(-u)(${QUOTED_OR_BARE_VALUE})`, "gimu");
26193
- URL_USERINFO_RE = /\b([a-z][a-z0-9+.-]{0,31}:\/\/)([^\s/?#@"':]{1,512})(:)([^\s/?#@"']{0,4096})@/giu;
26194
- URL_ENCODED_USERINFO_RE = /\b([a-z][a-z0-9+.-]{0,31}:\/\/)([^\s/?#@"']{1,512}?)(%3a)([^\s/?#@"']{0,4096})@/giu;
26195
- EXACT_CREDENTIAL_NAME = /^(?:authorization|proxy[-_]?authorization|api[-_]?key|access[-_]?token|auth[-_]?token|client[-_]?secret|token|secret|password|passwd|credential|private[-_]?key|cookie)$/iu;
26196
- SUFFIX_CREDENTIAL_NAME = /(?:^|[._-])(?:api[-_]?key|access[-_]?token|auth[-_]?token|client[-_]?secret|token|secret|password|passwd|credential|private[-_]?key)$/iu;
26197
- ARGV_FIELD_NAME = /^(?:argv|args|arguments|command|cmd)$/iu;
26198
- EXACT_LONG_FLAG_RE = new RegExp(`^--?${FLAG_NAME}$`, "iu");
26199
- CURL_EXECUTABLE_RE = /(?:^|[\\/])curl(?:\.exe)?$/iu;
26200
- }
26201
- });
26202
-
26203
26266
  // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/constants.js
26204
26267
  var require_constants = __commonJS({
26205
26268
  "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/constants.js"(exports, module) {
@@ -31867,7 +31930,7 @@ function createCodexAppServerBridge(options) {
31867
31930
  function codexAppServerBridgeEnabled() {
31868
31931
  return true;
31869
31932
  }
31870
- var CODEX_APP_SERVER_PROVIDER, CODEX_NATIVE_LISTEN_FLAG, CODEX_APP_SERVER_SUPPORTED_VERSION, CODEX_APP_SERVER_PROTOCOL_REVISION, aheadVersionWarned, PROTOCOL_FINGERPRINT, CLIENT_INFO, CLIENT_CAPABILITIES, CODEX_SANDBOX_MODES, CODEX_APPROVAL_POLICY, CODEX_DEFAULT_SANDBOX, SANDBOX_CONFIRM_TIMEOUT_MS, SANDBOX_NOOP_GRACE_MS, MAX_JSONL_BYTES, MAX_INBOUND_JSONL_BYTES, MAX_INBOUND_RECORDS, MAX_INBOUND_QUEUED_BYTES, MAX_OUTBOUND_REQUESTS, MAX_STDERR_BYTES, DEFAULT_REQUEST_TIMEOUT_MS, BRIDGE_DB_SCHEMA_VERSION, RpcIdSchema, Opaque, SafeTimestampMs, NullableString, CommandAction, NetworkApprovalContext, FileSystemSpecialPath, FileSystemPath, FileSystemSandboxEntry, NetworkPermissions, FileSystemPermissions, RequestedPermissions, NetworkPolicyAmendment, CommandApprovalParams, FileApprovalParams, PatchChangeKind, FileUpdateChange, FileChangeItem, CommandExecutionItem, ItemStartedNotification, ItemCompletedNotification, FileChangePatchUpdatedNotification, PermissionsApprovalParams, UserInputQuestion, UserInputParams, McpBase, McpElicitationParams, ResolvedNotification, RpcProtocolError, JsonlRpcConnection, BindingRowSchema, BridgeMetaRowSchema, DISPLAY_REDACTION, UNSAFE_DISPLAY_TEXT, SECRET_NAME, commandDecisionMap, InitializeResponse, ThreadResponse, TurnResponse, TurnSteerResponse, SkillsListResponse, ThreadResumeSandbox, ThreadResumeStatus, ThreadSettingsUpdated, TurnStarted, TurnCompleted, MAX_CORRELATED_FILE_ITEMS, CODEX_APP_SERVER_TABLES, CodexAppServerBridge;
31933
+ var CODEX_APP_SERVER_PROVIDER, CODEX_NATIVE_LISTEN_FLAG, CODEX_APP_SERVER_SUPPORTED_VERSION, CODEX_APP_SERVER_PROTOCOL_REVISION, aheadVersionWarned, PROTOCOL_FINGERPRINT, CLIENT_INFO, CLIENT_CAPABILITIES, CODEX_SANDBOX_MODES, CODEX_APPROVAL_POLICY, CODEX_DEFAULT_SANDBOX, SANDBOX_CONFIRM_TIMEOUT_MS, SANDBOX_NOOP_GRACE_MS, MAX_JSONL_BYTES, MAX_INBOUND_JSONL_BYTES, MAX_INBOUND_RECORDS, MAX_INBOUND_QUEUED_BYTES, MAX_OUTBOUND_REQUESTS, MAX_STDERR_BYTES, DEFAULT_REQUEST_TIMEOUT_MS, AUTH_REPLACEMENT_WAIT_MS, MAX_AUTH_REPLACEMENT_ATTEMPTS, BRIDGE_DB_SCHEMA_VERSION, RpcIdSchema, Opaque, SafeTimestampMs, NullableString, CommandAction, NetworkApprovalContext, FileSystemSpecialPath, FileSystemPath, FileSystemSandboxEntry, NetworkPermissions, FileSystemPermissions, RequestedPermissions, NetworkPolicyAmendment, CommandApprovalParams, FileApprovalParams, PatchChangeKind, FileUpdateChange, FileChangeItem, CommandExecutionItem, ItemStartedNotification, ItemCompletedNotification, FileChangePatchUpdatedNotification, PermissionsApprovalParams, UserInputQuestion, UserInputParams, McpBase, McpElicitationParams, ResolvedNotification, RpcProtocolError, JsonlRpcConnection, BindingRowSchema, BridgeMetaRowSchema, DISPLAY_REDACTION, UNSAFE_DISPLAY_TEXT, SECRET_NAME, commandDecisionMap, InitializeResponse, ThreadResponse, TurnResponse, TurnSteerResponse, SkillsListResponse, ThreadResumeSandbox, ThreadResumeStatus, ThreadSettingsUpdated, TurnStarted, TurnCompleted, MAX_CORRELATED_FILE_ITEMS, CODEX_APP_SERVER_TABLES, CodexAppServerBridge;
31871
31934
  var init_codex_app_server = __esm({
31872
31935
  "packages/server/src/backend/codex-app-server.ts"() {
31873
31936
  "use strict";
@@ -31881,6 +31944,7 @@ var init_codex_app_server = __esm({
31881
31944
  init_codex_app_server_native();
31882
31945
  init_auth_status();
31883
31946
  init_codex_mcp();
31947
+ init_codex_error();
31884
31948
  init_logging();
31885
31949
  CODEX_APP_SERVER_PROVIDER = "codex-app-server";
31886
31950
  CODEX_NATIVE_LISTEN_FLAG = "FRIZZ_CODEX_NATIVE_LISTEN";
@@ -31932,6 +31996,8 @@ var init_codex_app_server = __esm({
31932
31996
  MAX_OUTBOUND_REQUESTS = 128;
31933
31997
  MAX_STDERR_BYTES = 16 * 1024;
31934
31998
  DEFAULT_REQUEST_TIMEOUT_MS = 2e4;
31999
+ AUTH_REPLACEMENT_WAIT_MS = 2e4;
32000
+ MAX_AUTH_REPLACEMENT_ATTEMPTS = 3;
31935
32001
  BRIDGE_DB_SCHEMA_VERSION = 1;
31936
32002
  RpcIdSchema = external_exports.union([external_exports.string().min(1).max(256), external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER)]);
31937
32003
  Opaque = external_exports.string().min(1).max(256);
@@ -32451,6 +32517,7 @@ var init_codex_app_server = __esm({
32451
32517
  processAuthAccountId;
32452
32518
  /** Serializes account-driven replacement across concurrent session/turn starts. */
32453
32519
  authReplacement = null;
32520
+ authReplacementWaitMs;
32454
32521
  turnIdleWaiters = /* @__PURE__ */ new Set();
32455
32522
  /**
32456
32523
  * The handshake a FRESHLY FORKED daemon already gave us and we already rejected — i.e. what the
@@ -32486,6 +32553,9 @@ var init_codex_app_server = __esm({
32486
32553
  // durable, and it must not be — a processId belongs to one app-server process, so a stale one
32487
32554
  // surviving a restart would offer an × that addresses a PTY that no longer exists.
32488
32555
  liveExecs = /* @__PURE__ */ new Map();
32556
+ // Live notices fill the gap before task_complete reaches the durable rollout. Retry notices are
32557
+ // not retained by Codex at all. Session keys and current-turn checks prevent cross-thread leakage.
32558
+ providerErrors = /* @__PURE__ */ new Map();
32489
32559
  activeOperations = 0;
32490
32560
  operationWaiters = /* @__PURE__ */ new Set();
32491
32561
  shutdownPromise = null;
@@ -32495,6 +32565,7 @@ var init_codex_app_server = __esm({
32495
32565
  this.makeId = options.id ?? randomUUID11;
32496
32566
  this.codexBin = options.codexBin ?? "codex";
32497
32567
  this.timeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
32568
+ this.authReplacementWaitMs = options.authReplacementWaitMs ?? AUTH_REPLACEMENT_WAIT_MS;
32498
32569
  const hostKind = selectCodexHostKind(process.env[CODEX_NATIVE_LISTEN_FLAG], process.platform, Boolean(options.spawn));
32499
32570
  this.host = options.host ?? (hostKind === "direct" ? directChildHost(options.spawn) : hostKind === "native" ? nativeListenCodexAppServerHost : daemonCodexAppServerHost);
32500
32571
  this.db = options.db;
@@ -32682,7 +32753,9 @@ var init_codex_app_server = __esm({
32682
32753
  }
32683
32754
  if (binding.current_turn_id !== null) throw new Error("Codex app-server session already has an active turn");
32684
32755
  const pendingKey = turnKey(binding);
32756
+ this.providerErrors.delete(input.sessionId);
32685
32757
  this.pendingTurnStarts.add(pendingKey);
32758
+ this.options.onStatusChange?.();
32686
32759
  try {
32687
32760
  const response = TurnResponse.parse(await connection.request("turn/start", {
32688
32761
  threadId: binding.codex_thread_id,
@@ -32939,7 +33012,8 @@ var init_codex_app_server = __esm({
32939
33012
  const onThisConnection = row.state === "active" && row.connection_epoch === this.connectionEpoch;
32940
33013
  return {
32941
33014
  bridgeTurn: onThisConnection && (row.current_turn_id !== null || this.pendingTurnStarts.has(turnKey(row))),
32942
- ownedSince: row.updated_at
33015
+ ownedSince: row.updated_at,
33016
+ providerError: onThisConnection ? this.providerErrors.get(sessionId) : void 0
32943
33017
  };
32944
33018
  }
32945
33019
  /**
@@ -32981,6 +33055,7 @@ var init_codex_app_server = __esm({
32981
33055
  if (this.closed || this.dbReleased) return false;
32982
33056
  const row = this.bindingForScope(threadSlug, sessionId);
32983
33057
  if (!row) return false;
33058
+ this.providerErrors.delete(sessionId);
32984
33059
  const ownsCurrentProcess = row.connection_epoch === this.connectionEpoch || this.openingConnection !== null;
32985
33060
  try {
32986
33061
  this.forgetCorrelatedFileItems(row.codex_thread_id);
@@ -33139,12 +33214,27 @@ var init_codex_app_server = __esm({
33139
33214
  * keeps using the account it started with even after ccbroker atomically switches auth.json. Before
33140
33215
  * starting new model work, replace that stale process — but only after every turn already running
33141
33216
  * in the shared per-project process has reached its own completion event.
33217
+ *
33218
+ * THE WAIT IS BOUNDED, AND WHEN THE BOUND EXPIRES THE TURN GOES AHEAD ON THE ACCOUNT WE HAVE.
33219
+ * "Every turn in this project is idle" is a whole-PROJECT condition and the app-server is shared, so
33220
+ * on a board running several codex threads it can be a long time coming — and until it comes, this
33221
+ * used to hold the operator's own `turn/start` open with no timeout, no error and no way to tell.
33222
+ * Measured 2026-09-05: auth.json changed at 21:45Z, the thread's turn ended at 23:00Z, and every
33223
+ * follow-up typed into it from then on hung inside this wait until the project happened to go
33224
+ * quiet at 00:19Z — 1h 18m of an operator typing steers into a box that answered nothing (the
33225
+ * browser then queued each one behind the last, so not even a reload's worth of them ever left).
33226
+ *
33227
+ * Running one turn on the previous account is a visible, recoverable outcome; hanging the send is
33228
+ * neither. So the replacement stays armed and lands at the next real idle boundary, and every turn
33229
+ * started after it picks up the new account. A replacement that FAILS outright still throws — that
33230
+ * is a broken app-server, not a busy one.
33142
33231
  */
33143
33232
  async ensureCurrentAuth() {
33144
- for (; ; ) {
33233
+ for (let attempt = 0; ; attempt++) {
33145
33234
  const desiredAccountId = (this.options.codexAuthAccountId ?? readCodexAccountId)();
33146
33235
  const connection = await this.ensureConnected();
33147
33236
  if (!desiredAccountId || this.processAuthAccountId === desiredAccountId) return connection;
33237
+ if (attempt >= MAX_AUTH_REPLACEMENT_ATTEMPTS) return connection;
33148
33238
  if (!this.authReplacement) {
33149
33239
  const replacement2 = this.replaceAppServerForAuthChange();
33150
33240
  this.authReplacement = replacement2;
@@ -33152,7 +33242,23 @@ var init_codex_app_server = __esm({
33152
33242
  if (this.authReplacement === replacement2) this.authReplacement = null;
33153
33243
  }).catch(() => void 0);
33154
33244
  }
33155
- await this.authReplacement;
33245
+ if (!await this.awaitAuthReplacement(this.authReplacement)) return connection;
33246
+ }
33247
+ }
33248
+ /** Await an armed replacement for at most AUTH_REPLACEMENT_WAIT_MS. `false` = it is still waiting for
33249
+ * the project to go idle, so the caller should proceed rather than hang; a rejection propagates. */
33250
+ async awaitAuthReplacement(replacement2) {
33251
+ let timer;
33252
+ const expired = new Promise((resolve12) => {
33253
+ timer = setTimeout(() => resolve12(false), this.authReplacementWaitMs);
33254
+ timer.unref?.();
33255
+ });
33256
+ const settled = replacement2.then(() => true);
33257
+ try {
33258
+ return await Promise.race([settled, expired]);
33259
+ } finally {
33260
+ if (timer) clearTimeout(timer);
33261
+ void settled.catch(() => void 0);
33156
33262
  }
33157
33263
  }
33158
33264
  hasInFlightTurns() {
@@ -33314,6 +33420,7 @@ var init_codex_app_server = __esm({
33314
33420
  const epoch = this.connectionEpoch;
33315
33421
  this.connection = null;
33316
33422
  this.processAuthAccountId = void 0;
33423
+ this.providerErrors.clear();
33317
33424
  this.forgetCorrelatedFileItems();
33318
33425
  this.releaseSettingsWaiters();
33319
33426
  if (this.closed || this.dbReleased) return;
@@ -34056,9 +34163,20 @@ var init_codex_app_server = __esm({
34056
34163
  });
34057
34164
  }
34058
34165
  async handleNotification(connection, method, rawParams) {
34166
+ if (method === "error") {
34167
+ const parsed = external_exports.object({ threadId: Opaque, turnId: Opaque, error: external_exports.unknown(), willRetry: external_exports.boolean() }).passthrough().safeParse(rawParams);
34168
+ if (!parsed.success) return;
34169
+ const binding = this.bindingForCodexThread(parsed.data.threadId);
34170
+ if (!binding || binding.state !== "active" || binding.connection_epoch !== this.connectionEpoch || binding.current_turn_id !== parsed.data.turnId) return;
34171
+ this.providerErrors.set(binding.frizz_session_id, codexProviderError(parsed.data.error, this.now().toISOString(), parsed.data.willRetry));
34172
+ this.options.onStatusChange?.();
34173
+ return;
34174
+ }
34059
34175
  if (method === "item/started") {
34060
34176
  const envelope = ItemStartedNotification.safeParse(rawParams);
34061
34177
  if (!envelope.success) return;
34178
+ const binding = this.bindingForCodexThread(envelope.data.threadId);
34179
+ if (binding?.state === "active" && binding.connection_epoch === this.connectionEpoch && binding.current_turn_id === envelope.data.turnId && this.providerErrors.delete(binding.frizz_session_id)) this.options.onStatusChange?.();
34062
34180
  this.foldExecItem(envelope.data.threadId, envelope.data.item, envelope.data.startedAtMs);
34063
34181
  const item = FileChangeItem.safeParse(envelope.data.item);
34064
34182
  if (!item.success || item.data.status !== "inProgress") return;
@@ -34155,6 +34273,7 @@ var init_codex_app_server = __esm({
34155
34273
  return;
34156
34274
  }
34157
34275
  if (!this.pendingTurnStarts.has(turnKey(binding))) return;
34276
+ this.providerErrors.delete(binding.frizz_session_id);
34158
34277
  this.scope.prepare(`
34159
34278
  UPDATE codex_app_server_session SET current_turn_id = ?, updated_at = ?
34160
34279
  WHERE project_id = @project_id AND codex_thread_id = ? AND connection_epoch = ? AND current_turn_id IS NULL
@@ -34164,6 +34283,14 @@ var init_codex_app_server = __esm({
34164
34283
  if (method === "turn/completed") {
34165
34284
  const parsed = TurnCompleted.safeParse(rawParams);
34166
34285
  if (!parsed.success) return;
34286
+ const binding = this.bindingForCodexThread(parsed.data.threadId);
34287
+ if (binding?.state === "active" && binding.connection_epoch === this.connectionEpoch && binding.current_turn_id === parsed.data.turn.id) {
34288
+ if (parsed.data.turn.error != null || parsed.data.turn.status === "failed") {
34289
+ this.providerErrors.set(binding.frizz_session_id, codexProviderError(parsed.data.turn.error, this.now().toISOString()));
34290
+ } else {
34291
+ this.providerErrors.delete(binding.frizz_session_id);
34292
+ }
34293
+ }
34167
34294
  for (const item of [...this.correlatedFileItems.values()]) {
34168
34295
  if (item.threadId !== parsed.data.threadId || item.turnId !== parsed.data.turn.id) continue;
34169
34296
  const active = await this.invalidateCorrelatedFileApproval(
@@ -34180,6 +34307,7 @@ var init_codex_app_server = __esm({
34180
34307
  WHERE project_id = @project_id AND codex_thread_id = ? AND connection_epoch = ? AND current_turn_id = ?
34181
34308
  `).run(this.now().toISOString(), parsed.data.threadId, this.connectionEpoch, parsed.data.turn.id);
34182
34309
  this.notifyTurnIdleWaiters();
34310
+ this.options.onStatusChange?.();
34183
34311
  }
34184
34312
  }
34185
34313
  providerResponse(record, delivery2, input) {
@@ -37650,6 +37778,7 @@ function deriveNeedsYou(row, tele, runtime, hasActionableInteraction = false, no
37650
37778
  if (!atRest) return false;
37651
37779
  if (runtime === "exited" && tele?.turn === "in-flight") return true;
37652
37780
  if (hasFreshDelivery(row, deliveryProcessGone)) return false;
37781
+ if (tele?.providerError && !tele.providerError.retrying) return true;
37653
37782
  if (tele?.pendingQuestion) return true;
37654
37783
  if (openQuestions > 0) return true;
37655
37784
  if (limitPause) return true;
@@ -37663,7 +37792,7 @@ function deriveNeedsYou(row, tele, runtime, hasActionableInteraction = false, no
37663
37792
  }
37664
37793
  function deriveAwaitingBackground(row, tele, runtime, hasActionableInteraction = false, nowMs = Date.now(), limitPause = void 0, deliveryProcessGone = false, github = {}, registeredPrWatches = /* @__PURE__ */ new Set(), armedTimerIds = /* @__PURE__ */ new Set(), armedWatches = [], openQuestions = 0) {
37665
37794
  if (runtime !== "turn-idle" || !hasDeclaredWait(tele, nowMs, armedTimerIds, registeredPrWatches, armedWatches)) return false;
37666
- if (limitPause) return false;
37795
+ if (limitPause || tele?.providerError) return false;
37667
37796
  if (hasActionableInteraction || tele?.pendingAsk || tele?.pendingQuestion || openQuestions > 0) return false;
37668
37797
  if (tele?.lastFence?.kind === "done") return false;
37669
37798
  if (tele?.lastFence?.kind === "awaiting" && !hasParkedPrWatch(tele, registeredPrWatches) && !hasDeclaredBackgroundPark(tele, nowMs) && // A REGISTERED park is the same exception for the same reason. (A registration with no fence at all
@@ -37798,9 +37927,29 @@ function sessionThreadView(projectDir, storage, row, rawTele, registeredLegacyTe
37798
37927
  expiresAt: new Date(w.expires_at).toISOString()
37799
37928
  }));
37800
37929
  const supersededDone = questions.length > 0 || armedWatches.length > 0 || armedPrWatches.length > 0 || armedTimers.length > 0;
37801
- const done = supersededDone ? void 0 : registeredDoneFence(registries.done.get(row.slug), rawTele?.lastUserAt);
37802
- const tele = done && rawTele ? { ...rawTele, lastFence: done } : rawTele;
37803
- const headlessStalled = row.codex_runtime === "app-server" ? appServerTurnStalled(codexTurnLiveness(row.slug, row.session_id), tele?.lastActivityAt, nowMs) : isBrokerClaudeRow(row) ? !claudeBrokerDaemonAlive(row.session_id) : false;
37930
+ const codexLive = row.codex_runtime === "app-server" ? codexTurnLiveness(row.slug, row.session_id) : void 0;
37931
+ const nativeError = codexLive?.providerError;
37932
+ const nativeFailure = nativeError && !nativeError.retrying && !codexLive?.bridgeTurn && (!rawTele?.lastActivityAt || nativeError.at !== void 0 && nativeError.at >= rawTele.lastActivityAt);
37933
+ const sameError = rawTele?.providerError?.message === nativeError?.message && rawTele?.providerError?.code === nativeError?.code;
37934
+ const providerError = nativeError?.retrying ? nativeError : nativeFailure ? sameError ? rawTele?.providerError : nativeError : rawTele?.providerError;
37935
+ const failedTele = nativeFailure ? {
37936
+ subAgents: [],
37937
+ bgShells: [],
37938
+ ...rawTele,
37939
+ turn: "idle",
37940
+ permPrompt: false,
37941
+ pendingQuestion: false,
37942
+ pendingAsk: void 0,
37943
+ apiFault: true,
37944
+ providerError,
37945
+ lastAssistant: providerError?.message,
37946
+ lastAssistantAt: providerError?.at,
37947
+ lastFence: void 0,
37948
+ lastAssistantAllDone: false
37949
+ } : rawTele;
37950
+ const done = supersededDone || providerError ? void 0 : registeredDoneFence(registries.done.get(row.slug), rawTele?.lastUserAt);
37951
+ const tele = done && failedTele ? { ...failedTele, lastFence: done } : failedTele;
37952
+ const headlessStalled = row.codex_runtime === "app-server" ? !nativeFailure && appServerTurnStalled(codexLive, tele?.lastActivityAt, nowMs) : isBrokerClaudeRow(row) ? !claudeBrokerDaemonAlive(row.session_id) : false;
37804
37953
  const headlessLostWork = isBrokerClaudeRow(row) && headlessStalled && hasUnretiredOwnAgents(tele);
37805
37954
  const deliveryProcessGone = isBrokerClaudeRow(row) && headlessStalled;
37806
37955
  const runtime = degradeIfAwaitingAnswer(
@@ -37865,6 +38014,7 @@ function sessionThreadView(projectDir, storage, row, rawTele, registeredLegacyTe
37865
38014
  // Subscription window exhausted mid-turn — the credential is fine, so this is a WAIT, not a
37866
38015
  // sign-in. Drives the pause card and (while an auto-resume is promised) the queue excusal above.
37867
38016
  limitPause,
38017
+ providerError,
37868
38018
  kind: "session",
37869
38019
  foreign: false,
37870
38020
  lastFence: tele?.lastFence,
@@ -37979,6 +38129,7 @@ function foreignThreadView(sessionId, tele, backend) {
37979
38129
  questions: [],
37980
38130
  kind: "session",
37981
38131
  foreign: true,
38132
+ providerError: tele.providerError,
37982
38133
  needsYou: false,
37983
38134
  awaitingBackground: false,
37984
38135
  crashed: false,
@@ -39450,6 +39601,7 @@ function createScheduler(deps) {
39450
39601
  return tele.turn === "idle" ? "current-idle" : "current-busy";
39451
39602
  }
39452
39603
  if (isStopHookFenceId(item.fenceId)) {
39604
+ if (tele.authFault || tele.apiFault) return "superseded";
39453
39605
  const armed = armedRest(row);
39454
39606
  if (!armed || item.fenceId !== stopHookFenceId(armed.armedAt, tele.lastAssistantAt ?? "")) return "superseded";
39455
39607
  if (restMessageIsSignedOff(deps.storage, item.slug, tele, registeredPrWatchesOf(deps.storage, item.slug), armedTimerIdsOf(deps.storage, item.slug), armed.armedAt)) return "superseded";
@@ -39465,6 +39617,7 @@ function createScheduler(deps) {
39465
39617
  return tele.turn === "idle" ? "current-idle" : "current-busy";
39466
39618
  }
39467
39619
  if (isSignoffFenceId(item.fenceId)) {
39620
+ if (tele.authFault || tele.apiFault) return "superseded";
39468
39621
  if (item.fenceId !== signoffFenceId(tele.lastAssistantAt ?? "")) return "superseded";
39469
39622
  if (tele.lastFence || tele.pendingQuestion) return "superseded";
39470
39623
  return tele.turn === "idle" ? "current-idle" : "current-busy";
@@ -41907,6 +42060,7 @@ function createContextUnchecked(opts, resources) {
41907
42060
  // fact. Before this the diagnostic sink was unset and every death — the six-sub-agent loss
41908
42061
  // included — was an unattributable "the thread went quiet." See codex-app-server-diagnostics.ts.
41909
42062
  diagnostic: createCodexDiagnosticSink(project.stateDir, project.id),
42063
+ onStatusChange: () => board?.refresh(),
41910
42064
  // Never wake a thread the human has already put away: a restart-recovery nudge is only for a
41911
42065
  // thread that is still open and still theirs to come back to.
41912
42066
  shouldAutoResume: (slug) => {
@@ -46363,6 +46517,7 @@ function projectCodexTranscript(raw2, identityPrefix = "codex") {
46363
46517
  let sawFinalAnswer = false;
46364
46518
  let turnReasoning = null;
46365
46519
  let pendingCaption;
46520
+ let lastProviderError;
46366
46521
  let prevEventAt;
46367
46522
  let lastContextTokens;
46368
46523
  let openCompaction = null;
@@ -46383,6 +46538,20 @@ function projectCodexTranscript(raw2, identityPrefix = "codex") {
46383
46538
  for (const ev of parseCodexLine(line)) {
46384
46539
  const sourceId = `${identityPrefix}:${lineOffset}:${eventOrdinal++}`;
46385
46540
  switch (ev.kind) {
46541
+ case "provider-error": {
46542
+ const fingerprint = JSON.stringify({ ...ev.error, at: void 0 });
46543
+ if (fingerprint === lastProviderError?.fingerprint) {
46544
+ lastProviderError.message.providerError = ev.error;
46545
+ lastProviderError.message.at = ev.at;
46546
+ break;
46547
+ }
46548
+ cur = null;
46549
+ turnReasoning = null;
46550
+ const message = { sourceId, role: "assistant", kind: "event", text: ev.error.message, providerError: ev.error, tools: [], parts: [], at: ev.at };
46551
+ lastProviderError = { fingerprint, message };
46552
+ out.push(message);
46553
+ break;
46554
+ }
46386
46555
  case "assistant-text": {
46387
46556
  let text2 = extractCodexFrizzTitle(ev.text, ev.final).text;
46388
46557
  if (text2) {
@@ -46578,6 +46747,7 @@ ${text2}`;
46578
46747
  break;
46579
46748
  }
46580
46749
  case "turn-start":
46750
+ lastProviderError = void 0;
46581
46751
  sawFinalAnswer = false;
46582
46752
  turnReasoning = null;
46583
46753
  break;
@@ -53396,8 +53566,8 @@ var init_runtimes = __esm({
53396
53566
  "use strict";
53397
53567
  init_codex_app_server();
53398
53568
  init_frizz_paths();
53399
- CLAUDE_AGENT_SDK_VERSION = "0.3.261";
53400
- CLAUDE_CODE_VERSION = "2.1.261";
53569
+ CLAUDE_AGENT_SDK_VERSION = "0.3.263";
53570
+ CLAUDE_CODE_VERSION = "2.1.263";
53401
53571
  CODEX_VERSION = CODEX_APP_SERVER_SUPPORTED_VERSION;
53402
53572
  RUNTIMES_MODE_ENV = "FRIZZ_RUNTIMES";
53403
53573
  RUNTIMES_DIR_ENV = "FRIZZ_RUNTIMES_DIR";