very-happy-cli 0.2.166 → 0.2.168

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 (178) hide show
  1. package/dist/{AcpBackend-tRWk7yi7.mjs → AcpBackend-BoLDLYNT.mjs} +3 -3
  2. package/dist/{AcpBackend-20VHOXwb.cjs → AcpBackend-r83MMm-i.cjs} +3 -3
  3. package/dist/{BasePermissionHandler-COKc4pmt.cjs → BasePermissionHandler-CS0eRtT-.cjs} +1 -1
  4. package/dist/{BasePermissionHandler-CDCLIrZJ.mjs → BasePermissionHandler-DTcVlmKi.mjs} +1 -1
  5. package/dist/{BaseReasoningProcessor-BDVKvooR.mjs → BaseReasoningProcessor-BddnNlXQ.mjs} +1 -1
  6. package/dist/{BaseReasoningProcessor-DAGQdkNp.cjs → BaseReasoningProcessor-RJiBhA8h.cjs} +1 -1
  7. package/dist/{agentHome-2IbIjKCa.mjs → agentHome--LRsdUx6.mjs} +4 -4
  8. package/dist/{agentHome-KVWj6nCl.cjs → agentHome-D-e_j9hK.cjs} +4 -4
  9. package/dist/{api-DnNL5fLw.cjs → api-COSJ3Yb7.cjs} +88 -10
  10. package/dist/{api-Cmz3XS4P.mjs → api-hXLwtgMi.mjs} +88 -10
  11. package/dist/{apiMachine-DeoQ8QbZ.cjs → apiMachine-BTCUUGC6.cjs} +50 -15
  12. package/dist/{apiMachine-B6ySCFe0.mjs → apiMachine-BauSXWNd.mjs} +50 -15
  13. package/dist/{attachmentContent-DPWxHgX4.cjs → attachmentContent-BCK0AxDS.cjs} +2 -2
  14. package/dist/{attachmentContent-CTXapi-_.mjs → attachmentContent-CS0B2N0Q.mjs} +2 -2
  15. package/dist/{attachmentLimits-BfgKV5iE.cjs → attachmentLimits-BEYEEBm8.cjs} +13 -1
  16. package/dist/{attachmentLimits-C1PCCM79.mjs → attachmentLimits-CxG3T18E.mjs} +13 -1
  17. package/dist/{auth-pzWIFdOD.mjs → auth-BFeFguVs.mjs} +5 -5
  18. package/dist/{auth-BMaBjRAj.mjs → auth-BUXH1L2k.mjs} +10 -10
  19. package/dist/{auth-D4-eQz85.cjs → auth-CCj5KlYS.cjs} +10 -10
  20. package/dist/{auth-ietHtvwu.cjs → auth-CfB2XcAW.cjs} +5 -5
  21. package/dist/{auto-DL75Dx3I.mjs → auto-D5BYdAoT.mjs} +14 -14
  22. package/dist/{auto-DOWTQDPa.cjs → auto-ZCHKb4jo.cjs} +14 -14
  23. package/dist/{bootstrap-BpXIc2wn.cjs → bootstrap-DSX64t23.cjs} +2 -2
  24. package/dist/{bootstrap-XE8A7Ut2.mjs → bootstrap-DklT121U.mjs} +2 -2
  25. package/dist/{browser-CcG8GLRV.cjs → browser-CeekQeKt.cjs} +1 -1
  26. package/dist/{browser-DDFi1T8C.mjs → browser-DUf1dth8.mjs} +1 -1
  27. package/dist/{claudeLocal-DmM5Oyhv.mjs → claudeLocal-C8pXtb8q.mjs} +5 -5
  28. package/dist/{claudeLocal-DXBXwIOG.cjs → claudeLocal-hH0YYex3.cjs} +5 -5
  29. package/dist/{claudeLocalLauncher-Cs4eUC3P.mjs → claudeLocalLauncher-AtUe2tM-.mjs} +10 -10
  30. package/dist/{claudeLocalLauncher-C41Y6Kp4.cjs → claudeLocalLauncher-B-ta13pT.cjs} +10 -10
  31. package/dist/{claudeSessionFork-BdLnc2Hv.mjs → claudeSessionFork-BQPBKEHk.mjs} +1 -1
  32. package/dist/{claudeSessionFork-Cs0I3eGI.cjs → claudeSessionFork-Cq9FBfjD.cjs} +1 -1
  33. package/dist/{client-CbK33y_s.mjs → client-Bg6-mQKO.mjs} +3 -3
  34. package/dist/{client-GjTnsq6F.mjs → client-Cbl3ejoq.mjs} +2 -2
  35. package/dist/{client-JISJx2f-.cjs → client-DZpkmS5l.cjs} +3 -3
  36. package/dist/{client-DJ0kX_8M.cjs → client-EnFomCjx.cjs} +2 -2
  37. package/dist/codex/happyMcpStdioBridge.cjs +14 -14
  38. package/dist/codex/happyMcpStdioBridge.mjs +14 -14
  39. package/dist/{codexAppServerClient-BTjn2ZCZ.cjs → codexAppServerClient-pllsN90-.cjs} +4 -4
  40. package/dist/{codexAppServerClient-CldXEojt.mjs → codexAppServerClient-sWuwtddZ.mjs} +4 -4
  41. package/dist/{codexCommand-DjMU-Ijf.mjs → codexCommand-DbTkMlW4.mjs} +137 -56
  42. package/dist/{codexCommand-BpD0N1F7.cjs → codexCommand-_jkx59gI.cjs} +137 -56
  43. package/dist/{config-DuLL0Ppe.cjs → config-BuIIZPZK.cjs} +3 -3
  44. package/dist/{config-DjSJKatx.mjs → config-FCOoREKj.mjs} +3 -3
  45. package/dist/{configuration-D2v3puap.mjs → configuration-BZo1JWNV.mjs} +2 -2
  46. package/dist/{configuration-B0cb3xA3.cjs → configuration-DeuGrnej.cjs} +1 -1
  47. package/dist/{connect-CnNNyM9I.mjs → connect-C2yHh85e.mjs} +13 -13
  48. package/dist/{connect-B7JWEzyg.cjs → connect-CjDdF12U.cjs} +13 -13
  49. package/dist/{context-BFUpYT39.cjs → context-BhvZtm3j.cjs} +1 -1
  50. package/dist/{context-DjfqLWzE.mjs → context-DZIIcfld.mjs} +1 -1
  51. package/dist/{controlClient-BMUJfUeF.mjs → controlClient-CXD-Xdny.mjs} +18 -4
  52. package/dist/{controlClient-CmnHGcyl.cjs → controlClient-IDE3se23.cjs} +18 -3
  53. package/dist/{createSessionMetadata-DbfRBhRu.cjs → createSessionMetadata-BCHFLSLk.cjs} +56 -3
  54. package/dist/{createSessionMetadata-DU0bCg2m.mjs → createSessionMetadata-DoLFya-Q.mjs} +57 -5
  55. package/dist/defaultPermissionMode-BtZtLdQz.cjs +197 -0
  56. package/dist/defaultPermissionMode-Dxfv-5Ud.mjs +191 -0
  57. package/dist/{deterministicJson-Dp3TVyap.cjs → deterministicJson-BqQKrUzw.cjs} +8 -8
  58. package/dist/{deterministicJson-D-WPUrZb.mjs → deterministicJson-CF1fJMaM.mjs} +8 -8
  59. package/dist/{doctor-BlXXyQ1L.mjs → doctor-C98yYhYr.mjs} +6 -6
  60. package/dist/{doctor-CkJmdPbi.cjs → doctor-D61ncaeL.cjs} +6 -6
  61. package/dist/{downloadTarget-DjSwMHun.mjs → downloadTarget-CaISZbNy.mjs} +6 -6
  62. package/dist/{downloadTarget-CiQqRIc-.cjs → downloadTarget-Dist9t2e.cjs} +6 -6
  63. package/dist/{ensureDaemonRunning-C_aIOhgG.cjs → ensureDaemonRunning-BB0hnWY_.cjs} +5 -5
  64. package/dist/{ensureDaemonRunning-CAQag1zE.mjs → ensureDaemonRunning-CNiqOarI.mjs} +5 -5
  65. package/dist/{handleResumeCommand-Ci7wacT-.mjs → handleResumeCommand-BzcANj0i.mjs} +5 -5
  66. package/dist/{handleResumeCommand-6KzBGDnl.cjs → handleResumeCommand-CkzW-T_f.cjs} +5 -5
  67. package/dist/{index-DEKIgZUo.cjs → index-BQU1sS9K.cjs} +4 -4
  68. package/dist/{index-DBmNwMX9.cjs → index-BeeWN9Et.cjs} +33 -33
  69. package/dist/{index-WGCT6SSV.mjs → index-CdmIOFwG.mjs} +34 -34
  70. package/dist/{index-HQsigW_J.mjs → index-D2hg_u5i.mjs} +3 -3
  71. package/dist/{index-DQplgo0W.mjs → index-Dgqk3lfG.mjs} +4 -4
  72. package/dist/{index-CaFCAlX8.cjs → index-DipBfs9w.cjs} +3 -3
  73. package/dist/index.cjs +2 -2
  74. package/dist/index.mjs +2 -2
  75. package/dist/{install-oJUvsFu9.mjs → install-CK1FvmYQ.mjs} +3 -3
  76. package/dist/{install-CejEiRGW.cjs → install-VtuffPLu.cjs} +3 -3
  77. package/dist/lib.cjs +11 -11
  78. package/dist/lib.d.cts +61 -0
  79. package/dist/lib.d.mts +61 -0
  80. package/dist/lib.mjs +11 -11
  81. package/dist/{lidState-D8BmnJV1.cjs → lidState-2IT0tas7.cjs} +1 -1
  82. package/dist/{lidState-BfximpjX.mjs → lidState-CJ3XkJRn.mjs} +1 -1
  83. package/dist/{localHappyAgentAuth-d7B6S_o7.cjs → localHappyAgentAuth-CPMh61Su.cjs} +1 -1
  84. package/dist/{localHappyAgentAuth-Ct1aXwqd.mjs → localHappyAgentAuth-DkLbntlf.mjs} +1 -1
  85. package/dist/{logger-BpQcwNnt.mjs → logger-C6zzu57a.mjs} +2 -2
  86. package/dist/{logger-JTcJU-uL.cjs → logger-Ockf1cjN.cjs} +2 -2
  87. package/dist/{machineMetadata-BBg_Njw3.cjs → machineMetadata-CoMYwSlG.cjs} +4 -3
  88. package/dist/{machineMetadata-CBdxABeI.mjs → machineMetadata-DmTGIZAV.mjs} +4 -3
  89. package/dist/{main-B5b1gA3K.mjs → main-B8TX9xPq.mjs} +45 -45
  90. package/dist/{main-C16fOGgn.cjs → main-CThJ9JQb.cjs} +45 -45
  91. package/dist/{manager-BQ4flvQZ.mjs → manager-BEsI4qt3.mjs} +9 -3
  92. package/dist/{manager-Cly8xVIR.cjs → manager-HrEj442o.cjs} +8 -2
  93. package/dist/{mcp-BnNiBBax.cjs → mcp-Dwku1p2I.cjs} +14 -14
  94. package/dist/{mcp-DGNWgVdv.mjs → mcp-Yw93dOiW.mjs} +14 -14
  95. package/dist/mirrorProtocol-CQ5fAUgq.mjs +1247 -0
  96. package/dist/mirrorProtocol-CdPhEBSh.cjs +1270 -0
  97. package/dist/{package-BqwrPxL0.mjs → package-5xAdq5fu.mjs} +7 -7
  98. package/dist/{package-C1XvUQFy.cjs → package-DfoyJe1O.cjs} +7 -7
  99. package/dist/{peerTools-DPvbcs8V.cjs → peerTools-BEnBvEcU.cjs} +4 -4
  100. package/dist/{peerTools-CeCe-3lk.mjs → peerTools-uDR6MG0-.mjs} +4 -4
  101. package/dist/{persistence-2Xp_o6x6.cjs → persistence-B5oT6oQ9.cjs} +147 -25
  102. package/dist/{persistence-B9LmhAE2.mjs → persistence-B6M_W5iC.mjs} +123 -12
  103. package/dist/{piRunnerArgs-DI29dDNo.cjs → piRunnerArgs-MLN46-nK.cjs} +1 -1
  104. package/dist/{piRunnerArgs-7FaTyNOq.mjs → piRunnerArgs-vNIUWHqo.mjs} +1 -1
  105. package/dist/{piRuntime-R8XVChxK.cjs → piRuntime-DkUg8_5q.cjs} +1 -1
  106. package/dist/{piRuntime-0qEK5AqE.mjs → piRuntime-WMuI7f4q.mjs} +1 -1
  107. package/dist/{piTerminal-zcQKc8Sp.mjs → piTerminal-4NBSZVxd.mjs} +16 -16
  108. package/dist/{piTerminal-Ccj0KNPr.cjs → piTerminal-Bskvs69Z.cjs} +16 -16
  109. package/dist/{rateLimitWindows-C2Jk3Ih7.cjs → rateLimitWindows-C2-Ky86q.cjs} +1 -1
  110. package/dist/{rateLimitWindows-Dhfhbtqu.mjs → rateLimitWindows-CJ1xDAxa.mjs} +1 -1
  111. package/dist/{registerCommonHandlers-DdfGsFbM.mjs → registerCommonHandlers-BLHKlk5Z.mjs} +2 -2
  112. package/dist/{registerCommonHandlers-Aha_KfM3.cjs → registerCommonHandlers-COSTo15G.cjs} +2 -2
  113. package/dist/{registerKillSessionHandler-DboQlGcH.mjs → registerKillSessionHandler-BVQfhSgm.mjs} +14 -9
  114. package/dist/{registerKillSessionHandler-CjitOpUA.cjs → registerKillSessionHandler-DDZISNzu.cjs} +14 -9
  115. package/dist/{remoteSessionClient-BwI8rpQw.cjs → remoteSessionClient-B2pOMZRw.cjs} +5 -5
  116. package/dist/{remoteSessionClient-B2DtWuNP.mjs → remoteSessionClient-Dx0M2MXV.mjs} +5 -5
  117. package/dist/{reportProgressTool-B-Rcy0s3.cjs → reportProgressTool-C5vDEv9Y.cjs} +1 -1
  118. package/dist/{reportProgressTool-DnAD8wOa.mjs → reportProgressTool-CcwFr0ek.mjs} +1 -1
  119. package/dist/{run-Bh66Xs40.cjs → run-BKTv1E-D.cjs} +323 -37
  120. package/dist/{run-DPEwJpQR.mjs → run-BZjIDOGM.mjs} +322 -36
  121. package/dist/{runClaude-DLr_nBzw.mjs → runClaude-DFa77Ffl.mjs} +87 -25
  122. package/dist/{runClaude-C-lJdAKD.cjs → runClaude-DUlFZWiK.cjs} +87 -25
  123. package/dist/{runClaudeDeps-vWWLod7J.cjs → runClaudeDeps--TnER0c3.cjs} +100 -31
  124. package/dist/{runClaudeDeps-C7JV7nXG.mjs → runClaudeDeps-BYohagQU.mjs} +105 -36
  125. package/dist/{runGemini-o-CUSayc.cjs → runGemini-BSBejXek.cjs} +32 -32
  126. package/dist/{runGemini-tH6sLw-G.mjs → runGemini-CUiq1Zei.mjs} +32 -32
  127. package/dist/{runOpenClaw-C5DZvVhn.mjs → runOpenClaw-CgwRP4gR.mjs} +16 -16
  128. package/dist/{runOpenClaw-D24f35l0.cjs → runOpenClaw-DQFEi3E1.cjs} +16 -16
  129. package/dist/{sandbox-BaL1aslA.mjs → sandbox-BTwAN7Yi.mjs} +4 -4
  130. package/dist/{sandbox-TJZJ6ngw.cjs → sandbox-DuLRfMY3.cjs} +4 -4
  131. package/dist/selfCheck-DF26lf1b.mjs +84 -0
  132. package/dist/{selfCheck-Dugi0Nk_.cjs → selfCheck-DuOLndWl.cjs} +34 -34
  133. package/dist/{send-DDcJ3ayi.mjs → send-ComZSvT5.mjs} +8 -8
  134. package/dist/{send-CkWOSYmU.cjs → send-Dl4TJ0Ia.cjs} +8 -8
  135. package/dist/{server-7qFQ8J2u.cjs → server-CWmamKcS.cjs} +6 -6
  136. package/dist/{server-CUjRvQSd.mjs → server-CXFSsyZx.mjs} +4 -4
  137. package/dist/{sessionLock-DfhNICyS.cjs → sessionLock-BFD8cFNP.cjs} +12 -3
  138. package/dist/{sessionLock-DqVyHFAQ.mjs → sessionLock-DCKf-gjd.mjs} +12 -4
  139. package/dist/{sessionModeFile-M4OpiyrF.mjs → sessionModeFile-BYxsFSvc.mjs} +1 -1
  140. package/dist/{sessionModeFile-CIznKD7O.cjs → sessionModeFile-i-MVQRcU.cjs} +1 -1
  141. package/dist/{sessionOps-DOyy4gkY.cjs → sessionOps-BAQ_80Rg.cjs} +4 -4
  142. package/dist/{sessionOps-BnaEaOKs.mjs → sessionOps-CBXsQGV5.mjs} +4 -4
  143. package/dist/{sessionScanner-CcuOn9uU.mjs → sessionScanner-CwPBvQK2.mjs} +3 -3
  144. package/dist/{sessionScanner-Cu1yKlj4.cjs → sessionScanner-Dth3iDCi.cjs} +3 -3
  145. package/dist/{sessions-BQgk5Kw8.cjs → sessions-BULd_RQt.cjs} +9 -9
  146. package/dist/{sessions-C9O91rL1.mjs → sessions-DYAqiUS0.mjs} +9 -9
  147. package/dist/{setupOfflineReconnection-Byy8aeKT.mjs → setupOfflineReconnection-Bo9xb30l.mjs} +2 -2
  148. package/dist/{setupOfflineReconnection-DFmQ8s6I.cjs → setupOfflineReconnection-DI8BQf_g.cjs} +2 -2
  149. package/dist/{spawn-EZ2yrtWd.mjs → spawn-DmXpKIOT.mjs} +13 -13
  150. package/dist/{spawn-BS7LPmSm.cjs → spawn-oikb5mUh.cjs} +13 -13
  151. package/dist/{spawnHappyCLI-BAa49m0q.mjs → spawnHappyCLI-BCnZfffk.mjs} +1 -1
  152. package/dist/{spawnHappyCLI-DyaldIe5.cjs → spawnHappyCLI-Cs177BB4.cjs} +1 -1
  153. package/dist/{specialCommands-DouFaJ_0.cjs → specialCommands-CmrwEh71.cjs} +3 -3
  154. package/dist/{specialCommands-CCWtwIGZ.mjs → specialCommands-xD4uOtdG.mjs} +3 -3
  155. package/dist/{startFileWatcher-Dfs4whzr.mjs → startFileWatcher-De7rN8QW.mjs} +1 -1
  156. package/dist/{startFileWatcher-DQbbypJv.cjs → startFileWatcher-S_Af_QPR.cjs} +1 -1
  157. package/dist/{sync-x_lI_3j_.cjs → sync-BS9_zSQ2.cjs} +1 -1
  158. package/dist/{sync-BLpH13Kb.mjs → sync-CHOB3Org.mjs} +1 -1
  159. package/dist/{systemPrompt-4erwILTB.cjs → systemPrompt-D2ICcIsu.cjs} +1 -1
  160. package/dist/{systemPrompt-BanyDihy.mjs → systemPrompt-DNLUUejs.mjs} +1 -1
  161. package/dist/{teams-DzetlGWC.cjs → teams-BUbESH6L.cjs} +6 -6
  162. package/dist/{teams-D6BOT3lR.mjs → teams-By3oBC7r.mjs} +6 -6
  163. package/dist/{time-CfDKj6Bx.mjs → time-CN0jVVir.mjs} +1 -1
  164. package/dist/{time-T0YmeOhS.cjs → time-uSKpEhew.cjs} +1 -1
  165. package/dist/{titleGenerator-CoMxqKfP.cjs → titleGenerator-CLIXjn9b.cjs} +2 -2
  166. package/dist/{titleGenerator-ChImQ4q-.mjs → titleGenerator-CegRJ47n.mjs} +1 -1
  167. package/dist/{todo-CZZebKZg.cjs → todo-Bg1vurv9.cjs} +5 -5
  168. package/dist/{todo-SVtYxGON.mjs → todo-Bl3abqvy.mjs} +5 -5
  169. package/dist/{tools-3X2z3YDe.mjs → tools-BcLUrC57.mjs} +1 -1
  170. package/dist/{tools-IJ0TAcJs.cjs → tools-DuWKlc0k.cjs} +1 -1
  171. package/dist/{uninstall-CypD-kr1.mjs → uninstall-BlpZlM9U.mjs} +3 -3
  172. package/dist/{uninstall-CqqCWj7w.cjs → uninstall-DWnj2XVT.cjs} +3 -3
  173. package/package.json +7 -7
  174. package/dist/defaultPermissionMode-BnxJPVHT.mjs +0 -4
  175. package/dist/defaultPermissionMode-CxmTXUQR.cjs +0 -7
  176. package/dist/mirrorProtocol-BEGk2--0.cjs +0 -266
  177. package/dist/mirrorProtocol-h5WHpdhh.mjs +0 -248
  178. package/dist/selfCheck-DPi4lqme.mjs +0 -84
@@ -1,23 +1,23 @@
1
- import { i as isClaudeSessionId, f as extractCompleteLines, g as decideBackfill, h as parseTerminalHookPayload, j as decideMirrorBinding, M as MIRROR_BACKFILL_LINES_DEFAULT, m as mirrorLineKey, k as mirrorLocalId, d as summarizeSpawnSessionForLog, n as startAgentVersionChecks } from './mirrorProtocol-h5WHpdhh.mjs';
2
- import { P as PI_ADAPTER_INSTALL_HINT, s as sanitizeSpawnModel, d as detectDaemonSupervisor } from './piRunnerArgs-7FaTyNOq.mjs';
1
+ import { i as isClaudeSessionId, g as extractCompleteLines, h as decideBackfill, j as parseTerminalHookPayload, k as decideMirrorBinding, M as MIRROR_BACKFILL_LINES_DEFAULT, m as mirrorLineKey, n as mirrorLocalId, o as initializeOwnedWorktree, e as summarizeSpawnSessionForLog, q as startAgentVersionChecks, W as WORKTREE_CAPABILITY_VERSION, t as currentWorktreeService } from './mirrorProtocol-CQ5fAUgq.mjs';
2
+ import { P as PI_ADAPTER_INSTALL_HINT, s as sanitizeSpawnModel, d as detectDaemonSupervisor } from './piRunnerArgs-vNIUWHqo.mjs';
3
3
  import fs from 'fs/promises';
4
4
  import * as tmp from 'tmp';
5
5
  import axios from 'axios';
6
- import { T as TurnActivityTracker, A as ApiClient } from './api-Cmz3XS4P.mjs';
6
+ import { T as TurnActivityTracker, A as ApiClient } from './api-hXLwtgMi.mjs';
7
7
  import { S as SPAWN_AGENTS, i as isSpawnAgent, s as sanitizeSpawnPermissionMode, r as resolveSpawnPermissionMode, a as resolveFirstMessageMeta } from './spawnAgents-HDaE3C0-.mjs';
8
- import { l as logger } from './logger-BpQcwNnt.mjs';
8
+ import { l as logger } from './logger-C6zzu57a.mjs';
9
9
  import { readdirSync, statSync, unlinkSync, realpathSync, mkdirSync, writeFileSync, accessSync, constants as constants$1, existsSync, readFileSync, openSync, fsyncSync, closeSync, renameSync } from 'node:fs';
10
10
  import { join, isAbsolute, resolve, dirname, sep, basename, delimiter } from 'node:path';
11
- import { p as pruneStaleCompileCaches } from './index-HQsigW_J.mjs';
12
- import { a as authAndSetupMachineIfNeeded } from './auth-pzWIFdOD.mjs';
13
- import { c as configuration, f as ensurePrivateDirectorySync, w as writePrivateFileSync } from './configuration-D2v3puap.mjs';
11
+ import { p as pruneStaleCompileCaches } from './index-D2hg_u5i.mjs';
12
+ import { a as authAndSetupMachineIfNeeded } from './auth-BFeFguVs.mjs';
13
+ import { c as configuration, f as ensurePrivateDirectorySync, w as writePrivateFileSync } from './configuration-BZo1JWNV.mjs';
14
14
  import { spawn, execSync } from 'child_process';
15
- import { p as packageJson } from './package-BqwrPxL0.mjs';
16
- import { a as globalPrefixForPackage, g as getEnvironmentInfo } from './doctor-BlXXyQ1L.mjs';
17
- import { s as spawnHappyCLI } from './spawnHappyCLI-BAa49m0q.mjs';
18
- import { readPersistedSessions, readSettings, persistSession, readDaemonState, acquireDaemonLock, deletePersistedSessions, writeDaemonState, writeSettings, releaseDaemonLock } from './persistence-B9LmhAE2.mjs';
19
- import { i as isDaemonRunningCurrentlyInstalledHappyVersion, a as stopDaemon, q as cleanupDaemonState } from './controlClient-BMUJfUeF.mjs';
20
- import { e as sendUserMessage, f as readSessionMetadata, r as readSessionTranscript, l as listAccountSessions, a as listSessions, M as MAX_READ_LIMIT, s as sessionWebUrl, g as waitForSessionKey, d as archiveSession, j as analyzeLatestTurn, k as readSessionLog, m as TURN_WINDOW, n as userPromptText } from './sessionOps-BnaEaOKs.mjs';
15
+ import { p as packageJson } from './package-5xAdq5fu.mjs';
16
+ import { a as globalPrefixForPackage, g as getEnvironmentInfo } from './doctor-C98yYhYr.mjs';
17
+ import { s as spawnHappyCLI } from './spawnHappyCLI-BCnZfffk.mjs';
18
+ import { b as readPersistedSessions, r as readSettings, l as latchKeepAwake, q as reportSignature, s as decideDaemonHibernation, t as nextCheckDelay, v as persistSession, d as readDaemonState, x as acquireDaemonLock, a as resolveCheckMs, y as resolveIdleMs, z as deletePersistedSessions, A as writeDaemonState, B as writeSettings, C as settingIdleMs, u as updateSettings, D as releaseDaemonLock } from './persistence-B6M_W5iC.mjs';
19
+ import { i as isDaemonRunningCurrentlyInstalledHappyVersion, b as stopDaemon, t as cleanupDaemonState } from './controlClient-CXD-Xdny.mjs';
20
+ import { e as sendUserMessage, f as readSessionMetadata, r as readSessionTranscript, l as listAccountSessions, a as listSessions, M as MAX_READ_LIMIT, s as sessionWebUrl, g as waitForSessionKey, d as archiveSession, j as analyzeLatestTurn, k as readSessionLog, m as TURN_WINDOW, n as userPromptText } from './sessionOps-CBXsQGV5.mjs';
21
21
  import fastify from 'fastify';
22
22
  import { z } from 'zod';
23
23
  import { validatorCompiler, serializerCompiler } from 'fastify-type-provider-zod';
@@ -25,45 +25,45 @@ import { d as decodeBase64, e as encodeBase64, h as decrypt } from './authRelay-
25
25
  import { randomBytes, createHash, timingSafeEqual, randomUUID } from 'node:crypto';
26
26
  import { c as checkPreviewPath } from './previewPath-CXN4Vag0.mjs';
27
27
  import { a as BACKGROUND_TASKS_MAX, d as BACKGROUND_TASK_DESCRIPTION_MAX, e as BackgroundTaskTracker } from './backgroundTaskActivity-8PdPxrvy.mjs';
28
- import { b as sanitizeRateLimitReport } from './rateLimitWindows-Dhfhbtqu.mjs';
29
- import { f as formatEditConflictNotice, b as SESSION_PEER_SENT_FROM, s as sendPeerMessage, l as listPeerSessions, C as CLI_PEER_SENDER_ID } from './peerTools-CeCe-3lk.mjs';
28
+ import { b as sanitizeRateLimitReport } from './rateLimitWindows-CJ1xDAxa.mjs';
29
+ import { f as formatEditConflictNotice, b as SESSION_PEER_SENT_FROM, s as sendPeerMessage, l as listPeerSessions, C as CLI_PEER_SENDER_ID } from './peerTools-uDR6MG0-.mjs';
30
30
  import os, { hostname, homedir, userInfo, tmpdir } from 'node:os';
31
- import { c as RemoteCallBudget, e as REMOTE_WRITE_CALLS_PER_MINUTE, d as deliverToSession, g as guardRemoteSessionOpsRequest, h as remoteError, i as REMOTE_OP_DEADLINE_MS, j as formatRemoteAuditLine, k as REMOTE_SEND_COMMIT_DEADLINE_MS, m as REMOTE_RESUME_WAIT_MS, n as capRemoteTranscript, o as capRemoteText, p as REMOTE_ANSWER_MAX_BYTES, q as REMOTE_TITLE_MAX_BYTES } from './remoteSessionClient-B2DtWuNP.mjs';
32
- import { assistantHome, bootstrapAssistantHome } from './bootstrap-XE8A7Ut2.mjs';
33
- import { refreshAgentHomes, locateClaudeConversation, agentHomeSpawnEnv } from './index-DQplgo0W.mjs';
31
+ import { c as RemoteCallBudget, e as REMOTE_WRITE_CALLS_PER_MINUTE, d as deliverToSession, g as guardRemoteSessionOpsRequest, h as remoteError, i as REMOTE_OP_DEADLINE_MS, j as formatRemoteAuditLine, k as REMOTE_SEND_COMMIT_DEADLINE_MS, m as REMOTE_RESUME_WAIT_MS, n as capRemoteTranscript, o as capRemoteText, p as REMOTE_ANSWER_MAX_BYTES, q as REMOTE_TITLE_MAX_BYTES } from './remoteSessionClient-Dx0M2MXV.mjs';
32
+ import { assistantHome, bootstrapAssistantHome } from './bootstrap-DklT121U.mjs';
33
+ import { refreshAgentHomes, locateClaudeConversation, agentHomeSpawnEnv } from './index-Dgqk3lfG.mjs';
34
34
  import { existsSync as existsSync$1, statSync as statSync$1, mkdtempSync, rmSync } from 'fs';
35
35
  import { join as join$1 } from 'path';
36
36
  import { spawn as spawn$1, execFile, spawnSync } from 'node:child_process';
37
37
  import { p as projectPath } from './projectPath-BTBIMB57.mjs';
38
38
  import { d as daemonEndpointsMatch, r as resolveClaudeCredentialReadiness } from './doctorReadiness-C208SMN9.mjs';
39
- import { g as getInitialMachineMetadata, a as getStartupCliAvailability } from './machineMetadata-CBdxABeI.mjs';
40
- import { buildResumeLaunch } from './handleResumeCommand-Ci7wacT-.mjs';
39
+ import { g as getInitialMachineMetadata, a as getStartupCliAvailability } from './machineMetadata-DmTGIZAV.mjs';
40
+ import { buildResumeLaunch } from './handleResumeCommand-BzcANj0i.mjs';
41
41
  import { access, symlink, readFile, rm, unlink, readlink, lstat, constants, stat, open } from 'node:fs/promises';
42
42
  import { p as parseExactVersion, c as compareExactVersions, f as fetchCliUpdateState, r as resolveCliUpdateCheckInterval, D as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS } from './cliUpdate-Y34VGe9Y.mjs';
43
+ import { c as createAutomationsClient, i as isAutomationsUnavailable, d as AutomationsRequestError } from './client-Cbl3ejoq.mjs';
43
44
  import { createRequire } from 'node:module';
44
45
  import { g as getProjectPath } from './path-D2wdaNSk.mjs';
45
46
  import { b as extractClaudeEditPaths } from './editPaths-BVfS_FFL.mjs';
46
- import { s as startFileWatcher } from './startFileWatcher-Dfs4whzr.mjs';
47
- import { I as InvalidateSync } from './sync-BLpH13Kb.mjs';
47
+ import { s as startFileWatcher } from './startFileWatcher-De7rN8QW.mjs';
48
+ import { I as InvalidateSync } from './sync-CHOB3Org.mjs';
48
49
  import { R as RawJSONLinesSchema } from './types-CkqAACXx.mjs';
49
50
  import { t as tmuxArgs, a as scrubTmuxClientEnv, s as shellescape } from './tmuxSocket-B8Yx20sT.mjs';
50
- import { p as processIdentityFields, r as readSessionLock, t as terminateProcess } from './sessionLock-DqVyHFAQ.mjs';
51
+ import { p as processIdentityFields, r as readSessionLock, t as terminateProcess } from './sessionLock-DCKf-gjd.mjs';
51
52
  import { findAllHappyProcesses } from './doctor-BPkYWSuq.mjs';
52
53
  import { T as TEAM_SKILL } from './resources-BdFBQi8r.mjs';
53
54
  import { promisify } from 'node:util';
54
55
  import { t as AUTOMATION_SUMMARY_MAX_CHARS, u as AUTOMATION_PRECHECK_OUTPUT_MAX_CHARS, v as AUTOMATION_PRECHECK_DEFAULT_TIMEOUT_MS, a as AUTOMATION_PRECHECK_MAX_TIMEOUT_MS, w as AUTOMATION_CLAIM_MAX_RUNS, x as AUTOMATION_DAEMON_CAPABILITY_PRECHECK, y as AUTOMATION_DEFAULT_LEASE_MS, i as isAutomationRunTerminal } from './index-B0HEEYGh.mjs';
55
- import { c as createAutomationsClient, i as isAutomationsUnavailable, d as AutomationsRequestError } from './client-GjTnsq6F.mjs';
56
56
  import { c as clipText, r as renderAction, b as renderTemplate } from './template-CiOPa2rd.mjs';
57
57
  import { d as describeAgentHome } from './loginShellEnv-Dw8M7tkI.mjs';
58
- import './sessionModeFile-M4OpiyrF.mjs';
59
- import './lidState-BfximpjX.mjs';
58
+ import './sessionModeFile-BYxsFSvc.mjs';
59
+ import './lidState-CJ3XkJRn.mjs';
60
60
  import 'os';
61
61
  import 'node:events';
62
62
  import 'socket.io-client';
63
- import './attachmentLimits-C1PCCM79.mjs';
63
+ import './attachmentLimits-CxG3T18E.mjs';
64
64
  import './limits-DIo7rEBR.mjs';
65
- import './time-CfDKj6Bx.mjs';
66
- import './registerCommonHandlers-DdfGsFbM.mjs';
65
+ import './time-CN0jVVir.mjs';
66
+ import './registerCommonHandlers-BLHKlk5Z.mjs';
67
67
  import 'util';
68
68
  import 'crypto';
69
69
  import 'cross-spawn';
@@ -71,12 +71,12 @@ import '@paralleldrive/cuid2';
71
71
  import './contentLogMetadata-BlWI0egu.mjs';
72
72
  import 'chalk';
73
73
  import 'tweetnacl';
74
- import './browser-DDFi1T8C.mjs';
74
+ import './browser-DUf1dth8.mjs';
75
75
  import 'open';
76
76
  import './ids-DU6sLx4C.mjs';
77
77
  import 'url';
78
78
  import './detectCLI-CSGMlV51.mjs';
79
- import './localHappyAgentAuth-Ct1aXwqd.mjs';
79
+ import './localHappyAgentAuth-DkLbntlf.mjs';
80
80
  import 'ps-list';
81
81
 
82
82
  async function resolveRelaunchMetadata(snapshot, fetchServer) {
@@ -396,6 +396,29 @@ function isAuthorizedDaemonControlRequest(authorization, controlToken) {
396
396
  return configuredTokenIsUsable && timingSafeEqual(expectedDigest, candidateDigest);
397
397
  }
398
398
 
399
+ const WrapperIdleSnapshotSchema = z.object({
400
+ flavor: z.string().max(64),
401
+ resumable: z.boolean(),
402
+ uiSession: z.boolean(),
403
+ variant: z.string().max(64).optional(),
404
+ spawnedBy: z.string().max(64).optional(),
405
+ tags: z.array(z.string().max(128)).max(64).optional(),
406
+ keepAwake: z.boolean(),
407
+ keepAwakeSetting: z.boolean().optional(),
408
+ thinking: z.boolean(),
409
+ queuedInputs: z.number().int().nonnegative(),
410
+ waitingForInput: z.boolean(),
411
+ pendingRequests: z.number().int().nonnegative(),
412
+ backgroundTasks: z.number().int().nonnegative(),
413
+ scheduledWakeups: z.number().int().nonnegative().optional(),
414
+ lastActivityAt: z.number(),
415
+ exiting: z.boolean().optional()
416
+ }).passthrough();
417
+ const HibernateCheckBodySchema = z.object({
418
+ sessionId: z.string().min(1).max(200),
419
+ pid: z.number().int().positive(),
420
+ report: WrapperIdleSnapshotSchema
421
+ });
399
422
  const BackgroundTaskInfoSchema = z.object({
400
423
  id: z.string().min(1).max(200),
401
424
  type: z.string().max(64),
@@ -429,7 +452,8 @@ function startDaemonControlServer({
429
452
  onSessionEdit,
430
453
  listPeers,
431
454
  isTurnActive,
432
- onRateLimits
455
+ onRateLimits,
456
+ onHibernateCheck
433
457
  }) {
434
458
  return new Promise((resolve) => {
435
459
  const app = fastify({
@@ -512,6 +536,29 @@ function startDaemonControlServer({
512
536
  onSessionStateEvent?.(sessionId, event, spawnedBy);
513
537
  return { status: "ok" };
514
538
  });
539
+ if (onHibernateCheck) {
540
+ typed.post("/session-hibernate-check", {
541
+ schema: {
542
+ body: HibernateCheckBodySchema,
543
+ response: {
544
+ 200: z.object({
545
+ hibernate: z.boolean(),
546
+ reason: z.string().optional(),
547
+ idleMs: z.number().optional(),
548
+ nextCheckMs: z.number().optional(),
549
+ keepAwake: z.boolean().optional()
550
+ })
551
+ }
552
+ }
553
+ }, async (request) => {
554
+ try {
555
+ return await onHibernateCheck(request.body);
556
+ } catch (error) {
557
+ logger.debug("[CONTROL SERVER] hibernate check failed:", error);
558
+ return { hibernate: false, reason: "error" };
559
+ }
560
+ });
561
+ }
515
562
  typed.post("/list", {
516
563
  schema: {
517
564
  response: {
@@ -2391,6 +2438,133 @@ function createUpdateController(deps) {
2391
2438
  return { refresh, retry, request, tick, withHandover, holdHandover, isRunning: () => running };
2392
2439
  }
2393
2440
 
2441
+ const AUTOMATION_BINDINGS_TTL_MS = 10 * 60 * 1e3;
2442
+ const HIBERNATION_IN_FLIGHT_MS = 6e4;
2443
+ const HIBERNATION_EXIT_WAIT_MS = 15e3;
2444
+ async function waitForPidsToExit(pids, isAlive, timeoutMs = HIBERNATION_EXIT_WAIT_MS, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), now = Date.now) {
2445
+ const deadline = now() + timeoutMs;
2446
+ while (pids.some(isAlive)) {
2447
+ if (now() >= deadline) return false;
2448
+ await sleep(100);
2449
+ }
2450
+ return true;
2451
+ }
2452
+ function createDaemonHibernation(deps) {
2453
+ const now = () => (deps.now ?? Date.now)();
2454
+ const signatures = /* @__PURE__ */ new Map();
2455
+ const approved = /* @__PURE__ */ new Map();
2456
+ let bindings = null;
2457
+ let bindingsInFlight = null;
2458
+ async function automationBound(fresh = false) {
2459
+ if (!fresh && bindings && now() - bindings.at < AUTOMATION_BINDINGS_TTL_MS) return bindings.ids;
2460
+ if (fresh && bindingsInFlight) await bindingsInFlight;
2461
+ if (!bindingsInFlight) {
2462
+ bindingsInFlight = deps.loadAutomationBindings().then((ids) => {
2463
+ bindings = { at: now(), ids: new Set(ids) };
2464
+ return bindings.ids;
2465
+ }).catch((error) => {
2466
+ deps.log?.(`[hibernate] automation bindings unknown: ${error instanceof Error ? error.message : String(error)}`);
2467
+ return null;
2468
+ }).finally(() => {
2469
+ bindingsInFlight = null;
2470
+ });
2471
+ }
2472
+ return bindingsInFlight;
2473
+ }
2474
+ function inFlight(except) {
2475
+ const t = now();
2476
+ for (const [id, at] of approved) {
2477
+ if (t - at > HIBERNATION_IN_FLIGHT_MS) approved.delete(id);
2478
+ else if (id !== except) return true;
2479
+ }
2480
+ return false;
2481
+ }
2482
+ async function check(request) {
2483
+ const idleMs = deps.idleMs();
2484
+ const t = now();
2485
+ const tracked = deps.tracked(request.sessionId, request.pid);
2486
+ const latchedBefore = deps.readKeepAwake?.(request.sessionId) ?? false;
2487
+ const latched = latchKeepAwake(request.report.keepAwakeSetting, latchedBefore || request.report.keepAwake);
2488
+ if (latched !== latchedBefore) deps.writeKeepAwake?.(request.sessionId, latched);
2489
+ if (latched && !request.report.keepAwake) request = { ...request, report: { ...request.report, keepAwake: true } };
2490
+ const signature = reportSignature(request.report);
2491
+ const previousSignature = signatures.get(request.sessionId);
2492
+ signatures.set(request.sessionId, signature);
2493
+ const base = {
2494
+ idleMs,
2495
+ now: t,
2496
+ sessionId: request.sessionId,
2497
+ pid: request.pid,
2498
+ report: request.report,
2499
+ trackedLive: !!tracked?.live,
2500
+ trackedSpawnedBy: tracked?.spawnedBy,
2501
+ teamsMember: deps.teamsMember(request.sessionId),
2502
+ turnActive: deps.turnActive(request.sessionId),
2503
+ backgroundTasks: deps.backgroundTasks(request.sessionId),
2504
+ previousSignature,
2505
+ hibernationInFlight: inFlight(request.sessionId)
2506
+ };
2507
+ let verdict = decideDaemonHibernation({ ...base, automationBound: /* @__PURE__ */ new Set() });
2508
+ if (verdict.ok || verdict.reason === "unconfirmed" || verdict.reason === "busy") {
2509
+ verdict = decideDaemonHibernation({ ...base, automationBound: await automationBound() });
2510
+ }
2511
+ if (verdict.ok) {
2512
+ verdict = decideDaemonHibernation({ ...base, automationBound: await automationBound(true) });
2513
+ }
2514
+ if (verdict.ok) {
2515
+ approved.set(request.sessionId, t);
2516
+ signatures.delete(request.sessionId);
2517
+ deps.log?.(`[hibernate] approved ${request.sessionId} (pid ${request.pid}, idle ${Math.round((t - request.report.lastActivityAt) / 1e3)}s)`);
2518
+ return { hibernate: true, idleMs, ...latched ? { keepAwake: true } : {} };
2519
+ }
2520
+ const next = verdict.reason === "unconfirmed" ? deps.checkMs : nextCheckDelay(verdict, request.report, idleMs, deps.checkMs, t);
2521
+ return { hibernate: false, reason: verdict.reason, idleMs, nextCheckMs: next, ...latched ? { keepAwake: true } : {} };
2522
+ }
2523
+ return {
2524
+ check,
2525
+ /** Called when the wrapper exits: true when this exit is the hibernation we approved. */
2526
+ consumeExit(sessionId) {
2527
+ const at = approved.get(sessionId);
2528
+ approved.delete(sessionId);
2529
+ signatures.delete(sessionId);
2530
+ return at !== void 0 && now() - at <= HIBERNATION_IN_FLIGHT_MS * 5;
2531
+ },
2532
+ /** Review P1-2: an approved hibernation whose wrapper has not exited yet. */
2533
+ pendingExit(sessionId) {
2534
+ const at = approved.get(sessionId);
2535
+ return at !== void 0 && now() - at <= HIBERNATION_IN_FLIGHT_MS * 5;
2536
+ },
2537
+ forget(sessionId) {
2538
+ signatures.delete(sessionId);
2539
+ },
2540
+ /** Drop the cached Automations bindings (e.g. after the setting changed). */
2541
+ invalidateBindings() {
2542
+ bindings = null;
2543
+ }
2544
+ };
2545
+ }
2546
+ async function collectAutomationBindings(client, machineId) {
2547
+ const ids = /* @__PURE__ */ new Set();
2548
+ const automations = await client.list(machineId);
2549
+ for (const automation of automations) {
2550
+ const action = automation.action;
2551
+ if (action?.kind === "send" && typeof action.sessionId === "string") ids.add(action.sessionId);
2552
+ if (action?.kind === "spawn" && action.sticky) {
2553
+ for (const sticky of await client.stickies(automation.id)) ids.add(sticky.sessionId);
2554
+ }
2555
+ }
2556
+ return [...ids];
2557
+ }
2558
+ const AUTOMATION_WAKE_TIMEOUT_MS = 6e4;
2559
+ async function waitForSessionLive(sessionId, live, timeoutMs = AUTOMATION_WAKE_TIMEOUT_MS, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), now = Date.now) {
2560
+ const deadline = now() + timeoutMs;
2561
+ while (!live(sessionId)) {
2562
+ if (now() >= deadline) return false;
2563
+ await sleep(250);
2564
+ }
2565
+ return true;
2566
+ }
2567
+
2394
2568
  const CLAUDE_KEYCHAIN_SERVICE_PREFIX = "Claude Code";
2395
2569
  function keychainIdentity(env = process.env, deps = {}) {
2396
2570
  const home = deps.home ?? homedir();
@@ -3536,7 +3710,7 @@ function writeReceipt$1(home, receipt) {
3536
3710
 
3537
3711
  const exec = promisify(execFile);
3538
3712
  const git = async (directory, args) => (await exec("git", ["-C", directory, ...args], { timeout: 3e4, maxBuffer: 2 * 1024 * 1024 })).stdout.trim();
3539
- async function prepareTeamWorktree(home, repository, id) {
3713
+ async function prepareTeamWorktree(home, repository, id, origin = "teams") {
3540
3714
  if (repository === "~") repository = homedir();
3541
3715
  else if (repository.startsWith("~/") || process.platform === "win32" && repository.startsWith("~\\")) repository = join(homedir(), repository.slice(2));
3542
3716
  if (!isAbsolute(repository) || !/^[a-zA-Z0-9_-]{1,128}$/.test(id)) throw new Error("A team task requires an absolute repository path and valid operation id");
@@ -3553,6 +3727,7 @@ async function prepareTeamWorktree(home, repository, id) {
3553
3727
  if (resolve(common) !== resolve(expected)) throw new Error("Team worktree belongs to another repository");
3554
3728
  } else {
3555
3729
  await git(repository, ["worktree", "add", "-b", branch, directory, "HEAD"]);
3730
+ await initializeOwnedWorktree({ source: repository, worktree: directory, branch, origin });
3556
3731
  }
3557
3732
  return { directory, repository, branch };
3558
3733
  }
@@ -4200,6 +4375,35 @@ function createAutomationRunner(deps) {
4200
4375
  }
4201
4376
  })();
4202
4377
  }
4378
+ function wakeThenSend(claimed, sessionId, text, stickyKey) {
4379
+ const { run, automation } = claimed;
4380
+ const item = track(claimed, "send", sessionId);
4381
+ item.waking = true;
4382
+ gating++;
4383
+ void (async () => {
4384
+ try {
4385
+ const woke = await deps.wakeHibernated(sessionId).catch(() => false);
4386
+ if (!tracked.has(run.id) || closed) return;
4387
+ item.waking = false;
4388
+ if (!woke || !deps.live(sessionId)) {
4389
+ await finish(item, { claimId: run.claimId, status: "failed", sessionId, error: `Session ${sessionId} was hibernated and could not be woken in time`, needsAttention: true, attentionReason: "session_wake_failed" });
4390
+ return;
4391
+ }
4392
+ persist({ runId: run.id, automationId: automation.id, kind: "send", phase: "running", claimId: run.claimId, sessionId, ...stickyKey ? { stickyKey } : {} });
4393
+ try {
4394
+ await send(sessionId, text, { localId: `automation-${run.id}` });
4395
+ } catch (error) {
4396
+ await finish(item, { claimId: run.claimId, status: "failed", sessionId, error: clipText(`Message delivery failed: ${error instanceof Error ? error.message : String(error)}`, AUTOMATION_SUMMARY_MAX_CHARS), needsAttention: true, attentionReason: "send_failed" });
4397
+ return;
4398
+ }
4399
+ await reportRunning(item, sessionId, stickyKey);
4400
+ } finally {
4401
+ item.waking = false;
4402
+ gating--;
4403
+ }
4404
+ })();
4405
+ }
4406
+ const wakeable = (sessionId) => !deps.live(sessionId) && !!deps.wakeHibernated && deps.isHibernated?.(sessionId) === true;
4203
4407
  async function perform(claimed, action, context, env) {
4204
4408
  const { run, automation } = claimed;
4205
4409
  const header = automationPromptHeader(automation.name, run.id);
@@ -4227,6 +4431,11 @@ function createAutomationRunner(deps) {
4227
4431
  return;
4228
4432
  }
4229
4433
  if (action.kind === "send") {
4434
+ if (wakeable(action.sessionId)) {
4435
+ wakeThenSend(claimed, action.sessionId, `${header}
4436
+ ${action.prompt}`);
4437
+ return;
4438
+ }
4230
4439
  if (!deps.live(action.sessionId)) {
4231
4440
  await failNow(claimed, "send", `Session ${action.sessionId} is not running on this machine`, "session_not_live", action.sessionId);
4232
4441
  return;
@@ -4255,6 +4464,11 @@ ${action.prompt}`, { localId: `automation-${run.id}` });
4255
4464
  const stickyKey = action.sticky ? renderTemplate(action.sticky.key, context) : void 0;
4256
4465
  if (stickyKey) {
4257
4466
  const bound = claimed.stickies.find((sticky) => sticky.key === stickyKey);
4467
+ if (bound && wakeable(bound.sessionId)) {
4468
+ wakeThenSend(claimed, bound.sessionId, `${header}
4469
+ ${action.prompt}`, stickyKey);
4470
+ return;
4471
+ }
4258
4472
  if (bound && deps.live(bound.sessionId)) {
4259
4473
  persist({ runId: run.id, automationId: automation.id, kind: "send", phase: "running", claimId: run.claimId, sessionId: bound.sessionId, stickyKey });
4260
4474
  try {
@@ -4276,7 +4490,7 @@ ${action.prompt}`, { localId: `automation-${run.id}` });
4276
4490
  }
4277
4491
  if (action.worktree) {
4278
4492
  try {
4279
- directory = (await prepareWorktree(home, directory, `auto-${run.id}`)).directory;
4493
+ directory = (await prepareWorktree(home, directory, `auto-${run.id}`, "automation")).directory;
4280
4494
  } catch (error) {
4281
4495
  await failNow(claimed, "spawn", `Worktree preparation failed: ${error instanceof Error ? error.message : String(error)}`, "worktree_failed");
4282
4496
  return;
@@ -4308,7 +4522,7 @@ ${action.prompt}`, { localId: `automation-${run.id}`, ...meta });
4308
4522
  await finish(item, item.pendingFinal);
4309
4523
  continue;
4310
4524
  }
4311
- if (item.kind === "script") continue;
4525
+ if (item.kind === "script" || item.waking) continue;
4312
4526
  const sessionId = item.sessionId;
4313
4527
  const active = deps.turnActive(sessionId);
4314
4528
  if (active) item.sawTurn = true;
@@ -4526,6 +4740,7 @@ async function startDaemon() {
4526
4740
  let cliUpdateStateRef = null;
4527
4741
  let lastHandoverHold = null;
4528
4742
  let claudeCredentialStoreSetting = (await readSettings()).claudeCredentialStore === "file" ? "file" : "auto";
4743
+ let agentHibernationSetting = (await readSettings()).agentHibernationIdleMs;
4529
4744
  try {
4530
4745
  const homes = await refreshAgentHomes();
4531
4746
  logger.debug(`[DAEMON RUN] Claude config dir: ${describeAgentHome(homes.claudeConfigDir)}; Codex home: ${describeAgentHome(homes.codexHome)}`);
@@ -4612,6 +4827,40 @@ async function startDaemon() {
4612
4827
  const turnActivity = new TurnActivityTracker();
4613
4828
  const backgroundTasks = new BackgroundTaskTracker();
4614
4829
  const peerCoordinator = createPeerCoordinator({ getChildren: () => Array.from(pidToTrackedSession.values()) });
4830
+ const hibernationAutomations = createAutomationsClient({ serverUrl: configuration.serverUrl, token: credentials.token, client: "daemon-hibernate" });
4831
+ const daemonHibernation = createDaemonHibernation({
4832
+ idleMs: () => resolveIdleMs(agentHibernationSetting),
4833
+ checkMs: resolveCheckMs(),
4834
+ tracked: (sessionId, pid) => {
4835
+ const tracked = pidToTrackedSession.get(pid);
4836
+ if (!tracked || tracked.happySessionId !== sessionId) return null;
4837
+ let live = false;
4838
+ try {
4839
+ process.kill(pid, 0);
4840
+ live = true;
4841
+ } catch {
4842
+ live = false;
4843
+ }
4844
+ return { live, ...tracked.spawnedBy ? { spawnedBy: tracked.spawnedBy } : {} };
4845
+ },
4846
+ teamsMember: (sessionId) => teamWorker?.hasSession(sessionId) === true,
4847
+ turnActive: (sessionId) => turnActivity.activeSessions().includes(sessionId),
4848
+ backgroundTasks: (sessionId) => backgroundTasks.count(sessionId),
4849
+ loadAutomationBindings: async () => {
4850
+ try {
4851
+ return await collectAutomationBindings(hibernationAutomations, machineId);
4852
+ } catch (error) {
4853
+ if (isAutomationsUnavailable(error)) return [];
4854
+ throw error;
4855
+ }
4856
+ },
4857
+ log: (message) => logger.debug(`[DAEMON RUN] ${message}`),
4858
+ readKeepAwake: (sessionId) => readPersistedSessions()[sessionId]?.keepAwake === true,
4859
+ writeKeepAwake: (sessionId, value) => {
4860
+ const record = readPersistedSessions()[sessionId];
4861
+ if (record) persistSession(sessionId, { ...record, keepAwake: value || void 0 });
4862
+ }
4863
+ });
4615
4864
  const sessionIdToFinishedSession = /* @__PURE__ */ new Map();
4616
4865
  let teamWorker;
4617
4866
  let automationRunner;
@@ -5225,6 +5474,13 @@ async function startDaemon() {
5225
5474
  };
5226
5475
  const resumeSessionImpl = async (happySessionId, options) => {
5227
5476
  try {
5477
+ if (daemonHibernation.pendingExit(happySessionId)) {
5478
+ const dying = [...pidToTrackedSession.entries()].filter(([, s]) => s.happySessionId === happySessionId).map(([pid]) => pid);
5479
+ const exited = await waitForPidsToExit(dying, isPidAlive);
5480
+ logger.debug(`[DAEMON RUN] resume ${happySessionId}: waited for hibernating wrapper(s) ${dying.join(", ")} \u2192 ${exited ? "exited" : "still alive after timeout"}`);
5481
+ if (!exited) return { type: "error", errorMessage: `Session ${happySessionId} is still going to sleep; try again in a few seconds.` };
5482
+ for (const pid of dying) if (pidToTrackedSession.has(pid)) onChildExited(pid);
5483
+ }
5228
5484
  for (const [pid, live] of pidToTrackedSession.entries()) {
5229
5485
  if (live.happySessionId !== happySessionId) continue;
5230
5486
  if (isPidAlive(pid)) {
@@ -5485,6 +5741,14 @@ async function startDaemon() {
5485
5741
  if (session?.happySessionId) turnActivity.forget(session.happySessionId);
5486
5742
  if (session?.happySessionId) backgroundTasks.forget(session.happySessionId);
5487
5743
  if (session?.happySessionId) peerCoordinator.forget(session.happySessionId);
5744
+ if (session?.happySessionId && daemonHibernation.consumeExit(session.happySessionId)) {
5745
+ const persisted2 = readPersistedSessions()[session.happySessionId];
5746
+ if (persisted2) {
5747
+ const at = Date.now();
5748
+ persistSession(session.happySessionId, { ...persisted2, savedAt: at, hibernatedAt: at });
5749
+ }
5750
+ logger.debug(`[DAEMON RUN] Session ${session.happySessionId} hibernated (PID ${pid} exited)`);
5751
+ }
5488
5752
  if (session?.happySessionId && session.encryption) {
5489
5753
  sessionIdToFinishedSession.set(session.happySessionId, session);
5490
5754
  logger.debug(`[DAEMON RUN] Process PID ${pid} exited, preserved session ${session.happySessionId} for resume`);
@@ -5580,6 +5844,7 @@ async function startDaemon() {
5580
5844
  onRateLimits: (report) => {
5581
5845
  apiMachineRef?.reportRateLimits(report);
5582
5846
  },
5847
+ onHibernateCheck: (body) => daemonHibernation.check(body),
5583
5848
  listPeers: () => peerCoordinator.list(),
5584
5849
  // B-505: `daemon list` shows which sessions have a turn in flight, so an
5585
5850
  // operator can check the WHOLE machine before a supervised restart.
@@ -5701,6 +5966,13 @@ async function startDaemon() {
5701
5966
  setStore: (store) => claudeAuthService.setStore(store)
5702
5967
  });
5703
5968
  claudeAuthService.start();
5969
+ apiMachine.setAgentHibernationHandlers(resolveIdleMs(agentHibernationSetting), async (requested) => {
5970
+ const value = requested <= 0 ? 0 : settingIdleMs(requested);
5971
+ await updateSettings((current) => ({ ...current, agentHibernationIdleMs: value }));
5972
+ agentHibernationSetting = value;
5973
+ daemonHibernation.invalidateBindings();
5974
+ return resolveIdleMs(agentHibernationSetting);
5975
+ });
5704
5976
  apiMachine.connect();
5705
5977
  if (identityConflict?.confidence === "weak") {
5706
5978
  void apiMachine.updateMachineMetadata((current) => ({
@@ -5848,18 +6120,32 @@ async function startDaemon() {
5848
6120
  live: (id) => [...pidToTrackedSession.values()].some((s) => s.happySessionId === id && isPidAlive(s.pid)),
5849
6121
  turnActive: (id) => turnActivity.activeSessions().includes(id),
5850
6122
  backgroundTasks: (id) => backgroundTasks.count(id),
6123
+ // B-587 review P2-5: a hibernated target is woken (resume) and the send
6124
+ // waits until its wrapper is back; anything else stays session_not_live.
6125
+ isHibernated: (id) => {
6126
+ const record = readPersistedSessions()[id];
6127
+ return !!record && typeof record.hibernatedAt === "number" && record.hibernatedAt >= record.savedAt;
6128
+ },
6129
+ wakeHibernated: async (id) => {
6130
+ const result = await resumeSession(id);
6131
+ if (result.type !== "success") return false;
6132
+ return waitForSessionLive(id, (sid) => [...pidToTrackedSession.values()].some((s) => s.happySessionId === sid && isPidAlive(s.pid)));
6133
+ },
5851
6134
  log: (message) => logger.debug(`[DAEMON RUN] ${message}`)
5852
6135
  });
5853
6136
  void apiMachine.updateMachineMetadata((current) => ({
5854
6137
  ...current ?? initialMachineMetadata,
5855
6138
  teamsVersion: 1,
5856
- teamLaunchVersion: 1
6139
+ teamLaunchVersion: 1,
6140
+ // B-586: this daemon serves the worktree-* RPCs (web gates 「在新 worktree 中」 on it).
6141
+ worktreeVersion: WORKTREE_CAPABILITY_VERSION
5857
6142
  })).catch(() => logger.debug("[DAEMON RUN] Teams capability publication will retry on reconnect"));
5858
6143
  const cleanupAndShutdown = async (source, errorMessage) => {
5859
6144
  logger.debug(`[DAEMON RUN] Starting proper cleanup (source: ${source}, errorMessage: ${errorMessage})...`);
5860
6145
  const scrollbackFlush = apiMachine.flushTerminalScrollback();
5861
6146
  teamWorker?.stop();
5862
6147
  automationRunner?.stop({ killScripts: true });
6148
+ currentWorktreeService()?.stopAll();
5863
6149
  if (restartOnStaleVersionAndHeartbeat) {
5864
6150
  clearInterval(restartOnStaleVersionAndHeartbeat);
5865
6151
  logger.debug("[DAEMON RUN] Health check interval cleared");