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
@@ -2,6 +2,8 @@
2
2
 
3
3
  var claudeAgentSdk = require('@anthropic-ai/claude-agent-sdk');
4
4
  var smallFastModel = require('./smallFastModel-D_uxGMo3.cjs');
5
+ var logger = require('./logger-C1GWx3gi.cjs');
6
+ var processTreeSnapshot = require('./processTreeSnapshot-mDbnuojn.cjs');
5
7
 
6
8
  const HAPPY_DEFAULT_ENTRYPOINT = "remote_mobile";
7
9
  function resolveHappyEntrypoint(currentValue) {
@@ -11,6 +13,20 @@ function resolveHappyEntrypoint(currentValue) {
11
13
  return HAPPY_DEFAULT_ENTRYPOINT;
12
14
  }
13
15
 
16
+ const CLAUDE_TREE_REAP_DELAY_MS = 8e3;
17
+ function scheduleClaudeTreeReap(pid, deps = {}) {
18
+ const snapshot = (deps.snapshot ?? ((root) => processTreeSnapshot.snapshotTree(root, { includeRoot: true, read: deps.read })))(pid);
19
+ if (snapshot.length === 0) return snapshot;
20
+ const schedule = deps.schedule ?? ((callback, delayMs) => {
21
+ setTimeout(callback, delayMs).unref?.();
22
+ });
23
+ schedule(() => {
24
+ const killed = processTreeSnapshot.killSurvivors(snapshot, deps);
25
+ if (killed.length > 0) logger.logger.debug(`[claude] Reaped ${killed.length} process(es) left from aborted Claude Code ${pid}: ${killed.join(", ")}`);
26
+ }, CLAUDE_TREE_REAP_DELAY_MS);
27
+ return snapshot;
28
+ }
29
+
14
30
  function query(params) {
15
31
  const opts = params.options;
16
32
  let systemPrompt = void 0;
@@ -63,12 +79,20 @@ function query(params) {
63
79
  onUserDialog: opts?.onUserDialog,
64
80
  supportedDialogKinds: opts?.onUserDialog ? opts.supportedDialogKinds : void 0
65
81
  };
82
+ let claudePid;
83
+ sdkOptions.onProcessSpawned = (pid) => {
84
+ claudePid = pid;
85
+ opts?.onProcessSpawned?.(pid);
86
+ };
66
87
  if (opts?.abort) {
67
88
  const controller = new AbortController();
68
89
  if (opts.abort.aborted) {
69
90
  controller.abort(opts.abort.reason);
70
91
  } else {
71
- opts.abort.addEventListener("abort", () => controller.abort(opts.abort?.reason), { once: true });
92
+ opts.abort.addEventListener("abort", () => {
93
+ if (claudePid !== void 0) scheduleClaudeTreeReap(claudePid);
94
+ controller.abort(opts.abort?.reason);
95
+ }, { once: true });
72
96
  }
73
97
  sdkOptions.abortController = controller;
74
98
  }
@@ -103,8 +127,4 @@ function query(params) {
103
127
  });
104
128
  }
105
129
 
106
- Object.defineProperty(exports, "AbortError", {
107
- enumerable: true,
108
- get: function () { return claudeAgentSdk.AbortError; }
109
- });
110
130
  exports.query = query;
@@ -1,6 +1,7 @@
1
1
  import { query as query$1 } from '@anthropic-ai/claude-agent-sdk';
2
- export { AbortError } from '@anthropic-ai/claude-agent-sdk';
3
2
  import { p as pinSmallFastModel, e as ensureLocalProxyBypass } from './smallFastModel-BLNgMrwR.mjs';
3
+ import { l as logger } from './logger-BtVhHnD8.mjs';
4
+ import { s as snapshotTree, k as killSurvivors } from './processTreeSnapshot-CuLJDNC-.mjs';
4
5
 
5
6
  const HAPPY_DEFAULT_ENTRYPOINT = "remote_mobile";
6
7
  function resolveHappyEntrypoint(currentValue) {
@@ -10,6 +11,20 @@ function resolveHappyEntrypoint(currentValue) {
10
11
  return HAPPY_DEFAULT_ENTRYPOINT;
11
12
  }
12
13
 
14
+ const CLAUDE_TREE_REAP_DELAY_MS = 8e3;
15
+ function scheduleClaudeTreeReap(pid, deps = {}) {
16
+ const snapshot = (deps.snapshot ?? ((root) => snapshotTree(root, { includeRoot: true, read: deps.read })))(pid);
17
+ if (snapshot.length === 0) return snapshot;
18
+ const schedule = deps.schedule ?? ((callback, delayMs) => {
19
+ setTimeout(callback, delayMs).unref?.();
20
+ });
21
+ schedule(() => {
22
+ const killed = killSurvivors(snapshot, deps);
23
+ if (killed.length > 0) logger.debug(`[claude] Reaped ${killed.length} process(es) left from aborted Claude Code ${pid}: ${killed.join(", ")}`);
24
+ }, CLAUDE_TREE_REAP_DELAY_MS);
25
+ return snapshot;
26
+ }
27
+
13
28
  function query(params) {
14
29
  const opts = params.options;
15
30
  let systemPrompt = void 0;
@@ -62,12 +77,20 @@ function query(params) {
62
77
  onUserDialog: opts?.onUserDialog,
63
78
  supportedDialogKinds: opts?.onUserDialog ? opts.supportedDialogKinds : void 0
64
79
  };
80
+ let claudePid;
81
+ sdkOptions.onProcessSpawned = (pid) => {
82
+ claudePid = pid;
83
+ opts?.onProcessSpawned?.(pid);
84
+ };
65
85
  if (opts?.abort) {
66
86
  const controller = new AbortController();
67
87
  if (opts.abort.aborted) {
68
88
  controller.abort(opts.abort.reason);
69
89
  } else {
70
- opts.abort.addEventListener("abort", () => controller.abort(opts.abort?.reason), { once: true });
90
+ opts.abort.addEventListener("abort", () => {
91
+ if (claudePid !== void 0) scheduleClaudeTreeReap(claudePid);
92
+ controller.abort(opts.abort?.reason);
93
+ }, { once: true });
71
94
  }
72
95
  sdkOptions.abortController = controller;
73
96
  }
@@ -102,4 +125,4 @@ function query(params) {
102
125
  });
103
126
  }
104
127
 
105
- export { query };
128
+ export { query as q };
@@ -1,4 +1,4 @@
1
- import { l as logger } from './logger-13cBr_ew.mjs';
1
+ import { l as logger } from './logger-BtVhHnD8.mjs';
2
2
 
3
3
  const MAX_WINDOWS_PER_PROVIDER = 8;
4
4
  function finite(value) {
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var logger = require('./logger-LvwVeATU.cjs');
3
+ var logger = require('./logger-C1GWx3gi.cjs');
4
4
 
5
5
  const MAX_WINDOWS_PER_PROVIDER = 8;
6
6
  function finite(value) {
@@ -1,4 +1,4 @@
1
- import { l as logger } from './logger-13cBr_ew.mjs';
1
+ import { l as logger } from './logger-BtVhHnD8.mjs';
2
2
  import { spawn as spawn$1, exec } from 'child_process';
3
3
  import { promisify } from 'util';
4
4
  import { mkdir, writeFile, appendFile, stat, rename, unlink, readdir, readFile } from 'fs/promises';
@@ -7,7 +7,7 @@ import { resolve, join, sep } from 'path';
7
7
  import { spawn } from 'cross-spawn';
8
8
  import { p as projectPath } from './projectPath-BTBIMB57.mjs';
9
9
  import { platform } from 'os';
10
- import { c as configuration } from './configuration-D55F0t16.mjs';
10
+ import { c as configuration } from './configuration-WMi4idBB.mjs';
11
11
 
12
12
  function run$1(args, options) {
13
13
  const RUNNER_PATH = resolve(join(projectPath(), "scripts", "ripgrep_launcher.cjs"));
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var logger = require('./logger-LvwVeATU.cjs');
3
+ var logger = require('./logger-C1GWx3gi.cjs');
4
4
  var child_process = require('child_process');
5
5
  var util = require('util');
6
6
  var fs = require('fs/promises');
@@ -9,7 +9,7 @@ var path = require('path');
9
9
  var spawn = require('cross-spawn');
10
10
  var projectPath = require('./projectPath-ChLhdOyt.cjs');
11
11
  var os = require('os');
12
- var configuration = require('./configuration-DZPy0T9Z.cjs');
12
+ var configuration = require('./configuration-CMHZnp6G.cjs');
13
13
 
14
14
  function run$1(args, options) {
15
15
  const RUNNER_PATH = path.resolve(path.join(projectPath.projectPath(), "scripts", "ripgrep_launcher.cjs"));
@@ -1,17 +1,17 @@
1
- import { l as logger } from './logger-13cBr_ew.mjs';
1
+ import { l as logger } from './logger-BtVhHnD8.mjs';
2
2
  import 'axios';
3
3
  import 'node:events';
4
4
  import 'socket.io-client';
5
- import './attachmentLimits-Di1Z93lN.mjs';
5
+ import './pushNotifications-BdFjDjQe.mjs';
6
6
  import 'node:crypto';
7
7
  import 'tweetnacl';
8
- import './configuration-D55F0t16.mjs';
9
- import './index-DMy3OCBe.mjs';
10
- import './registerCommonHandlers-D8OMpBbQ.mjs';
8
+ import './configuration-WMi4idBB.mjs';
9
+ import './index-DPOa4NhL.mjs';
10
+ import './registerCommonHandlers-BAlP7SGc.mjs';
11
11
  import 'os';
12
12
  import 'child_process';
13
13
  import '@paralleldrive/cuid2';
14
- import './persistence-C_tYtOqK.mjs';
14
+ import './persistence-Cr-wutZ4.mjs';
15
15
  import 'chalk';
16
16
  import './types-CkqAACXx.mjs';
17
17
 
@@ -1,19 +1,19 @@
1
1
  'use strict';
2
2
 
3
- var logger = require('./logger-LvwVeATU.cjs');
3
+ var logger = require('./logger-C1GWx3gi.cjs');
4
4
  require('axios');
5
5
  require('node:events');
6
6
  require('socket.io-client');
7
- require('./attachmentLimits-DtFqqiwR.cjs');
7
+ require('./pushNotifications-DaLQUyi0.cjs');
8
8
  require('node:crypto');
9
9
  require('tweetnacl');
10
- require('./configuration-DZPy0T9Z.cjs');
11
- require('./index-De8L5lFK.cjs');
12
- require('./registerCommonHandlers-60VuTkdg.cjs');
10
+ require('./configuration-CMHZnp6G.cjs');
11
+ require('./index-C6O2vVjm.cjs');
12
+ require('./registerCommonHandlers-Cj084Sg7.cjs');
13
13
  require('os');
14
14
  require('child_process');
15
15
  require('@paralleldrive/cuid2');
16
- require('./persistence-DXbKOHxl.cjs');
16
+ require('./persistence-BegE7NPa.cjs');
17
17
  require('chalk');
18
18
  require('./types-CRS-srZK.cjs');
19
19
 
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var controlClient = require('./controlClient-SX8gSza2.cjs');
4
- var sessionOps = require('./sessionOps-Dmt7WUUs.cjs');
5
- var time = require('./time-Dg5tVB8S.cjs');
3
+ var controlClient = require('./controlClient-C-5qCt8W.cjs');
4
+ var sessionOps = require('./sessionOps-S-qPBLFf.cjs');
5
+ var time = require('./time-CrwIMHta.cjs');
6
6
  var axios = require('axios');
7
7
  var os = require('node:os');
8
- var configuration = require('./configuration-DZPy0T9Z.cjs');
9
- var persistence = require('./persistence-DXbKOHxl.cjs');
8
+ var configuration = require('./configuration-CMHZnp6G.cjs');
9
+ var persistence = require('./persistence-BegE7NPa.cjs');
10
10
  var node_crypto = require('node:crypto');
11
11
 
12
12
  const ACTIVE_FRESH_WINDOW_MS = 15 * 60 * 1e3;
@@ -1,10 +1,10 @@
1
- import { h as resumeDaemonSession, l as listDaemonSessions } from './controlClient-C4xB5J6O.mjs';
2
- import { d as archiveSession, u as unarchiveSession, h as sessionLiveness, e as sendUserMessage, i as readSessionState, o as openUserScopedSocket } from './sessionOps-CdgbEJgf.mjs';
3
- import { d as delay } from './time-yEL6wHUF.mjs';
1
+ import { h as resumeDaemonSession, l as listDaemonSessions } from './controlClient-BWUJrj3t.mjs';
2
+ import { d as archiveSession, u as unarchiveSession, h as sessionLiveness, e as sendUserMessage, i as readSessionState, o as openUserScopedSocket } from './sessionOps-BIGgRube.mjs';
3
+ import { d as delay } from './time-65DcU6Jx.mjs';
4
4
  import axios from 'axios';
5
5
  import { hostname } from 'node:os';
6
- import { c as configuration } from './configuration-D55F0t16.mjs';
7
- import { r as readSettings, c as readCredentialsForConfiguredRelay } from './persistence-C_tYtOqK.mjs';
6
+ import { c as configuration } from './configuration-WMi4idBB.mjs';
7
+ import { r as readSettings, b as readCredentialsForConfiguredRelay } from './persistence-Cr-wutZ4.mjs';
8
8
  import { randomUUID } from 'node:crypto';
9
9
 
10
10
  const ACTIVE_FRESH_WINDOW_MS = 15 * 60 * 1e3;
@@ -1,9 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  var z = require('zod');
4
- var index = require('./index-De8L5lFK.cjs');
5
- var client = require('./client-COmgDDy0.cjs');
4
+ var index = require('./index-C6O2vVjm.cjs');
5
+ var client = require('./client-CuVdN6PP.cjs');
6
6
  var precheckCompat = require('./precheckCompat-CWOi5c9L.cjs');
7
+ var client$1 = require('./client-ZjOsn6nZ.cjs');
8
+ var prompt = require('./prompt-lgF9IE82.cjs');
7
9
  var agentGuidance = require('./agentGuidance-BtBx2xxE.cjs');
8
10
 
9
11
  const AUTOMATION_TOOL_NAMES = [
@@ -183,6 +185,83 @@ function registerAutomationTools(server, execute = createAutomationToolExecutor(
183
185
  }
184
186
  }
185
187
 
188
+ const PROJECT_TOOL_NAMES = ["project_context", "project_note"];
189
+ const PROJECT_TOOL_SCHEMAS = {
190
+ project_context: {
191
+ title: "Read Project Context",
192
+ readOnly: true,
193
+ description: `Read this session's Very Happy project: instructions, decisions in effect, recent log entries, other sessions and unread messages. By default returns only what changed since you last read it (\u22642KB); full=true returns everything. Returns "not in a project" when the session has no project.`,
194
+ inputSchema: {
195
+ section: z.z.enum(["instructions", "log", "sessions", "messages"]).optional().describe("Only this part"),
196
+ full: z.z.boolean().optional().describe("Everything, not just changes since your last read")
197
+ }
198
+ },
199
+ project_note: {
200
+ title: "Write Project Note",
201
+ readOnly: false,
202
+ description: 'Append to the project log what other sessions will need: kind "decision" (changes how they work), "finding" (they would otherwise redo it) or "handoff" (when you stop). Not progress. Takes effect immediately; the user can revoke it. To change an entry, write a new one with supersedes; revoke=true with supersedes withdraws your own entry.',
203
+ inputSchema: {
204
+ kind: z.z.enum(["decision", "finding", "handoff"]).describe("decision | finding | handoff"),
205
+ title: z.z.string().min(1).max(200).describe("One line"),
206
+ body: z.z.string().max(4e3).optional().describe("Details (\u22644KB)"),
207
+ supersedes: z.z.string().min(1).max(128).optional().describe('Entry it replaces: "#12" or its id'),
208
+ revoke: z.z.boolean().optional().describe("With supersedes: withdraw that entry (only your own) instead of writing a new one")
209
+ }
210
+ }
211
+ };
212
+ function describeError(error) {
213
+ if (error instanceof client$1.ProjectsUnsupportedError) return "This Very Happy server does not support projects yet.";
214
+ if (error instanceof client$1.ProjectRequestError) {
215
+ if (error.code === "project_note_quota_exceeded" && typeof error.details.suggestion === "string") return error.details.suggestion;
216
+ if (error.code === "not_a_project_member") return "not in a project";
217
+ if (error.code) return `Project request failed: ${error.code}`;
218
+ return "Project request failed";
219
+ }
220
+ return error instanceof Error && error.message ? error.message : "Project request failed";
221
+ }
222
+ function createProjectToolExecutor(sessionId, client = client$1.sharedProjectsClient()) {
223
+ return async (name, args) => {
224
+ const sid = sessionId();
225
+ if (name === "project_context") {
226
+ const full = args?.full === true;
227
+ const ctx = await client.context(sid, { full });
228
+ return { text: prompt.formatContextForTool(ctx, { full, section: typeof args?.section === "string" ? args.section : void 0 }) };
229
+ }
230
+ const membership = await client.membership(sid);
231
+ if (!membership.projectId) return { text: "not in a project" };
232
+ if (args?.revoke) {
233
+ if (!args?.supersedes) throw new Error("revoke needs supersedes (the entry to withdraw)");
234
+ const { entry: entry2 } = await client.revoke(membership.projectId, String(args.supersedes), sid);
235
+ return { text: `revoked #${entry2.seq}` };
236
+ }
237
+ const { entry } = await client.note(membership.projectId, {
238
+ kind: String(args?.kind),
239
+ title: String(args?.title ?? ""),
240
+ authorSessionId: sid,
241
+ ...typeof args?.body === "string" && args.body ? { body: args.body } : {},
242
+ ...typeof args?.supersedes === "string" ? { supersedes: args.supersedes } : {}
243
+ });
244
+ return { text: `recorded #${entry.seq}${entry.supersedes ? " (supersedes an earlier entry)" : ""}` };
245
+ };
246
+ }
247
+ function registerProjectTools(server, execute) {
248
+ for (const name of PROJECT_TOOL_NAMES) {
249
+ const spec = PROJECT_TOOL_SCHEMAS[name];
250
+ server.registerTool(name, {
251
+ description: spec.description,
252
+ title: spec.title,
253
+ inputSchema: spec.inputSchema,
254
+ annotations: { readOnlyHint: spec.readOnly, idempotentHint: spec.readOnly, openWorldHint: false, destructiveHint: false }
255
+ }, async (args) => {
256
+ try {
257
+ return { content: [{ type: "text", text: (await execute(name, args ?? {})).text }], isError: false };
258
+ } catch (error) {
259
+ return { content: [{ type: "text", text: describeError(error) }], isError: true };
260
+ }
261
+ });
262
+ }
263
+ }
264
+
186
265
  const SELF_REPORT_MIN_INTERVAL_MS = 30 * 1e3;
187
266
  const SELF_REPORT_FRESH_MS = 15 * 60 * 1e3;
188
267
  const ATTENTION_VALUES = ["none", "review", "blocked"];
@@ -234,11 +313,14 @@ function registerReportProgressTool(server, execute) {
234
313
  }
235
314
 
236
315
  exports.AUTOMATION_TOOL_NAMES = AUTOMATION_TOOL_NAMES;
316
+ exports.PROJECT_TOOL_NAMES = PROJECT_TOOL_NAMES;
317
+ exports.createProjectToolExecutor = createProjectToolExecutor;
237
318
  exports.createSelfReportState = createSelfReportState;
238
319
  exports.isSelfReportFresh = isSelfReportFresh;
239
320
  exports.normalizeAttention = normalizeAttention;
240
321
  exports.normalizePhase = normalizePhase;
241
322
  exports.normalizeProgress = normalizeProgress;
242
323
  exports.registerAutomationTools = registerAutomationTools;
324
+ exports.registerProjectTools = registerProjectTools;
243
325
  exports.registerReportProgressTool = registerReportProgressTool;
244
326
  exports.shouldAcceptSelfReport = shouldAcceptSelfReport;
@@ -1,7 +1,9 @@
1
1
  import { z } from 'zod';
2
- import { h as AutomationNameSchema, b as AutomationPrecheckSchema, j as AutomationConcurrencySchema, k as AutomationActionSchema, l as AutomationTriggerSchema } from './index-DMy3OCBe.mjs';
3
- import { a as authenticatedAutomationsClient, b as automationRunIdFromEnv } from './client-DG5ndWLw.mjs';
2
+ import { k as AutomationNameSchema, c as AutomationPrecheckSchema, l as AutomationConcurrencySchema, m as AutomationActionSchema, o as AutomationTriggerSchema } from './index-DPOa4NhL.mjs';
3
+ import { a as authenticatedAutomationsClient, b as automationRunIdFromEnv } from './client-wo9nbxuf.mjs';
4
4
  import { u as updateAutomationChecked, c as createAutomationChecked } from './precheckCompat-DeEbilbr.mjs';
5
+ import { P as ProjectsUnsupportedError, a as ProjectRequestError, s as sharedProjectsClient } from './client-BhoEBnuN.mjs';
6
+ import { f as formatContextForTool } from './prompt-BOouDaTM.mjs';
5
7
  import { R as REPORT_PROGRESS_TOOL_NAME, d as REPORT_PROGRESS_TOOL_TITLE, e as REPORT_PROGRESS_TOOL_DESCRIPTION } from './agentGuidance-BDYt2Qy2.mjs';
6
8
 
7
9
  const AUTOMATION_TOOL_NAMES = [
@@ -181,6 +183,83 @@ function registerAutomationTools(server, execute = createAutomationToolExecutor(
181
183
  }
182
184
  }
183
185
 
186
+ const PROJECT_TOOL_NAMES = ["project_context", "project_note"];
187
+ const PROJECT_TOOL_SCHEMAS = {
188
+ project_context: {
189
+ title: "Read Project Context",
190
+ readOnly: true,
191
+ description: `Read this session's Very Happy project: instructions, decisions in effect, recent log entries, other sessions and unread messages. By default returns only what changed since you last read it (\u22642KB); full=true returns everything. Returns "not in a project" when the session has no project.`,
192
+ inputSchema: {
193
+ section: z.enum(["instructions", "log", "sessions", "messages"]).optional().describe("Only this part"),
194
+ full: z.boolean().optional().describe("Everything, not just changes since your last read")
195
+ }
196
+ },
197
+ project_note: {
198
+ title: "Write Project Note",
199
+ readOnly: false,
200
+ description: 'Append to the project log what other sessions will need: kind "decision" (changes how they work), "finding" (they would otherwise redo it) or "handoff" (when you stop). Not progress. Takes effect immediately; the user can revoke it. To change an entry, write a new one with supersedes; revoke=true with supersedes withdraws your own entry.',
201
+ inputSchema: {
202
+ kind: z.enum(["decision", "finding", "handoff"]).describe("decision | finding | handoff"),
203
+ title: z.string().min(1).max(200).describe("One line"),
204
+ body: z.string().max(4e3).optional().describe("Details (\u22644KB)"),
205
+ supersedes: z.string().min(1).max(128).optional().describe('Entry it replaces: "#12" or its id'),
206
+ revoke: z.boolean().optional().describe("With supersedes: withdraw that entry (only your own) instead of writing a new one")
207
+ }
208
+ }
209
+ };
210
+ function describeError(error) {
211
+ if (error instanceof ProjectsUnsupportedError) return "This Very Happy server does not support projects yet.";
212
+ if (error instanceof ProjectRequestError) {
213
+ if (error.code === "project_note_quota_exceeded" && typeof error.details.suggestion === "string") return error.details.suggestion;
214
+ if (error.code === "not_a_project_member") return "not in a project";
215
+ if (error.code) return `Project request failed: ${error.code}`;
216
+ return "Project request failed";
217
+ }
218
+ return error instanceof Error && error.message ? error.message : "Project request failed";
219
+ }
220
+ function createProjectToolExecutor(sessionId, client = sharedProjectsClient()) {
221
+ return async (name, args) => {
222
+ const sid = sessionId();
223
+ if (name === "project_context") {
224
+ const full = args?.full === true;
225
+ const ctx = await client.context(sid, { full });
226
+ return { text: formatContextForTool(ctx, { full, section: typeof args?.section === "string" ? args.section : void 0 }) };
227
+ }
228
+ const membership = await client.membership(sid);
229
+ if (!membership.projectId) return { text: "not in a project" };
230
+ if (args?.revoke) {
231
+ if (!args?.supersedes) throw new Error("revoke needs supersedes (the entry to withdraw)");
232
+ const { entry: entry2 } = await client.revoke(membership.projectId, String(args.supersedes), sid);
233
+ return { text: `revoked #${entry2.seq}` };
234
+ }
235
+ const { entry } = await client.note(membership.projectId, {
236
+ kind: String(args?.kind),
237
+ title: String(args?.title ?? ""),
238
+ authorSessionId: sid,
239
+ ...typeof args?.body === "string" && args.body ? { body: args.body } : {},
240
+ ...typeof args?.supersedes === "string" ? { supersedes: args.supersedes } : {}
241
+ });
242
+ return { text: `recorded #${entry.seq}${entry.supersedes ? " (supersedes an earlier entry)" : ""}` };
243
+ };
244
+ }
245
+ function registerProjectTools(server, execute) {
246
+ for (const name of PROJECT_TOOL_NAMES) {
247
+ const spec = PROJECT_TOOL_SCHEMAS[name];
248
+ server.registerTool(name, {
249
+ description: spec.description,
250
+ title: spec.title,
251
+ inputSchema: spec.inputSchema,
252
+ annotations: { readOnlyHint: spec.readOnly, idempotentHint: spec.readOnly, openWorldHint: false, destructiveHint: false }
253
+ }, async (args) => {
254
+ try {
255
+ return { content: [{ type: "text", text: (await execute(name, args ?? {})).text }], isError: false };
256
+ } catch (error) {
257
+ return { content: [{ type: "text", text: describeError(error) }], isError: true };
258
+ }
259
+ });
260
+ }
261
+ }
262
+
184
263
  const SELF_REPORT_MIN_INTERVAL_MS = 30 * 1e3;
185
264
  const SELF_REPORT_FRESH_MS = 15 * 60 * 1e3;
186
265
  const ATTENTION_VALUES = ["none", "review", "blocked"];
@@ -231,4 +310,4 @@ function registerReportProgressTool(server, execute) {
231
310
  });
232
311
  }
233
312
 
234
- export { AUTOMATION_TOOL_NAMES as A, registerReportProgressTool as a, normalizePhase as b, createSelfReportState as c, normalizeProgress as d, isSelfReportFresh as i, normalizeAttention as n, registerAutomationTools as r, shouldAcceptSelfReport as s };
313
+ export { AUTOMATION_TOOL_NAMES as A, PROJECT_TOOL_NAMES as P, registerProjectTools as a, registerReportProgressTool as b, createSelfReportState as c, createProjectToolExecutor as d, normalizePhase as e, normalizeProgress as f, isSelfReportFresh as i, normalizeAttention as n, registerAutomationTools as r, shouldAcceptSelfReport as s };
@@ -53,6 +53,36 @@ export default async function(pi) {
53
53
  });
54
54
  }
55
55
  }
56
+ const steerEndpoint = managed && process.env.HAPPY_PI_STEER_URL;
57
+ if (steerEndpoint && pi.sendUserMessage) {
58
+ // B-632: \u300CSteer\u300D from the web \u2014 taken from the wrapper's long poll while pi runs,
59
+ // handed to pi as a steer, acknowledged (agent/acp/piSteerChannel.ts).
60
+ const target = new URL(steerEndpoint);
61
+ if (target.origin !== url.origin || !target.pathname.startsWith('/runtime-steer/')) throw new Error('Very Happy steer must be local');
62
+ const post = (suffix, body) => fetch(steerEndpoint + suffix, {method:'POST', redirect:'error', headers:{'content-type':'application/json'}, body:JSON.stringify(body || {}), signal:AbortSignal.timeout(2000)}).catch(() => {});
63
+ let running = false, polling = false;
64
+ const poll = async () => {
65
+ if (polling) return;
66
+ polling = true;
67
+ try {
68
+ while (running) {
69
+ let item = null;
70
+ try {
71
+ const response = await fetch(steerEndpoint, {redirect:'error', signal:AbortSignal.timeout(30000)});
72
+ if (response.status === 200) item = await response.json();
73
+ else if (response.status !== 204) await new Promise(r => setTimeout(r, 1000));
74
+ } catch { await new Promise(r => setTimeout(r, 1000)); continue; }
75
+ if (!item || typeof item.text !== 'string') continue;
76
+ if (!running) { await post('/ack', {id:item.id, delivered:false}); continue; }
77
+ try { pi.sendUserMessage(item.text, {deliverAs:'steer'}); await post('/ack', {id:item.id, delivered:true}); }
78
+ catch { await post('/ack', {id:item.id, delivered:false}); }
79
+ }
80
+ } finally { polling = false; }
81
+ };
82
+ pi.on('agent_start', async () => { running = true; void poll(); });
83
+ pi.on('agent_end', async () => { running = false; });
84
+ await post('/hello');
85
+ }
56
86
  if (managed) pi.on('tool_call', async (event, ctx) => {
57
87
  let mode = process.env.HAPPY_PERMISSION_MODE || 'default';
58
88
  const sid = process.env.HAPPY_SESSION_ID;
@@ -51,6 +51,36 @@ export default async function(pi) {
51
51
  });
52
52
  }
53
53
  }
54
+ const steerEndpoint = managed && process.env.HAPPY_PI_STEER_URL;
55
+ if (steerEndpoint && pi.sendUserMessage) {
56
+ // B-632: \u300CSteer\u300D from the web \u2014 taken from the wrapper's long poll while pi runs,
57
+ // handed to pi as a steer, acknowledged (agent/acp/piSteerChannel.ts).
58
+ const target = new URL(steerEndpoint);
59
+ if (target.origin !== url.origin || !target.pathname.startsWith('/runtime-steer/')) throw new Error('Very Happy steer must be local');
60
+ const post = (suffix, body) => fetch(steerEndpoint + suffix, {method:'POST', redirect:'error', headers:{'content-type':'application/json'}, body:JSON.stringify(body || {}), signal:AbortSignal.timeout(2000)}).catch(() => {});
61
+ let running = false, polling = false;
62
+ const poll = async () => {
63
+ if (polling) return;
64
+ polling = true;
65
+ try {
66
+ while (running) {
67
+ let item = null;
68
+ try {
69
+ const response = await fetch(steerEndpoint, {redirect:'error', signal:AbortSignal.timeout(30000)});
70
+ if (response.status === 200) item = await response.json();
71
+ else if (response.status !== 204) await new Promise(r => setTimeout(r, 1000));
72
+ } catch { await new Promise(r => setTimeout(r, 1000)); continue; }
73
+ if (!item || typeof item.text !== 'string') continue;
74
+ if (!running) { await post('/ack', {id:item.id, delivered:false}); continue; }
75
+ try { pi.sendUserMessage(item.text, {deliverAs:'steer'}); await post('/ack', {id:item.id, delivered:true}); }
76
+ catch { await post('/ack', {id:item.id, delivered:false}); }
77
+ }
78
+ } finally { polling = false; }
79
+ };
80
+ pi.on('agent_start', async () => { running = true; void poll(); });
81
+ pi.on('agent_end', async () => { running = false; });
82
+ await post('/hello');
83
+ }
54
84
  if (managed) pi.on('tool_call', async (event, ctx) => {
55
85
  let mode = process.env.HAPPY_PERMISSION_MODE || 'default';
56
86
  const sid = process.env.HAPPY_SESSION_ID;