very-happy-cli 0.2.175 → 0.2.177

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 (185) hide show
  1. package/dist/{AcpBackend-Sb6N_HcB.cjs → AcpBackend-B-ny68XM.cjs} +188 -37
  2. package/dist/{AcpBackend-BZrLVcHb.mjs → AcpBackend-B0K0WrtW.mjs} +187 -38
  3. package/dist/{AcpSessionManager-C2MqOirs.cjs → AcpSessionManager-CjdJLofq.cjs} +1 -1
  4. package/dist/{AcpSessionManager-y1Iy1mzc.mjs → AcpSessionManager-DykjzBM4.mjs} +1 -1
  5. package/dist/{BasePermissionHandler-BbLYwd13.cjs → BasePermissionHandler-DR6nxuEn.cjs} +1 -1
  6. package/dist/{BasePermissionHandler-DriZLITp.mjs → BasePermissionHandler-hdY7kTqX.mjs} +1 -1
  7. package/dist/{agentHome-BoYfpemd.cjs → agentHome-BdTXEUPe.cjs} +4 -4
  8. package/dist/{agentHome-BtuRubHG.mjs → agentHome-GRN2VfHv.mjs} +4 -4
  9. package/dist/{api-KZmVqSKO.cjs → api-BWX10o97.cjs} +17 -10
  10. package/dist/{api-D08IEaWa.mjs → api-CKBViqI3.mjs} +18 -11
  11. package/dist/{apiMachine-Dct2GDAq.cjs → apiMachine-BYYFGgFs.cjs} +15 -14
  12. package/dist/{apiMachine-Cx9Zn-78.mjs → apiMachine-DttO4UFj.mjs} +15 -14
  13. package/dist/{attachmentContent-PrNJg8gG.mjs → attachmentContent-cPVF463_.mjs} +2 -2
  14. package/dist/{attachmentContent-4L9dO8E3.cjs → attachmentContent-kJKXpkMX.cjs} +2 -2
  15. package/dist/{attachmentLimits-BLbji11b.mjs → attachmentLimits-Di1Z93lN.mjs} +1 -1
  16. package/dist/{attachmentLimits-D6bT2jU1.cjs → attachmentLimits-DtFqqiwR.cjs} +1 -1
  17. package/dist/{auth-D1qHU-i_.mjs → auth-BmESeKuM.mjs} +5 -5
  18. package/dist/{auth-PY_HGlzz.mjs → auth-CKdXb9zp.mjs} +8 -8
  19. package/dist/{auth-BGmM3Vlm.cjs → auth-CTECt2Oz.cjs} +5 -5
  20. package/dist/{auth-BI0CsMcy.cjs → auth-DNxVmVbn.cjs} +8 -8
  21. package/dist/{auto-COMphIfD.mjs → auto-Ch3203qd.mjs} +17 -16
  22. package/dist/{auto-DM4_FeKb.cjs → auto-D1ypjjfx.cjs} +16 -15
  23. package/dist/{backgroundTaskActivity-8PdPxrvy.mjs → backgroundTaskActivity-BVwJBl02.mjs} +1 -1
  24. package/dist/{bootstrap-DTJ6-vYT.cjs → bootstrap-6OI698q9.cjs} +2 -2
  25. package/dist/{bootstrap-CWjpC5-J.mjs → bootstrap-C0s2bPFQ.mjs} +2 -2
  26. package/dist/{browser-xuW4fiHo.mjs → browser-BlLWZUMx.mjs} +1 -1
  27. package/dist/{browser-DmgVoopB.cjs → browser-DG6Uof5O.cjs} +1 -1
  28. package/dist/{claudeLocal-B0P-wVJJ.mjs → claudeLocal-CcWcKnoo.mjs} +5 -5
  29. package/dist/{claudeLocal-CtZVz3ee.cjs → claudeLocal-CemsIArT.cjs} +5 -5
  30. package/dist/{claudeLocalLauncher-D4vmjI3c.mjs → claudeLocalLauncher-7p6y88nj.mjs} +15 -18
  31. package/dist/{claudeLocalLauncher-Dnv4CH8r.cjs → claudeLocalLauncher-A4VuevIi.cjs} +15 -18
  32. package/dist/{claudeSessionFork-CxjOBoBh.mjs → claudeSessionFork-BtROOjqf.mjs} +1 -1
  33. package/dist/{claudeSessionFork-DQk5-dzR.cjs → claudeSessionFork-CbDfm8Fz.cjs} +1 -1
  34. package/dist/{client-eQjOvC55.mjs → client-BPMWutfs.mjs} +3 -3
  35. package/dist/{client-BhLhjj_x.cjs → client-COmgDDy0.cjs} +2 -2
  36. package/dist/{client-C4ddTzrD.mjs → client-DG5ndWLw.mjs} +2 -2
  37. package/dist/{client-BHZVyQwi.cjs → client-DyvBTYee.cjs} +3 -3
  38. package/dist/codex/happyMcpStdioBridge.cjs +15 -15
  39. package/dist/codex/happyMcpStdioBridge.mjs +16 -16
  40. package/dist/{codexAppServerClient-CppPl_R6.mjs → codexAppServerClient-D-Z8qSfI.mjs} +233 -24
  41. package/dist/{codexAppServerClient-D-9z-lWP.cjs → codexAppServerClient-R24WZZfg.cjs} +233 -24
  42. package/dist/{codexCommand-AgVJYnFU.cjs → codexCommand-6hW19gsq.cjs} +159 -84
  43. package/dist/{codexCommand-BdrBNbZu.mjs → codexCommand-CVTkZJ1o.mjs} +158 -83
  44. package/dist/{BaseReasoningProcessor-_S1PbSvH.cjs → codexTermination-BBU7e92y.cjs} +25 -1
  45. package/dist/{BaseReasoningProcessor-DnykPlPo.mjs → codexTermination-CCIfwzcx.mjs} +25 -2
  46. package/dist/{config-Cr3VUzbE.mjs → config-CvsNChKX.mjs} +3 -3
  47. package/dist/{config-D89sE3wK.cjs → config-DhdrvOLV.cjs} +3 -3
  48. package/dist/{configuration-BNGPXg07.mjs → configuration-D55F0t16.mjs} +1 -1
  49. package/dist/{configuration-UV4EE5ui.cjs → configuration-DZPy0T9Z.cjs} +1 -1
  50. package/dist/{connect-C0iLkCiY.mjs → connect-CwCXMRmD.mjs} +14 -14
  51. package/dist/{connect-B35YXbdZ.cjs → connect-Wz-XZYXW.cjs} +13 -13
  52. package/dist/{context-BmH2BKip.cjs → context-BKbrZ55r.cjs} +1 -1
  53. package/dist/{context-Ptdnlcv6.mjs → context-CCRpVXFo.mjs} +1 -1
  54. package/dist/{controlClient-DqtC0pq1.mjs → controlClient-C4xB5J6O.mjs} +4 -4
  55. package/dist/{controlClient-CtsQMw--.cjs → controlClient-SX8gSza2.cjs} +3 -3
  56. package/dist/{createSessionMetadata-2IuH5nlA.cjs → createSessionMetadata-BCFmYlBo.cjs} +2 -2
  57. package/dist/{createSessionMetadata-CtNMvfth.mjs → createSessionMetadata-Bi-m0Y_O.mjs} +2 -2
  58. package/dist/{defaultPermissionMode-Bn4HcU8S.cjs → defaultPermissionMode-DMBEnXll.cjs} +2 -2
  59. package/dist/{defaultPermissionMode-DYihjV2g.mjs → defaultPermissionMode-wBcbBezm.mjs} +2 -2
  60. package/dist/{deterministicJson-DF4xv6MH.mjs → deterministicJson-BkQETt8_.mjs} +9 -9
  61. package/dist/{deterministicJson-je21npNx.cjs → deterministicJson-ChGfQEF6.cjs} +9 -9
  62. package/dist/{doctor-Ba92L7-b.mjs → doctor-B9c2C9dF.mjs} +8 -8
  63. package/dist/{doctor-BXKcYVGU.cjs → doctor-BsN3JZJn.cjs} +7 -7
  64. package/dist/{downloadTarget-CUJg8iJV.mjs → downloadTarget-ByXzbDK4.mjs} +6 -6
  65. package/dist/{downloadTarget-JC7FZl7W.cjs → downloadTarget-Dj3WoVJa.cjs} +6 -6
  66. package/dist/{ensureDaemonRunning-JPA9tHNE.mjs → ensureDaemonRunning--HYzs5Ce.mjs} +5 -5
  67. package/dist/{ensureDaemonRunning-bIp6-vgi.cjs → ensureDaemonRunning-7Wb8M7Lv.cjs} +5 -5
  68. package/dist/{handleResumeCommand-B6lE5DtU.mjs → handleResumeCommand-DHddBkNJ.mjs} +5 -5
  69. package/dist/{handleResumeCommand-B6b9kIYf.cjs → handleResumeCommand-OmuUGYjQ.cjs} +5 -5
  70. package/dist/{index-B2KL0aPc.cjs → index-BRJzH4sc.cjs} +141 -87
  71. package/dist/{index-CjE4kBKx.mjs → index-BzJNDsJq.mjs} +143 -89
  72. package/dist/{index-B6UGRQ7h.mjs → index-CEjJnq05.mjs} +3 -0
  73. package/dist/{index-CZLwo1FS.mjs → index-CEm0MYiS.mjs} +3 -3
  74. package/dist/{index-B1ABQRrB.cjs → index-CrR4JISa.cjs} +4 -4
  75. package/dist/{index-D759ViMU.cjs → index-D9NoYc5I.cjs} +3 -3
  76. package/dist/{index-D3kI0hDR.cjs → index-DFPT4HOO.cjs} +3 -0
  77. package/dist/{index-boE-d8CM.mjs → index-DMy3OCBe.mjs} +8 -1
  78. package/dist/{index-BZdhwBKa.cjs → index-De8L5lFK.cjs} +8 -0
  79. package/dist/{index-DW1ONaGc.mjs → index-Dhl6_bw7.mjs} +4 -4
  80. package/dist/index.cjs +2 -2
  81. package/dist/index.mjs +2 -2
  82. package/dist/{install-KjIsK_EA.cjs → install-1qn-D9FS.cjs} +3 -3
  83. package/dist/{install-CmojqnLK.mjs → install-BDIUtPXi.mjs} +3 -3
  84. package/dist/lib.cjs +12 -12
  85. package/dist/lib.d.cts +7 -1
  86. package/dist/lib.d.mts +7 -1
  87. package/dist/lib.mjs +13 -13
  88. package/dist/{lidState-CL1NdKfQ.mjs → lidState-BqVsw7H1.mjs} +1 -1
  89. package/dist/{lidState-BmJp2pLt.cjs → lidState-DxbK0qfu.cjs} +1 -1
  90. package/dist/{localHappyAgentAuth-B7f4Ysn0.mjs → localHappyAgentAuth-Ce8kO2yc.mjs} +1 -1
  91. package/dist/{localHappyAgentAuth-9SP7hdiw.cjs → localHappyAgentAuth-D5tANdRD.cjs} +1 -1
  92. package/dist/{logger-D5EzMy30.mjs → logger-13cBr_ew.mjs} +2 -2
  93. package/dist/{logger-C7dRaCkE.cjs → logger-LvwVeATU.cjs} +2 -2
  94. package/dist/{machineMetadata-DYYuK_0c.cjs → machineMetadata-29h7vgf4.cjs} +3 -3
  95. package/dist/{machineMetadata-DqplCWue.mjs → machineMetadata-dMida2qq.mjs} +3 -3
  96. package/dist/{main-kgCQgknK.cjs → main-DpM5jaFH.cjs} +44 -44
  97. package/dist/{main-CnV62agu.mjs → main-x4nAhdH5.mjs} +44 -44
  98. package/dist/{mcp-bDPaj-tM.mjs → mcp-DMiFGYMT.mjs} +15 -15
  99. package/dist/{mcp-BV0vxHtz.cjs → mcp-DQv3caXs.cjs} +14 -14
  100. package/dist/{mirrorProtocol-BSHVZ8Nf.cjs → mirrorProtocol-BfrERW7Z.cjs} +3 -3
  101. package/dist/{mirrorProtocol-ClKhNXYe.mjs → mirrorProtocol-Bz8tEabR.mjs} +3 -3
  102. package/dist/{package-VqWv7EI5.cjs → package-Ch9WGDV_.cjs} +7 -7
  103. package/dist/{package-D0dxZ-W8.mjs → package-CjlsAaRe.mjs} +7 -7
  104. package/dist/{peerTools-B_eiNB3P.mjs → peerTools-CxmrKnfV.mjs} +4 -4
  105. package/dist/{peerTools-BktGmlpd.cjs → peerTools-DtGKWli5.cjs} +4 -4
  106. package/dist/{persistence-CIIhP0Uw.mjs → persistence-C_tYtOqK.mjs} +2 -2
  107. package/dist/{persistence-DweHi8xa.cjs → persistence-DXbKOHxl.cjs} +2 -2
  108. package/dist/{piRunnerArgs-BNzWTNRV.cjs → piRunnerArgs-BVRZe2AR.cjs} +1 -1
  109. package/dist/{piRunnerArgs-cQafsadv.mjs → piRunnerArgs-BpHc-JZl.mjs} +1 -1
  110. package/dist/{piRuntime-VZLSwW-4.cjs → piRuntime-D7eio8Ix.cjs} +1 -1
  111. package/dist/{piRuntime-Bel5lOLb.mjs → piRuntime-DOdGF395.mjs} +1 -1
  112. package/dist/{piTerminal-CS5SDi_H.mjs → piTerminal-dpxz4Q8D.mjs} +17 -17
  113. package/dist/{piTerminal-DkR8sPv-.cjs → piTerminal-y_PRo2NY.cjs} +16 -16
  114. package/dist/processTree-CMHWlVse.cjs +66 -0
  115. package/dist/processTree-CP5IvQ2Z.mjs +61 -0
  116. package/dist/{rateLimitWindows-Bp4T21RI.cjs → rateLimitWindows-DFnMU2Vt.cjs} +1 -1
  117. package/dist/{rateLimitWindows-Bo6XVnie.mjs → rateLimitWindows-DYHDGuzQ.mjs} +1 -1
  118. package/dist/{registerCommonHandlers-B7QZxkCL.cjs → registerCommonHandlers-60VuTkdg.cjs} +2 -2
  119. package/dist/{registerCommonHandlers-CR5jpiSx.mjs → registerCommonHandlers-D8OMpBbQ.mjs} +2 -2
  120. package/dist/{registerKillSessionHandler-DLiu24CQ.mjs → registerKillSessionHandler-Drhf7-Vz.mjs} +6 -6
  121. package/dist/{registerKillSessionHandler-CcX84g-T.cjs → registerKillSessionHandler-pqChBKwO.cjs} +6 -6
  122. package/dist/{remoteSessionClient-CL3akj0K.cjs → remoteSessionClient-B7NvjHD3.cjs} +5 -5
  123. package/dist/{remoteSessionClient-CUjw1COc.mjs → remoteSessionClient-D01Hso2-.mjs} +5 -5
  124. package/dist/{reportProgressTool-BLLwMQrN.mjs → reportProgressTool-B203EZCR.mjs} +2 -2
  125. package/dist/{reportProgressTool-DzMi4mvH.cjs → reportProgressTool-Du_zAK4h.cjs} +2 -2
  126. package/dist/{run-DGokR_6q.mjs → run-DX4Zs3Ug.mjs} +34 -34
  127. package/dist/{run-5pmOElaW.cjs → run-DZ5jU53c.cjs} +34 -34
  128. package/dist/{runClaude-BFlpZQds.mjs → runClaude-CgPHXP0L.mjs} +27 -23
  129. package/dist/{runClaude-EnYNvkV0.cjs → runClaude-ClRhHpwR.cjs} +26 -22
  130. package/dist/{runClaudeDeps-CUDebE9e.cjs → runClaudeDeps-D2v_WDSL.cjs} +387 -89
  131. package/dist/{runClaudeDeps-D1M1dzlZ.mjs → runClaudeDeps-Dz2iydq4.mjs} +393 -95
  132. package/dist/{runGemini-Bu69Zu1u.cjs → runGemini-BtZqGFkp.cjs} +208 -193
  133. package/dist/{runGemini-Bub8T5cM.mjs → runGemini-DBXxpoY8.mjs} +208 -193
  134. package/dist/{runOpenClaw-DVu73F_i.mjs → runOpenClaw-BOHpzCEU.mjs} +19 -19
  135. package/dist/{runOpenClaw-Cob5F3FC.cjs → runOpenClaw-D8q8G57u.cjs} +18 -18
  136. package/dist/{sandbox-9EKOFyQF.mjs → sandbox-C452Vrsc.mjs} +4 -4
  137. package/dist/{sandbox-GDqMagSF.cjs → sandbox-Cu9mMzjx.cjs} +4 -4
  138. package/dist/selfCheck-BAvqBwBR.mjs +84 -0
  139. package/dist/{selfCheck-DiNo34da.cjs → selfCheck-gKa3uVr1.cjs} +35 -35
  140. package/dist/{send-ThC80164.cjs → send-2Vb5eppI.cjs} +8 -8
  141. package/dist/{send-wgtHphq8.mjs → send-B8HARi7x.mjs} +9 -9
  142. package/dist/{server-Bb8v2fOj.mjs → server-BBWCIZyS.mjs} +4 -4
  143. package/dist/{server-bidHnstE.cjs → server-Db9Wuam3.cjs} +6 -6
  144. package/dist/{sessionLock-BWBcBZKh.cjs → sessionLock-6qL_N6Rn.cjs} +3 -3
  145. package/dist/{sessionLock-gb32sVPR.mjs → sessionLock-ZfvFVdUi.mjs} +3 -3
  146. package/dist/{sessionModeFile-C-fr1M1h.mjs → sessionModeFile-CWVq8AT9.mjs} +1 -1
  147. package/dist/{sessionModeFile-DhuTNcJr.cjs → sessionModeFile-CsLtn_PL.cjs} +1 -1
  148. package/dist/{sessionOps-ByZJbkMq.mjs → sessionOps-CdgbEJgf.mjs} +5 -5
  149. package/dist/{sessionOps-9MChM9Op.cjs → sessionOps-Dmt7WUUs.cjs} +4 -4
  150. package/dist/{sessionScanner-CxXPAVyS.mjs → sessionScanner-CNVaSNOn.mjs} +34 -4
  151. package/dist/{sessionScanner-BpegdnXK.cjs → sessionScanner-CQL_WSaC.cjs} +34 -3
  152. package/dist/{sessions-C1X4z_Lm.cjs → sessions-BJblG_Hx.cjs} +9 -9
  153. package/dist/{sessions-l-UgJGjV.mjs → sessions-DTomHfFg.mjs} +10 -10
  154. package/dist/{setupOfflineReconnection-CgtXlV74.mjs → setupOfflineReconnection-C5trsV-j.mjs} +2 -2
  155. package/dist/{setupOfflineReconnection-CS_8Da8R.cjs → setupOfflineReconnection-DVA0VpQL.cjs} +2 -2
  156. package/dist/{spawn-FyoHqYWo.mjs → spawn-CQJFgoOq.mjs} +15 -14
  157. package/dist/{spawn-D2BlNdZu.cjs → spawn-DRyNAqD8.cjs} +14 -13
  158. package/dist/{spawnAgents-BhsbJ253.mjs → spawnAgents-BjtmjBvP.mjs} +1 -1
  159. package/dist/{spawnAgents-CgMKuOhZ.cjs → spawnAgents-CCjJifAW.cjs} +1 -1
  160. package/dist/{spawnHappyCLI-DsC256j_.mjs → spawnHappyCLI-B_0RWxD4.mjs} +1 -1
  161. package/dist/{spawnHappyCLI-DByQcqEN.cjs → spawnHappyCLI-ChniczJ5.cjs} +1 -1
  162. package/dist/{specialCommands-DGUeZqdm.cjs → specialCommands-DbntVs0d.cjs} +3 -3
  163. package/dist/{specialCommands-DUUBqzvd.mjs → specialCommands-DkdFJi4N.mjs} +3 -3
  164. package/dist/{startFileWatcher-BtBaahTn.cjs → startFileWatcher-C292fhra.cjs} +1 -1
  165. package/dist/{startFileWatcher-CaYRObJu.mjs → startFileWatcher-UQyTSRAP.mjs} +1 -1
  166. package/dist/{streamRelay-DqPFsCgx.cjs → streamRelay-Cx01enfe.cjs} +1 -1
  167. package/dist/{streamRelay-C8zI7OnR.mjs → streamRelay-_qCd873P.mjs} +1 -1
  168. package/dist/{sync-D5YqUVjS.mjs → sync-C3p7-KLn.mjs} +1 -1
  169. package/dist/{sync-BK-IBkuB.cjs → sync-C7sxoUYG.cjs} +1 -1
  170. package/dist/{systemPrompt-e-qeag_h.mjs → systemPrompt-CdHOlyVW.mjs} +2 -2
  171. package/dist/{systemPrompt-DaTKLEb-.cjs → systemPrompt-DtibzbRU.cjs} +2 -2
  172. package/dist/{teams-D9xwa_d3.cjs → teams-D7O7TpVU.cjs} +6 -6
  173. package/dist/{teams-ClrppvKu.mjs → teams-ujXr3AFn.mjs} +6 -6
  174. package/dist/{time-0szhiPo4.cjs → time-Dg5tVB8S.cjs} +1 -1
  175. package/dist/{time-CvrpeD3S.mjs → time-yEL6wHUF.mjs} +1 -1
  176. package/dist/{titleGenerator-Dz5P7sE1.cjs → titleGenerator-BMEaDTwU.cjs} +2 -2
  177. package/dist/{titleGenerator-BZ5770wq.mjs → titleGenerator-Dr-BtjzO.mjs} +1 -1
  178. package/dist/{todo-CkmNJQey.cjs → todo-CUcFamGs.cjs} +6 -6
  179. package/dist/{todo-o-miKcN2.mjs → todo-CvJe4M2C.mjs} +6 -6
  180. package/dist/{tools-Cp0qJeBq.mjs → tools-BrM3bZW5.mjs} +1 -1
  181. package/dist/{tools-C77-Ssan.cjs → tools-DDKTB5aQ.cjs} +1 -1
  182. package/dist/{uninstall-DGUPERDX.cjs → uninstall-7oLuhYIu.cjs} +3 -3
  183. package/dist/{uninstall-jNJDCLD_.mjs → uninstall-CEcMMQGz.mjs} +3 -3
  184. package/package.json +7 -7
  185. package/dist/selfCheck-CNo4uzGB.mjs +0 -84
@@ -1,86 +1,86 @@
1
- import { l as logger } from './logger-D5EzMy30.mjs';
2
- import { o as notifyDaemonSessionEvent, q as notifyDaemonClaudeAuthFailed } from './controlClient-DqtC0pq1.mjs';
3
- export { j as reportSessionEditToDaemon } from './controlClient-DqtC0pq1.mjs';
4
- import { s as sameBackgroundTasks, c as createBackgroundTaskTracker } from './backgroundTaskActivity-8PdPxrvy.mjs';
1
+ import { l as logger } from './logger-13cBr_ew.mjs';
2
+ import { q as notifyDaemonSessionEvent, t as notifyDaemonClaudeAuthFailed } from './controlClient-C4xB5J6O.mjs';
3
+ export { j as reportSessionEditToDaemon } from './controlClient-C4xB5J6O.mjs';
4
+ import { s as sameBackgroundTasks, e as createBackgroundTaskTracker } from './backgroundTaskActivity-BVwJBl02.mjs';
5
5
  import { randomInt, randomUUID, createHash } from 'node:crypto';
6
6
  import { M as MessageBuffer } from './messageBuffer-BWlGgR3A.mjs';
7
- import { query } from './index-B6UGRQ7h.mjs';
7
+ import { query } from './index-CEjJnq05.mjs';
8
8
  import { AbortError } from '@anthropic-ai/claude-agent-sdk';
9
9
  import { m as mapToClaudeMode, p as parseClaudePermissionMode, c as resolveRemoteClaudePermissionMode } from './permissionMode-CH4FoZfU.mjs';
10
- import { c as claudeCheckSession, s as systemPrompt } from './systemPrompt-e-qeag_h.mjs';
10
+ import { c as claudeCheckSession, s as systemPrompt } from './systemPrompt-CdHOlyVW.mjs';
11
11
  import { join, resolve, dirname } from 'node:path';
12
- import { p as parseSpecialCommand, w as wrapperRateLimitReporter } from './specialCommands-DUUBqzvd.mjs';
12
+ import { p as parseSpecialCommand, w as wrapperRateLimitReporter } from './specialCommands-DkdFJi4N.mjs';
13
13
  import 'axios';
14
14
  import 'node:events';
15
15
  import 'socket.io-client';
16
- import { A as AsyncLock } from './attachmentLimits-BLbji11b.mjs';
16
+ import { A as AsyncLock } from './attachmentLimits-Di1Z93lN.mjs';
17
17
  import 'tweetnacl';
18
- import { c as configuration, e as ensurePrivateDirectory } from './configuration-BNGPXg07.mjs';
19
- import './index-boE-d8CM.mjs';
20
- import './registerCommonHandlers-CR5jpiSx.mjs';
18
+ import { c as configuration, e as ensurePrivateDirectory } from './configuration-D55F0t16.mjs';
19
+ import './index-DMy3OCBe.mjs';
20
+ import './registerCommonHandlers-D8OMpBbQ.mjs';
21
21
  import 'os';
22
22
  import 'child_process';
23
23
  import '@paralleldrive/cuid2';
24
- import './persistence-CIIhP0Uw.mjs';
24
+ import './persistence-C_tYtOqK.mjs';
25
25
  import { c as contentLogMetadata } from './contentLogMetadata-BlWI0egu.mjs';
26
26
  import 'chalk';
27
27
  export { R as RawJSONLinesSchema } from './types-CkqAACXx.mjs';
28
28
  import { g as getProjectPath } from './path-D2wdaNSk.mjs';
29
29
  import { access } from 'fs/promises';
30
- import { d as delay } from './time-CvrpeD3S.mjs';
30
+ import { d as delay } from './time-yEL6wHUF.mjs';
31
31
  import { mkdirSync, writeFileSync, readFileSync, unlinkSync, renameSync, statSync, existsSync } from 'node:fs';
32
- import { h as hashObject } from './deterministicJson-DF4xv6MH.mjs';
33
- export { s as startHappyServer } from './deterministicJson-DF4xv6MH.mjs';
34
- import { F as Future } from './sessionScanner-CxXPAVyS.mjs';
35
- export { c as createSessionScanner } from './sessionScanner-CxXPAVyS.mjs';
32
+ import { h as hashObject } from './deterministicJson-BkQETt8_.mjs';
33
+ export { s as startHappyServer } from './deterministicJson-BkQETt8_.mjs';
34
+ import { F as Future, d as describeClaudeProcessExit } from './sessionScanner-CNVaSNOn.mjs';
35
+ export { c as createSessionScanner } from './sessionScanner-CNVaSNOn.mjs';
36
36
  import { execSync } from 'node:child_process';
37
- import { S as StreamRelay } from './streamRelay-C8zI7OnR.mjs';
38
- import { C as CLAUDE_ATTACHMENT_KINDS, c as chatAttachmentDirectory, a as stageClaudeAttachments, b as appendStagedAttachmentsToPrompt } from './attachmentContent-PrNJg8gG.mjs';
37
+ import { S as StreamRelay } from './streamRelay-_qCd873P.mjs';
38
+ import { C as CLAUDE_ATTACHMENT_KINDS, c as chatAttachmentDirectory, a as stageClaudeAttachments, b as appendStagedAttachmentsToPrompt } from './attachmentContent-cPVF463_.mjs';
39
39
  import { writeFile, rename, unlink, readFile } from 'node:fs/promises';
40
- import { F as ForkSourceMissingError } from './claudeSessionFork-CxjOBoBh.mjs';
41
- export { M as MessageQueue2, r as registerKillSessionHandler } from './registerKillSessionHandler-DLiu24CQ.mjs';
42
- export { g as getEnvironmentInfo } from './doctor-Ba92L7-b.mjs';
40
+ import { F as ForkSourceMissingError } from './claudeSessionFork-BtROOjqf.mjs';
41
+ export { M as MessageQueue2, r as registerKillSessionHandler } from './registerKillSessionHandler-Drhf7-Vz.mjs';
42
+ export { a as getEnvironmentInfo } from './doctor-B9c2C9dF.mjs';
43
43
  import { createServer } from 'node:http';
44
44
  export { E as EditReportThrottle, b as extractClaudeEditPaths } from './editPaths-BVfS_FFL.mjs';
45
45
  import { p as projectPath } from './projectPath-BTBIMB57.mjs';
46
- import { r as resolveClaudeBinary, a as runClaudeOneShot } from './titleGenerator-BZ5770wq.mjs';
47
- export { T as TitleGenerator } from './titleGenerator-BZ5770wq.mjs';
46
+ import { r as resolveClaudeBinary, a as runClaudeOneShot } from './titleGenerator-Dr-BtjzO.mjs';
47
+ export { T as TitleGenerator } from './titleGenerator-Dr-BtjzO.mjs';
48
48
  import { B as BOARD_ANALYZER_PROMPT_PREFIX } from './oneShotPrompts-DT4p6RNd.mjs';
49
- import { i as isSelfReportFresh } from './reportProgressTool-BLLwMQrN.mjs';
50
- export { c as createSelfReportState } from './reportProgressTool-BLLwMQrN.mjs';
49
+ import { i as isSelfReportFresh } from './reportProgressTool-B203EZCR.mjs';
50
+ export { c as createSelfReportState } from './reportProgressTool-B203EZCR.mjs';
51
51
  import 'node:util';
52
52
  import './smallFastModel-BLNgMrwR.mjs';
53
53
  import './trimIdent-BAjmv_TG.mjs';
54
54
  import 'node:os';
55
55
  import './agentGuidance-BDYt2Qy2.mjs';
56
- import './rateLimitWindows-Bo6XVnie.mjs';
56
+ import './rateLimitWindows-DYHDGuzQ.mjs';
57
57
  import 'zod';
58
- import './package-D0dxZ-W8.mjs';
58
+ import './package-CjlsAaRe.mjs';
59
59
  import 'util';
60
60
  import 'crypto';
61
61
  import 'path';
62
62
  import 'cross-spawn';
63
63
  import './authRelay-DSAvg1uv.mjs';
64
- import './client-eQjOvC55.mjs';
65
- import './context-Ptdnlcv6.mjs';
66
- import './sessionOps-ByZJbkMq.mjs';
64
+ import './client-BPMWutfs.mjs';
65
+ import './context-CCRpVXFo.mjs';
66
+ import './sessionOps-CdgbEJgf.mjs';
67
67
  import './resources-BdFBQi8r.mjs';
68
- import './tools-Cp0qJeBq.mjs';
69
- import './peerTools-B_eiNB3P.mjs';
68
+ import './tools-BrM3bZW5.mjs';
69
+ import './peerTools-CxmrKnfV.mjs';
70
70
  import './ids-DU6sLx4C.mjs';
71
- import './remoteSessionClient-CUjw1COc.mjs';
71
+ import './remoteSessionClient-D01Hso2-.mjs';
72
72
  import '@modelcontextprotocol/sdk/server/mcp.js';
73
73
  import '@modelcontextprotocol/sdk/server/streamableHttp.js';
74
74
  import './limits-DIo7rEBR.mjs';
75
- import './downloadTarget-CUJg8iJV.mjs';
75
+ import './downloadTarget-ByXzbDK4.mjs';
76
76
  import './terminals-Dlg0x3nY.mjs';
77
77
  import './terminalTitleSuggest-CeKsX_V6.mjs';
78
78
  import './tmuxSocket-B8Yx20sT.mjs';
79
- import './bootstrap-CWjpC5-J.mjs';
79
+ import './bootstrap-C0s2bPFQ.mjs';
80
80
  import './previewPath-CXN4Vag0.mjs';
81
- import './sync-D5YqUVjS.mjs';
81
+ import './sync-C3p7-KLn.mjs';
82
82
  import './transcriptCursor-B7T_gkQ0.mjs';
83
- import './startFileWatcher-CaYRObJu.mjs';
83
+ import './startFileWatcher-UQyTSRAP.mjs';
84
84
  import 'node:readline';
85
85
  import './doctor-BPkYWSuq.mjs';
86
86
  import 'ps-list';
@@ -88,11 +88,11 @@ import './doctorReadiness-C208SMN9.mjs';
88
88
  import './detectCLI-CSGMlV51.mjs';
89
89
  import 'fs';
90
90
  import './cliUpdate-Y34VGe9Y.mjs';
91
- import './piRunnerArgs-cQafsadv.mjs';
92
- import './sessionModeFile-C-fr1M1h.mjs';
91
+ import './piRunnerArgs-BpHc-JZl.mjs';
92
+ import './sessionModeFile-CWVq8AT9.mjs';
93
93
  import 'url';
94
94
  import 'node:module';
95
- import './client-C4ddTzrD.mjs';
95
+ import './client-DG5ndWLw.mjs';
96
96
  import './precheckCompat-DeEbilbr.mjs';
97
97
 
98
98
  const SCHEDULE_WAKEUP_GRACE_MS = 6e4;
@@ -1026,17 +1026,159 @@ function createClaudePrewarmLease(input) {
1026
1026
  return lease;
1027
1027
  }
1028
1028
 
1029
- function withTimeout(promise, ms) {
1029
+ class TimeoutError extends Error {
1030
+ constructor(message) {
1031
+ super(message);
1032
+ this.name = "TimeoutError";
1033
+ }
1034
+ }
1035
+ function withTimeout(promise, ms, label) {
1030
1036
  promise.catch(() => {
1031
1037
  });
1032
1038
  let timer;
1033
1039
  const timeout = new Promise((_, reject) => {
1034
- timer = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);
1040
+ timer = setTimeout(() => reject(new TimeoutError(`${label ? `${label} ` : ""}timed out after ${ms}ms`)), ms);
1035
1041
  });
1036
1042
  return Promise.race([promise, timeout]).finally(() => {
1037
1043
  if (timer) clearTimeout(timer);
1038
1044
  });
1039
1045
  }
1046
+
1047
+ function readClaudeSessionState(message) {
1048
+ const m = message;
1049
+ if (!m || m.type !== "system" || m.subtype !== "session_state_changed") return null;
1050
+ return m.state === "idle" || m.state === "running" || m.state === "requires_action" ? m.state : null;
1051
+ }
1052
+ function createClaudeTurnTracker() {
1053
+ let pending = false;
1054
+ let open = false;
1055
+ let idleOwed = 0;
1056
+ return {
1057
+ get isOpen() {
1058
+ return open;
1059
+ },
1060
+ get isPending() {
1061
+ return pending;
1062
+ },
1063
+ /** A prompt was pushed into the Query. Not a turn yet: the CLI has to pick it up. */
1064
+ pushed() {
1065
+ pending = true;
1066
+ },
1067
+ /** The CLI reported `init` for a turn: it is running. Idempotent. */
1068
+ announced() {
1069
+ open = true;
1070
+ pending = false;
1071
+ },
1072
+ /** A `result` frame: true when it ends the turn (the caller runs its turn-end), false when the turn already ended. */
1073
+ onResult() {
1074
+ if (!open && !pending) return false;
1075
+ open = false;
1076
+ pending = false;
1077
+ idleOwed += 1;
1078
+ return true;
1079
+ },
1080
+ onSessionState(state) {
1081
+ if (state === "running") {
1082
+ idleOwed = 0;
1083
+ open = true;
1084
+ pending = false;
1085
+ return "ignore";
1086
+ }
1087
+ if (state !== "idle") return "ignore";
1088
+ if (idleOwed > 0) {
1089
+ idleOwed -= 1;
1090
+ return "duplicate";
1091
+ }
1092
+ if (!open) return "ignore";
1093
+ open = false;
1094
+ return "end";
1095
+ }
1096
+ };
1097
+ }
1098
+
1099
+ const CLAUDE_COMMAND_LIFECYCLE_STATES = ["queued", "started", "completed", "cancelled", "discarded", "refused"];
1100
+ function readClaudeCommandLifecycle(frame) {
1101
+ const m = frame;
1102
+ if (!m) return null;
1103
+ const isLifecycle = m.type === "command_lifecycle" || m.type === "system" && m.subtype === "command_lifecycle";
1104
+ if (!isLifecycle || typeof m.command_uuid !== "string" || m.command_uuid.length === 0) return null;
1105
+ const state = CLAUDE_COMMAND_LIFECYCLE_STATES.find((candidate) => candidate === m.state);
1106
+ return state ? { uuid: m.command_uuid, state } : null;
1107
+ }
1108
+ const uuidList = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.length > 0) : [];
1109
+ const INTERRUPT_CANCEL_QUEUED_CAPABILITY = "interrupt_cancel_queued_v1";
1110
+ const PENDING_MAX = 256;
1111
+ const REPORTED_MAX = 512;
1112
+ function createClaudeCommandTracker() {
1113
+ const pending = /* @__PURE__ */ new Map();
1114
+ const reported = /* @__PURE__ */ new Set();
1115
+ const drop = (uuid) => {
1116
+ pending.delete(uuid);
1117
+ if (reported.has(uuid)) return null;
1118
+ reported.add(uuid);
1119
+ if (reported.size > REPORTED_MAX) reported.delete(reported.values().next().value);
1120
+ return uuid;
1121
+ };
1122
+ return {
1123
+ /** A uuid-stamped user message (prompt or steer) was handed to the Query. */
1124
+ track(uuid) {
1125
+ if (!pending.has(uuid) && pending.size >= PENDING_MAX) pending.delete(pending.keys().next().value);
1126
+ pending.set(uuid, { started: false });
1127
+ },
1128
+ isTracked(uuid) {
1129
+ return pending.has(uuid);
1130
+ },
1131
+ /** A lifecycle frame; returns the uuids now known to have never run. */
1132
+ observe(lifecycle) {
1133
+ const entry = pending.get(lifecycle.uuid);
1134
+ if (!entry) return [];
1135
+ switch (lifecycle.state) {
1136
+ case "queued":
1137
+ return [];
1138
+ case "started":
1139
+ entry.started = true;
1140
+ return [];
1141
+ case "completed":
1142
+ pending.delete(lifecycle.uuid);
1143
+ return [];
1144
+ default: {
1145
+ if (entry.started) {
1146
+ pending.delete(lifecycle.uuid);
1147
+ return [];
1148
+ }
1149
+ const dropped = drop(lifecycle.uuid);
1150
+ return dropped ? [dropped] : [];
1151
+ }
1152
+ }
1153
+ },
1154
+ /**
1155
+ * An interrupt's receipt: `cancelled` members we track never ran;
1156
+ * `still_queued` members we track are returned for the per-uuid
1157
+ * follow-up (`cancel_async_message`) a CLI without cancel_queued needs.
1158
+ */
1159
+ onInterruptReceipt(receipt) {
1160
+ const dropped = [];
1161
+ for (const uuid of uuidList(receipt?.cancelled)) {
1162
+ if (!pending.has(uuid)) continue;
1163
+ const result = drop(uuid);
1164
+ if (result) dropped.push(result);
1165
+ }
1166
+ const stillQueued = uuidList(receipt?.still_queued).filter((uuid) => pending.has(uuid));
1167
+ return { dropped, stillQueued };
1168
+ },
1169
+ /** The answer to `cancel_async_message`: true = withdrawn before it ran; false = already dequeued, its lifecycle frames follow. */
1170
+ onCancelResponse(uuid, cancelled) {
1171
+ if (!cancelled || !pending.has(uuid)) return [];
1172
+ const dropped = drop(uuid);
1173
+ return dropped ? [dropped] : [];
1174
+ },
1175
+ clear() {
1176
+ pending.clear();
1177
+ }
1178
+ };
1179
+ }
1180
+
1181
+ const SET_MODEL_TIMEOUT_MS = 3e4;
1040
1182
  const PROMPT_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1041
1183
  function promptUuid(uuid) {
1042
1184
  return uuid && PROMPT_UUID_RE.test(uuid) ? { uuid } : {};
@@ -1081,6 +1223,14 @@ async function claudeRemote(opts) {
1081
1223
  }
1082
1224
  }
1083
1225
  };
1226
+ const turn = createClaudeTurnTracker();
1227
+ const commandTracker = createClaudeCommandTracker();
1228
+ let cliCapabilities = /* @__PURE__ */ new Set();
1229
+ const reportDroppedCommands = (uuids) => {
1230
+ if (uuids.length === 0) return;
1231
+ logger.debug(`[claudeRemote] ${uuids.length} user message(s) were never read by Claude Code: ${uuids.join(", ")}`);
1232
+ opts.onCommandsDropped?.(uuids);
1233
+ };
1084
1234
  let callbackDepth = 0;
1085
1235
  const guardCallback = (callback) => (async (...args) => {
1086
1236
  callbackDepth++;
@@ -1338,7 +1488,19 @@ async function claudeRemote(opts) {
1338
1488
  setPermissionMode: (mode2) => response.setPermissionMode(mode2),
1339
1489
  setModel: (model) => response.setModel(modelTarget(model)),
1340
1490
  interrupt: async () => {
1341
- await response.interrupt();
1491
+ const cancelQueued = cliCapabilities.has(INTERRUPT_CANCEL_QUEUED_CAPABILITY);
1492
+ const receipt = await response.interrupt(cancelQueued ? { cancelQueued: true } : void 0);
1493
+ const { dropped, stillQueued } = commandTracker.onInterruptReceipt(receipt);
1494
+ if (!cancelQueued && stillQueued.length > 0) {
1495
+ const cancelAsyncMessage = response.cancelAsyncMessage;
1496
+ if (typeof cancelAsyncMessage === "function") {
1497
+ for (const uuid of stillQueued) {
1498
+ const cancelled = await cancelAsyncMessage.call(response, uuid).then((value) => value === true, () => false);
1499
+ dropped.push(...commandTracker.onCancelResponse(uuid, cancelled));
1500
+ }
1501
+ }
1502
+ }
1503
+ reportDroppedCommands(dropped);
1342
1504
  },
1343
1505
  // `request` is the SDK's generic control-request sender (every typed
1344
1506
  // method wraps it); the public types omit `side_question`, the CLI
@@ -1348,19 +1510,90 @@ async function claudeRemote(opts) {
1348
1510
  const body = raw?.response;
1349
1511
  return body && typeof body === "object" ? body : { response: null };
1350
1512
  },
1351
- steer: (message, nextMode) => {
1513
+ steer: (message, nextMode, localKey) => {
1352
1514
  mode = { ...nextMode, model: mode.model };
1515
+ const uuid = promptUuid(localKey);
1516
+ if (uuid.uuid) commandTracker.track(uuid.uuid);
1353
1517
  messages.push({
1354
1518
  type: "user",
1355
1519
  parent_tool_use_id: null,
1356
1520
  priority: "now",
1357
1521
  origin: { kind: "human" },
1522
+ ...uuid,
1358
1523
  message: { role: "user", content: message }
1359
1524
  });
1360
1525
  }
1361
1526
  });
1362
1527
  }
1363
1528
  let lastAssistantError;
1529
+ turn.pushed();
1530
+ if (initialUserMessage.uuid) commandTracker.track(initialUserMessage.uuid);
1531
+ let modelUnconfirmed = false;
1532
+ let pullingNext = false;
1533
+ const pullNextMessage = () => {
1534
+ if (pullingNext) {
1535
+ logger.debug("[claudeRemote] Already waiting for the next message");
1536
+ return;
1537
+ }
1538
+ pullingNext = true;
1539
+ opts.nextMessage().then(async (next) => {
1540
+ if (!next) {
1541
+ messages.end();
1542
+ return;
1543
+ }
1544
+ if (modelUnconfirmed || needsModelSwitch(mode.model, next.mode.model)) {
1545
+ try {
1546
+ await withTimeout(response.setModel(modelTarget(next.mode.model)), SET_MODEL_TIMEOUT_MS, "set_model");
1547
+ modelUnconfirmed = false;
1548
+ logger.debug(`[claudeRemote] Model switched to ${modelTarget(next.mode.model) ?? "default"}`);
1549
+ } catch (e) {
1550
+ logger.debug(`[claudeRemote] setModel failed: ${e instanceof Error ? e.message : String(e)}`);
1551
+ opts.onCompletionEvent?.(modelSwitchFailureNotice(next.mode.model, e));
1552
+ if (e instanceof TimeoutError) modelUnconfirmed = true;
1553
+ next = { ...next, mode: { ...next.mode, model: mode.model } };
1554
+ }
1555
+ }
1556
+ mode = next.mode;
1557
+ updateThinking(true);
1558
+ turn.pushed();
1559
+ const uuid = promptUuid(next.uuid);
1560
+ if (uuid.uuid) commandTracker.track(uuid.uuid);
1561
+ timingMarks = { pushedAt: next.enqueuedAt ?? Date.now() };
1562
+ messages.push({
1563
+ type: "user",
1564
+ parent_tool_use_id: null,
1565
+ origin: { kind: "human" },
1566
+ ...uuid,
1567
+ message: { role: "user", content: next.message }
1568
+ });
1569
+ }).catch(() => {
1570
+ messages.end();
1571
+ }).finally(() => {
1572
+ pullingNext = false;
1573
+ });
1574
+ };
1575
+ const recycleIfPoisoned = (result) => {
1576
+ const recycleReason = queryRecycleReason(result ?? { }, lastAssistantError);
1577
+ lastAssistantError = void 0;
1578
+ if (!recycleReason) return false;
1579
+ logger.warn(`[claudeRemote] Ending SDK query after ${recycleReason}; the next message starts a fresh Claude Code process`);
1580
+ opts.onCompletionEvent?.(QUERY_RECYCLE_NOTICE[recycleReason]);
1581
+ opts.onAuthFailure?.(recycleReason);
1582
+ messages.end();
1583
+ return true;
1584
+ };
1585
+ const endTurnWithoutResult = () => {
1586
+ updateThinking(false);
1587
+ logger.debug(`[claudeRemote] Turn ${timingTurn} ended by session_state_changed idle without a result frame`);
1588
+ timingTurn++;
1589
+ timingMarks = {};
1590
+ if (isCompactCommand) {
1591
+ logger.debug("[claudeRemote] /compact ended without a result; outcome unknown");
1592
+ isCompactCommand = false;
1593
+ }
1594
+ opts.onReady(void 0);
1595
+ if (!recycleIfPoisoned()) pullNextMessage();
1596
+ };
1364
1597
  updateThinking(true);
1365
1598
  try {
1366
1599
  logger.debug(`[claudeRemote] Starting to iterate over response`);
@@ -1392,9 +1625,22 @@ async function claudeRemote(opts) {
1392
1625
  }
1393
1626
  const outboundMessage = isCompactCommand && message.type === "assistant" ? { ...message, isCompactSummary: true } : message;
1394
1627
  opts.onMessage(outboundMessage);
1628
+ const lifecycle = readClaudeCommandLifecycle(message);
1629
+ if (lifecycle) reportDroppedCommands(commandTracker.observe(lifecycle));
1630
+ const sessionState = readClaudeSessionState(message);
1631
+ if (sessionState) {
1632
+ const verdict = turn.onSessionState(sessionState);
1633
+ if (verdict === "end") {
1634
+ endTurnWithoutResult();
1635
+ } else {
1636
+ logger.debug(`[claudeRemote] session_state_changed ${sessionState}: ${verdict}`);
1637
+ }
1638
+ }
1395
1639
  if (message.type === "system" && message.subtype === "init") {
1396
1640
  updateThinking(true);
1641
+ turn.announced();
1397
1642
  const systemInit = message;
1643
+ cliCapabilities = new Set(Array.isArray(systemInit.capabilities) ? systemInit.capabilities : []);
1398
1644
  if (opts.onSDKMetadata) {
1399
1645
  opts.onSDKMetadata({
1400
1646
  models,
@@ -1427,8 +1673,9 @@ async function claudeRemote(opts) {
1427
1673
  }
1428
1674
  }
1429
1675
  if (message.type === "result") {
1676
+ const endsTurn = turn.onResult();
1430
1677
  updateThinking(false);
1431
- logger.debug("[claudeRemote] Result received");
1678
+ logger.debug(endsTurn ? "[claudeRemote] Result received" : "[claudeRemote] Result received for a turn already ended by idle");
1432
1679
  logger.debug(formatClaudeTimingLine({
1433
1680
  turn: timingTurn,
1434
1681
  firstTurnOfProcess: timingTurn === 1,
@@ -1450,44 +1697,9 @@ async function claudeRemote(opts) {
1450
1697
  }
1451
1698
  isCompactCommand = false;
1452
1699
  }
1453
- opts.onReady(message);
1454
- const recycleReason = queryRecycleReason(message, lastAssistantError);
1455
- lastAssistantError = void 0;
1456
- if (recycleReason) {
1457
- logger.warn(`[claudeRemote] Ending SDK query after ${recycleReason}; the next message starts a fresh Claude Code process`);
1458
- opts.onCompletionEvent?.(QUERY_RECYCLE_NOTICE[recycleReason]);
1459
- opts.onAuthFailure?.(recycleReason);
1460
- messages.end();
1461
- continue;
1462
- }
1463
- opts.nextMessage().then(async (next) => {
1464
- if (!next) {
1465
- messages.end();
1466
- return;
1467
- }
1468
- if (needsModelSwitch(mode.model, next.mode.model)) {
1469
- try {
1470
- await response.setModel(modelTarget(next.mode.model));
1471
- logger.debug(`[claudeRemote] Model switched to ${modelTarget(next.mode.model) ?? "default"}`);
1472
- } catch (e) {
1473
- logger.debug(`[claudeRemote] setModel failed: ${e instanceof Error ? e.message : String(e)}`);
1474
- opts.onCompletionEvent?.(modelSwitchFailureNotice(next.mode.model, e));
1475
- next = { ...next, mode: { ...next.mode, model: mode.model } };
1476
- }
1477
- }
1478
- mode = next.mode;
1479
- updateThinking(true);
1480
- timingMarks = { pushedAt: next.enqueuedAt ?? Date.now() };
1481
- messages.push({
1482
- type: "user",
1483
- parent_tool_use_id: null,
1484
- origin: { kind: "human" },
1485
- ...promptUuid(next.uuid),
1486
- message: { role: "user", content: next.message }
1487
- });
1488
- }).catch(() => {
1489
- messages.end();
1490
- });
1700
+ if (endsTurn) opts.onReady(message);
1701
+ if (recycleIfPoisoned(message)) continue;
1702
+ if (endsTurn) pullNextMessage();
1491
1703
  }
1492
1704
  if (message.type === "user") {
1493
1705
  const msg = message;
@@ -1525,6 +1737,7 @@ function getToolDescriptor(toolName) {
1525
1737
  return { edit: false, exitPlan: false, dangerous: false };
1526
1738
  }
1527
1739
 
1740
+ const LIVE_PERMISSION_MODE_TIMEOUT_MS = 15e3;
1528
1741
  function elicitationContent(input) {
1529
1742
  if (!input) return void 0;
1530
1743
  const content = {};
@@ -1621,10 +1834,16 @@ class PermissionHandler {
1621
1834
  return;
1622
1835
  }
1623
1836
  await new Promise((resolve) => setImmediate(resolve));
1624
- await this.setPermissionModeCallback(mode);
1837
+ await withTimeout(this.setPermissionModeCallback(mode), LIVE_PERMISSION_MODE_TIMEOUT_MS, "set_permission_mode");
1625
1838
  } catch (error) {
1626
1839
  this.permissionMode = previousMode;
1627
1840
  if (this.deferredPermissionMode === mode) this.deferredPermissionMode = void 0;
1841
+ if (error instanceof TimeoutError && this.setPermissionModeCallback) {
1842
+ this.setPermissionModeCallback(previousMode).then(
1843
+ () => logger.debug(`[PermissionHandler] Re-asserted ${previousMode} after the switch to ${mode} timed out`),
1844
+ (reassertError) => logger.debug("[PermissionHandler] Re-asserting the previous permission mode failed", reassertError)
1845
+ );
1846
+ }
1628
1847
  throw error;
1629
1848
  }
1630
1849
  }
@@ -1635,7 +1854,7 @@ class PermissionHandler {
1635
1854
  setImmediate(() => {
1636
1855
  const task = this.modeChangeQueue.then(async () => {
1637
1856
  if (!this.setPermissionModeCallback || this.permissionMode !== mode) return;
1638
- await this.setPermissionModeCallback(mode);
1857
+ await withTimeout(this.setPermissionModeCallback(mode), LIVE_PERMISSION_MODE_TIMEOUT_MS, "set_permission_mode");
1639
1858
  });
1640
1859
  this.modeChangeQueue = task.catch((error) => {
1641
1860
  logger.debug("[PermissionHandler] Deferred SDK permission mode update failed", error);
@@ -2268,6 +2487,7 @@ class SDKToLogConverter {
2268
2487
  timestamp
2269
2488
  };
2270
2489
  let logMessage = null;
2490
+ if (sdkMessage.type === "command_lifecycle") return null;
2271
2491
  switch (sdkMessage.type) {
2272
2492
  case "user": {
2273
2493
  const userMsg = sdkMessage;
@@ -2707,10 +2927,13 @@ function applyClaudeSdkMetadata(current, update) {
2707
2927
  };
2708
2928
  }
2709
2929
 
2710
- function createTurnSteeringController() {
2930
+ const INTERRUPT_TIMEOUT_MS = 8e3;
2931
+ function createTurnSteeringController(opts = {}) {
2932
+ const interruptTimeoutMs = opts.interruptTimeoutMs ?? INTERRUPT_TIMEOUT_MS;
2711
2933
  let interrupt = null;
2712
2934
  let steering = false;
2713
2935
  let interrupting = false;
2936
+ const boundedInterrupt = (run) => withTimeout(run(), interruptTimeoutMs, "interrupt");
2714
2937
  return {
2715
2938
  setInterrupt(next) {
2716
2939
  interrupt = next;
@@ -2719,7 +2942,7 @@ function createTurnSteeringController() {
2719
2942
  if (!interrupt) return false;
2720
2943
  steering = true;
2721
2944
  try {
2722
- await interrupt();
2945
+ await boundedInterrupt(interrupt);
2723
2946
  return true;
2724
2947
  } catch (error) {
2725
2948
  steering = false;
@@ -2737,7 +2960,7 @@ function createTurnSteeringController() {
2737
2960
  if (!interrupt) return false;
2738
2961
  interrupting = true;
2739
2962
  try {
2740
- await interrupt();
2963
+ await boundedInterrupt(interrupt);
2741
2964
  return true;
2742
2965
  } catch (error) {
2743
2966
  interrupting = false;
@@ -3360,6 +3583,56 @@ async function persistRewindRecord(client, record, opts = {}) {
3360
3583
  }
3361
3584
  }
3362
3585
 
3586
+ const int = (value) => typeof value === "number" && Number.isFinite(value) ? Math.trunc(value) : null;
3587
+ function delayText(ms) {
3588
+ if (ms < 1e3) return `${ms}ms`;
3589
+ const seconds = ms / 1e3;
3590
+ return `${Number.isInteger(seconds) ? seconds : seconds.toFixed(1)}s`;
3591
+ }
3592
+ function describeClaudeApiRetry(frame) {
3593
+ const status = int(frame.error_status);
3594
+ const kind = typeof frame.error === "string" && frame.error && frame.error !== "unknown" ? frame.error.replace(/_/g, " ") : "";
3595
+ const cause = status !== null ? `HTTP ${status}${kind ? ` ${kind}` : ""}` : "a connection error";
3596
+ const attempt = int(frame.attempt);
3597
+ const max = int(frame.max_retries);
3598
+ const delay = int(frame.retry_delay_ms);
3599
+ const details = [];
3600
+ if (attempt !== null) details.push(`attempt ${attempt}${max !== null ? `/${max}` : ""}`);
3601
+ if (delay !== null && delay >= 0) details.push(`next retry in ${delayText(delay)}`);
3602
+ return `Claude is retrying after ${cause}${details.length ? ` (${details.join(", ")})` : ""}`;
3603
+ }
3604
+ const API_RETRY_NOTICE_MIN_INTERVAL_MS = 6e4;
3605
+ function createClaudeApiRetryGate(opts = {}) {
3606
+ const minIntervalMs = opts.minIntervalMs ?? API_RETRY_NOTICE_MIN_INTERVAL_MS;
3607
+ let lastAttempt = null;
3608
+ let lastPersistedAt = null;
3609
+ return {
3610
+ /** True when this frame should be persisted. */
3611
+ observe(frame, now) {
3612
+ const attempt = int(frame.attempt);
3613
+ const newRun = attempt !== null && (lastAttempt === null || attempt <= lastAttempt);
3614
+ if (attempt !== null) lastAttempt = attempt;
3615
+ if (newRun || lastPersistedAt === null || now - lastPersistedAt >= minIntervalMs) {
3616
+ lastPersistedAt = now;
3617
+ return true;
3618
+ }
3619
+ return false;
3620
+ },
3621
+ /** The turn ended: the next retry is a new run. */
3622
+ reset() {
3623
+ lastAttempt = null;
3624
+ lastPersistedAt = null;
3625
+ }
3626
+ };
3627
+ }
3628
+ const INFORMATIONAL_MAX_CHARS = 500;
3629
+ function describeClaudeInformational(frame) {
3630
+ if (frame.level !== "warning" || typeof frame.content !== "string") return null;
3631
+ const text = frame.content.replace(/\s+/g, " ").trim();
3632
+ if (!text) return null;
3633
+ return text.length > INFORMATIONAL_MAX_CHARS ? `${text.slice(0, INFORMATIONAL_MAX_CHARS - 1)}\u2026` : text;
3634
+ }
3635
+
3363
3636
  const ABORT_INTERRUPT_GRACE_MS = 4e3;
3364
3637
  const REWIND_LOG_WINDOW = 500;
3365
3638
  const REWIND_STARTUP_BUDGET_MS = 15e3;
@@ -3527,6 +3800,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3527
3800
  const streamRelay = new StreamRelay({
3528
3801
  send: (frame) => session.client.sendStreamFrame(frame)
3529
3802
  });
3803
+ const apiRetryGate = createClaudeApiRetryGate();
3530
3804
  const messageQueue = new OutgoingMessageQueue(
3531
3805
  (logMessage) => session.client.sendClaudeSessionMessage(logMessage)
3532
3806
  );
@@ -3548,6 +3822,21 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3548
3822
  backgroundTasks.observe(message);
3549
3823
  session.setBackgroundTasks(backgroundTasks.list());
3550
3824
  session.scheduledWakeups.observe(message);
3825
+ if (message.type === "system" && message.subtype === "api_retry") {
3826
+ const notice = describeClaudeApiRetry(message);
3827
+ messageBuffer.addMessage(notice, "status");
3828
+ if (apiRetryGate.observe(message, Date.now())) {
3829
+ session.client.sendSessionEvent({ type: "message", message: notice, kind: "claude-api-retry" });
3830
+ }
3831
+ } else if (message.type === "system" && message.subtype === "informational") {
3832
+ const warning = describeClaudeInformational(message);
3833
+ if (warning) {
3834
+ messageBuffer.addMessage(warning, "status");
3835
+ session.client.sendSessionEvent({ type: "message", message: warning, kind: "claude-warning" });
3836
+ }
3837
+ } else if (message.type === "result") {
3838
+ apiRetryGate.reset();
3839
+ }
3551
3840
  if (isRuntimeCheckpointReplay(message)) return;
3552
3841
  if (message.type === "user" && isClaudeInterruptSentinelContent(message.message.content)) {
3553
3842
  sdkToLogConverter.convert(message);
@@ -3801,7 +4090,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3801
4090
  }
3802
4091
  if (!session.thinking || !modeGate.matches(input.mode)) return false;
3803
4092
  if (typeof message === "string") onPromptFinalized?.(message);
3804
- q.steer(message, input.mode);
4093
+ q.steer(message, input.mode, input.localKey);
3805
4094
  return true;
3806
4095
  });
3807
4096
  permissionHandler.setPermissionModeUpdater(async (mode) => {
@@ -3831,6 +4120,14 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3831
4120
  logger.debug("[remote]: Session reset");
3832
4121
  session.clearSessionId();
3833
4122
  },
4123
+ // B-631: a Stop swept these user messages (steers, or prompts
4124
+ // queued behind a pre-empting steer's turn) before the model
4125
+ // read them — the same tombstone a destroyed queue item gets
4126
+ // (B-332), so the web shows them as not delivered, not answered.
4127
+ onCommandsDropped: (uuids) => {
4128
+ logger.debug(`[remote]: ${uuids.length} user message(s) never read before the turn ended`);
4129
+ session.client.sendQueueCancelReason(uuids, "aborted");
4130
+ },
3834
4131
  onReady: (result) => {
3835
4132
  if (turnSteering.consumeReady()) {
3836
4133
  session.client.closeClaudeSessionTurn("cancelled");
@@ -3876,9 +4173,10 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3876
4173
  session.client.closeClaudeSessionTurn("cancelled");
3877
4174
  continue;
3878
4175
  }
3879
- session.client.closeClaudeSessionTurn("failed");
3880
- session.client.sendSessionEvent({ type: "message", message: "Process exited unexpectedly" });
3881
- session.onSessionError(e instanceof Error ? e.message : "Process exited unexpectedly");
4176
+ const exit = describeClaudeProcessExit(e);
4177
+ const closed = session.client.closeClaudeSessionTurn("failed", { error: exit });
4178
+ if (!closed) session.client.sendSessionEvent({ type: "message", message: exit, kind: "claude-process-exit" });
4179
+ session.onSessionError(exit);
3882
4180
  continue;
3883
4181
  }
3884
4182
  } finally {
@@ -3968,7 +4266,7 @@ async function loop(opts) {
3968
4266
  logger.debug(`[loop] Iteration with mode: ${mode}`);
3969
4267
  switch (mode) {
3970
4268
  case "local": {
3971
- const { claudeLocalLauncher } = await import('./claudeLocalLauncher-D4vmjI3c.mjs');
4269
+ const { claudeLocalLauncher } = await import('./claudeLocalLauncher-7p6y88nj.mjs');
3972
4270
  const result = await claudeLocalLauncher(session);
3973
4271
  switch (result.type) {
3974
4272
  case "switch":
@@ -4374,7 +4672,7 @@ function registerSideQuestionHandler(rpc, deps) {
4374
4672
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
4375
4673
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
4376
4674
  const fork = deps.run ?? (async (input) => {
4377
- const { query } = await import('./index-B6UGRQ7h.mjs');
4675
+ const { query } = await import('./index-CEjJnq05.mjs');
4378
4676
  return runSideQuestion(query, input);
4379
4677
  });
4380
4678
  const run = async (input, live) => {