very-happy-cli 0.2.165 → 0.2.167

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 (198) hide show
  1. package/README.md +1 -1
  2. package/dist/{AcpBackend-DCfNt9bD.cjs → AcpBackend-D1IKJGz_.cjs} +3 -3
  3. package/dist/{AcpBackend-C11FnVw5.mjs → AcpBackend-kFZlee5E.mjs} +3 -3
  4. package/dist/{AcpSessionManager-BQnDJvct.mjs → AcpSessionManager-B7FIrsys.mjs} +1 -1
  5. package/dist/{AcpSessionManager-9yN2iH4b.cjs → AcpSessionManager-Zf00QnlL.cjs} +1 -1
  6. package/dist/{BasePermissionHandler-BwQHxl6M.cjs → BasePermissionHandler-DHxYAK5L.cjs} +1 -1
  7. package/dist/{BasePermissionHandler-CwJ48yiB.mjs → BasePermissionHandler-DS0kRTNI.mjs} +1 -1
  8. package/dist/{BaseReasoningProcessor-ClF2g1qz.mjs → BaseReasoningProcessor-BRtCCt7q.mjs} +1 -1
  9. package/dist/{BaseReasoningProcessor-81lf_M8G.cjs → BaseReasoningProcessor-CsjVdt_H.cjs} +1 -1
  10. package/dist/{agentGuidance-CQuNlNx8.mjs → agentGuidance-BDYt2Qy2.mjs} +4 -2
  11. package/dist/{agentGuidance-B5NATuFa.cjs → agentGuidance-BtBx2xxE.cjs} +4 -1
  12. package/dist/{agentHome-DvR176E5.mjs → agentHome-Ct-VXFeG.mjs} +4 -4
  13. package/dist/{agentHome-D3Nn82kI.cjs → agentHome-DeAWzhSe.cjs} +4 -4
  14. package/dist/{api-AzdzTKFs.cjs → api-BZYLRDM9.cjs} +93 -13
  15. package/dist/{api-DTVPUE7g.mjs → api-CReZazeT.mjs} +93 -13
  16. package/dist/{apiMachine-B_cJldfa.cjs → apiMachine-BgMxGPsR.cjs} +2173 -66
  17. package/dist/{apiMachine-BQ-b4Lu3.mjs → apiMachine-CWndf1Vn.mjs} +2176 -69
  18. package/dist/{attachmentContent-muDCe4Gy.cjs → attachmentContent-HcJqFQW8.cjs} +2 -2
  19. package/dist/{attachmentContent-dzIs-wis.mjs → attachmentContent-j875mwU7.mjs} +2 -2
  20. package/dist/{attachmentLimits-eJZ4ZBjF.cjs → attachmentLimits-BEYEEBm8.cjs} +40 -2
  21. package/dist/{attachmentLimits-B8nzhw-i.mjs → attachmentLimits-CxG3T18E.mjs} +40 -2
  22. package/dist/{auth-Jtmvh1w4.mjs → auth-BIHuc7vY.mjs} +10 -10
  23. package/dist/{auth-BY5ujhGn.mjs → auth-CFS9Lfgv.mjs} +5 -5
  24. package/dist/{auth-DtP-B4gf.cjs → auth-Myr2Q42x.cjs} +10 -10
  25. package/dist/{auth-CfLd3phE.cjs → auth-VzWpbo5P.cjs} +5 -5
  26. package/dist/{auto-ClNnbSoF.cjs → auto-Bf6Dr7_o.cjs} +85 -21
  27. package/dist/{auto-DjWfR1UB.mjs → auto-Df9-zmuN.mjs} +84 -22
  28. package/dist/{bootstrap-D_ExGrY2.mjs → bootstrap-BSOxYpaP.mjs} +2 -2
  29. package/dist/{bootstrap-B1dMZA-u.cjs → bootstrap-Dj8WBiR2.cjs} +2 -2
  30. package/dist/{browser-mwzpOmcw.mjs → browser-BCFIHOvo.mjs} +1 -1
  31. package/dist/{browser-_gV7tcPs.cjs → browser-BoCV40yC.cjs} +1 -1
  32. package/dist/{claudeLocal-G5UmJ81F.cjs → claudeLocal-CGsq7Kul.cjs} +7 -7
  33. package/dist/{claudeLocal-BeHToEK5.mjs → claudeLocal-D5-eA9SC.mjs} +7 -7
  34. package/dist/{claudeLocalLauncher-Cq6bqAT4.mjs → claudeLocalLauncher-C9Cc438l.mjs} +15 -12
  35. package/dist/{claudeLocalLauncher-B4y2BsmO.cjs → claudeLocalLauncher-Cf9QeYDT.cjs} +15 -12
  36. package/dist/{claudeSessionFork-CDJq_b9r.cjs → claudeSessionFork-Byd8zD1U.cjs} +1 -1
  37. package/dist/{claudeSessionFork-CokUhS4r.mjs → claudeSessionFork-CMzAva8G.mjs} +1 -1
  38. package/dist/{client-Do7cGPEq.cjs → client-BKnKRLSt.cjs} +3 -3
  39. package/dist/{client-CJZKBZCE.mjs → client-C7FYMer0.mjs} +2 -2
  40. package/dist/{client-uN9d6Git.cjs → client-D0T5-6Ds.cjs} +2 -2
  41. package/dist/{client-BwaWdlCm.mjs → client-Dsfy_SAb.mjs} +3 -3
  42. package/dist/codex/happyMcpStdioBridge.cjs +23 -18
  43. package/dist/codex/happyMcpStdioBridge.mjs +22 -17
  44. package/dist/{codexAppServerClient-B0QaMQsC.mjs → codexAppServerClient-Dd_4TxHv.mjs} +48 -4
  45. package/dist/{codexAppServerClient-BuSdeUxT.cjs → codexAppServerClient-TiW9OBk4.cjs} +47 -3
  46. package/dist/{codexCommand-C3gdjMAw.mjs → codexCommand-BZSr4MKI.mjs} +170 -69
  47. package/dist/{codexCommand-YdYmykAR.cjs → codexCommand-Bxryqh90.cjs} +170 -69
  48. package/dist/{config-CGCIFRCN.mjs → config-C_Pj7yxV.mjs} +3 -3
  49. package/dist/{config-ChoHFnfO.cjs → config-DXPash-r.cjs} +3 -3
  50. package/dist/{configuration-BE61XNsg.cjs → configuration-C3piBtxY.cjs} +1 -1
  51. package/dist/{configuration-L1qcGTFM.mjs → configuration-WspKd2C2.mjs} +2 -2
  52. package/dist/{connect-D5IKfcfd.cjs → connect-BN-IBElA.cjs} +14 -14
  53. package/dist/{connect-CFD0Em6a.mjs → connect-DGPZs5px.mjs} +14 -14
  54. package/dist/{context-DaCCB4cm.mjs → context-Cr6a3NTg.mjs} +1 -1
  55. package/dist/{context-3WVw8qPz.cjs → context-Jrq4-eCZ.cjs} +1 -1
  56. package/dist/{controlClient-RWTlQA4_.cjs → controlClient-BI6Fw3fQ.cjs} +28 -5
  57. package/dist/{controlClient-Ci7HTMII.mjs → controlClient-DTheOlvC.mjs} +27 -6
  58. package/dist/{createSessionMetadata-CWR-AB2A.mjs → createSessionMetadata-BEZ4DIDA.mjs} +57 -5
  59. package/dist/{createSessionMetadata-CPGTztXP.cjs → createSessionMetadata-zQSz3hgk.cjs} +56 -3
  60. package/dist/defaultPermissionMode-Cif_RHGb.mjs +191 -0
  61. package/dist/defaultPermissionMode-DNKNzk7l.cjs +197 -0
  62. package/dist/{deterministicJson-BBwG-Ase.mjs → deterministicJson-BMMifViN.mjs} +36 -52
  63. package/dist/{deterministicJson-C4Jo2RWy.cjs → deterministicJson-C7O2ulKY.cjs} +41 -59
  64. package/dist/{doctor-ZOQLE5AH.cjs → doctor-BykBaMTr.cjs} +6 -6
  65. package/dist/{doctor-CAC6qY9Z.mjs → doctor-D1KKyPzB.mjs} +6 -6
  66. package/dist/{assistantTools-BsrG3PD-.cjs → downloadTarget-CWTb2-EM.cjs} +44 -6
  67. package/dist/{assistantTools-DPGga5lM.mjs → downloadTarget-Cp48jrIP.mjs} +45 -8
  68. package/dist/{ensureDaemonRunning-b1pvEFcS.mjs → ensureDaemonRunning-Ba5fYoxb.mjs} +5 -5
  69. package/dist/{ensureDaemonRunning-mIgX2vnc.cjs → ensureDaemonRunning-CCxX7MoP.cjs} +5 -5
  70. package/dist/{handleResumeCommand-CTGbZkCL.mjs → handleResumeCommand-BTUGlNjB.mjs} +5 -5
  71. package/dist/{handleResumeCommand-DGNhbv-3.cjs → handleResumeCommand-yPdDQHqz.cjs} +5 -5
  72. package/dist/{index-vVWpCoTr.mjs → index-B0HEEYGh.mjs} +22 -5
  73. package/dist/{index-BzIxE0Eu.cjs → index-BjhKqDa0.cjs} +3 -3
  74. package/dist/{index-BgzjPv07.mjs → index-C3_83bqS.mjs} +3 -3
  75. package/dist/{index-DqlyNgt4.cjs → index-C9hI8a10.cjs} +26 -4
  76. package/dist/{index-DjtBengz.mjs → index-CE2GgPbr.mjs} +40 -39
  77. package/dist/{index-Diu6HdWH.mjs → index-D8m8Ripb.mjs} +4 -4
  78. package/dist/{index-DrSPR59N.cjs → index-DifM62wX.cjs} +39 -38
  79. package/dist/{index-DIodyAqF.cjs → index-PNMQPKhz.cjs} +4 -4
  80. package/dist/index.cjs +2 -2
  81. package/dist/index.mjs +2 -2
  82. package/dist/{install-BO_W7VhL.mjs → install-BdvKiOQw.mjs} +2 -0
  83. package/dist/{install-Cp_aB-NQ.mjs → install-C0-QFn9s.mjs} +3 -3
  84. package/dist/{install-Cs5qAPrB.cjs → install-Cf6AFSWC.cjs} +2 -0
  85. package/dist/{install-DrUQk2DJ.cjs → install-CqZVeze8.cjs} +3 -3
  86. package/dist/lib.cjs +12 -12
  87. package/dist/lib.d.cts +116 -2
  88. package/dist/lib.d.mts +116 -2
  89. package/dist/lib.mjs +12 -12
  90. package/dist/{lidState-BLHLmhwd.mjs → lidState-B2ZxdREe.mjs} +1 -1
  91. package/dist/{lidState-z9ekRpZu.cjs → lidState-Bc2K9H9l.cjs} +1 -1
  92. package/dist/{localHappyAgentAuth-BWvmc_Hg.mjs → localHappyAgentAuth-B5XPEMwk.mjs} +1 -1
  93. package/dist/{localHappyAgentAuth-BCx0y1qW.cjs → localHappyAgentAuth-T5GOvRha.cjs} +1 -1
  94. package/dist/{logger-D0hkk7Vo.cjs → logger-B_MWPbZz.cjs} +2 -2
  95. package/dist/{logger-CknSVkIe.mjs → logger-CbBv3q_b.mjs} +2 -2
  96. package/dist/{machineMetadata-BDCYOXQg.cjs → machineMetadata-BafS4JY8.cjs} +4 -3
  97. package/dist/{machineMetadata-Cj1DoFot.mjs → machineMetadata-DHg238U4.mjs} +4 -3
  98. package/dist/{main-COAPGIso.cjs → main-DNrA0qBy.cjs} +45 -45
  99. package/dist/{main-CKUfkVG_.mjs → main-DXAK0n7x.mjs} +45 -45
  100. package/dist/{manager-BQ4flvQZ.mjs → manager-BEsI4qt3.mjs} +9 -3
  101. package/dist/{manager-Cly8xVIR.cjs → manager-HrEj442o.cjs} +8 -2
  102. package/dist/{mcp-BILnw4si.cjs → mcp-AvPOhDXy.cjs} +24 -19
  103. package/dist/{mcp-DeYUfpo8.mjs → mcp-BotAjCdD.mjs} +23 -18
  104. package/dist/mirrorProtocol-BdcN6QlN.cjs +1270 -0
  105. package/dist/mirrorProtocol-BwHm8odn.mjs +1247 -0
  106. package/dist/{package-UkmvSFsg.cjs → package-C9ZP9bpX.cjs} +7 -7
  107. package/dist/{package-VIUXrYZ1.mjs → package-DU1DxhH9.mjs} +7 -7
  108. package/dist/{peerTools-CttfOxti.cjs → peerTools-Dkbu7gag.cjs} +4 -4
  109. package/dist/{peerTools-SWITnkqz.mjs → peerTools-os2DVjA0.mjs} +4 -4
  110. package/dist/{persistence-C6ztVW1W.cjs → persistence-BYGl0QYw.cjs} +147 -25
  111. package/dist/{persistence-DujtUH94.mjs → persistence-ON0zpHfb.mjs} +123 -12
  112. package/dist/{piRunnerArgs-BVJHIjlk.mjs → piRunnerArgs-CYsnT9sV.mjs} +1 -1
  113. package/dist/{piRunnerArgs-tBQg6xDw.cjs → piRunnerArgs-DpbvstUX.cjs} +1 -1
  114. package/dist/{piRuntime-DZzjF9It.cjs → piRuntime-CDnILlCd.cjs} +1 -1
  115. package/dist/{piRuntime-DKFA8u8t.mjs → piRuntime-CmEid-wu.mjs} +1 -1
  116. package/dist/{piTerminal-BTSaFlpV.mjs → piTerminal-0eNlXSlL.mjs} +17 -17
  117. package/dist/{piTerminal-t5pQHCPT.cjs → piTerminal-B57TgMON.cjs} +17 -17
  118. package/dist/precheckCompat-CWOi5c9L.cjs +29 -0
  119. package/dist/precheckCompat-DeEbilbr.mjs +26 -0
  120. package/dist/rateLimitWindows-CusGIqlq.cjs +258 -0
  121. package/dist/rateLimitWindows-vZ9Bo7aT.mjs +248 -0
  122. package/dist/{registerCommonHandlers-BR0J4g64.mjs → registerCommonHandlers-B0PVff2U.mjs} +2 -2
  123. package/dist/{registerCommonHandlers--8ds2auE.cjs → registerCommonHandlers-DVYB3iVn.cjs} +2 -2
  124. package/dist/{registerKillSessionHandler-Czz0tdki.mjs → registerKillSessionHandler-BJMHJHXe.mjs} +15 -10
  125. package/dist/{registerKillSessionHandler-CI23l8aJ.cjs → registerKillSessionHandler-BwXGKtg_.cjs} +15 -10
  126. package/dist/{remoteSessionClient-DCAUHgPz.mjs → remoteSessionClient-BzPXSC21.mjs} +5 -5
  127. package/dist/{remoteSessionClient-BAkIwM2S.cjs → remoteSessionClient-PyUAIhwK.cjs} +5 -5
  128. package/dist/{tools-BVRoGcQH.mjs → reportProgressTool-BvB13EwC.mjs} +67 -10
  129. package/dist/{tools-mWqsE6ji.cjs → reportProgressTool-D4KB_4cP.cjs} +73 -9
  130. package/dist/{run-CkKujjn8.cjs → run-BC8jzq_h.cjs} +558 -122
  131. package/dist/{run-B75qm2I6.mjs → run-O2M8LsWf.mjs} +556 -120
  132. package/dist/{runClaude-B1T9DLLi.cjs → runClaude-C7jPa8VP.cjs} +93 -26
  133. package/dist/{runClaude-aBfBweec.mjs → runClaude-DGkr5E7s.mjs} +93 -26
  134. package/dist/{runClaudeDeps-BGjNGfuZ.cjs → runClaudeDeps-5kzncqME.cjs} +113 -35
  135. package/dist/{runClaudeDeps-BOrPP4J1.mjs → runClaudeDeps-CX_TxS78.mjs} +116 -37
  136. package/dist/{runGemini-BuAA_OQb.cjs → runGemini-BfYA4Uqc.cjs} +43 -36
  137. package/dist/{runGemini-a-V7JE-J.mjs → runGemini-CwmGBH3L.mjs} +43 -36
  138. package/dist/{runOpenClaw-DUSwXg1A.mjs → runOpenClaw-BYAPYFyL.mjs} +18 -18
  139. package/dist/{runOpenClaw-BBVffIh9.cjs → runOpenClaw-C72jut7v.cjs} +18 -18
  140. package/dist/{sandbox-Fd2G5yaq.cjs → sandbox-Bqkp8IT7.cjs} +4 -4
  141. package/dist/{sandbox-Brb_5wzc.mjs → sandbox-DlVnK1Vi.mjs} +4 -4
  142. package/dist/{selfCheck-NuJKMInJ.cjs → selfCheck-B4lLZplk.cjs} +34 -34
  143. package/dist/selfCheck-DYTGBdIO.mjs +84 -0
  144. package/dist/{send-DEQJiq_x.mjs → send-B5bWW9Tl.mjs} +8 -8
  145. package/dist/{send-4dgHKC3u.cjs → send-BCwS6n_s.cjs} +8 -8
  146. package/dist/{server-C6AlUFkw.mjs → server-CEJfRQfj.mjs} +4 -4
  147. package/dist/{server-DWGcDmHG.cjs → server-CFWZehnC.cjs} +6 -6
  148. package/dist/{sessionLock-Dm8QyGo4.mjs → sessionLock-AwOYsKT7.mjs} +12 -4
  149. package/dist/{sessionLock-B1GgaO1q.cjs → sessionLock-LBWNjpHf.cjs} +12 -3
  150. package/dist/{sessionModeFile-BvOEJ4Fl.cjs → sessionModeFile-CyPuZRIU.cjs} +1 -1
  151. package/dist/{sessionModeFile-CuNAWCKL.mjs → sessionModeFile-fvFn1JVG.mjs} +1 -1
  152. package/dist/{sessionOps-DG5MMEp_.mjs → sessionOps-DZRH4-hV.mjs} +4 -4
  153. package/dist/{sessionOps-JP64uJmc.cjs → sessionOps-DzbZI3Eq.cjs} +4 -4
  154. package/dist/{sessionScanner-DqSk5Ol_.mjs → sessionScanner-Q_Ei2flB.mjs} +75 -19
  155. package/dist/{sessionScanner-BBPEgJ5S.cjs → sessionScanner-i-cgwFVw.cjs} +75 -19
  156. package/dist/{sessions-4isbBAWi.mjs → sessions-DAmjMAZN.mjs} +9 -9
  157. package/dist/{sessions-DgJuw_i0.cjs → sessions-DYK5hD4T.cjs} +9 -9
  158. package/dist/{setupOfflineReconnection-_MoZtsro.mjs → setupOfflineReconnection-BfDBxNdo.mjs} +2 -2
  159. package/dist/{setupOfflineReconnection-CKJKVIUS.cjs → setupOfflineReconnection-C2LO3hSP.cjs} +2 -2
  160. package/dist/{spawn-BTOG4tTm.mjs → spawn-BmjG5j5Y.mjs} +15 -14
  161. package/dist/{spawn-CshERWbY.cjs → spawn-GK_sXE8h.cjs} +15 -14
  162. package/dist/{spawnAgents-Czi2VDzj.mjs → spawnAgents-HDaE3C0-.mjs} +1 -1
  163. package/dist/{spawnAgents-McixdtV1.cjs → spawnAgents-vglexX9N.cjs} +1 -1
  164. package/dist/{spawnHappyCLI-Dc4xYm8P.mjs → spawnHappyCLI-B2h0P4b5.mjs} +1 -1
  165. package/dist/{spawnHappyCLI-Dd5_8Vex.cjs → spawnHappyCLI-J4iEhfyZ.cjs} +1 -1
  166. package/dist/specialCommands-DisVxagO.mjs +93 -0
  167. package/dist/specialCommands-DmJMKspE.cjs +96 -0
  168. package/dist/{startFileWatcher-B0VlG-Fn.mjs → startFileWatcher-CeK1k5gt.mjs} +1 -1
  169. package/dist/{startFileWatcher-1LedLBY-.cjs → startFileWatcher-xKo8AoYl.cjs} +1 -1
  170. package/dist/{streamRelay-C0AffuX6.cjs → streamRelay-Ce9sgcOV.cjs} +1 -1
  171. package/dist/{streamRelay-BzMEEvJU.mjs → streamRelay-Iogsh51a.mjs} +1 -1
  172. package/dist/{sync-DwUUGGFz.cjs → sync-Bvc-vh6C.cjs} +1 -1
  173. package/dist/{sync-Dfm6K2te.mjs → sync-CCwYpJMS.mjs} +1 -1
  174. package/dist/{systemPrompt-D41Zw1a3.mjs → systemPrompt-BNIkP3tR.mjs} +3 -3
  175. package/dist/{systemPrompt-CB1Ls0AE.cjs → systemPrompt-DwOddbuG.cjs} +3 -3
  176. package/dist/{teams-D8Ly3i6u.mjs → teams-DRrLBcys.mjs} +7 -7
  177. package/dist/{teams-NWv2ji16.cjs → teams-GHMCRZOw.cjs} +7 -7
  178. package/dist/{time-BbzJ7PJQ.cjs → time-BXvtjhe9.cjs} +1 -1
  179. package/dist/{time-v1Y_qEJp.mjs → time-PG5Dfwdv.mjs} +1 -1
  180. package/dist/{titleGenerator-cH6IkPRi.cjs → titleGenerator-B07bZA0V.cjs} +2 -2
  181. package/dist/{titleGenerator-BhoblAQY.mjs → titleGenerator-CIzfpfZW.mjs} +1 -1
  182. package/dist/{todo-D1hgWV6d.cjs → todo-B0aeoNu3.cjs} +6 -6
  183. package/dist/{todo-CuNct-fw.mjs → todo-CfL7SBFc.mjs} +6 -6
  184. package/dist/{tools-jof0Bu54.mjs → tools-D91mq5Ib.mjs} +1 -1
  185. package/dist/{tools-c2fb0CF5.cjs → tools-DJIANHSh.cjs} +1 -1
  186. package/dist/transcriptCursor-B7T_gkQ0.mjs +102 -0
  187. package/dist/transcriptCursor-DcXGLeSc.cjs +106 -0
  188. package/dist/{uninstall-BB7WYYAk.mjs → uninstall-5xz3Xvhf.mjs} +3 -3
  189. package/dist/{uninstall-VPH5GfrA.cjs → uninstall-AtzOfdrj.cjs} +3 -3
  190. package/package.json +7 -7
  191. package/scripts/terminal_status_forwarder.cjs +89 -0
  192. package/dist/defaultPermissionMode-BnxJPVHT.mjs +0 -4
  193. package/dist/defaultPermissionMode-CxmTXUQR.cjs +0 -7
  194. package/dist/mirrorProtocol-BNLtoWjO.mjs +0 -170
  195. package/dist/mirrorProtocol-BUtmg1ws.cjs +0 -186
  196. package/dist/selfCheck-BgwJ3NGS.mjs +0 -84
  197. package/dist/specialCommands-BSqhYg5X.mjs +0 -52
  198. package/dist/specialCommands-DSsTeRej.cjs +0 -54
@@ -1,58 +1,59 @@
1
1
  'use strict';
2
2
 
3
3
  var os = require('node:os');
4
- var sessionLock = require('./sessionLock-B1GgaO1q.cjs');
4
+ var sessionLock = require('./sessionLock-LBWNjpHf.cjs');
5
+ var persistence = require('./persistence-BYGl0QYw.cjs');
6
+ var defaultPermissionMode = require('./defaultPermissionMode-DNKNzk7l.cjs');
5
7
  var node_crypto = require('node:crypto');
6
- var api = require('./api-AzdzTKFs.cjs');
7
- var logger = require('./logger-D0hkk7Vo.cjs');
8
- var _package = require('./package-UkmvSFsg.cjs');
9
- var persistence = require('./persistence-C6ztVW1W.cjs');
10
- var createSessionMetadata = require('./createSessionMetadata-CPGTztXP.cjs');
11
- var index = require('./index-DqlyNgt4.cjs');
8
+ var api = require('./api-BZYLRDM9.cjs');
9
+ var logger = require('./logger-B_MWPbZz.cjs');
10
+ var createSessionMetadata = require('./createSessionMetadata-zQSz3hgk.cjs');
11
+ var _package = require('./package-C9ZP9bpX.cjs');
12
+ var index = require('./index-C9hI8a10.cjs');
12
13
  var forkBackfill = require('./forkBackfill-8eLDeS73.cjs');
13
- var configuration = require('./configuration-BE61XNsg.cjs');
14
- var controlClient = require('./controlClient-RWTlQA4_.cjs');
15
- var machineMetadata = require('./machineMetadata-BDCYOXQg.cjs');
14
+ var configuration = require('./configuration-C3piBtxY.cjs');
15
+ var controlClient = require('./controlClient-BI6Fw3fQ.cjs');
16
+ var machineMetadata = require('./machineMetadata-BafS4JY8.cjs');
16
17
  var projectPath = require('./projectPath-ChLhdOyt.cjs');
17
18
  var path = require('node:path');
18
19
  var permissionMode = require('./permissionMode-CrV-XuMs.cjs');
19
20
  var authRelay = require('./authRelay-BdYkC1Po.cjs');
20
21
  var promises = require('node:fs/promises');
21
- var defaultPermissionMode = require('./defaultPermissionMode-CxmTXUQR.cjs');
22
- var attachmentContent = require('./attachmentContent-muDCe4Gy.cjs');
22
+ var attachmentContent = require('./attachmentContent-HcJqFQW8.cjs');
23
+ var transcriptCursor = require('./transcriptCursor-DcXGLeSc.cjs');
23
24
  var startupPlan = require('./startupPlan-BLMbfQIH.cjs');
24
25
  require('node:fs');
26
+ require('zod');
25
27
  require('axios');
26
- require('./lidState-z9ekRpZu.cjs');
28
+ require('./lidState-Bc2K9H9l.cjs');
27
29
  require('os');
28
30
  require('child_process');
29
31
  require('node:events');
30
32
  require('socket.io-client');
31
- require('./attachmentLimits-eJZ4ZBjF.cjs');
32
- require('zod');
33
+ require('./attachmentLimits-BEYEEBm8.cjs');
33
34
  require('./limits-C-a7gr04.cjs');
34
- require('./time-BbzJ7PJQ.cjs');
35
- require('./registerCommonHandlers--8ds2auE.cjs');
35
+ require('./time-BXvtjhe9.cjs');
36
+ require('./registerCommonHandlers-DVYB3iVn.cjs');
36
37
  require('util');
37
38
  require('fs/promises');
38
39
  require('crypto');
39
40
  require('path');
40
41
  require('cross-spawn');
41
42
  require('@paralleldrive/cuid2');
42
- require('./sync-DwUUGGFz.cjs');
43
+ require('./sync-Bvc-vh6C.cjs');
43
44
  require('./backgroundTaskActivity-CBvUdj39.cjs');
44
45
  require('./contentLogMetadata-ZSFk_NjQ.cjs');
45
46
  require('chalk');
46
47
  require('node:util');
47
48
  require('./detectCLI-DR9ZaN6B.cjs');
48
49
  require('fs');
49
- require('./localHappyAgentAuth-BCx0y1qW.cjs');
50
+ require('./localHappyAgentAuth-T5GOvRha.cjs');
50
51
  require('tweetnacl');
51
52
  require('url');
52
53
 
53
54
  const DEFAULT_CLAUDE_MODEL = void 0;
54
55
  const DEFAULT_CLAUDE_EFFORT = void 0;
55
- const importRunClaudeDeps = () => Promise.resolve().then(function () { return require('./runClaudeDeps-BGjNGfuZ.cjs'); });
56
+ const importRunClaudeDeps = () => Promise.resolve().then(function () { return require('./runClaudeDeps-5kzncqME.cjs'); });
56
57
  async function runClaude(credentials, options = {}) {
57
58
  logger.logger.debug(`[CLAUDE] ===== CLAUDE MODE STARTING =====`);
58
59
  logger.logger.debug(`[CLAUDE] This is the Claude agent, NOT Gemini`);
@@ -66,7 +67,7 @@ async function runClaude(credentials, options = {}) {
66
67
  const isAssistantVariant = process.env.HAPPY_SESSION_VARIANT === "assistant";
67
68
  if (isAssistantVariant) {
68
69
  try {
69
- const { bootstrapAssistantHome } = await Promise.resolve().then(function () { return require('./bootstrap-B1dMZA-u.cjs'); });
70
+ const { bootstrapAssistantHome } = await Promise.resolve().then(function () { return require('./bootstrap-Dj8WBiR2.cjs'); });
70
71
  await bootstrapAssistantHome();
71
72
  } catch (error) {
72
73
  logger.logger.debug("[START] Assistant home bootstrap failed:", error);
@@ -141,7 +142,7 @@ async function runClaude(credentials, options = {}) {
141
142
  // a brand-new session cannot pick a PDF until after sending once.
142
143
  attachmentKinds: [...attachmentContent.CLAUDE_ATTACHMENT_KINDS],
143
144
  queueCancellation: true,
144
- capabilities: ["claude-steer-v1", "claude-live-permission-v1", "claude-live-permission-v2", "claude-btw-v1", "claude-runtime-controls-v1", "claude-opus-5-5-v1", index.PROMPT_QUEUE_CAPABILITY, forkBackfill.FORK_BACKFILL_CAPABILITY],
145
+ capabilities: ["claude-steer-v1", "claude-live-permission-v1", "claude-live-permission-v2", "claude-btw-v1", "claude-runtime-controls-v1", "claude-opus-5-5-v1", index.PROMPT_QUEUE_CAPABILITY, forkBackfill.FORK_BACKFILL_CAPABILITY, persistence.HIBERNATION_CAPABILITY],
145
146
  // Effective mode this process enforces. Kept current by
146
147
  // publishPermissionMode below; the web renders it instead of guessing.
147
148
  permissionMode: permissionMode.mapToClaudeMode(initialPermissionMode ?? "default"),
@@ -158,7 +159,9 @@ async function runClaude(credentials, options = {}) {
158
159
  // itself — that one is the variant above and never joins the lists at
159
160
  // all. (Shared helper: the other flavors get the same tag via
160
161
  // createSessionMetadata.)
161
- ...originTags ? { tags: originTags } : {}
162
+ ...originTags ? { tags: originTags } : {},
163
+ // B-586: linked git worktree → branch shown in the session list.
164
+ ...createSessionMetadata.sessionWorktreeMetadata(workingDirectory)
162
165
  };
163
166
  const reconnectSessionId = process.env.HAPPY_RECONNECT_SESSION_ID;
164
167
  const reconnectKeyBase64 = process.env.HAPPY_RECONNECT_ENCRYPTION_KEY;
@@ -184,7 +187,7 @@ async function runClaude(credentials, options = {}) {
184
187
  }
185
188
  if (!response) {
186
189
  let offlineSessionId = null;
187
- const { claudeLocal } = await Promise.resolve().then(function () { return require('./claudeLocal-G5UmJ81F.cjs'); });
190
+ const { claudeLocal } = await Promise.resolve().then(function () { return require('./claudeLocal-CGsq7Kul.cjs'); });
188
191
  const { createSessionScanner: createSessionScanner2 } = await loadDeps();
189
192
  const reconnection = api.startOfflineReconnection({
190
193
  serverUrl: configuration.configuration.serverUrl,
@@ -231,12 +234,17 @@ async function runClaude(credentials, options = {}) {
231
234
  throw new Error(`Failed to reactivate archived session ${response.id}`);
232
235
  }
233
236
  let reconnectSeeded = false;
237
+ let wakingFromHibernation = false;
234
238
  if (reconnectSessionId) {
235
239
  const snapshot = await api$1.getSession(response.id, response.encryptionKey, response.encryptionVariant);
236
240
  if (snapshot.ok) {
237
241
  response = sessionLock.applyServerSnapshot(response, snapshot.session);
238
242
  reconnectSeeded = true;
239
243
  logger.logger.debug(`[START] Reconnect seeded from server: seq=${snapshot.session.seq} metadataVersion=${snapshot.session.metadataVersion}`);
244
+ const wake = sessionLock.applyHibernationReplay(response);
245
+ response = wake.response;
246
+ wakingFromHibernation = wake.replaying;
247
+ if (wake.replaying) logger.logger.debug(`[START] Waking from hibernation: replaying records after seq=${response.seq}`);
240
248
  } else {
241
249
  response = sessionLock.withoutServerSnapshot(response);
242
250
  logger.logger.debug(`[START] Reconnect without server snapshot (${snapshot.reason}); skipping existing messages`);
@@ -328,7 +336,7 @@ async function runClaude(credentials, options = {}) {
328
336
  if (reconnectSessionId) {
329
337
  session.suppressNextArchiveSignal();
330
338
  if (!reconnectSeeded) session.skipExistingMessages();
331
- void session.cancelUndeliveredQueuedInputs();
339
+ if (!wakingFromHibernation) void session.cancelUndeliveredQueuedInputs();
332
340
  session.updateMetadata((meta) => ({
333
341
  ...sessionLock.mergeReconnectMetadata(meta, metadata, Date.now()),
334
342
  queueCancellation: true,
@@ -423,9 +431,11 @@ async function runClaude(credentials, options = {}) {
423
431
  });
424
432
  options = { ...options, claudeEnvVars: { ...options.claudeEnvVars, VH_PEER_SESSION_ID: response.id } };
425
433
  const initialScannerSessionId = forkClaudeSessionId ?? (metadata.claudeSessionId ?? null);
434
+ const transcriptPathHints = new transcriptCursor.TranscriptPathHints();
426
435
  const remoteScanner = await createSessionScanner({
427
436
  sessionId: initialScannerSessionId,
428
437
  workingDirectory,
438
+ transcriptPathHints,
429
439
  onMessage: (raw) => {
430
440
  if (currentRunMode !== "remote") return;
431
441
  if (raw.type !== "user") return;
@@ -456,6 +466,7 @@ async function runClaude(credentials, options = {}) {
456
466
  return;
457
467
  }
458
468
  logger.logger.debug(`[START] Session hook received: ${sessionId}`, contentLogMetadata(data));
469
+ transcriptPathHints.note(sessionId, data.transcript_path);
459
470
  announceSessionToScanner(sessionId);
460
471
  if (currentSession) {
461
472
  const previousSessionId = currentSession.sessionId;
@@ -777,12 +788,14 @@ async function runClaude(credentials, options = {}) {
777
788
  });
778
789
  });
779
790
  const exitGate = new SessionExitGate();
791
+ let hibernationProbe = null;
780
792
  const cleanup = async (opts = { archive: true }) => {
781
- const intent = exitGate.claim(exitIntentFromArchiveFlag(opts.archive));
793
+ const intent = opts.hibernation ? "hibernate" : exitGate.claim(exitIntentFromArchiveFlag(opts.archive));
782
794
  if (intent === null) {
783
795
  logger.logger.debug(`[START] Termination (archive=${opts.archive ?? true}) ignored: cleanup already running as ${exitGate.current}`);
784
796
  return;
785
797
  }
798
+ hibernationProbe?.stop();
786
799
  logger.logger.debug(`[START] Received termination signal, cleaning up (archive=${intent === "archive"})...`);
787
800
  promptQueueDrain.close();
788
801
  cleanupPrewarm();
@@ -791,6 +804,7 @@ async function runClaude(credentials, options = {}) {
791
804
  currentSession?.cleanup();
792
805
  await settleSessionOnExit(session.sessionId, intent, {
793
806
  updateMetadata: (handler) => session.updateMetadata(handler),
807
+ updateMetadataAndWait: (handler) => session.updateMetadataAndWait(handler),
794
808
  sendSessionDeath: () => session.sendSessionDeath(),
795
809
  archiveSession: (id) => api$1.archiveSession(id),
796
810
  deactivateSession: (id) => api$1.deactivateSession(id),
@@ -833,6 +847,58 @@ async function runClaude(credentials, options = {}) {
833
847
  void cleanup({ archive: true });
834
848
  });
835
849
  registerKillSessionHandler(session.rpcHandlerManager, () => cleanup({ archive: true }), session);
850
+ let keepAwakeLatch = false;
851
+ const hibernationSnapshot = () => {
852
+ const agentState = session.getAgentState();
853
+ const current = currentSession;
854
+ const meta = session.getMetadata();
855
+ return {
856
+ flavor: "claude",
857
+ resumable: typeof meta?.claudeSessionId === "string" && meta.claudeSessionId.length > 0,
858
+ uiSession: options.startedBy === "daemon" && options.startingMode === "remote" && agentState?.controlledByUser !== true,
859
+ ...isAssistantVariant ? { variant: "assistant" } : {},
860
+ ...process.env.HAPPY_SPAWNED_BY ? { spawnedBy: process.env.HAPPY_SPAWNED_BY } : {},
861
+ ...meta?.tags ? { tags: meta.tags } : {},
862
+ keepAwake: keepAwakeLatch = persistence.latchKeepAwake(meta?.keepAwake, keepAwakeLatch),
863
+ ...typeof meta?.keepAwake === "boolean" ? { keepAwakeSetting: meta.keepAwake } : {},
864
+ thinking: current?.thinking === true,
865
+ queuedInputs: messageQueue.size() + (session.promptQueueHasPending() ? 1 : 0),
866
+ waitingForInput: messageQueue.isWaiting(),
867
+ pendingRequests: Object.keys(agentState?.requests ?? {}).length,
868
+ backgroundTasks: current?.backgroundTasks.length ?? 0,
869
+ scheduledWakeups: current?.scheduledWakeups.pending() ?? 0,
870
+ lastActivityAt: session.lastActivityAt,
871
+ ...exitGate.current && exitGate.current !== "hibernate" ? { exiting: true } : {}
872
+ };
873
+ };
874
+ if (options.startedBy === "daemon" && options.startingMode === "remote" && !isAssistantVariant) {
875
+ hibernationProbe = new defaultPermissionMode.HibernationProbe({
876
+ checkMs: persistence.resolveCheckMs(),
877
+ snapshot: hibernationSnapshot,
878
+ ask: (report) => controlClient.checkDaemonHibernation({ sessionId: session.sessionId, pid: process.pid, report }),
879
+ commit: (idleMs) => defaultPermissionMode.commitHibernation({
880
+ client: session,
881
+ claimExit: () => exitGate.claim("hibernate") !== null,
882
+ exitRequested: () => exitGate.exitRequested,
883
+ markCommitted: () => exitGate.commitHibernate(),
884
+ // Review P1-1: an archive / kill / SIGTERM deferred during the
885
+ // commit window runs now instead of being lost.
886
+ releaseExit: () => {
887
+ const deferred = exitGate.release("hibernate");
888
+ if (deferred) void cleanup({ archive: deferred === "archive" });
889
+ },
890
+ recheck: () => persistence.evaluateWrapperIdle(hibernationSnapshot(), idleMs, Date.now()),
891
+ idleMs,
892
+ finish: (stamp) => cleanup({ archive: false, hibernation: stamp })
893
+ }),
894
+ // Review P3-3: the daemon still holds keep-awake but an old web
895
+ // stripped the field — put it back so every web shows it checked.
896
+ onKeepAwakeLatched: () => {
897
+ if (session.getMetadata()?.keepAwake === void 0) session.updateMetadata((m) => m.keepAwake === void 0 ? { ...m, keepAwake: true } : m);
898
+ }
899
+ });
900
+ hibernationProbe.start();
901
+ }
836
902
  const exitCode = await loop({
837
903
  path: workingDirectory,
838
904
  model: options.model,
@@ -851,6 +917,7 @@ async function runClaude(credentials, options = {}) {
851
917
  },
852
918
  onSessionReady: (sessionInstance) => {
853
919
  currentSession = sessionInstance;
920
+ sessionInstance.transcriptPathHints = transcriptPathHints;
854
921
  sessionInstance.addSessionFoundCallback?.(announceSessionToScanner);
855
922
  },
856
923
  // B-515: lease for a warm Claude process, taken once by the first
@@ -1,56 +1,57 @@
1
1
  import os from 'node:os';
2
- import { c as claimSessionOrExit, a as applyServerSnapshot, w as withoutServerSnapshot, m as mergeReconnectMetadata } from './sessionLock-Dm8QyGo4.mjs';
2
+ import { c as claimSessionOrExit, a as applyServerSnapshot, b as applyHibernationReplay, w as withoutServerSnapshot, m as mergeReconnectMetadata } from './sessionLock-AwOYsKT7.mjs';
3
+ import { r as readSettings, H as HIBERNATION_CAPABILITY, a as resolveCheckMs, l as latchKeepAwake, e as evaluateWrapperIdle } from './persistence-ON0zpHfb.mjs';
4
+ import { D as DEFAULT_CLAUDE_PERMISSION_MODE, H as HibernationProbe, c as commitHibernation } from './defaultPermissionMode-Cif_RHGb.mjs';
3
5
  import { randomUUID } from 'node:crypto';
4
- import { c as connectionState, A as ApiClient, s as startOfflineReconnection } from './api-DTVPUE7g.mjs';
5
- import { l as logger } from './logger-CknSVkIe.mjs';
6
- import { p as packageJson } from './package-VIUXrYZ1.mjs';
7
- import { readSettings } from './persistence-DujtUH94.mjs';
8
- import { s as spawnOriginTags } from './createSessionMetadata-CWR-AB2A.mjs';
9
- import { P as PROMPT_QUEUE_CAPABILITY } from './index-vVWpCoTr.mjs';
6
+ import { c as connectionState, A as ApiClient, s as startOfflineReconnection } from './api-CReZazeT.mjs';
7
+ import { l as logger } from './logger-CbBv3q_b.mjs';
8
+ import { s as spawnOriginTags, a as sessionWorktreeMetadata } from './createSessionMetadata-BEZ4DIDA.mjs';
9
+ import { p as packageJson } from './package-DU1DxhH9.mjs';
10
+ import { P as PROMPT_QUEUE_CAPABILITY } from './index-B0HEEYGh.mjs';
10
11
  import { F as FORK_BACKFILL_CAPABILITY, p as publishForkBackfillWhenCommitted } from './forkBackfill-DYIjlN1Z.mjs';
11
- import { c as configuration } from './configuration-L1qcGTFM.mjs';
12
- import { n as notifyDaemonSessionStarted } from './controlClient-Ci7HTMII.mjs';
13
- import { g as getInitialMachineMetadata } from './machineMetadata-Cj1DoFot.mjs';
12
+ import { c as configuration } from './configuration-WspKd2C2.mjs';
13
+ import { n as notifyDaemonSessionStarted, c as checkDaemonHibernation } from './controlClient-DTheOlvC.mjs';
14
+ import { g as getInitialMachineMetadata } from './machineMetadata-DHg238U4.mjs';
14
15
  import { p as projectPath } from './projectPath-BTBIMB57.mjs';
15
16
  import { resolve, join } from 'node:path';
16
17
  import { a as applySandboxPermissionPolicy, r as resolveInitialClaudePermissionMode, m as mapToClaudeMode, b as reconcilePublishedPermissionMode } from './permissionMode-CH4FoZfU.mjs';
17
18
  import { d as decodeBase64, e as encodeBase64 } from './authRelay-DSAvg1uv.mjs';
18
19
  import { readFile } from 'node:fs/promises';
19
- import { D as DEFAULT_CLAUDE_PERMISSION_MODE } from './defaultPermissionMode-BnxJPVHT.mjs';
20
- import { C as CLAUDE_ATTACHMENT_KINDS, s as stripAttachmentManifest } from './attachmentContent-dzIs-wis.mjs';
20
+ import { C as CLAUDE_ATTACHMENT_KINDS, s as stripAttachmentManifest } from './attachmentContent-j875mwU7.mjs';
21
+ import { T as TranscriptPathHints } from './transcriptCursor-B7T_gkQ0.mjs';
21
22
  import { p as planClaudeStartup } from './startupPlan-DFMyNgAs.mjs';
22
23
  import 'node:fs';
24
+ import 'zod';
23
25
  import 'axios';
24
- import './lidState-BLHLmhwd.mjs';
26
+ import './lidState-B2ZxdREe.mjs';
25
27
  import 'os';
26
28
  import 'child_process';
27
29
  import 'node:events';
28
30
  import 'socket.io-client';
29
- import './attachmentLimits-B8nzhw-i.mjs';
30
- import 'zod';
31
+ import './attachmentLimits-CxG3T18E.mjs';
31
32
  import './limits-DIo7rEBR.mjs';
32
- import './time-v1Y_qEJp.mjs';
33
- import './registerCommonHandlers-BR0J4g64.mjs';
33
+ import './time-PG5Dfwdv.mjs';
34
+ import './registerCommonHandlers-B0PVff2U.mjs';
34
35
  import 'util';
35
36
  import 'fs/promises';
36
37
  import 'crypto';
37
38
  import 'path';
38
39
  import 'cross-spawn';
39
40
  import '@paralleldrive/cuid2';
40
- import './sync-Dfm6K2te.mjs';
41
+ import './sync-CCwYpJMS.mjs';
41
42
  import './backgroundTaskActivity-8PdPxrvy.mjs';
42
43
  import './contentLogMetadata-BlWI0egu.mjs';
43
44
  import 'chalk';
44
45
  import 'node:util';
45
46
  import './detectCLI-CSGMlV51.mjs';
46
47
  import 'fs';
47
- import './localHappyAgentAuth-BWvmc_Hg.mjs';
48
+ import './localHappyAgentAuth-B5XPEMwk.mjs';
48
49
  import 'tweetnacl';
49
50
  import 'url';
50
51
 
51
52
  const DEFAULT_CLAUDE_MODEL = void 0;
52
53
  const DEFAULT_CLAUDE_EFFORT = void 0;
53
- const importRunClaudeDeps = () => import('./runClaudeDeps-BOrPP4J1.mjs');
54
+ const importRunClaudeDeps = () => import('./runClaudeDeps-CX_TxS78.mjs');
54
55
  async function runClaude(credentials, options = {}) {
55
56
  logger.debug(`[CLAUDE] ===== CLAUDE MODE STARTING =====`);
56
57
  logger.debug(`[CLAUDE] This is the Claude agent, NOT Gemini`);
@@ -64,7 +65,7 @@ async function runClaude(credentials, options = {}) {
64
65
  const isAssistantVariant = process.env.HAPPY_SESSION_VARIANT === "assistant";
65
66
  if (isAssistantVariant) {
66
67
  try {
67
- const { bootstrapAssistantHome } = await import('./bootstrap-D_ExGrY2.mjs');
68
+ const { bootstrapAssistantHome } = await import('./bootstrap-BSOxYpaP.mjs');
68
69
  await bootstrapAssistantHome();
69
70
  } catch (error) {
70
71
  logger.debug("[START] Assistant home bootstrap failed:", error);
@@ -139,7 +140,7 @@ async function runClaude(credentials, options = {}) {
139
140
  // a brand-new session cannot pick a PDF until after sending once.
140
141
  attachmentKinds: [...CLAUDE_ATTACHMENT_KINDS],
141
142
  queueCancellation: true,
142
- capabilities: ["claude-steer-v1", "claude-live-permission-v1", "claude-live-permission-v2", "claude-btw-v1", "claude-runtime-controls-v1", "claude-opus-5-5-v1", PROMPT_QUEUE_CAPABILITY, FORK_BACKFILL_CAPABILITY],
143
+ capabilities: ["claude-steer-v1", "claude-live-permission-v1", "claude-live-permission-v2", "claude-btw-v1", "claude-runtime-controls-v1", "claude-opus-5-5-v1", PROMPT_QUEUE_CAPABILITY, FORK_BACKFILL_CAPABILITY, HIBERNATION_CAPABILITY],
143
144
  // Effective mode this process enforces. Kept current by
144
145
  // publishPermissionMode below; the web renders it instead of guessing.
145
146
  permissionMode: mapToClaudeMode(initialPermissionMode ?? "default"),
@@ -156,7 +157,9 @@ async function runClaude(credentials, options = {}) {
156
157
  // itself — that one is the variant above and never joins the lists at
157
158
  // all. (Shared helper: the other flavors get the same tag via
158
159
  // createSessionMetadata.)
159
- ...originTags ? { tags: originTags } : {}
160
+ ...originTags ? { tags: originTags } : {},
161
+ // B-586: linked git worktree → branch shown in the session list.
162
+ ...sessionWorktreeMetadata(workingDirectory)
160
163
  };
161
164
  const reconnectSessionId = process.env.HAPPY_RECONNECT_SESSION_ID;
162
165
  const reconnectKeyBase64 = process.env.HAPPY_RECONNECT_ENCRYPTION_KEY;
@@ -182,7 +185,7 @@ async function runClaude(credentials, options = {}) {
182
185
  }
183
186
  if (!response) {
184
187
  let offlineSessionId = null;
185
- const { claudeLocal } = await import('./claudeLocal-BeHToEK5.mjs');
188
+ const { claudeLocal } = await import('./claudeLocal-D5-eA9SC.mjs');
186
189
  const { createSessionScanner: createSessionScanner2 } = await loadDeps();
187
190
  const reconnection = startOfflineReconnection({
188
191
  serverUrl: configuration.serverUrl,
@@ -229,12 +232,17 @@ async function runClaude(credentials, options = {}) {
229
232
  throw new Error(`Failed to reactivate archived session ${response.id}`);
230
233
  }
231
234
  let reconnectSeeded = false;
235
+ let wakingFromHibernation = false;
232
236
  if (reconnectSessionId) {
233
237
  const snapshot = await api.getSession(response.id, response.encryptionKey, response.encryptionVariant);
234
238
  if (snapshot.ok) {
235
239
  response = applyServerSnapshot(response, snapshot.session);
236
240
  reconnectSeeded = true;
237
241
  logger.debug(`[START] Reconnect seeded from server: seq=${snapshot.session.seq} metadataVersion=${snapshot.session.metadataVersion}`);
242
+ const wake = applyHibernationReplay(response);
243
+ response = wake.response;
244
+ wakingFromHibernation = wake.replaying;
245
+ if (wake.replaying) logger.debug(`[START] Waking from hibernation: replaying records after seq=${response.seq}`);
238
246
  } else {
239
247
  response = withoutServerSnapshot(response);
240
248
  logger.debug(`[START] Reconnect without server snapshot (${snapshot.reason}); skipping existing messages`);
@@ -326,7 +334,7 @@ async function runClaude(credentials, options = {}) {
326
334
  if (reconnectSessionId) {
327
335
  session.suppressNextArchiveSignal();
328
336
  if (!reconnectSeeded) session.skipExistingMessages();
329
- void session.cancelUndeliveredQueuedInputs();
337
+ if (!wakingFromHibernation) void session.cancelUndeliveredQueuedInputs();
330
338
  session.updateMetadata((meta) => ({
331
339
  ...mergeReconnectMetadata(meta, metadata, Date.now()),
332
340
  queueCancellation: true,
@@ -421,9 +429,11 @@ async function runClaude(credentials, options = {}) {
421
429
  });
422
430
  options = { ...options, claudeEnvVars: { ...options.claudeEnvVars, VH_PEER_SESSION_ID: response.id } };
423
431
  const initialScannerSessionId = forkClaudeSessionId ?? (metadata.claudeSessionId ?? null);
432
+ const transcriptPathHints = new TranscriptPathHints();
424
433
  const remoteScanner = await createSessionScanner({
425
434
  sessionId: initialScannerSessionId,
426
435
  workingDirectory,
436
+ transcriptPathHints,
427
437
  onMessage: (raw) => {
428
438
  if (currentRunMode !== "remote") return;
429
439
  if (raw.type !== "user") return;
@@ -454,6 +464,7 @@ async function runClaude(credentials, options = {}) {
454
464
  return;
455
465
  }
456
466
  logger.debug(`[START] Session hook received: ${sessionId}`, contentLogMetadata(data));
467
+ transcriptPathHints.note(sessionId, data.transcript_path);
457
468
  announceSessionToScanner(sessionId);
458
469
  if (currentSession) {
459
470
  const previousSessionId = currentSession.sessionId;
@@ -775,12 +786,14 @@ async function runClaude(credentials, options = {}) {
775
786
  });
776
787
  });
777
788
  const exitGate = new SessionExitGate();
789
+ let hibernationProbe = null;
778
790
  const cleanup = async (opts = { archive: true }) => {
779
- const intent = exitGate.claim(exitIntentFromArchiveFlag(opts.archive));
791
+ const intent = opts.hibernation ? "hibernate" : exitGate.claim(exitIntentFromArchiveFlag(opts.archive));
780
792
  if (intent === null) {
781
793
  logger.debug(`[START] Termination (archive=${opts.archive ?? true}) ignored: cleanup already running as ${exitGate.current}`);
782
794
  return;
783
795
  }
796
+ hibernationProbe?.stop();
784
797
  logger.debug(`[START] Received termination signal, cleaning up (archive=${intent === "archive"})...`);
785
798
  promptQueueDrain.close();
786
799
  cleanupPrewarm();
@@ -789,6 +802,7 @@ async function runClaude(credentials, options = {}) {
789
802
  currentSession?.cleanup();
790
803
  await settleSessionOnExit(session.sessionId, intent, {
791
804
  updateMetadata: (handler) => session.updateMetadata(handler),
805
+ updateMetadataAndWait: (handler) => session.updateMetadataAndWait(handler),
792
806
  sendSessionDeath: () => session.sendSessionDeath(),
793
807
  archiveSession: (id) => api.archiveSession(id),
794
808
  deactivateSession: (id) => api.deactivateSession(id),
@@ -831,6 +845,58 @@ async function runClaude(credentials, options = {}) {
831
845
  void cleanup({ archive: true });
832
846
  });
833
847
  registerKillSessionHandler(session.rpcHandlerManager, () => cleanup({ archive: true }), session);
848
+ let keepAwakeLatch = false;
849
+ const hibernationSnapshot = () => {
850
+ const agentState = session.getAgentState();
851
+ const current = currentSession;
852
+ const meta = session.getMetadata();
853
+ return {
854
+ flavor: "claude",
855
+ resumable: typeof meta?.claudeSessionId === "string" && meta.claudeSessionId.length > 0,
856
+ uiSession: options.startedBy === "daemon" && options.startingMode === "remote" && agentState?.controlledByUser !== true,
857
+ ...isAssistantVariant ? { variant: "assistant" } : {},
858
+ ...process.env.HAPPY_SPAWNED_BY ? { spawnedBy: process.env.HAPPY_SPAWNED_BY } : {},
859
+ ...meta?.tags ? { tags: meta.tags } : {},
860
+ keepAwake: keepAwakeLatch = latchKeepAwake(meta?.keepAwake, keepAwakeLatch),
861
+ ...typeof meta?.keepAwake === "boolean" ? { keepAwakeSetting: meta.keepAwake } : {},
862
+ thinking: current?.thinking === true,
863
+ queuedInputs: messageQueue.size() + (session.promptQueueHasPending() ? 1 : 0),
864
+ waitingForInput: messageQueue.isWaiting(),
865
+ pendingRequests: Object.keys(agentState?.requests ?? {}).length,
866
+ backgroundTasks: current?.backgroundTasks.length ?? 0,
867
+ scheduledWakeups: current?.scheduledWakeups.pending() ?? 0,
868
+ lastActivityAt: session.lastActivityAt,
869
+ ...exitGate.current && exitGate.current !== "hibernate" ? { exiting: true } : {}
870
+ };
871
+ };
872
+ if (options.startedBy === "daemon" && options.startingMode === "remote" && !isAssistantVariant) {
873
+ hibernationProbe = new HibernationProbe({
874
+ checkMs: resolveCheckMs(),
875
+ snapshot: hibernationSnapshot,
876
+ ask: (report) => checkDaemonHibernation({ sessionId: session.sessionId, pid: process.pid, report }),
877
+ commit: (idleMs) => commitHibernation({
878
+ client: session,
879
+ claimExit: () => exitGate.claim("hibernate") !== null,
880
+ exitRequested: () => exitGate.exitRequested,
881
+ markCommitted: () => exitGate.commitHibernate(),
882
+ // Review P1-1: an archive / kill / SIGTERM deferred during the
883
+ // commit window runs now instead of being lost.
884
+ releaseExit: () => {
885
+ const deferred = exitGate.release("hibernate");
886
+ if (deferred) void cleanup({ archive: deferred === "archive" });
887
+ },
888
+ recheck: () => evaluateWrapperIdle(hibernationSnapshot(), idleMs, Date.now()),
889
+ idleMs,
890
+ finish: (stamp) => cleanup({ archive: false, hibernation: stamp })
891
+ }),
892
+ // Review P3-3: the daemon still holds keep-awake but an old web
893
+ // stripped the field — put it back so every web shows it checked.
894
+ onKeepAwakeLatched: () => {
895
+ if (session.getMetadata()?.keepAwake === void 0) session.updateMetadata((m) => m.keepAwake === void 0 ? { ...m, keepAwake: true } : m);
896
+ }
897
+ });
898
+ hibernationProbe.start();
899
+ }
834
900
  const exitCode = await loop({
835
901
  path: workingDirectory,
836
902
  model: options.model,
@@ -849,6 +915,7 @@ async function runClaude(credentials, options = {}) {
849
915
  },
850
916
  onSessionReady: (sessionInstance) => {
851
917
  currentSession = sessionInstance;
918
+ sessionInstance.transcriptPathHints = transcriptPathHints;
852
919
  sessionInstance.addSessionFoundCallback?.(announceSessionToScanner);
853
920
  },
854
921
  // B-515: lease for a warm Claude process, taken once by the first