very-happy-cli 0.2.177 → 0.2.179

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 (203) hide show
  1. package/dist/{AcpBackend-B0K0WrtW.mjs → AcpBackend-CHp3y7cb.mjs} +135 -16
  2. package/dist/{AcpBackend-B-ny68XM.cjs → AcpBackend-DFipFF7-.cjs} +135 -16
  3. package/dist/{AcpSessionManager-CjdJLofq.cjs → AcpSessionManager-0zpvRJXc.cjs} +38 -4
  4. package/dist/{AcpSessionManager-DykjzBM4.mjs → AcpSessionManager-d2-rKWWa.mjs} +38 -4
  5. package/dist/{BasePermissionHandler-DR6nxuEn.cjs → BasePermissionHandler-CH3zuEkA.cjs} +5 -2
  6. package/dist/{BasePermissionHandler-hdY7kTqX.mjs → BasePermissionHandler-DdZBYIR4.mjs} +5 -2
  7. package/dist/acpSessionResume-DTGmAPLt.mjs +67 -0
  8. package/dist/acpSessionResume-oiCBnAVA.cjs +74 -0
  9. package/dist/{agentHome-BdTXEUPe.cjs → agentHome-BWcz8mz0.cjs} +5 -5
  10. package/dist/{agentHome-GRN2VfHv.mjs → agentHome-CghLvL_1.mjs} +5 -5
  11. package/dist/{api-BWX10o97.cjs → api-Cmjfr8Z7.cjs} +29 -261
  12. package/dist/{api-CKBViqI3.mjs → api-CzwFpJQc.mjs} +22 -254
  13. package/dist/{apiMachine-DttO4UFj.mjs → apiMachine-DJkTEiqy.mjs} +53 -16
  14. package/dist/{apiMachine-BYYFGgFs.cjs → apiMachine-G6OogT08.cjs} +53 -16
  15. package/dist/{attachmentContent-cPVF463_.mjs → attachmentContent-B2os4HbA.mjs} +2 -2
  16. package/dist/{attachmentContent-kJKXpkMX.cjs → attachmentContent-Bo0UAsSu.cjs} +4 -4
  17. package/dist/{auth-BmESeKuM.mjs → auth-BS6PaOOG.mjs} +6 -6
  18. package/dist/{auth-CTECt2Oz.cjs → auth-D6bBUwZa.cjs} +6 -6
  19. package/dist/{auth-CKdXb9zp.mjs → auth-DMX0xPNK.mjs} +9 -9
  20. package/dist/{auth-DNxVmVbn.cjs → auth-HEhRaNgL.cjs} +9 -9
  21. package/dist/{authRelay-DSAvg1uv.mjs → authRelay-DhQhkBvX.mjs} +1 -1
  22. package/dist/{authRelay-BdYkC1Po.cjs → authRelay-Dy1qU9td.cjs} +1 -0
  23. package/dist/{auto-D1ypjjfx.cjs → auto-C6I55iOh.cjs} +19 -18
  24. package/dist/{auto-Ch3203qd.mjs → auto-Cl1SEDcD.mjs} +19 -18
  25. package/dist/{bootstrap-6OI698q9.cjs → bootstrap-exVucYav.cjs} +2 -2
  26. package/dist/{bootstrap-C0s2bPFQ.mjs → bootstrap-iuyufnp3.mjs} +2 -2
  27. package/dist/{browser-DG6Uof5O.cjs → browser-BohJK12g.cjs} +1 -1
  28. package/dist/{browser-BlLWZUMx.mjs → browser-CSYum7xH.mjs} +1 -1
  29. package/dist/{claudeLocal-CcWcKnoo.mjs → claudeLocal-Dq_R3Ax_.mjs} +6 -5
  30. package/dist/{claudeLocal-CemsIArT.cjs → claudeLocal-re4yjSTx.cjs} +6 -5
  31. package/dist/{claudeLocalLauncher-A4VuevIi.cjs → claudeLocalLauncher-B4hJHpCA.cjs} +11 -10
  32. package/dist/{claudeLocalLauncher-7p6y88nj.mjs → claudeLocalLauncher-CN67lN7-.mjs} +11 -10
  33. package/dist/{claudeSessionFork-BtROOjqf.mjs → claudeSessionFork-BihfD0Ik.mjs} +1 -1
  34. package/dist/{claudeSessionFork-CbDfm8Fz.cjs → claudeSessionFork-DiSMYerV.cjs} +1 -1
  35. package/dist/{client-DyvBTYee.cjs → client-BKcK1Bi-.cjs} +3 -3
  36. package/dist/client-BhoEBnuN.mjs +71 -0
  37. package/dist/{client-COmgDDy0.cjs → client-CuVdN6PP.cjs} +2 -2
  38. package/dist/{client-BPMWutfs.mjs → client-DuTDwWSQ.mjs} +3 -3
  39. package/dist/client-ZjOsn6nZ.cjs +76 -0
  40. package/dist/{client-DG5ndWLw.mjs → client-wo9nbxuf.mjs} +2 -2
  41. package/dist/codex/happyMcpStdioBridge.cjs +25 -16
  42. package/dist/codex/happyMcpStdioBridge.mjs +25 -16
  43. package/dist/{codexAppServerClient-D-Z8qSfI.mjs → codexAppServerClient-BK3zra_1.mjs} +3 -3
  44. package/dist/{codexAppServerClient-R24WZZfg.cjs → codexAppServerClient-Dt5zxrun.cjs} +3 -3
  45. package/dist/{codexCommand-CVTkZJ1o.mjs → codexCommand-B6pY7CMh.mjs} +66 -61
  46. package/dist/{codexCommand-6hW19gsq.cjs → codexCommand-CAZ1SLjg.cjs} +89 -84
  47. package/dist/{codexTermination-CCIfwzcx.mjs → codexTermination-Cd1Eon_4.mjs} +1 -1
  48. package/dist/{codexTermination-BBU7e92y.cjs → codexTermination-DmGbHxcD.cjs} +1 -1
  49. package/dist/{config-CvsNChKX.mjs → config-2oMG_fEI.mjs} +3 -3
  50. package/dist/{config-DhdrvOLV.cjs → config-B0uK6K7n.cjs} +3 -3
  51. package/dist/{configuration-DZPy0T9Z.cjs → configuration-CMHZnp6G.cjs} +1 -1
  52. package/dist/{configuration-D55F0t16.mjs → configuration-WMi4idBB.mjs} +1 -1
  53. package/dist/{connect-CwCXMRmD.mjs → connect-BLVHhHzA.mjs} +15 -15
  54. package/dist/{connect-Wz-XZYXW.cjs → connect-uaglGrde.cjs} +15 -15
  55. package/dist/{context-BKbrZ55r.cjs → context-DXzU5bFM.cjs} +1 -1
  56. package/dist/{context-CCRpVXFo.mjs → context-DploEcoN.mjs} +1 -1
  57. package/dist/{controlClient-C4xB5J6O.mjs → controlClient-BWUJrj3t.mjs} +3 -3
  58. package/dist/{controlClient-SX8gSza2.cjs → controlClient-C-5qCt8W.cjs} +3 -3
  59. package/dist/{createSessionMetadata-Bi-m0Y_O.mjs → createSessionMetadata-3uXrJgOW.mjs} +2 -2
  60. package/dist/{createSessionMetadata-BCFmYlBo.cjs → createSessionMetadata-BkIzHALd.cjs} +2 -2
  61. package/dist/{defaultPermissionMode-wBcbBezm.mjs → defaultPermissionMode-BzxLh20a.mjs} +2 -2
  62. package/dist/{defaultPermissionMode-DMBEnXll.cjs → defaultPermissionMode-pS3vmiSg.cjs} +2 -2
  63. package/dist/{deterministicJson-ChGfQEF6.cjs → deterministicJson-B8z2GPi9.cjs} +220 -14
  64. package/dist/{deterministicJson-BkQETt8_.mjs → deterministicJson-D_whDMFd.mjs} +217 -12
  65. package/dist/{doctor-BsN3JZJn.cjs → doctor-Br1Kcy2J.cjs} +8 -8
  66. package/dist/{doctor-B9c2C9dF.mjs → doctor-CmtSsR2-.mjs} +8 -8
  67. package/dist/{downloadTarget-Dj3WoVJa.cjs → downloadTarget-BQJK_6oH.cjs} +6 -6
  68. package/dist/{downloadTarget-ByXzbDK4.mjs → downloadTarget-BoNwTIH_.mjs} +6 -6
  69. package/dist/{ensureDaemonRunning-7Wb8M7Lv.cjs → ensureDaemonRunning-BRUmsq6J.cjs} +5 -5
  70. package/dist/{ensureDaemonRunning--HYzs5Ce.mjs → ensureDaemonRunning-Czo9IHJQ.mjs} +5 -5
  71. package/dist/{handleResumeCommand-DHddBkNJ.mjs → handleResumeCommand-C8thKjqf.mjs} +22 -6
  72. package/dist/{handleResumeCommand-OmuUGYjQ.cjs → handleResumeCommand-tKD_Hpxc.cjs} +22 -6
  73. package/dist/{index-CrR4JISa.cjs → index-B0UjHlAe.cjs} +5 -5
  74. package/dist/{index-BzJNDsJq.mjs → index-BTxHphpV.mjs} +254 -49
  75. package/dist/index-BiyC7cZ3.mjs +18 -0
  76. package/dist/{index-De8L5lFK.cjs → index-C6O2vVjm.cjs} +156 -34
  77. package/dist/index-CUuc6iCn.cjs +24 -0
  78. package/dist/{index-Dhl6_bw7.mjs → index-CdQI0C9p.mjs} +5 -5
  79. package/dist/{index-D9NoYc5I.cjs → index-D09T1m8Y.cjs} +3 -3
  80. package/dist/{index-CEm0MYiS.mjs → index-D3bidoG8.mjs} +3 -3
  81. package/dist/{index-BRJzH4sc.cjs → index-DMqDMT1Q.cjs} +257 -52
  82. package/dist/{index-DMy3OCBe.mjs → index-DPOa4NhL.mjs} +154 -35
  83. package/dist/index.cjs +2 -2
  84. package/dist/index.mjs +2 -2
  85. package/dist/{install-BdvKiOQw.mjs → install-BX3lv3NO.mjs} +1 -1
  86. package/dist/{install-Cf6AFSWC.cjs → install-BXvf2E3o.cjs} +1 -1
  87. package/dist/{install-1qn-D9FS.cjs → install-CYRZxS87.cjs} +3 -3
  88. package/dist/{install-BDIUtPXi.mjs → install-hnve_9vq.mjs} +3 -3
  89. package/dist/lib.cjs +14 -14
  90. package/dist/lib.d.cts +65 -1
  91. package/dist/lib.d.mts +65 -1
  92. package/dist/lib.mjs +14 -14
  93. package/dist/{lidState-BqVsw7H1.mjs → lidState-Bb8fgXg3.mjs} +2 -2
  94. package/dist/{lidState-DxbK0qfu.cjs → lidState-Dv2wwFTj.cjs} +2 -2
  95. package/dist/{localHappyAgentAuth-D5tANdRD.cjs → localHappyAgentAuth-DjYvkXvV.cjs} +2 -2
  96. package/dist/{localHappyAgentAuth-Ce8kO2yc.mjs → localHappyAgentAuth-NEU7fax7.mjs} +2 -2
  97. package/dist/{logger-13cBr_ew.mjs → logger-BtVhHnD8.mjs} +2 -2
  98. package/dist/{logger-LvwVeATU.cjs → logger-C1GWx3gi.cjs} +2 -2
  99. package/dist/{machineMetadata-29h7vgf4.cjs → machineMetadata-CLHS9sv_.cjs} +3 -3
  100. package/dist/{machineMetadata-dMida2qq.mjs → machineMetadata-D-g--oU_.mjs} +3 -3
  101. package/dist/{main-x4nAhdH5.mjs → main-B2LWV8DI.mjs} +59 -46
  102. package/dist/{main-DpM5jaFH.cjs → main-CWhSsbtU.cjs} +59 -46
  103. package/dist/{mcp-DQv3caXs.cjs → mcp-CARUsXHV.cjs} +15 -15
  104. package/dist/{mcp-DMiFGYMT.mjs → mcp-ext92q3Y.mjs} +15 -15
  105. package/dist/{mirrorProtocol-Bz8tEabR.mjs → mirrorProtocol-BwYibqry.mjs} +3 -3
  106. package/dist/{mirrorProtocol-BfrERW7Z.cjs → mirrorProtocol-DEy2g1CB.cjs} +3 -3
  107. package/dist/{package-CjlsAaRe.mjs → package-BPPebGQF.mjs} +7 -7
  108. package/dist/{package-Ch9WGDV_.cjs → package-SgqTYsjn.cjs} +7 -7
  109. package/dist/panels-BZ0_Tt7B.mjs +137 -0
  110. package/dist/panels-D1c7q2dD.cjs +142 -0
  111. package/dist/{peerTools-CxmrKnfV.mjs → peerTools-CWKzcQ7u.mjs} +60 -10
  112. package/dist/{peerTools-DtGKWli5.cjs → peerTools-DRQETXaz.cjs} +60 -9
  113. package/dist/{persistence-DXbKOHxl.cjs → persistence-BegE7NPa.cjs} +14 -3
  114. package/dist/{persistence-C_tYtOqK.mjs → persistence-Cr-wutZ4.mjs} +14 -4
  115. package/dist/{piRunnerArgs-BVRZe2AR.cjs → piRunnerArgs-Cs-378Vz.cjs} +8 -2
  116. package/dist/{piRunnerArgs-BpHc-JZl.mjs → piRunnerArgs-DwvM_yWA.mjs} +7 -1
  117. package/dist/{piRuntime-D7eio8Ix.cjs → piRuntime-BG-1td_n.cjs} +2 -2
  118. package/dist/{piRuntime-DOdGF395.mjs → piRuntime-Bue5mnlc.mjs} +2 -2
  119. package/dist/{piTerminal-dpxz4Q8D.mjs → piTerminal-B5x9X5yV.mjs} +18 -18
  120. package/dist/{piTerminal-y_PRo2NY.cjs → piTerminal-G4z-xVyy.cjs} +18 -18
  121. package/dist/processTreeSnapshot-CuLJDNC-.mjs +101 -0
  122. package/dist/processTreeSnapshot-mDbnuojn.cjs +105 -0
  123. package/dist/prompt-BOouDaTM.mjs +99 -0
  124. package/dist/prompt-lgF9IE82.cjs +105 -0
  125. package/dist/{attachmentLimits-Di1Z93lN.mjs → pushNotifications-BdFjDjQe.mjs} +303 -3
  126. package/dist/{attachmentLimits-DtFqqiwR.cjs → pushNotifications-DaLQUyi0.cjs} +304 -2
  127. package/dist/{index-DFPT4HOO.cjs → query-Ctfg-5gy.cjs} +25 -5
  128. package/dist/{index-CEjJnq05.mjs → query-DYP_W1wp.mjs} +26 -3
  129. package/dist/{rateLimitWindows-DYHDGuzQ.mjs → rateLimitWindows-CuEqk_0g.mjs} +1 -1
  130. package/dist/{rateLimitWindows-DFnMU2Vt.cjs → rateLimitWindows-Dj_8voBK.cjs} +1 -1
  131. package/dist/{registerCommonHandlers-D8OMpBbQ.mjs → registerCommonHandlers-BAlP7SGc.mjs} +2 -2
  132. package/dist/{registerCommonHandlers-60VuTkdg.cjs → registerCommonHandlers-Cj084Sg7.cjs} +2 -2
  133. package/dist/{registerKillSessionHandler-Drhf7-Vz.mjs → registerKillSessionHandler-PD0jWtQo.mjs} +6 -6
  134. package/dist/{registerKillSessionHandler-pqChBKwO.cjs → registerKillSessionHandler-qMju0ZfF.cjs} +6 -6
  135. package/dist/{remoteSessionClient-B7NvjHD3.cjs → remoteSessionClient-B7i7MkYV.cjs} +5 -5
  136. package/dist/{remoteSessionClient-D01Hso2-.mjs → remoteSessionClient-Bn2qu5C5.mjs} +5 -5
  137. package/dist/{reportProgressTool-Du_zAK4h.cjs → reportProgressTool-CM1JFAHg.cjs} +84 -2
  138. package/dist/{reportProgressTool-B203EZCR.mjs → reportProgressTool-gHItlSzz.mjs} +82 -3
  139. package/dist/{resources-JDPugcDq.cjs → resources-CvIlkzpP.cjs} +30 -0
  140. package/dist/{resources-BdFBQi8r.mjs → resources-y9jfyO-_.mjs} +30 -0
  141. package/dist/{run-DX4Zs3Ug.mjs → run-BM4TxiyN.mjs} +249 -45
  142. package/dist/{run-DZ5jU53c.cjs → run-CNXwIe0A.cjs} +263 -59
  143. package/dist/{runClaude-ClRhHpwR.cjs → runClaude-CWhj2V4Q.cjs} +37 -41
  144. package/dist/{runClaude-CgPHXP0L.mjs → runClaude-C_3I8hvR.mjs} +37 -41
  145. package/dist/{runClaudeDeps-D2v_WDSL.cjs → runClaudeDeps-B81cOKnH.cjs} +295 -157
  146. package/dist/{runClaudeDeps-Dz2iydq4.mjs → runClaudeDeps-QGrOeDe2.mjs} +295 -160
  147. package/dist/{runGemini-DBXxpoY8.mjs → runGemini-BEdWEZLR.mjs} +61 -55
  148. package/dist/{runGemini-BtZqGFkp.cjs → runGemini-CgRLYbt5.cjs} +61 -55
  149. package/dist/{runOpenClaw-D8q8G57u.cjs → runOpenClaw-C1NVmzOL.cjs} +19 -19
  150. package/dist/{runOpenClaw-BOHpzCEU.mjs → runOpenClaw-DdQZAYj1.mjs} +19 -19
  151. package/dist/{sandbox-C452Vrsc.mjs → sandbox-DjQUdCMG.mjs} +5 -5
  152. package/dist/{sandbox-Cu9mMzjx.cjs → sandbox-nocIjliq.cjs} +5 -5
  153. package/dist/selfCheck-CjCF4C3v.mjs +85 -0
  154. package/dist/{selfCheck-gKa3uVr1.cjs → selfCheck-DCt4Uzbq.cjs} +36 -35
  155. package/dist/{send-B8HARi7x.mjs → send-Ct7X4pPU.mjs} +9 -9
  156. package/dist/{send-2Vb5eppI.cjs → send-Dydf_hwZ.cjs} +9 -9
  157. package/dist/{server-Db9Wuam3.cjs → server-CosABFbd.cjs} +7 -7
  158. package/dist/{server-BBWCIZyS.mjs → server-DTQGZMxh.mjs} +5 -5
  159. package/dist/{sessionLock-6qL_N6Rn.cjs → sessionLock-DokGab2R.cjs} +16 -3
  160. package/dist/{sessionLock-ZfvFVdUi.mjs → sessionLock-WYIyaVO4.mjs} +16 -4
  161. package/dist/{sessionOps-CdgbEJgf.mjs → sessionOps-BIGgRube.mjs} +11 -6
  162. package/dist/{sessionOps-Dmt7WUUs.cjs → sessionOps-S-qPBLFf.cjs} +11 -6
  163. package/dist/{sessionScanner-CQL_WSaC.cjs → sessionScanner-CIMM2hvZ.cjs} +3 -3
  164. package/dist/{sessionScanner-CNVaSNOn.mjs → sessionScanner-o5hnMi5e.mjs} +3 -3
  165. package/dist/{sessions-DTomHfFg.mjs → sessions-BJHEZpi2.mjs} +40 -18
  166. package/dist/{sessions-BJblG_Hx.cjs → sessions-JchI1w3z.cjs} +40 -17
  167. package/dist/{setupOfflineReconnection-DVA0VpQL.cjs → setupOfflineReconnection-CNiAt5ZP.cjs} +2 -2
  168. package/dist/{setupOfflineReconnection-C5trsV-j.mjs → setupOfflineReconnection-DMiBO2y9.mjs} +2 -2
  169. package/dist/{spawn-DRyNAqD8.cjs → spawn-6PD7nnoC.cjs} +49 -18
  170. package/dist/{spawn-CQJFgoOq.mjs → spawn-DgvUNYEo.mjs} +49 -18
  171. package/dist/{spawnAgents-CCjJifAW.cjs → spawnAgents-DsXgegHM.cjs} +37 -1
  172. package/dist/spawnAgents-P006Hqio.mjs +79 -0
  173. package/dist/{spawnHappyCLI-B_0RWxD4.mjs → spawnHappyCLI-CCOrEtf9.mjs} +1 -1
  174. package/dist/{spawnHappyCLI-ChniczJ5.cjs → spawnHappyCLI-Dywezwk6.cjs} +1 -1
  175. package/dist/{specialCommands-DkdFJi4N.mjs → specialCommands-DPcd9edP.mjs} +3 -3
  176. package/dist/{specialCommands-DbntVs0d.cjs → specialCommands-QxPpkGKf.cjs} +3 -3
  177. package/dist/{startFileWatcher-UQyTSRAP.mjs → startFileWatcher-DghDOCO4.mjs} +1 -1
  178. package/dist/{startFileWatcher-C292fhra.cjs → startFileWatcher-RECH5qY8.cjs} +1 -1
  179. package/dist/{streamRelay-_qCd873P.mjs → streamRelay-DMV_TXfS.mjs} +1 -1
  180. package/dist/{streamRelay-Cx01enfe.cjs → streamRelay-DlUWKUpo.cjs} +1 -1
  181. package/dist/{sync-C3p7-KLn.mjs → sync-CSe0Rf45.mjs} +1 -1
  182. package/dist/{sync-C7sxoUYG.cjs → sync-D23jbqVa.cjs} +1 -1
  183. package/dist/{systemPrompt-DtibzbRU.cjs → systemPrompt-BOy4kU4P.cjs} +4 -3
  184. package/dist/{systemPrompt-CdHOlyVW.mjs → systemPrompt-CFNKnh65.mjs} +4 -3
  185. package/dist/{teams-ujXr3AFn.mjs → teams-DyY669f0.mjs} +9 -9
  186. package/dist/{teams-D7O7TpVU.cjs → teams-Ov2BDT-A.cjs} +9 -9
  187. package/dist/{time-yEL6wHUF.mjs → time-65DcU6Jx.mjs} +1 -1
  188. package/dist/{time-Dg5tVB8S.cjs → time-CrwIMHta.cjs} +1 -1
  189. package/dist/{titleGenerator-BMEaDTwU.cjs → titleGenerator-CS_rh2_J.cjs} +9 -8
  190. package/dist/{titleGenerator-Dr-BtjzO.mjs → titleGenerator-CiAMxf7s.mjs} +9 -8
  191. package/dist/{todo-CvJe4M2C.mjs → todo-BDONw0sK.mjs} +7 -7
  192. package/dist/{todo-CUcFamGs.cjs → todo-KY-okGii.cjs} +7 -7
  193. package/dist/{tools-BrM3bZW5.mjs → tools-D8-PnZEG.mjs} +1 -1
  194. package/dist/{tools-DDKTB5aQ.cjs → tools-_w52DZG6.cjs} +1 -1
  195. package/dist/{uninstall-7oLuhYIu.cjs → uninstall-8vnLN-IE.cjs} +3 -3
  196. package/dist/{uninstall-CEcMMQGz.mjs → uninstall-_fjGRP9b.mjs} +3 -3
  197. package/dist/webPanels-B2_C2-3g.mjs +49 -0
  198. package/dist/webPanels-FCgFKvVe.cjs +53 -0
  199. package/package.json +7 -7
  200. package/dist/selfCheck-BAvqBwBR.mjs +0 -84
  201. package/dist/sessionModeFile-CWVq8AT9.mjs +0 -32
  202. package/dist/sessionModeFile-CsLtn_PL.cjs +0 -36
  203. package/dist/spawnAgents-BjtmjBvP.mjs +0 -45
@@ -1,83 +1,86 @@
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-Bz8tEabR.mjs';
2
- import { P as PI_ADAPTER_INSTALL_HINT, s as sanitizeSpawnModel } from './piRunnerArgs-BpHc-JZl.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-BwYibqry.mjs';
2
+ import { P as PI_ADAPTER_INSTALL_HINT, s as sanitizeSpawnModel } from './piRunnerArgs-DwvM_yWA.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-CKBViqI3.mjs';
7
- import { S as SPAWN_AGENTS, i as isSpawnAgent, s as sanitizeSpawnPermissionMode, r as resolveSpawnPermissionMode, a as resolveFirstMessageMeta } from './spawnAgents-BjtmjBvP.mjs';
8
- import { l as logger } from './logger-13cBr_ew.mjs';
6
+ import { T as TurnActivityTracker, A as ApiClient } from './api-CzwFpJQc.mjs';
7
+ import { S as SPAWN_AGENTS, i as isSpawnAgent, s as sanitizeSpawnPermissionMode, r as resolveSpawnPermissionMode, a as resolveFirstMessageMeta, j as joinProject } from './spawnAgents-P006Hqio.mjs';
8
+ import { l as logger } from './logger-BtVhHnD8.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-CEm0MYiS.mjs';
12
- import { a as authAndSetupMachineIfNeeded } from './auth-BmESeKuM.mjs';
13
- import { c as configuration, f as ensurePrivateDirectorySync, w as writePrivateFileSync } from './configuration-D55F0t16.mjs';
11
+ import { p as pruneStaleCompileCaches } from './index-D3bidoG8.mjs';
12
+ import { a as authAndSetupMachineIfNeeded } from './auth-BS6PaOOG.mjs';
13
+ import { c as configuration, f as ensurePrivateDirectorySync, w as writePrivateFileSync } from './configuration-WMi4idBB.mjs';
14
14
  import { spawn, execSync } from 'child_process';
15
- import { p as packageJson } from './package-CjlsAaRe.mjs';
16
- import { g as globalPrefixForPackage, a as getEnvironmentInfo } from './doctor-B9c2C9dF.mjs';
17
- import { s as spawnHappyCLI } from './spawnHappyCLI-B_0RWxD4.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-C_tYtOqK.mjs';
19
- import { i as isDaemonRunningCurrentlyInstalledHappyVersion, b as stopDaemon, o as cleanupDaemonState } from './controlClient-C4xB5J6O.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-CdgbEJgf.mjs';
15
+ import { p as packageJson } from './package-BPPebGQF.mjs';
16
+ import { g as globalPrefixForPackage, a as getEnvironmentInfo } from './doctor-CmtSsR2-.mjs';
17
+ import { s as spawnHappyCLI } from './spawnHappyCLI-CCOrEtf9.mjs';
18
+ import { c 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 rewriteCredentialsForRelay, g as readCredentials, E as releaseDaemonLock } from './persistence-Cr-wutZ4.mjs';
19
+ import { i as isDaemonRunningCurrentlyInstalledHappyVersion, b as stopDaemon, o as cleanupDaemonState } from './controlClient-BWUJrj3t.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-BIGgRube.mjs';
21
21
  import fastify from 'fastify';
22
22
  import { z } from 'zod';
23
23
  import { validatorCompiler, serializerCompiler } from 'fastify-type-provider-zod';
24
- import { d as decodeBase64, e as encodeBase64, h as decrypt } from './authRelay-DSAvg1uv.mjs';
24
+ import { d as decodeBase64, s as sameRelay, e as encodeBase64, h as decrypt } from './authRelay-DhQhkBvX.mjs';
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, c as BACKGROUND_TASK_DESCRIPTION_MAX, d as BackgroundTaskTracker } from './backgroundTaskActivity-BVwJBl02.mjs';
28
- import { b as sanitizeRateLimitReport } from './rateLimitWindows-DYHDGuzQ.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-CxmrKnfV.mjs';
28
+ import { b as sanitizeRateLimitReport } from './rateLimitWindows-CuEqk_0g.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-CWKzcQ7u.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-D01Hso2-.mjs';
32
- import { assistantHome, bootstrapAssistantHome } from './bootstrap-C0s2bPFQ.mjs';
33
- import { refreshAgentHomes, locateClaudeConversation, agentHomeSpawnEnv } from './index-Dhl6_bw7.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-Bn2qu5C5.mjs';
32
+ import { assistantHome, bootstrapAssistantHome } from './bootstrap-iuyufnp3.mjs';
33
+ import { refreshAgentHomes, locateClaudeConversation, agentHomeSpawnEnv } from './index-CdQI0C9p.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-dMida2qq.mjs';
40
- import { buildResumeLaunch } from './handleResumeCommand-DHddBkNJ.mjs';
39
+ import { g as getInitialMachineMetadata, a as getStartupCliAvailability } from './machineMetadata-D-g--oU_.mjs';
40
+ import { buildResumeLaunch } from './handleResumeCommand-C8thKjqf.mjs';
41
+ import { n as normalizeWebPanels } from './webPanels-B2_C2-3g.mjs';
42
+ import { w as ServerMigrateNoticeSchema, x as AUTOMATION_SUMMARY_MAX_CHARS, y as AUTOMATION_PRECHECK_OUTPUT_MAX_CHARS, z as AUTOMATION_PRECHECK_DEFAULT_TIMEOUT_MS, b as AUTOMATION_PRECHECK_MAX_TIMEOUT_MS, D as AUTOMATION_CLAIM_MAX_RUNS, E as AUTOMATION_DAEMON_CAPABILITY_PRECHECK, F as AUTOMATION_DEFAULT_LEASE_MS, i as isAutomationRunTerminal } from './index-DPOa4NhL.mjs';
41
43
  import { access, symlink, readFile, rm, unlink, readlink, lstat, constants, stat, open } from 'node:fs/promises';
42
44
  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-DG5ndWLw.mjs';
45
+ import { P as ProjectsUnsupportedError, c as createProjectsClient } from './client-BhoEBnuN.mjs';
46
+ import { c as createAutomationsClient, i as isAutomationsUnavailable, d as AutomationsRequestError } from './client-wo9nbxuf.mjs';
44
47
  import { createRequire } from 'node:module';
45
48
  import { g as getProjectPath } from './path-D2wdaNSk.mjs';
46
49
  import { b as extractClaudeEditPaths } from './editPaths-BVfS_FFL.mjs';
47
- import { s as startFileWatcher } from './startFileWatcher-UQyTSRAP.mjs';
48
- import { I as InvalidateSync } from './sync-C3p7-KLn.mjs';
50
+ import { s as startFileWatcher } from './startFileWatcher-DghDOCO4.mjs';
51
+ import { I as InvalidateSync } from './sync-CSe0Rf45.mjs';
49
52
  import { R as RawJSONLinesSchema } from './types-CkqAACXx.mjs';
50
53
  import { t as tmuxArgs, a as scrubTmuxClientEnv, s as shellescape } from './tmuxSocket-B8Yx20sT.mjs';
51
- import { p as processIdentityFields, r as readSessionLock, t as terminateProcess } from './sessionLock-ZfvFVdUi.mjs';
54
+ import { p as processIdentityFields, r as readSessionLock, t as terminateProcess, d as terminateProcessTree } from './sessionLock-WYIyaVO4.mjs';
52
55
  import { findAllHappyProcesses } from './doctor-BPkYWSuq.mjs';
53
- import { T as TEAM_SKILL } from './resources-BdFBQi8r.mjs';
56
+ import { T as TEAM_SKILL } from './resources-y9jfyO-_.mjs';
54
57
  import { promisify } from 'node:util';
55
- import { u as AUTOMATION_SUMMARY_MAX_CHARS, v as AUTOMATION_PRECHECK_OUTPUT_MAX_CHARS, w as AUTOMATION_PRECHECK_DEFAULT_TIMEOUT_MS, a as AUTOMATION_PRECHECK_MAX_TIMEOUT_MS, x as AUTOMATION_CLAIM_MAX_RUNS, y as AUTOMATION_DAEMON_CAPABILITY_PRECHECK, z as AUTOMATION_DEFAULT_LEASE_MS, i as isAutomationRunTerminal } from './index-DMy3OCBe.mjs';
56
58
  import { c as clipText, r as renderAction, b as renderTemplate } from './template-CiOPa2rd.mjs';
57
59
  import { d as detectDaemonSupervisor } from './daemonSupervisor-C6urv3_8.mjs';
58
60
  import { d as describeAgentHome } from './loginShellEnv-Dw8M7tkI.mjs';
59
- import './sessionModeFile-CWVq8AT9.mjs';
60
- import './lidState-BqVsw7H1.mjs';
61
+ import './acpSessionResume-DTGmAPLt.mjs';
62
+ import './lidState-Bb8fgXg3.mjs';
61
63
  import 'os';
62
64
  import 'node:events';
63
65
  import 'socket.io-client';
64
- import './attachmentLimits-Di1Z93lN.mjs';
66
+ import './pushNotifications-BdFjDjQe.mjs';
67
+ import './contentLogMetadata-BlWI0egu.mjs';
65
68
  import './limits-DIo7rEBR.mjs';
66
- import './time-yEL6wHUF.mjs';
67
- import './registerCommonHandlers-D8OMpBbQ.mjs';
69
+ import './time-65DcU6Jx.mjs';
70
+ import './registerCommonHandlers-BAlP7SGc.mjs';
68
71
  import 'util';
69
72
  import 'crypto';
70
73
  import 'cross-spawn';
71
74
  import '@paralleldrive/cuid2';
72
- import './contentLogMetadata-BlWI0egu.mjs';
73
75
  import 'chalk';
74
76
  import 'tweetnacl';
75
- import './browser-BlLWZUMx.mjs';
77
+ import './browser-CSYum7xH.mjs';
76
78
  import 'open';
77
79
  import './ids-DU6sLx4C.mjs';
78
80
  import 'url';
79
81
  import './detectCLI-CSGMlV51.mjs';
80
- import './localHappyAgentAuth-Ce8kO2yc.mjs';
82
+ import './localHappyAgentAuth-NEU7fax7.mjs';
83
+ import './processTreeSnapshot-CuLJDNC-.mjs';
81
84
  import 'ps-list';
82
85
 
83
86
  async function resolveRelaunchMetadata(snapshot, fetchServer) {
@@ -165,7 +168,7 @@ function startCaffeinate() {
165
168
  }
166
169
  killOrphanedCaffeinateProcesses();
167
170
  try {
168
- caffeinateProcess = spawn("caffeinate", ["-im"], {
171
+ caffeinateProcess = spawn("caffeinate", caffeinateArgs(process.pid), {
169
172
  stdio: "ignore",
170
173
  detached: false
171
174
  });
@@ -232,12 +235,36 @@ function setupCleanupHandlers() {
232
235
  cleanup();
233
236
  });
234
237
  }
238
+ function caffeinateArgs(daemonPid) {
239
+ return ["-im", "-w", String(daemonPid)];
240
+ }
241
+ function orphanedLegacyCaffeinatePids(psOutput) {
242
+ const pids = [];
243
+ for (const line of psOutput.split("\n")) {
244
+ const m = /^\s*(\d+)\s+(\d+)\s+(.*?)\s*$/.exec(line);
245
+ if (!m) continue;
246
+ const [, pid, ppid, command] = m;
247
+ if (ppid !== "1") continue;
248
+ if (!/^(?:\/usr\/bin\/)?caffeinate -im$/.test(command)) continue;
249
+ pids.push(Number(pid));
250
+ }
251
+ return pids;
252
+ }
235
253
  function killOrphanedCaffeinateProcesses() {
236
254
  if (process.platform !== "darwin") return;
255
+ let ps;
237
256
  try {
238
- execSync('pkill -f "caffeinate -im"', { timeout: 5e3, stdio: "ignore" });
239
- logger.debug("[caffeinate] Killed orphaned caffeinate processes");
240
- } catch {
257
+ ps = execSync("ps -A -o pid=,ppid=,command=", { timeout: 5e3, encoding: "utf8" });
258
+ } catch (error) {
259
+ logger.debug("[caffeinate] Could not list processes; skipping orphan cleanup:", error);
260
+ return;
261
+ }
262
+ for (const pid of orphanedLegacyCaffeinatePids(ps)) {
263
+ try {
264
+ process.kill(pid, "SIGTERM");
265
+ logger.debug(`[caffeinate] Killed orphaned legacy caffeinate PID ${pid}`);
266
+ } catch {
267
+ }
241
268
  }
242
269
  }
243
270
 
@@ -347,6 +374,12 @@ function formatAssistantReportMessage(title, sessionId, event) {
347
374
 
348
375
  function resumePrecheck(metadata, fs) {
349
376
  const flavor = metadata.flavor ?? "claude";
377
+ if (flavor === "acp" && metadata.piSessionId) {
378
+ if (!metadata.path || !fs.cwdExists(metadata.path)) {
379
+ return { ok: false, reason: "missing-cwd", detail: `working directory ${metadata.path ?? "(none)"} does not exist` };
380
+ }
381
+ return { ok: true };
382
+ }
350
383
  if (flavor !== "claude" && flavor !== "codex") {
351
384
  return { ok: false, reason: "unsupported-flavor", detail: `flavor "${flavor}" cannot be resumed` };
352
385
  }
@@ -2030,6 +2063,89 @@ function spawnAgentUnavailableError(agent, availability) {
2030
2063
  return null;
2031
2064
  }
2032
2065
 
2066
+ function startWebPanelsSync(deps) {
2067
+ let lastMtime;
2068
+ let lastProblems = "";
2069
+ let stopped = false;
2070
+ let inflight = null;
2071
+ const run = async () => {
2072
+ try {
2073
+ const mtime = await deps.statMtime();
2074
+ if (mtime === lastMtime) return;
2075
+ lastMtime = mtime;
2076
+ const { panels, problems } = normalizeWebPanels(mtime === null ? void 0 : await deps.readRaw());
2077
+ const key = JSON.stringify(problems);
2078
+ if (problems.length > 0 && key !== lastProblems) deps.logProblems(problems);
2079
+ lastProblems = key;
2080
+ await deps.publish(panels);
2081
+ } catch {
2082
+ lastMtime = void 0;
2083
+ }
2084
+ };
2085
+ const tick = () => {
2086
+ if (stopped) return Promise.resolve();
2087
+ inflight ??= run().finally(() => {
2088
+ inflight = null;
2089
+ });
2090
+ return inflight;
2091
+ };
2092
+ void tick();
2093
+ const timer = setInterval(() => {
2094
+ void tick();
2095
+ }, deps.intervalMs ?? 2e3);
2096
+ timer.unref?.();
2097
+ return { stop: () => {
2098
+ stopped = true;
2099
+ clearInterval(timer);
2100
+ }, tick };
2101
+ }
2102
+
2103
+ function isAcceptableRelayUrl(url) {
2104
+ try {
2105
+ const parsed = new URL(url);
2106
+ const loopback = parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]";
2107
+ return parsed.protocol === "https:" || parsed.protocol === "http:" && loopback;
2108
+ } catch {
2109
+ return false;
2110
+ }
2111
+ }
2112
+ async function applyServerMigration(raw, deps) {
2113
+ const parsed = ServerMigrateNoticeSchema.safeParse(raw);
2114
+ if (!parsed.success) return { action: "ignored", reason: "malformed notice" };
2115
+ const notice = parsed.data;
2116
+ if (sameRelay(notice.url, deps.configuredServerUrl)) return { action: "ignored", reason: "already on that relay" };
2117
+ if (!isAcceptableRelayUrl(notice.url) || !isAcceptableRelayUrl(notice.webappUrl)) {
2118
+ return refuse(deps, `relay URL must be https: ${notice.url}`);
2119
+ }
2120
+ if (deps.env.HAPPY_SERVER_URL?.trim()) {
2121
+ return refuse(deps, `HAPPY_SERVER_URL is set in this daemon's environment; unset it (or point it at ${notice.url}) and restart the daemon`);
2122
+ }
2123
+ const credentials = await deps.readCredentials();
2124
+ if (!credentials) return refuse(deps, "no credentials on disk");
2125
+ let token;
2126
+ try {
2127
+ const response = await deps.fetch(`${notice.url}/v1/auth/migrate/complete`, {
2128
+ method: "POST",
2129
+ headers: { "content-type": "application/json", "X-Happy-Client": deps.clientId },
2130
+ body: JSON.stringify({ handoff: notice.handoff })
2131
+ });
2132
+ if (!response.ok) return refuse(deps, `${notice.url} refused the handoff (HTTP ${response.status})`);
2133
+ const body = await response.json();
2134
+ if (body.kind !== "daemon" || typeof body.token !== "string" || !body.token) return refuse(deps, `${notice.url} answered without a daemon token`);
2135
+ token = body.token;
2136
+ } catch (error) {
2137
+ return refuse(deps, `${notice.url} unreachable: ${error instanceof Error ? error.message : String(error)}`);
2138
+ }
2139
+ await deps.updateSettings((current) => ({ ...current, serverUrl: notice.url, webappUrl: notice.webappUrl }));
2140
+ await deps.rewriteCredentials(credentials, { token, authServerUrl: notice.url });
2141
+ deps.log(`[RELAY MOVE] Moved this machine from ${deps.configuredServerUrl} to ${notice.url}; handing over to a new daemon`);
2142
+ return { action: "moved", serverUrl: notice.url, webappUrl: notice.webappUrl };
2143
+ }
2144
+ function refuse(deps, reason) {
2145
+ deps.log(`[RELAY MOVE] Not moving this machine: ${reason}`);
2146
+ return { action: "refused", reason };
2147
+ }
2148
+
2033
2149
  function str(value) {
2034
2150
  return typeof value === "string" && value.length > 0 ? value : void 0;
2035
2151
  }
@@ -2439,6 +2555,44 @@ function createUpdateController(deps) {
2439
2555
  return { refresh, retry, request, tick, withHandover, holdHandover, isRunning: () => running };
2440
2556
  }
2441
2557
 
2558
+ function buildPresenceBatch(live, previous) {
2559
+ const current = new Set(live.map((s) => s.sessionId));
2560
+ const sessions = live.slice(0, 200).map((s) => ({
2561
+ sessionId: s.sessionId,
2562
+ state: s.running ? "running" : "idle",
2563
+ ...s.flavor ? { agent: s.flavor } : {},
2564
+ ...s.branch ? { branch: s.branch.slice(0, 200) } : {}
2565
+ }));
2566
+ const gone = [...previous].filter((id) => !current.has(id)).slice(0, 200);
2567
+ return { sessions, gone, current };
2568
+ }
2569
+ function createProjectPresenceReporter(deps) {
2570
+ let previous = /* @__PURE__ */ new Set();
2571
+ let running = false;
2572
+ async function tick() {
2573
+ if (running || deps.client.isDisabled()) return;
2574
+ running = true;
2575
+ try {
2576
+ const batch = buildPresenceBatch(deps.live(), previous);
2577
+ if (batch.sessions.length === 0 && batch.gone.length === 0) {
2578
+ previous = batch.current;
2579
+ return;
2580
+ }
2581
+ await deps.client.presence(deps.machineId, batch.sessions, batch.gone);
2582
+ previous = batch.current;
2583
+ } catch (error) {
2584
+ if (!(error instanceof ProjectsUnsupportedError)) deps.log(`project presence tick failed: ${String(error)}`);
2585
+ } finally {
2586
+ running = false;
2587
+ }
2588
+ }
2589
+ const timer = setInterval(() => {
2590
+ void tick();
2591
+ }, deps.intervalMs ?? 6e4);
2592
+ timer.unref?.();
2593
+ return { tick, stop: () => clearInterval(timer) };
2594
+ }
2595
+
2442
2596
  const AUTOMATION_BINDINGS_TTL_MS = 10 * 60 * 1e3;
2443
2597
  const HIBERNATION_IN_FLIGHT_MS = 6e4;
2444
2598
  const HIBERNATION_EXIT_WAIT_MS = 15e3;
@@ -4505,6 +4659,7 @@ ${action.prompt}`, { localId: `automation-${run.id}` });
4505
4659
  }
4506
4660
  persist({ runId: run.id, automationId: automation.id, kind: "spawn", phase: "running", claimId: run.claimId, sessionId: spawned.sessionId, stickyKey, ...action.worktree ? { directory } : {} });
4507
4661
  const item = track(claimed, "spawn", spawned.sessionId);
4662
+ if (automation.projectId && deps.joinProject) await deps.joinProject(spawned.sessionId, automation.projectId).catch(() => void 0);
4508
4663
  try {
4509
4664
  const capabilities = readPersistedSessions()[spawned.sessionId]?.metadata?.capabilities ?? null;
4510
4665
  const meta = resolveFirstMessageMeta({ agent, permissionMode, explicitModel: action.model ?? void 0, capabilities });
@@ -4865,6 +5020,7 @@ async function startDaemon() {
4865
5020
  const sessionIdToFinishedSession = /* @__PURE__ */ new Map();
4866
5021
  let teamWorker;
4867
5022
  let automationRunner;
5023
+ let projectPresence;
4868
5024
  const persisted = readPersistedSessions();
4869
5025
  const liveHappyProcesses = await findAllHappyProcesses();
4870
5026
  for (const [id, s] of Object.entries(persisted)) {
@@ -4954,6 +5110,7 @@ async function startDaemon() {
4954
5110
  }
4955
5111
  };
4956
5112
  const assistantSpawnGate = createSpawnGate();
5113
+ const projectsClient = createProjectsClient({ token: async () => credentials.token });
4957
5114
  const spawnSession = async (options) => {
4958
5115
  const timer = createSpawnTimer();
4959
5116
  await refreshAgentHomes(Date.now(), { allowStale: true });
@@ -4965,6 +5122,10 @@ async function startDaemon() {
4965
5122
  result = await (options.forceNew ? assistantSpawnGate.replace(() => spawnSessionImpl(options, timer)) : assistantSpawnGate.join(() => spawnSessionImpl(options, timer)));
4966
5123
  }
4967
5124
  logger.debug(timer.format({ agent: options.agent ?? "claude", outcome: result.type }));
5125
+ if (result.type === "success" && options.parentSessionId) {
5126
+ const outcome = await joinProject(projectsClient, result.sessionId, { kind: "lineage", parentSessionId: options.parentSessionId });
5127
+ if (outcome.joined) logger.debug(`[DAEMON RUN] fork ${result.sessionId} joined project ${outcome.projectId} (lineage)`);
5128
+ }
4968
5129
  return result;
4969
5130
  };
4970
5131
  const currentCliAvailability = () => apiMachineRef?.getCLIAvailability() ?? startupCliAvailability;
@@ -5595,7 +5756,7 @@ async function startDaemon() {
5595
5756
  resolve();
5596
5757
  }
5597
5758
  };
5598
- const requested = terminateProcess(pid, () => {
5759
+ const requested = terminateProcessTree(pid, () => {
5599
5760
  const tracked = pidToTrackedSession.get(pid);
5600
5761
  if (tracked) {
5601
5762
  if (tracked.happySessionId && tracked.encryption) {
@@ -5711,7 +5872,7 @@ async function startDaemon() {
5711
5872
  logger.debug(`[DAEMON RUN] Attempting to stop session ${sessionId}`);
5712
5873
  for (const [pid, session] of pidToTrackedSession.entries()) {
5713
5874
  if (session.happySessionId === sessionId || sessionId.startsWith("PID-") && pid === parseInt(sessionId.replace("PID-", ""))) {
5714
- const requested = terminateProcess(pid, (stopped) => {
5875
+ const requested = terminateProcessTree(pid, (stopped) => {
5715
5876
  if (!stopped) {
5716
5877
  logger.debug(`[DAEMON RUN] Session ${sessionId} survived SIGTERM and SIGKILL attempts`);
5717
5878
  return;
@@ -5974,6 +6135,12 @@ async function startDaemon() {
5974
6135
  daemonHibernation.invalidateBindings();
5975
6136
  return resolveIdleMs(agentHibernationSetting);
5976
6137
  });
6138
+ const webPanelsSync = startWebPanelsSync({
6139
+ statMtime: async () => (await fs.stat(configuration.settingsFile).catch(() => null))?.mtimeMs ?? null,
6140
+ readRaw: async () => (await readSettings()).webPanels,
6141
+ publish: (panels) => apiMachine.setWebPanels(panels),
6142
+ logProblems: (problems) => logger.warn(`[DAEMON RUN] settings.json webPanels: skipped ${problems.length} entr${problems.length === 1 ? "y" : "ies"}: ${problems.map((p) => `#${p.index}${p.id ? ` (${p.id})` : ""} ${p.reason}`).join("; ")}`)
6143
+ });
5977
6144
  apiMachine.connect();
5978
6145
  if (identityConflict?.confidence === "weak") {
5979
6146
  void apiMachine.updateMachineMetadata((current) => ({
@@ -6007,6 +6174,27 @@ async function startDaemon() {
6007
6174
  });
6008
6175
  apiMachine.setCliUpdateRetryHandler(updateController.retry);
6009
6176
  apiMachine.setCliUpdateRequestHandler(updateController.request);
6177
+ let pendingRelayMove = null;
6178
+ let relayMoveInFlight = null;
6179
+ apiMachine.setServerMigrateHandler((notice) => {
6180
+ if (relayMoveInFlight || pendingRelayMove) return;
6181
+ relayMoveInFlight = applyServerMigration(notice, {
6182
+ configuredServerUrl: configuration.serverUrl,
6183
+ env: process.env,
6184
+ clientId: `cli-daemon/${configuration.currentCliVersion}`,
6185
+ fetch,
6186
+ readCredentials,
6187
+ rewriteCredentials: rewriteCredentialsForRelay,
6188
+ updateSettings,
6189
+ log: (message) => logger.warn(message)
6190
+ }).then((outcome) => {
6191
+ if (outcome.action === "moved") pendingRelayMove = { serverUrl: outcome.serverUrl };
6192
+ }).catch((error) => {
6193
+ logger.warn("[RELAY MOVE] Failed:", error);
6194
+ }).finally(() => {
6195
+ relayMoveInFlight = null;
6196
+ });
6197
+ });
6010
6198
  const refreshCliUpdate = () => updateController.refresh().catch((error) => {
6011
6199
  logger.debug("[DAEMON RUN] CLI update policy check failed:", error);
6012
6200
  });
@@ -6044,8 +6232,9 @@ async function startDaemon() {
6044
6232
  } catch {
6045
6233
  }
6046
6234
  }
6047
- if (bundleReplaced && !teamWorker?.busy && !automationRunner?.busy && !updateController.isRunning() && !turnActivity.hasActiveTurn() && !backgroundTasks.hasAny()) {
6048
- const preflight = await preflightNewBundle(bundlePath);
6235
+ const relayMove = pendingRelayMove;
6236
+ if ((bundleReplaced || relayMove) && !teamWorker?.busy && !automationRunner?.busy && !updateController.isRunning() && !turnActivity.hasActiveTurn() && !backgroundTasks.hasAny()) {
6237
+ const preflight = bundleReplaced ? await preflightNewBundle(bundlePath) : { action: "proceed" };
6049
6238
  if (preflight.action === "hold") {
6050
6239
  if (lastHandoverHold !== preflight.reason) {
6051
6240
  lastHandoverHold = preflight.reason;
@@ -6056,9 +6245,10 @@ async function startDaemon() {
6056
6245
  }
6057
6246
  if (teamWorker?.busy || automationRunner?.busy || updateController.isRunning() || turnActivity.hasActiveTurn() || backgroundTasks.hasAny()) return;
6058
6247
  lastHandoverHold = null;
6059
- logger.debug("[DAEMON RUN] Daemon bundle replaced on disk and verified, handing off to new daemon");
6248
+ logger.debug(relayMove ? `[DAEMON RUN] Relay moved to ${relayMove.serverUrl}; handing off to a new daemon on the new settings` : "[DAEMON RUN] Daemon bundle replaced on disk and verified, handing off to new daemon");
6060
6249
  teamWorker?.stop();
6061
6250
  automationRunner?.stop();
6251
+ projectPresence?.stop();
6062
6252
  clearInterval(restartOnStaleVersionAndHeartbeat);
6063
6253
  clearInterval(cliUpdateInterval);
6064
6254
  stopAgentVersionChecks();
@@ -6132,6 +6322,18 @@ async function startDaemon() {
6132
6322
  if (result.type !== "success") return false;
6133
6323
  return waitForSessionLive(id, (sid) => [...pidToTrackedSession.values()].some((s) => s.happySessionId === sid && isPidAlive(s.pid)));
6134
6324
  },
6325
+ joinProject: (sessionId, projectId) => joinProject(projectsClient, sessionId, { kind: "explicit", projectId }, { via: "automation" }),
6326
+ log: (message) => logger.debug(`[DAEMON RUN] ${message}`)
6327
+ });
6328
+ projectPresence = createProjectPresenceReporter({
6329
+ machineId,
6330
+ client: projectsClient,
6331
+ live: () => [...pidToTrackedSession.values()].filter((s) => s.happySessionId && isPidAlive(s.pid)).map((s) => ({
6332
+ sessionId: s.happySessionId,
6333
+ flavor: s.happySessionMetadataFromLocalWebhook?.flavor ?? null,
6334
+ branch: s.happySessionMetadataFromLocalWebhook?.worktree?.branch ?? null,
6335
+ running: turnActivity.activeSessions().includes(s.happySessionId)
6336
+ })),
6135
6337
  log: (message) => logger.debug(`[DAEMON RUN] ${message}`)
6136
6338
  });
6137
6339
  void apiMachine.updateMachineMetadata((current) => ({
@@ -6142,10 +6344,12 @@ async function startDaemon() {
6142
6344
  worktreeVersion: WORKTREE_CAPABILITY_VERSION
6143
6345
  })).catch(() => logger.debug("[DAEMON RUN] Teams capability publication will retry on reconnect"));
6144
6346
  const cleanupAndShutdown = async (source, errorMessage) => {
6347
+ webPanelsSync.stop();
6145
6348
  logger.debug(`[DAEMON RUN] Starting proper cleanup (source: ${source}, errorMessage: ${errorMessage})...`);
6146
6349
  const scrollbackFlush = apiMachine.flushTerminalScrollback();
6147
6350
  teamWorker?.stop();
6148
6351
  automationRunner?.stop({ killScripts: true });
6352
+ projectPresence?.stop();
6149
6353
  currentWorktreeService()?.stopAll();
6150
6354
  if (restartOnStaleVersionAndHeartbeat) {
6151
6355
  clearInterval(restartOnStaleVersionAndHeartbeat);