very-happy-cli 0.2.162 → 0.2.164

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 (174) hide show
  1. package/dist/{AcpBackend--TmFHgRH.mjs → AcpBackend-B8l1ZePt.mjs} +3 -3
  2. package/dist/{AcpBackend-9asD_DL7.cjs → AcpBackend-CHDqSii9.cjs} +3 -3
  3. package/dist/{AcpSessionManager-BvIuBzoO.cjs → AcpSessionManager-9yN2iH4b.cjs} +1 -1
  4. package/dist/{AcpSessionManager-BSIBnWUb.mjs → AcpSessionManager-BQnDJvct.mjs} +1 -1
  5. package/dist/{BasePermissionHandler-D4B-NNu2.cjs → BasePermissionHandler-DGQYvBPg.cjs} +1 -1
  6. package/dist/{BasePermissionHandler-DUBySe0f.mjs → BasePermissionHandler-DgtAtJTV.mjs} +1 -1
  7. package/dist/{BaseReasoningProcessor-CqLl-ikP.cjs → BaseReasoningProcessor-BqalZhQO.cjs} +1 -1
  8. package/dist/{BaseReasoningProcessor-9TybUGTq.mjs → BaseReasoningProcessor-Dfacnfhj.mjs} +1 -1
  9. package/dist/{agentHome-DQrq_FG1.mjs → agentHome-DM0urHEI.mjs} +4 -4
  10. package/dist/{agentHome-BohNUYnE.cjs → agentHome-DtsPKfTS.cjs} +4 -4
  11. package/dist/{api-CQnLOqRS.cjs → api-EKlS0r1w.cjs} +57 -15
  12. package/dist/{api-D57dsd6_.mjs → api-Yoh_zKdR.mjs} +57 -15
  13. package/dist/{apiMachine-fFFaWxYy.cjs → apiMachine-q71suojS.cjs} +20 -17
  14. package/dist/{apiMachine-78Aqzg--.mjs → apiMachine-s3HiV-SL.mjs} +20 -17
  15. package/dist/{assistantTools-mEz6uNqL.mjs → assistantTools-BWfAV349.mjs} +6 -6
  16. package/dist/{assistantTools-CwESq24n.cjs → assistantTools-D3cZvgUX.cjs} +6 -6
  17. package/dist/{attachmentContent-s1xPha4Q.mjs → attachmentContent-BLyyo1al.mjs} +2 -2
  18. package/dist/{attachmentContent-GHOk6Muq.cjs → attachmentContent-Bakb0XV3.cjs} +2 -2
  19. package/dist/{attachmentLimits-D5pgmASK.mjs → attachmentLimits-B8nzhw-i.mjs} +1 -1
  20. package/dist/{attachmentLimits-DzlBPyJP.cjs → attachmentLimits-eJZ4ZBjF.cjs} +1 -1
  21. package/dist/{auth-BOaHWquu.mjs → auth-BTfv8yW0.mjs} +8 -8
  22. package/dist/{auth-BbSdXMQ_.cjs → auth-Cn3dQInF.cjs} +5 -5
  23. package/dist/{auth-C8V7-oUT.mjs → auth-Cxhx5evk.mjs} +5 -5
  24. package/dist/{auth-B8EagV6G.cjs → auth-Hpg4Yxfa.cjs} +8 -8
  25. package/dist/{auto-CWDOX35m.mjs → auto-BAAEVGZa.mjs} +15 -14
  26. package/dist/{auto-Bw_h0yVc.cjs → auto-CK8irHum.cjs} +15 -14
  27. package/dist/{bootstrap-BKmsYSwh.mjs → bootstrap-CTNjn_aj.mjs} +2 -2
  28. package/dist/{bootstrap-DvZjEa9_.cjs → bootstrap-D9SUykG_.cjs} +2 -2
  29. package/dist/{browser-CBZj-1Wx.cjs → browser-C8ztaIkm.cjs} +1 -1
  30. package/dist/{browser-CrMAr5fI.mjs → browser-DydXWySF.mjs} +1 -1
  31. package/dist/{claudeLocal-dhdlcQ6F.mjs → claudeLocal-CdJJovWq.mjs} +5 -5
  32. package/dist/{claudeLocal-Bpw-u9et.cjs → claudeLocal-CsLFMvFU.cjs} +5 -5
  33. package/dist/{claudeLocalLauncher-BFfGT4eY.mjs → claudeLocalLauncher-CKazNnl0.mjs} +10 -10
  34. package/dist/{claudeLocalLauncher-DWFWuLhY.cjs → claudeLocalLauncher-DRc-tET5.cjs} +10 -10
  35. package/dist/{claudeSessionFork-D9-mANmu.cjs → claudeSessionFork-BWdhyy9B.cjs} +1 -1
  36. package/dist/{claudeSessionFork-_DUrXaqd.mjs → claudeSessionFork-BfPW9D2S.mjs} +1 -1
  37. package/dist/{client-CVQJWqjx.cjs → client-BZtKFCJr.cjs} +2 -2
  38. package/dist/{client-DiBTHWNU.cjs → client-C1GAIJ04.cjs} +3 -3
  39. package/dist/{client-DwqHDsLb.mjs → client-DkoV3VWl.mjs} +2 -2
  40. package/dist/{client-Dk7x-s-O.mjs → client-Do5CHQnZ.mjs} +3 -3
  41. package/dist/codex/happyMcpStdioBridge.cjs +15 -15
  42. package/dist/codex/happyMcpStdioBridge.mjs +15 -15
  43. package/dist/{codexAppServerClient-C2ybs2mZ.mjs → codexAppServerClient-CfF33X-8.mjs} +2 -2
  44. package/dist/{codexAppServerClient-DlKv5TjG.cjs → codexAppServerClient-JddkV_aP.cjs} +2 -2
  45. package/dist/{codexCommand-4vLE31fj.cjs → codexCommand-Bdj3XZbi.cjs} +43 -40
  46. package/dist/{codexCommand-DnmFr9Qx.mjs → codexCommand-btJso8yC.mjs} +43 -40
  47. package/dist/{config-Btd4B05_.cjs → config-DpCNivmg.cjs} +3 -3
  48. package/dist/{config-CSOG_ZcP.mjs → config-nziuMb7g.mjs} +3 -3
  49. package/dist/{configuration-A5gW_0GE.mjs → configuration-CiBUH72C.mjs} +1 -1
  50. package/dist/{configuration-UsI0sxEv.cjs → configuration-PXAE4-FP.cjs} +1 -1
  51. package/dist/{connect-C9yxp8Om.cjs → connect-D7ehaW2C.cjs} +13 -13
  52. package/dist/{connect-DWYj8LP_.mjs → connect-XHdi6Vtc.mjs} +13 -13
  53. package/dist/{context-BXnxalWW.mjs → context-BpEYcuLv.mjs} +1 -1
  54. package/dist/{context-0FjjA4vJ.cjs → context-DhvXl1oC.cjs} +1 -1
  55. package/dist/{controlClient-BXktrQ4z.cjs → controlClient-DI-Er-Ww.cjs} +3 -3
  56. package/dist/{controlClient-CYzHrh3e.mjs → controlClient-DzmCQrY_.mjs} +3 -3
  57. package/dist/{createSessionMetadata-Dyg33ZlU.mjs → createSessionMetadata-B47GrTX6.mjs} +2 -2
  58. package/dist/{createSessionMetadata-EX1eAlHx.cjs → createSessionMetadata-D04x6OMW.cjs} +2 -2
  59. package/dist/{deterministicJson-eha_oMZ2.cjs → deterministicJson-BM8e8QwP.cjs} +9 -9
  60. package/dist/{deterministicJson-DiR7EOMO.mjs → deterministicJson-CKqT3awl.mjs} +9 -9
  61. package/dist/{doctor-FuCvKdRa.mjs → doctor-CSgzbG5L.mjs} +6 -6
  62. package/dist/{doctor-DunLBgVi.cjs → doctor-Cl6cqvok.cjs} +6 -6
  63. package/dist/{ensureDaemonRunning-B4dZFmUy.cjs → ensureDaemonRunning-CJ4-U32n.cjs} +5 -5
  64. package/dist/{ensureDaemonRunning-EZkb-CAF.mjs → ensureDaemonRunning-fPVSsjIm.mjs} +5 -5
  65. package/dist/forkBackfill-8eLDeS73.cjs +66 -0
  66. package/dist/forkBackfill-DYIjlN1Z.mjs +62 -0
  67. package/dist/{handleResumeCommand-CsXendKb.mjs → handleResumeCommand-B84dt2aH.mjs} +5 -5
  68. package/dist/{handleResumeCommand-CKMIw4pE.cjs → handleResumeCommand-bX-aNF_z.cjs} +5 -5
  69. package/dist/{index-DRhWHEuW.cjs → index-B2UvSWo_.cjs} +3 -3
  70. package/dist/{index-BOhgL3rh.cjs → index-CP2fh7JX.cjs} +38 -38
  71. package/dist/{index-9L39wqYR.mjs → index-CRJtZCK-.mjs} +39 -39
  72. package/dist/{index-CvXcVQ06.mjs → index-CbF87SeZ.mjs} +3 -3
  73. package/dist/{index-CZWAiydF.cjs → index-DaTxsAC3.cjs} +4 -4
  74. package/dist/{index-DJ-oV52i.cjs → index-DqlyNgt4.cjs} +6 -1
  75. package/dist/{index-DK2JpTJf.mjs → index-OEGj3BxE.mjs} +4 -4
  76. package/dist/{index-BBg9j0XK.mjs → index-vVWpCoTr.mjs} +6 -1
  77. package/dist/index.cjs +2 -2
  78. package/dist/index.mjs +2 -2
  79. package/dist/{install-B2duVo9a.mjs → install-CurvoW2u.mjs} +3 -3
  80. package/dist/{install-C8WyZI9K.cjs → install-__Mni4NU.cjs} +3 -3
  81. package/dist/lib.cjs +17 -17
  82. package/dist/lib.d.cts +47 -0
  83. package/dist/lib.d.mts +47 -0
  84. package/dist/lib.mjs +17 -17
  85. package/dist/{lidState-CigXWxhe.mjs → lidState-BbR6y9rq.mjs} +66 -2
  86. package/dist/{lidState-Ds-6ytZV.cjs → lidState-De2HP6nu.cjs} +67 -1
  87. package/dist/{localHappyAgentAuth-CaCyKzYp.mjs → localHappyAgentAuth-C7rDePjF.mjs} +1 -1
  88. package/dist/{localHappyAgentAuth-l0Na-5Ys.cjs → localHappyAgentAuth-CboZb3_a.cjs} +1 -1
  89. package/dist/{logger-CGE4C8ho.mjs → logger-8dtZPn3n.mjs} +2 -2
  90. package/dist/{logger-7ucWm9wp.cjs → logger-B1k7eZnq.cjs} +2 -2
  91. package/dist/{machineMetadata-ue1nkowa.mjs → machineMetadata-Bhp_w3-_.mjs} +3 -3
  92. package/dist/{machineMetadata-lMPtpF16.cjs → machineMetadata-C4OfKn6I.cjs} +3 -3
  93. package/dist/{main-3fIFXD-t.mjs → main-BQTaUrz0.mjs} +44 -44
  94. package/dist/{main-CFI0datL.cjs → main-eAiLspBM.cjs} +44 -44
  95. package/dist/{mcp-DARQBZ7l.mjs → mcp-DXCdbQHM.mjs} +14 -14
  96. package/dist/{mcp-DfxLAc1G.cjs → mcp-fapbM7Q4.cjs} +14 -14
  97. package/dist/{package-D1A-8ZJy.cjs → package-CC_txQ31.cjs} +8 -8
  98. package/dist/{package-DQsvY1XN.mjs → package-tVYgFJoK.mjs} +8 -8
  99. package/dist/{peerTools-D19hhSQF.mjs → peerTools-C1cduHh1.mjs} +4 -4
  100. package/dist/{peerTools-DLwNaEEV.cjs → peerTools-CqIcCEIg.cjs} +4 -4
  101. package/dist/{persistence-Cw8aLoyL.mjs → persistence-C_xFQLsD.mjs} +3 -3
  102. package/dist/{persistence-i0nQMLlk.cjs → persistence-d3ZyER6o.cjs} +3 -3
  103. package/dist/{piRunnerArgs-BUyxPxjZ.cjs → piRunnerArgs-DSxolPlV.cjs} +1 -1
  104. package/dist/{piRunnerArgs-58t454gw.mjs → piRunnerArgs-aq0zJX1Q.mjs} +1 -1
  105. package/dist/{piRuntime-DVPixFjl.mjs → piRuntime-BnNl5Lmb.mjs} +1 -1
  106. package/dist/{piRuntime-Dff73XCb.cjs → piRuntime-Dne1LPu-.cjs} +1 -1
  107. package/dist/{piTerminal-gHWFAyzq.mjs → piTerminal-CKWxWtW-.mjs} +16 -16
  108. package/dist/{piTerminal-Dz1RrO70.cjs → piTerminal-fjado4cR.cjs} +16 -16
  109. package/dist/{registerCommonHandlers-CMROPdJz.cjs → registerCommonHandlers-Dausbdsb.cjs} +2 -2
  110. package/dist/{registerCommonHandlers-Ckv5boQI.mjs → registerCommonHandlers-bSskMveZ.mjs} +2 -2
  111. package/dist/{registerKillSessionHandler-Cll4-o8Y.mjs → registerKillSessionHandler-Ben5lAsN.mjs} +6 -6
  112. package/dist/{registerKillSessionHandler-CA9-oelM.cjs → registerKillSessionHandler-CgKyzwqw.cjs} +6 -6
  113. package/dist/{remoteSessionClient-DX9jHLeW.cjs → remoteSessionClient-BkJt8SHa.cjs} +5 -5
  114. package/dist/{remoteSessionClient-BMjsbuBh.mjs → remoteSessionClient-DnCIuZpQ.mjs} +5 -5
  115. package/dist/{run-CjbGo2wb.cjs → run-B8dxbDsg.cjs} +33 -33
  116. package/dist/{run-CrunzDlt.mjs → run-BEYMVE4J.mjs} +32 -32
  117. package/dist/{runClaude-KN-4Y4LH.cjs → runClaude-Cy_HzLyO.cjs} +26 -23
  118. package/dist/{runClaude-WDBWRtnF.mjs → runClaude-Dd_P1c0f.mjs} +26 -23
  119. package/dist/{runClaudeDeps-QaEx8y5r.mjs → runClaudeDeps-JG7EUH7B.mjs} +441 -49
  120. package/dist/{runClaudeDeps-DW-8lnHv.cjs → runClaudeDeps-dxv910DR.cjs} +436 -44
  121. package/dist/{runGemini-Nf6SKBpw.mjs → runGemini-CpaBuvoW.mjs} +34 -34
  122. package/dist/{runGemini-Djmwjdv1.cjs → runGemini-DY1IDW_f.cjs} +34 -34
  123. package/dist/{runOpenClaw-CAqP5KFH.cjs → runOpenClaw-C0VARcYj.cjs} +20 -20
  124. package/dist/{runOpenClaw-9nHtmYbN.mjs → runOpenClaw-C7vrDQbq.mjs} +20 -20
  125. package/dist/{sandbox-C8Dd8GPM.cjs → sandbox-Bx9-M9rN.cjs} +4 -4
  126. package/dist/{sandbox-SP0THMt0.mjs → sandbox-DRUJZuaM.mjs} +4 -4
  127. package/dist/{selfCheck-D9ZXrK7h.cjs → selfCheck-Ba1sECTO.cjs} +34 -34
  128. package/dist/selfCheck-DdT8r263.mjs +84 -0
  129. package/dist/{send-DOx9aQsx.mjs → send-BrzkbMy2.mjs} +8 -8
  130. package/dist/{send-LPk6Q5HI.cjs → send-Dqdpx-w5.cjs} +8 -8
  131. package/dist/{server-BZNi8Hq_.mjs → server-CPMPoEAA.mjs} +4 -4
  132. package/dist/{server-CxT8jNyn.cjs → server-CfB8EWCg.cjs} +6 -6
  133. package/dist/{sessionLock-y9rnA4LK.cjs → sessionLock-BsP3Y_nG.cjs} +2 -2
  134. package/dist/{sessionLock-CfLqJfeI.mjs → sessionLock-DukLVzAQ.mjs} +2 -2
  135. package/dist/{sessionModeFile-BKxgNH3P.mjs → sessionModeFile-CSvi4H_t.mjs} +1 -1
  136. package/dist/{sessionModeFile-B5YeoQJh.cjs → sessionModeFile-JWWF6Nn7.cjs} +1 -1
  137. package/dist/{sessionOps-CdwVPSZz.mjs → sessionOps-BlMg1uAa.mjs} +5 -5
  138. package/dist/{sessionOps-GsELm2PZ.cjs → sessionOps-HuoMXcIZ.cjs} +4 -4
  139. package/dist/{sessionScanner-aLEv7mD3.cjs → sessionScanner-BWU6KvZw.cjs} +3 -3
  140. package/dist/{sessionScanner-Cdukzo70.mjs → sessionScanner-Ct-JoNHP.mjs} +3 -3
  141. package/dist/{sessions-Dne-OiRL.mjs → sessions-3Hw1xXMV.mjs} +9 -9
  142. package/dist/{sessions-CfG4WGN0.cjs → sessions-AjflCj5y.cjs} +9 -9
  143. package/dist/{setupOfflineReconnection-DiQma2Cc.mjs → setupOfflineReconnection-B_9xp36H.mjs} +2 -2
  144. package/dist/{setupOfflineReconnection-CFwltTcP.cjs → setupOfflineReconnection-Cxh9Sz9M.cjs} +2 -2
  145. package/dist/{spawn-DkgP2BGF.mjs → spawn-BXEVKCQK.mjs} +38 -18
  146. package/dist/{spawn-BI_sdgWs.cjs → spawn-CN8PH11G.cjs} +38 -17
  147. package/dist/{spawnAgents-Y1LjnCt9.mjs → spawnAgents-Czi2VDzj.mjs} +1 -1
  148. package/dist/{spawnAgents-iSu1Xzs5.cjs → spawnAgents-McixdtV1.cjs} +1 -1
  149. package/dist/{spawnHappyCLI-9mx4lPxh.mjs → spawnHappyCLI-BFN0h2fK.mjs} +1 -1
  150. package/dist/{spawnHappyCLI-BRdx0sAX.cjs → spawnHappyCLI-Cj-9-d_7.cjs} +1 -1
  151. package/dist/{startFileWatcher-C2HC2_Dg.cjs → startFileWatcher-BfMu444W.cjs} +1 -1
  152. package/dist/{startFileWatcher-COD5UKNs.mjs → startFileWatcher-Csql7gdv.mjs} +1 -1
  153. package/dist/{streamRelay-BLgU9X3R.mjs → streamRelay-BzMEEvJU.mjs} +1 -1
  154. package/dist/{streamRelay-DnObXZZj.cjs → streamRelay-C0AffuX6.cjs} +1 -1
  155. package/dist/{sync-Dj92ZJ8Y.cjs → sync--uxtLWbo.cjs} +5 -1
  156. package/dist/{sync-BpLasLu2.mjs → sync-SCvDzRy6.mjs} +5 -1
  157. package/dist/{systemPrompt-CyEz_IfR.cjs → systemPrompt-C1tRiZ-u.cjs} +2 -2
  158. package/dist/{systemPrompt-DsQoUgQw.mjs → systemPrompt-D0KMySrK.mjs} +2 -2
  159. package/dist/{teams-BETNMjpZ.mjs → teams-By-hcvMF.mjs} +6 -6
  160. package/dist/{teams-Ctx9zXn4.cjs → teams-CYDIFXEC.cjs} +6 -6
  161. package/dist/{time-CLwVAz6s.cjs → time-C7BplxuS.cjs} +1 -1
  162. package/dist/{time-CVvxdEDh.mjs → time-CRvAaC5H.mjs} +1 -1
  163. package/dist/{titleGenerator-B4AW3dLr.mjs → titleGenerator-CUG-n2r3.mjs} +1 -1
  164. package/dist/{titleGenerator-FDpdizn7.cjs → titleGenerator-Kw3sTnNQ.cjs} +2 -2
  165. package/dist/{todo-C3tyFeq1.cjs → todo-B7a7J5Ng.cjs} +6 -6
  166. package/dist/{todo-Jk4Vs7hP.mjs → todo-yuIsUvU8.mjs} +6 -6
  167. package/dist/{tools-CGxq3I52.cjs → tools-BTBgpiRc.cjs} +2 -2
  168. package/dist/{tools-O5beDK-s.cjs → tools-D7UeLMZ7.cjs} +1 -1
  169. package/dist/{tools-_kFe4m_l.mjs → tools-RvMKw7yx.mjs} +1 -1
  170. package/dist/{tools-BA1qkiV1.mjs → tools-gUjkPpCw.mjs} +2 -2
  171. package/dist/{uninstall-DHKF90lo.cjs → uninstall-D5D16-KM.cjs} +3 -3
  172. package/dist/{uninstall-C_mdAZlm.mjs → uninstall-Dx9FmLXs.mjs} +3 -3
  173. package/package.json +8 -8
  174. package/dist/selfCheck-7FaZtVu2.mjs +0 -84
@@ -1,50 +1,50 @@
1
- import { l as logger } from './logger-CGE4C8ho.mjs';
2
- import { k as notifyDaemonSessionEvent, m as notifyDaemonClaudeAuthFailed } from './controlClient-CYzHrh3e.mjs';
3
- export { g as reportSessionEditToDaemon } from './controlClient-CYzHrh3e.mjs';
1
+ import { l as logger } from './logger-8dtZPn3n.mjs';
2
+ import { k as notifyDaemonSessionEvent, m as notifyDaemonClaudeAuthFailed } from './controlClient-DzmCQrY_.mjs';
3
+ export { g as reportSessionEditToDaemon } from './controlClient-DzmCQrY_.mjs';
4
4
  import { s as sameBackgroundTasks, c as createBackgroundTaskTracker } from './backgroundTaskActivity-8PdPxrvy.mjs';
5
5
  import { randomInt, randomUUID, createHash } from 'node:crypto';
6
6
  import { M as MessageBuffer } from './messageBuffer-BWlGgR3A.mjs';
7
7
  import { query } from './index-B6UGRQ7h.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-DsQoUgQw.mjs';
10
+ import { c as claudeCheckSession, s as systemPrompt } from './systemPrompt-D0KMySrK.mjs';
11
11
  import { join, resolve, dirname } from 'node:path';
12
12
  import { p as parseSpecialCommand } from './specialCommands-BSqhYg5X.mjs';
13
13
  import 'axios';
14
14
  import 'node:events';
15
15
  import 'socket.io-client';
16
- import { A as AsyncLock } from './attachmentLimits-D5pgmASK.mjs';
16
+ import { A as AsyncLock } from './attachmentLimits-B8nzhw-i.mjs';
17
17
  import 'tweetnacl';
18
- import { c as configuration, e as ensurePrivateDirectory } from './configuration-A5gW_0GE.mjs';
19
- import './index-BBg9j0XK.mjs';
20
- import './registerCommonHandlers-Ckv5boQI.mjs';
18
+ import { c as configuration, e as ensurePrivateDirectory } from './configuration-CiBUH72C.mjs';
19
+ import './index-vVWpCoTr.mjs';
20
+ import './registerCommonHandlers-bSskMveZ.mjs';
21
21
  import 'os';
22
22
  import 'child_process';
23
23
  import '@paralleldrive/cuid2';
24
- import './persistence-Cw8aLoyL.mjs';
24
+ import './persistence-C_xFQLsD.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-CVvxdEDh.mjs';
30
+ import { d as delay } from './time-CRvAaC5H.mjs';
31
31
  import { mkdirSync, writeFileSync, readFileSync, unlinkSync, renameSync, statSync, existsSync } from 'node:fs';
32
- import { h as hashObject, i as isSelfReportFresh } from './deterministicJson-DiR7EOMO.mjs';
33
- export { c as createSelfReportState, s as startHappyServer } from './deterministicJson-DiR7EOMO.mjs';
34
- import { F as Future } from './sessionScanner-Cdukzo70.mjs';
35
- export { c as createSessionScanner } from './sessionScanner-Cdukzo70.mjs';
32
+ import { h as hashObject, i as isSelfReportFresh } from './deterministicJson-CKqT3awl.mjs';
33
+ export { c as createSelfReportState, s as startHappyServer } from './deterministicJson-CKqT3awl.mjs';
34
+ import { F as Future } from './sessionScanner-Ct-JoNHP.mjs';
35
+ export { c as createSessionScanner } from './sessionScanner-Ct-JoNHP.mjs';
36
36
  import { execSync } from 'node:child_process';
37
- import { S as StreamRelay } from './streamRelay-BLgU9X3R.mjs';
38
- import { C as CLAUDE_ATTACHMENT_KINDS, c as chatAttachmentDirectory, a as stageClaudeAttachments, b as appendStagedAttachmentsToPrompt } from './attachmentContent-s1xPha4Q.mjs';
39
- import { readFile, writeFile, rename, unlink } from 'node:fs/promises';
40
- import { F as ForkSourceMissingError } from './claudeSessionFork-_DUrXaqd.mjs';
41
- export { M as MessageQueue2, r as registerKillSessionHandler } from './registerKillSessionHandler-Cll4-o8Y.mjs';
42
- export { g as getEnvironmentInfo } from './doctor-FuCvKdRa.mjs';
37
+ import { S as StreamRelay } from './streamRelay-BzMEEvJU.mjs';
38
+ import { C as CLAUDE_ATTACHMENT_KINDS, c as chatAttachmentDirectory, a as stageClaudeAttachments, b as appendStagedAttachmentsToPrompt } from './attachmentContent-BLyyo1al.mjs';
39
+ import { writeFile, rename, unlink, readFile } from 'node:fs/promises';
40
+ import { F as ForkSourceMissingError } from './claudeSessionFork-BfPW9D2S.mjs';
41
+ export { M as MessageQueue2, r as registerKillSessionHandler } from './registerKillSessionHandler-Ben5lAsN.mjs';
42
+ export { g as getEnvironmentInfo } from './doctor-CSgzbG5L.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-B4AW3dLr.mjs';
47
- export { T as TitleGenerator } from './titleGenerator-B4AW3dLr.mjs';
46
+ import { r as resolveClaudeBinary, a as runClaudeOneShot } from './titleGenerator-CUG-n2r3.mjs';
47
+ export { T as TitleGenerator } from './titleGenerator-CUG-n2r3.mjs';
48
48
  import { B as BOARD_ANALYZER_PROMPT_PREFIX } from './oneShotPrompts-DT4p6RNd.mjs';
49
49
  import 'node:util';
50
50
  import './smallFastModel-BLNgMrwR.mjs';
@@ -52,33 +52,33 @@ import './trimIdent-BAjmv_TG.mjs';
52
52
  import 'node:os';
53
53
  import './agentGuidance-CQuNlNx8.mjs';
54
54
  import 'zod';
55
- import './package-DQsvY1XN.mjs';
55
+ import './package-tVYgFJoK.mjs';
56
56
  import 'util';
57
57
  import 'crypto';
58
58
  import 'path';
59
59
  import 'cross-spawn';
60
60
  import './authRelay-DSAvg1uv.mjs';
61
- import './client-Dk7x-s-O.mjs';
62
- import './context-BXnxalWW.mjs';
63
- import './sessionOps-CdwVPSZz.mjs';
61
+ import './client-Do5CHQnZ.mjs';
62
+ import './context-BpEYcuLv.mjs';
63
+ import './sessionOps-BlMg1uAa.mjs';
64
64
  import './resources-BdFBQi8r.mjs';
65
- import './tools-_kFe4m_l.mjs';
66
- import './tools-BA1qkiV1.mjs';
67
- import './client-DwqHDsLb.mjs';
68
- import './peerTools-D19hhSQF.mjs';
65
+ import './tools-RvMKw7yx.mjs';
66
+ import './tools-gUjkPpCw.mjs';
67
+ import './client-DkoV3VWl.mjs';
68
+ import './peerTools-C1cduHh1.mjs';
69
69
  import './ids-DU6sLx4C.mjs';
70
- import './remoteSessionClient-BMjsbuBh.mjs';
70
+ import './remoteSessionClient-DnCIuZpQ.mjs';
71
71
  import '@modelcontextprotocol/sdk/server/mcp.js';
72
72
  import '@modelcontextprotocol/sdk/server/streamableHttp.js';
73
73
  import './limits-DIo7rEBR.mjs';
74
- import './assistantTools-mEz6uNqL.mjs';
74
+ import './assistantTools-BWfAV349.mjs';
75
75
  import './terminals-Dlg0x3nY.mjs';
76
76
  import './terminalTitleSuggest-CeKsX_V6.mjs';
77
77
  import './tmuxSocket-B8Yx20sT.mjs';
78
- import './bootstrap-BKmsYSwh.mjs';
78
+ import './bootstrap-CTNjn_aj.mjs';
79
79
  import './previewPath-CXN4Vag0.mjs';
80
- import './sync-BpLasLu2.mjs';
81
- import './startFileWatcher-COD5UKNs.mjs';
80
+ import './sync-SCvDzRy6.mjs';
81
+ import './startFileWatcher-Csql7gdv.mjs';
82
82
  import 'node:readline';
83
83
  import './doctor-BPkYWSuq.mjs';
84
84
  import 'ps-list';
@@ -2893,16 +2893,55 @@ function rewindTranscriptLines(lines, action, target) {
2893
2893
  });
2894
2894
  return [...before.map((entry) => entry.line), ...relinked];
2895
2895
  }
2896
- async function rewindClaudeTranscript(projectDir, claudeSessionId, action, target) {
2897
- const source = join(projectDir, `${claudeSessionId}.jsonl`);
2898
- let raw;
2896
+ function transcriptSourceId(lines, claudeSessionId) {
2897
+ let source = null;
2898
+ for (const line of lines) {
2899
+ if (!line || !line.includes('"sessionId"')) continue;
2900
+ let parsed;
2901
+ try {
2902
+ parsed = JSON.parse(line);
2903
+ } catch {
2904
+ continue;
2905
+ }
2906
+ if (typeof parsed?.sessionId === "string" && parsed.sessionId && parsed.sessionId !== claudeSessionId) source = parsed.sessionId;
2907
+ }
2908
+ return source;
2909
+ }
2910
+ const MAX_LINEAGE_DEPTH = 4;
2911
+ async function readTranscriptLines(projectDir, claudeSessionId) {
2912
+ const path = join(projectDir, `${claudeSessionId}.jsonl`);
2899
2913
  try {
2900
- raw = await readFile(source, "utf-8");
2914
+ return (await readFile(path, "utf-8")).split("\n");
2901
2915
  } catch (error) {
2902
- if (error.code === "ENOENT") throw new ForkSourceMissingError(source);
2916
+ if (error.code === "ENOENT") throw new ForkSourceMissingError(path);
2903
2917
  throw error;
2904
2918
  }
2905
- const kept = rewindTranscriptLines(raw.split("\n"), action, target);
2919
+ }
2920
+ async function rewindAcrossLineage(load, claudeSessionId, action, target) {
2921
+ let id = claudeSessionId;
2922
+ let lines = await load(id);
2923
+ if (!lines) throw new ForkSourceMissingError(id);
2924
+ for (let depth = 0; ; depth++) {
2925
+ try {
2926
+ return { kept: rewindTranscriptLines(lines, action, target), from: id };
2927
+ } catch (error) {
2928
+ if (!(error instanceof ConversationRewindError) || error.code !== "not-found" || depth >= MAX_LINEAGE_DEPTH) throw error;
2929
+ const source = transcriptSourceId(lines, id);
2930
+ const sourceLines = source ? await load(source) : null;
2931
+ if (!source || !sourceLines) throw error;
2932
+ id = source;
2933
+ lines = sourceLines;
2934
+ }
2935
+ }
2936
+ }
2937
+ async function rewindClaudeTranscript(projectDir, claudeSessionId, action, target) {
2938
+ const { kept } = await rewindAcrossLineage(async (id) => {
2939
+ if (id === claudeSessionId) return readTranscriptLines(projectDir, id);
2940
+ return readTranscriptLines(projectDir, id).catch((error) => {
2941
+ if (error instanceof ForkSourceMissingError) return null;
2942
+ throw error;
2943
+ });
2944
+ }, claudeSessionId, action, target);
2906
2945
  if (kept === null) return null;
2907
2946
  const newId = randomUUID();
2908
2947
  const destination = join(projectDir, `${newId}.jsonl`);
@@ -2917,6 +2956,7 @@ async function rewindClaudeTranscript(projectDir, claudeSessionId, action, targe
2917
2956
  return newId;
2918
2957
  }
2919
2958
 
2959
+ const REQUEST_ID = /^[A-Za-z0-9_-]{1,100}$/;
2920
2960
  const STOP_WAIT_MS = 8e3;
2921
2961
  function createConversationRewind(deps) {
2922
2962
  let inFlight = false;
@@ -2926,6 +2966,7 @@ function createConversationRewind(deps) {
2926
2966
  const action = request.action;
2927
2967
  const sourceId = typeof request.sourceId === "string" && request.sourceId.length > 0 && request.sourceId.length <= 200 ? request.sourceId : void 0;
2928
2968
  const text = typeof request.text === "string" && request.text.length <= 2e5 ? request.text : void 0;
2969
+ const requestId = typeof request.requestId === "string" && REQUEST_ID.test(request.requestId) ? request.requestId : void 0;
2929
2970
  if (action !== "edit" && action !== "delete" || !sourceId && !text?.trim()) {
2930
2971
  return { ok: false, code: "invalid", error: "Invalid rewind request" };
2931
2972
  }
@@ -2942,7 +2983,9 @@ function createConversationRewind(deps) {
2942
2983
  if (!current) return { ok: false, code: "no-conversation", error: "The agent has no conversation to change yet" };
2943
2984
  const uuids = sourceId ? [sourceId, ...deps.aliases(sourceId)] : [];
2944
2985
  const next = await rewrite(deps.projectDir(), current, action, { uuids, text });
2986
+ const recorded = requestId && deps.beginPending ? deps.beginPending({ requestId, action, sourceClaudeSessionId: current, claudeSessionId: next, at: (deps.now ?? Date.now)() }) : null;
2945
2987
  await deps.switchConversation(next);
2988
+ if (recorded) await recorded;
2946
2989
  return { ok: true, action, freshConversation: next === null };
2947
2990
  } catch (error) {
2948
2991
  if (error instanceof ConversationRewindError) return { ok: false, code: error.code, error: error.message };
@@ -2954,7 +2997,326 @@ function createConversationRewind(deps) {
2954
2997
  };
2955
2998
  }
2956
2999
 
3000
+ const REWIND_CONFIRM_MS = 12e4;
3001
+ function parseRewindRecord(raw) {
3002
+ if (!raw || typeof raw !== "object") return null;
3003
+ const r = raw;
3004
+ if (typeof r.requestId !== "string" || !r.requestId) return null;
3005
+ if (r.action !== "edit" && r.action !== "delete") return null;
3006
+ if (typeof r.sourceClaudeSessionId !== "string" || !r.sourceClaudeSessionId) return null;
3007
+ if (r.claudeSessionId !== null && typeof r.claudeSessionId !== "string") return null;
3008
+ if (typeof r.at !== "number" || !Number.isFinite(r.at)) return null;
3009
+ if (typeof r.state !== "string") return null;
3010
+ return {
3011
+ requestId: r.requestId,
3012
+ action: r.action,
3013
+ sourceClaudeSessionId: r.sourceClaudeSessionId,
3014
+ claudeSessionId: r.claudeSessionId,
3015
+ at: r.at,
3016
+ state: r.state
3017
+ };
3018
+ }
3019
+ function pendingResumeId(claudeArgs) {
3020
+ if (!claudeArgs) return null;
3021
+ const index = claudeArgs.indexOf("--resume");
3022
+ const next = index >= 0 ? claudeArgs[index + 1] : void 0;
3023
+ return next && !next.startsWith("-") && next.includes("-") ? next : null;
3024
+ }
3025
+ function decideRewind(record, confirmedRequestIds, now, currentClaudeSessionId) {
3026
+ if (!record || record.state !== "pending") return { kind: "none" };
3027
+ if (confirmedRequestIds.has(record.requestId)) return { kind: "confirm" };
3028
+ const deadline = record.at + REWIND_CONFIRM_MS;
3029
+ if (now < deadline) return { kind: "wait", ms: deadline - now };
3030
+ if (currentClaudeSessionId !== record.claudeSessionId) return { kind: "supersede" };
3031
+ return { kind: "revert", to: record.sourceClaudeSessionId };
3032
+ }
3033
+ function chainRewindRecord(next, pending) {
3034
+ if (!pending || pending.state !== "pending") return next;
3035
+ return { ...next, sourceClaudeSessionId: pending.sourceClaudeSessionId };
3036
+ }
3037
+ function transcriptDropOf(body) {
3038
+ const b = body;
3039
+ if (b?.role !== "session" || b.content?.type !== "session") return null;
3040
+ const ev = b.content.data?.ev;
3041
+ if (ev?.t !== "transcript-drop" || typeof ev.fromSeq !== "number") return null;
3042
+ return {
3043
+ fromSeq: ev.fromSeq,
3044
+ ...typeof ev.toSeq === "number" ? { toSeq: ev.toSeq } : {},
3045
+ ...typeof ev.requestId === "string" && ev.requestId ? { requestId: ev.requestId } : {}
3046
+ };
3047
+ }
3048
+ function tombstoneRequestIds(records) {
3049
+ const ids = /* @__PURE__ */ new Set();
3050
+ for (const record of records) {
3051
+ const drop = transcriptDropOf(record.body);
3052
+ if (drop?.requestId) ids.add(drop.requestId);
3053
+ }
3054
+ return ids;
3055
+ }
3056
+ function visibleUserLocalIds(records) {
3057
+ const drops = [];
3058
+ for (const record of records) {
3059
+ const drop = transcriptDropOf(record.body);
3060
+ if (drop) drops.push({ seq: record.seq, ...drop });
3061
+ }
3062
+ const hidden = (seq) => drops.some((drop) => seq >= drop.fromSeq && seq < (drop.toSeq ?? drop.seq));
3063
+ return records.filter((record) => record.body?.role === "user" && typeof record.localId === "string" && record.localId).filter((record) => !hidden(record.seq)).map((record) => record.localId);
3064
+ }
3065
+ function transcriptLineage(lines, claudeSessionId) {
3066
+ const promptUuids = /* @__PURE__ */ new Set();
3067
+ for (const line of lines) {
3068
+ if (!line) continue;
3069
+ let parsed;
3070
+ try {
3071
+ parsed = JSON.parse(line);
3072
+ } catch {
3073
+ continue;
3074
+ }
3075
+ if (typeof parsed?.uuid === "string" && transcriptPromptText(parsed) !== null) promptUuids.add(parsed.uuid);
3076
+ }
3077
+ return { promptUuids, sourceClaudeSessionId: transcriptSourceId(lines, claudeSessionId) };
3078
+ }
3079
+ function decideLineageRepair(input) {
3080
+ if (!input.source) return { kind: "none" };
3081
+ const missing = input.visibleLocalIds.filter((id) => !input.current.promptUuids.has(id) && input.source.promptUuids.has(id));
3082
+ if (missing.length === 0) return { kind: "none" };
3083
+ const onlyInCurrent = input.visibleLocalIds.filter((id) => input.current.promptUuids.has(id) && !input.source.promptUuids.has(id));
3084
+ return { kind: "revert", to: input.source.claudeSessionId, missing, onlyInCurrent };
3085
+ }
3086
+
3087
+ const REWIND_POLL_MS = 15e3;
3088
+ class RewindReconciler {
3089
+ constructor(deps) {
3090
+ this.deps = deps;
3091
+ }
3092
+ pending = null;
3093
+ /** The last rewind this process rolled back — a late tombstone re-applies it. */
3094
+ lastReverted = null;
3095
+ confirmedIds = /* @__PURE__ */ new Set();
3096
+ waiters = [];
3097
+ timer = null;
3098
+ checking = null;
3099
+ disposed = false;
3100
+ get pendingRecord() {
3101
+ return this.pending;
3102
+ }
3103
+ /** Synchronously marks the rewind pending; the returned promise is the metadata write. */
3104
+ begin(record) {
3105
+ const next = chainRewindRecord({ ...record, state: "pending" }, this.pending);
3106
+ this.pending = next;
3107
+ this.arm(next);
3108
+ this.deps.log(`[rewind] pending ${next.requestId}: ${next.sourceClaudeSessionId} -> ${next.claudeSessionId ?? "(fresh)"}`);
3109
+ const written = this.deps.writeRecord(next);
3110
+ if (this.confirmedIds.has(next.requestId)) void this.apply(next, { kind: "confirm" });
3111
+ return written;
3112
+ }
3113
+ /** Every inbound session record. */
3114
+ observe(body) {
3115
+ const requestId = transcriptDropOf(body)?.requestId;
3116
+ if (!requestId) return;
3117
+ this.confirmedIds.add(requestId);
3118
+ const record = this.pending;
3119
+ if (record && record.requestId === requestId) {
3120
+ void this.apply(record, { kind: "confirm" });
3121
+ return;
3122
+ }
3123
+ void this.reapplyIfReverted(requestId);
3124
+ }
3125
+ /**
3126
+ * The web hides the turns only AFTER it saw our record, but its tombstone
3127
+ * may still land after the deadline (slow outbox). The log then says
3128
+ * "rewound": follow it, or screen and agent disagree again. Synchronous up
3129
+ * to the abort, so the edited prompt that follows the tombstone is not
3130
+ * dequeued by the old query.
3131
+ */
3132
+ reapplyIfReverted(requestId) {
3133
+ const reverted = this.lastReverted;
3134
+ if (this.pending || reverted?.requestId !== requestId || this.deps.currentClaudeSessionId() !== reverted.sourceClaudeSessionId) {
3135
+ return Promise.resolve();
3136
+ }
3137
+ this.lastReverted = null;
3138
+ this.deps.log(`[rewind] late tombstone for reverted ${requestId}; re-applying the rewind`);
3139
+ return this.deps.switchConversation(reverted.claudeSessionId).then(() => this.deps.writeRecord({ ...reverted, state: "confirmed" })).catch((error) => this.deps.log("[rewind] re-applying failed", error));
3140
+ }
3141
+ /** Resolves when no rewind is pending (or `signal` aborts). */
3142
+ settled(signal) {
3143
+ if (!this.pending || signal?.aborted) return Promise.resolve();
3144
+ return new Promise((resolve) => {
3145
+ const done = () => {
3146
+ signal?.removeEventListener("abort", done);
3147
+ resolve();
3148
+ };
3149
+ this.waiters.push(done);
3150
+ signal?.addEventListener("abort", done, { once: true });
3151
+ });
3152
+ }
3153
+ check() {
3154
+ if (!this.checking) {
3155
+ this.checking = this.runCheck().finally(() => {
3156
+ this.checking = null;
3157
+ });
3158
+ }
3159
+ return this.checking;
3160
+ }
3161
+ /** Wrapper start / resume: decide a leftover pending record, else repair a legacy split. */
3162
+ async startup() {
3163
+ const record = parseRewindRecord(this.deps.readRecord());
3164
+ if (record?.state === "pending") {
3165
+ this.pending = chainRewindRecord(record, this.pending);
3166
+ this.deps.log(`[rewind] startup: pending record ${record.requestId} from ${new Date(record.at).toISOString()}`);
3167
+ await this.check();
3168
+ return;
3169
+ }
3170
+ if (record?.state === "reverted") {
3171
+ this.lastReverted = record;
3172
+ if (tombstoneRequestIds(await this.deps.readLog()).has(record.requestId)) {
3173
+ await this.reapplyIfReverted(record.requestId);
3174
+ return;
3175
+ }
3176
+ }
3177
+ await this.repairLineage();
3178
+ }
3179
+ dispose() {
3180
+ this.disposed = true;
3181
+ this.clearTimer();
3182
+ this.release();
3183
+ }
3184
+ arm(record, ms) {
3185
+ if (this.disposed) return;
3186
+ if (this.timer) clearTimeout(this.timer);
3187
+ const wait = ms ?? Math.min(REWIND_POLL_MS, Math.max(0, decideWaitMs(record, this.deps.now())));
3188
+ this.timer = setTimeout(() => {
3189
+ this.timer = null;
3190
+ void this.check().catch((error) => this.deps.log("[rewind] check failed", error));
3191
+ }, wait);
3192
+ this.timer.unref?.();
3193
+ }
3194
+ async runCheck() {
3195
+ const record = this.pending;
3196
+ if (!record) return;
3197
+ let decision = this.decide(record);
3198
+ if (decision.kind !== "confirm" && decision.kind !== "none") {
3199
+ try {
3200
+ for (const id of tombstoneRequestIds(await this.deps.readLog())) this.confirmedIds.add(id);
3201
+ } catch (error) {
3202
+ this.deps.log("[rewind] reading the session log failed; retrying", error);
3203
+ if (this.pending === record) this.arm(record, REWIND_POLL_MS);
3204
+ return;
3205
+ }
3206
+ if (this.pending !== record) return;
3207
+ decision = this.decide(record);
3208
+ }
3209
+ await this.apply(record, decision);
3210
+ }
3211
+ decide(record) {
3212
+ return decideRewind(record, this.confirmedIds, this.deps.now(), this.deps.currentClaudeSessionId());
3213
+ }
3214
+ async apply(record, decision) {
3215
+ if (this.pending !== record) return;
3216
+ switch (decision.kind) {
3217
+ case "none":
3218
+ this.pending = null;
3219
+ this.release();
3220
+ return;
3221
+ case "wait":
3222
+ this.arm(record);
3223
+ return;
3224
+ case "confirm":
3225
+ this.finish(record, "confirmed");
3226
+ return;
3227
+ case "supersede":
3228
+ this.deps.log(`[rewind] ${record.requestId} unconfirmed but the agent already moved on; closing it`);
3229
+ this.finish(record, "superseded");
3230
+ return;
3231
+ case "revert": {
3232
+ this.deps.log(`[rewind] ${record.requestId} never confirmed by the log; switching back to ${decision.to}`);
3233
+ this.pending = null;
3234
+ this.clearTimer();
3235
+ this.lastReverted = record;
3236
+ try {
3237
+ await this.deps.switchConversation(decision.to);
3238
+ } catch (error) {
3239
+ this.deps.log("[rewind] switching back failed; retrying", error);
3240
+ if (!this.pending && this.lastReverted === record) {
3241
+ this.lastReverted = null;
3242
+ this.pending = record;
3243
+ this.arm(record, REWIND_POLL_MS);
3244
+ }
3245
+ return;
3246
+ }
3247
+ if (this.lastReverted === record) this.record(record, "reverted");
3248
+ if (!this.pending) this.release();
3249
+ return;
3250
+ }
3251
+ }
3252
+ }
3253
+ finish(record, state) {
3254
+ if (this.pending !== record) return;
3255
+ this.pending = null;
3256
+ this.clearTimer();
3257
+ this.lastReverted = null;
3258
+ this.record(record, state);
3259
+ this.release();
3260
+ }
3261
+ record(record, state) {
3262
+ this.deps.log(`[rewind] ${record.requestId} ${state}`);
3263
+ void this.deps.writeRecord({ ...record, state }).catch((error) => this.deps.log("[rewind] recording state failed", error));
3264
+ }
3265
+ clearTimer() {
3266
+ if (this.timer) clearTimeout(this.timer);
3267
+ this.timer = null;
3268
+ }
3269
+ release() {
3270
+ const waiters = this.waiters;
3271
+ this.waiters = [];
3272
+ for (const resolve of waiters) resolve();
3273
+ }
3274
+ async repairLineage() {
3275
+ const current = this.deps.currentClaudeSessionId();
3276
+ if (!current) return;
3277
+ const lines = await this.deps.readTranscript(current);
3278
+ if (!lines) return;
3279
+ const lineage = transcriptLineage(lines, current);
3280
+ if (!lineage.sourceClaudeSessionId) return;
3281
+ const sourceLines = await this.deps.readTranscript(lineage.sourceClaudeSessionId);
3282
+ if (!sourceLines) return;
3283
+ const source = transcriptLineage(sourceLines, lineage.sourceClaudeSessionId);
3284
+ const repair = decideLineageRepair({
3285
+ visibleLocalIds: visibleUserLocalIds(await this.deps.readLog()),
3286
+ current: lineage,
3287
+ source: { claudeSessionId: lineage.sourceClaudeSessionId, promptUuids: source.promptUuids }
3288
+ });
3289
+ if (repair.kind === "none") return;
3290
+ if (this.pending || this.deps.currentClaudeSessionId() !== current) return;
3291
+ this.deps.log(`[rewind] startup: ${current} is an unconfirmed rewound copy (${repair.missing.length} visible prompt(s) only in ${repair.to}); switching back`, {
3292
+ missing: repair.missing,
3293
+ forgottenAfterSplit: repair.onlyInCurrent
3294
+ });
3295
+ await this.deps.switchConversation(repair.to);
3296
+ }
3297
+ }
3298
+ function decideWaitMs(record, now) {
3299
+ const decision = decideRewind(record, /* @__PURE__ */ new Set(), now, record.claudeSessionId);
3300
+ return decision.kind === "wait" ? decision.ms : 0;
3301
+ }
3302
+ async function persistRewindRecord(client, record, opts = {}) {
3303
+ const owns = (raw) => {
3304
+ const existing = parseRewindRecord(raw);
3305
+ return record.state === "pending" || !existing || existing.requestId === record.requestId;
3306
+ };
3307
+ if (!owns(client.getMetadata()?.rewind)) return;
3308
+ client.updateMetadata((metadata) => owns(metadata?.rewind) ? { ...metadata, rewind: record } : metadata);
3309
+ const deadline = Date.now() + (opts.timeoutMs ?? 8e3);
3310
+ while (Date.now() < deadline) {
3311
+ const current = parseRewindRecord(client.getMetadata()?.rewind);
3312
+ if (current?.requestId === record.requestId && current.state === record.state) return;
3313
+ await new Promise((resolve) => setTimeout(resolve, opts.pollMs ?? 100));
3314
+ }
3315
+ }
3316
+
2957
3317
  const ABORT_INTERRUPT_GRACE_MS = 4e3;
3318
+ const REWIND_LOG_WINDOW = 500;
3319
+ const REWIND_STARTUP_BUDGET_MS = 15e3;
2958
3320
  async function claudeRemoteLauncher(session, onPermissionModeChange, onEffectivePermissionMode, onPromptFinalized) {
2959
3321
  logger.debug("[claudeRemoteLauncher] Starting remote launcher");
2960
3322
  const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
@@ -3056,8 +3418,35 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3056
3418
  return first;
3057
3419
  };
3058
3420
  let silentRelaunch = false;
3421
+ const agentConversationId = () => session.sessionId ?? pendingResumeId(session.claudeArgs);
3422
+ const switchConversation = async (claudeSessionId) => {
3423
+ if (claudeSessionId) session.onSessionFound(claudeSessionId);
3424
+ else session.clearSessionId();
3425
+ if (!abortController || abortController.signal.aborted) return;
3426
+ silentRelaunch = true;
3427
+ await abort();
3428
+ };
3429
+ const rewindReconciler = new RewindReconciler({
3430
+ now: Date.now,
3431
+ readRecord: () => session.client.getMetadata()?.rewind,
3432
+ writeRecord: (record) => persistRewindRecord(session.client, record),
3433
+ readLog: () => session.client.readLogTail(REWIND_LOG_WINDOW),
3434
+ currentClaudeSessionId: () => agentConversationId(),
3435
+ readTranscript: async (claudeSessionId) => {
3436
+ try {
3437
+ return (await readFile(join(getProjectPath(session.path), `${claudeSessionId}.jsonl`), "utf-8")).split("\n");
3438
+ } catch (error) {
3439
+ if (error.code === "ENOENT") return null;
3440
+ throw error;
3441
+ }
3442
+ },
3443
+ switchConversation,
3444
+ log: (message, data) => logger.debug(message, data)
3445
+ });
3446
+ const observeSessionRecord = (body) => rewindReconciler.observe(body);
3447
+ session.client.on("message", observeSessionRecord);
3059
3448
  session.client.rpcHandlerManager.registerHandler("conversation-rewind", createConversationRewind({
3060
- claudeSessionId: () => session.sessionId,
3449
+ claudeSessionId: () => agentConversationId(),
3061
3450
  projectDir: () => getProjectPath(session.path),
3062
3451
  isThinking: () => session.thinking,
3063
3452
  stopTurn: doAbort,
@@ -3066,12 +3455,8 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3066
3455
  const alias = promptAliases.get(sourceId);
3067
3456
  return alias ? [alias] : [];
3068
3457
  },
3069
- switchConversation: async (claudeSessionId) => {
3070
- if (claudeSessionId) session.onSessionFound(claudeSessionId);
3071
- else session.clearSessionId();
3072
- silentRelaunch = true;
3073
- await abort();
3074
- }
3458
+ switchConversation,
3459
+ beginPending: (record) => rewindReconciler.begin(record)
3075
3460
  }));
3076
3461
  let livePermissionModeHandler = null;
3077
3462
  let idlePermissionModeHandler = null;
@@ -3229,6 +3614,10 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3229
3614
  try {
3230
3615
  const modeGate = new LaunchModeGate(session.queue.modeHasher);
3231
3616
  let previousSessionId = null;
3617
+ await Promise.race([
3618
+ rewindReconciler.startup().catch((error) => logger.debug("[rewind] startup reconcile failed", error)),
3619
+ new Promise((resolve) => setTimeout(resolve, REWIND_STARTUP_BUDGET_MS).unref?.())
3620
+ ]);
3232
3621
  while (!exitReason) {
3233
3622
  logger.debug("[remote]: launch");
3234
3623
  messageBuffer.addMessage("\u2550".repeat(40), "status");
@@ -3285,6 +3674,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3285
3674
  if (typeof parked.message === "string") onPromptFinalized?.(parked.message);
3286
3675
  return parked;
3287
3676
  }
3677
+ await rewindReconciler.settled(controller.signal);
3288
3678
  let msg = await session.queue.waitForMessagesAndGetAsString(controller.signal);
3289
3679
  if (msg) {
3290
3680
  if (modeGate.requiresRelaunch(msg.hash, msg.isolate)) {
@@ -3477,6 +3867,8 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3477
3867
  }
3478
3868
  }
3479
3869
  } finally {
3870
+ session.client.off("message", observeSessionRecord);
3871
+ rewindReconciler.dispose();
3480
3872
  permissionHandler.reset();
3481
3873
  const t0 = Date.now();
3482
3874
  logger.debug(`[remote]: cleanup begin exitReason=${exitReason} hasInk=${!!inkInstance} rawMode=${process.stdin.isRaw}`);
@@ -3526,7 +3918,7 @@ async function loop(opts) {
3526
3918
  logger.debug(`[loop] Iteration with mode: ${mode}`);
3527
3919
  switch (mode) {
3528
3920
  case "local": {
3529
- const { claudeLocalLauncher } = await import('./claudeLocalLauncher-BFfGT4eY.mjs');
3921
+ const { claudeLocalLauncher } = await import('./claudeLocalLauncher-CKazNnl0.mjs');
3530
3922
  const result = await claudeLocalLauncher(session);
3531
3923
  switch (result.type) {
3532
3924
  case "switch":