very-happy-cli 0.2.164 → 0.2.166

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 (190) hide show
  1. package/README.md +1 -1
  2. package/dist/{AcpBackend-CHDqSii9.cjs → AcpBackend-20VHOXwb.cjs} +3 -3
  3. package/dist/{AcpBackend-B8l1ZePt.mjs → AcpBackend-tRWk7yi7.mjs} +3 -3
  4. package/dist/{AcpSessionManager-BQnDJvct.mjs → AcpSessionManager-B7FIrsys.mjs} +1 -1
  5. package/dist/{AcpSessionManager-9yN2iH4b.cjs → AcpSessionManager-Zf00QnlL.cjs} +1 -1
  6. package/dist/{BasePermissionHandler-DgtAtJTV.mjs → BasePermissionHandler-CDCLIrZJ.mjs} +1 -1
  7. package/dist/{BasePermissionHandler-DGQYvBPg.cjs → BasePermissionHandler-COKc4pmt.cjs} +1 -1
  8. package/dist/{BaseReasoningProcessor-Dfacnfhj.mjs → BaseReasoningProcessor-BDVKvooR.mjs} +1 -1
  9. package/dist/{BaseReasoningProcessor-BqalZhQO.cjs → BaseReasoningProcessor-DAGQdkNp.cjs} +1 -1
  10. package/dist/{agentGuidance-CQuNlNx8.mjs → agentGuidance-BDYt2Qy2.mjs} +4 -2
  11. package/dist/{agentGuidance-B5NATuFa.cjs → agentGuidance-BtBx2xxE.cjs} +4 -1
  12. package/dist/{agentHome-DM0urHEI.mjs → agentHome-2IbIjKCa.mjs} +4 -4
  13. package/dist/{agentHome-DtsPKfTS.cjs → agentHome-KVWj6nCl.cjs} +4 -4
  14. package/dist/{api-Yoh_zKdR.mjs → api-Cmz3XS4P.mjs} +14 -12
  15. package/dist/{api-EKlS0r1w.cjs → api-DnNL5fLw.cjs} +14 -12
  16. package/dist/{apiMachine-s3HiV-SL.mjs → apiMachine-B6ySCFe0.mjs} +2137 -65
  17. package/dist/{apiMachine-q71suojS.cjs → apiMachine-DeoQ8QbZ.cjs} +2134 -62
  18. package/dist/{attachmentContent-BLyyo1al.mjs → attachmentContent-CTXapi-_.mjs} +2 -2
  19. package/dist/{attachmentContent-Bakb0XV3.cjs → attachmentContent-DPWxHgX4.cjs} +2 -2
  20. package/dist/{attachmentLimits-eJZ4ZBjF.cjs → attachmentLimits-BfgKV5iE.cjs} +28 -2
  21. package/dist/{attachmentLimits-B8nzhw-i.mjs → attachmentLimits-C1PCCM79.mjs} +28 -2
  22. package/dist/{auth-BTfv8yW0.mjs → auth-BMaBjRAj.mjs} +8 -8
  23. package/dist/{auth-Hpg4Yxfa.cjs → auth-D4-eQz85.cjs} +8 -8
  24. package/dist/{auth-Cn3dQInF.cjs → auth-ietHtvwu.cjs} +5 -5
  25. package/dist/{auth-Cxhx5evk.mjs → auth-pzWIFdOD.mjs} +5 -5
  26. package/dist/{auto-BAAEVGZa.mjs → auto-DL75Dx3I.mjs} +83 -21
  27. package/dist/{auto-CK8irHum.cjs → auto-DOWTQDPa.cjs} +84 -20
  28. package/dist/{bootstrap-D9SUykG_.cjs → bootstrap-BpXIc2wn.cjs} +2 -2
  29. package/dist/{bootstrap-CTNjn_aj.mjs → bootstrap-XE8A7Ut2.mjs} +2 -2
  30. package/dist/{browser-C8ztaIkm.cjs → browser-CcG8GLRV.cjs} +1 -1
  31. package/dist/{browser-DydXWySF.mjs → browser-DDFi1T8C.mjs} +1 -1
  32. package/dist/{claudeLocal-CsLFMvFU.cjs → claudeLocal-DXBXwIOG.cjs} +6 -6
  33. package/dist/{claudeLocal-CdJJovWq.mjs → claudeLocal-DmM5Oyhv.mjs} +6 -6
  34. package/dist/{claudeLocalLauncher-DRc-tET5.cjs → claudeLocalLauncher-C41Y6Kp4.cjs} +14 -11
  35. package/dist/{claudeLocalLauncher-CKazNnl0.mjs → claudeLocalLauncher-Cs4eUC3P.mjs} +14 -11
  36. package/dist/{claudeSessionFork-BfPW9D2S.mjs → claudeSessionFork-BdLnc2Hv.mjs} +1 -1
  37. package/dist/{claudeSessionFork-BWdhyy9B.cjs → claudeSessionFork-Cs0I3eGI.cjs} +1 -1
  38. package/dist/{client-Do5CHQnZ.mjs → client-CbK33y_s.mjs} +3 -3
  39. package/dist/{client-BZtKFCJr.cjs → client-DJ0kX_8M.cjs} +2 -2
  40. package/dist/{client-DkoV3VWl.mjs → client-GjTnsq6F.mjs} +2 -2
  41. package/dist/{client-C1GAIJ04.cjs → client-JISJx2f-.cjs} +3 -3
  42. package/dist/codex/happyMcpStdioBridge.cjs +23 -18
  43. package/dist/codex/happyMcpStdioBridge.mjs +22 -17
  44. package/dist/{codexAppServerClient-JddkV_aP.cjs → codexAppServerClient-BTjn2ZCZ.cjs} +46 -2
  45. package/dist/{codexAppServerClient-CfF33X-8.mjs → codexAppServerClient-CldXEojt.mjs} +47 -3
  46. package/dist/{codexCommand-Bdj3XZbi.cjs → codexCommand-BpD0N1F7.cjs} +71 -51
  47. package/dist/{codexCommand-btJso8yC.mjs → codexCommand-DjMU-Ijf.mjs} +71 -51
  48. package/dist/{config-nziuMb7g.mjs → config-DjSJKatx.mjs} +3 -3
  49. package/dist/{config-DpCNivmg.cjs → config-DuLL0Ppe.cjs} +3 -3
  50. package/dist/{configuration-PXAE4-FP.cjs → configuration-B0cb3xA3.cjs} +1 -1
  51. package/dist/{configuration-CiBUH72C.mjs → configuration-D2v3puap.mjs} +1 -1
  52. package/dist/{connect-D7ehaW2C.cjs → connect-B7JWEzyg.cjs} +13 -13
  53. package/dist/{connect-XHdi6Vtc.mjs → connect-CnNNyM9I.mjs} +13 -13
  54. package/dist/{context-DhvXl1oC.cjs → context-BFUpYT39.cjs} +1 -1
  55. package/dist/{context-BpEYcuLv.mjs → context-DjfqLWzE.mjs} +1 -1
  56. package/dist/{controlClient-DzmCQrY_.mjs → controlClient-BMUJfUeF.mjs} +13 -6
  57. package/dist/{controlClient-DI-Er-Ww.cjs → controlClient-CmnHGcyl.cjs} +13 -5
  58. package/dist/{createSessionMetadata-B47GrTX6.mjs → createSessionMetadata-DU0bCg2m.mjs} +2 -2
  59. package/dist/{createSessionMetadata-D04x6OMW.cjs → createSessionMetadata-DbfRBhRu.cjs} +2 -2
  60. package/dist/{deterministicJson-CKqT3awl.mjs → deterministicJson-D-WPUrZb.mjs} +36 -52
  61. package/dist/{deterministicJson-BM8e8QwP.cjs → deterministicJson-Dp3TVyap.cjs} +41 -59
  62. package/dist/{doctor-CSgzbG5L.mjs → doctor-BlXXyQ1L.mjs} +6 -6
  63. package/dist/{doctor-Cl6cqvok.cjs → doctor-CkJmdPbi.cjs} +6 -6
  64. package/dist/{assistantTools-D3cZvgUX.cjs → downloadTarget-CiQqRIc-.cjs} +44 -6
  65. package/dist/{assistantTools-BWfAV349.mjs → downloadTarget-DjSwMHun.mjs} +45 -8
  66. package/dist/{ensureDaemonRunning-fPVSsjIm.mjs → ensureDaemonRunning-CAQag1zE.mjs} +5 -5
  67. package/dist/{ensureDaemonRunning-CJ4-U32n.cjs → ensureDaemonRunning-C_aIOhgG.cjs} +5 -5
  68. package/dist/{handleResumeCommand-bX-aNF_z.cjs → handleResumeCommand-6KzBGDnl.cjs} +5 -5
  69. package/dist/{handleResumeCommand-B84dt2aH.mjs → handleResumeCommand-Ci7wacT-.mjs} +5 -5
  70. package/dist/{index-vVWpCoTr.mjs → index-B0HEEYGh.mjs} +22 -5
  71. package/dist/{index-DqlyNgt4.cjs → index-C9hI8a10.cjs} +26 -4
  72. package/dist/{index-B2UvSWo_.cjs → index-CaFCAlX8.cjs} +3 -3
  73. package/dist/{index-CP2fh7JX.cjs → index-DBmNwMX9.cjs} +39 -38
  74. package/dist/{index-DaTxsAC3.cjs → index-DEKIgZUo.cjs} +4 -4
  75. package/dist/{index-OEGj3BxE.mjs → index-DQplgo0W.mjs} +4 -4
  76. package/dist/{index-CbF87SeZ.mjs → index-HQsigW_J.mjs} +3 -3
  77. package/dist/{index-CRJtZCK-.mjs → index-WGCT6SSV.mjs} +40 -39
  78. package/dist/index.cjs +2 -2
  79. package/dist/index.mjs +2 -2
  80. package/dist/{install-BO_W7VhL.mjs → install-BdvKiOQw.mjs} +2 -0
  81. package/dist/{install-__Mni4NU.cjs → install-CejEiRGW.cjs} +3 -3
  82. package/dist/{install-Cs5qAPrB.cjs → install-Cf6AFSWC.cjs} +2 -0
  83. package/dist/{install-CurvoW2u.mjs → install-oJUvsFu9.mjs} +3 -3
  84. package/dist/lib.cjs +12 -12
  85. package/dist/lib.d.cts +55 -2
  86. package/dist/lib.d.mts +55 -2
  87. package/dist/lib.mjs +12 -12
  88. package/dist/{lidState-BbR6y9rq.mjs → lidState-BfximpjX.mjs} +1 -1
  89. package/dist/{lidState-De2HP6nu.cjs → lidState-D8BmnJV1.cjs} +1 -1
  90. package/dist/{localHappyAgentAuth-C7rDePjF.mjs → localHappyAgentAuth-Ct1aXwqd.mjs} +1 -1
  91. package/dist/{localHappyAgentAuth-CboZb3_a.cjs → localHappyAgentAuth-d7B6S_o7.cjs} +1 -1
  92. package/dist/{logger-8dtZPn3n.mjs → logger-BpQcwNnt.mjs} +2 -2
  93. package/dist/{logger-B1k7eZnq.cjs → logger-JTcJU-uL.cjs} +2 -2
  94. package/dist/{machineMetadata-C4OfKn6I.cjs → machineMetadata-BBg_Njw3.cjs} +3 -3
  95. package/dist/{machineMetadata-Bhp_w3-_.mjs → machineMetadata-CBdxABeI.mjs} +3 -3
  96. package/dist/{main-BQTaUrz0.mjs → main-B5b1gA3K.mjs} +44 -44
  97. package/dist/{main-eAiLspBM.cjs → main-C16fOGgn.cjs} +44 -44
  98. package/dist/{mcp-fapbM7Q4.cjs → mcp-BnNiBBax.cjs} +24 -19
  99. package/dist/{mcp-DXCdbQHM.mjs → mcp-DGNWgVdv.mjs} +23 -18
  100. package/dist/{mirrorProtocol-BUtmg1ws.cjs → mirrorProtocol-BEGk2--0.cjs} +80 -0
  101. package/dist/{mirrorProtocol-BNLtoWjO.mjs → mirrorProtocol-h5WHpdhh.mjs} +79 -1
  102. package/dist/{package-tVYgFJoK.mjs → package-BqwrPxL0.mjs} +7 -7
  103. package/dist/{package-CC_txQ31.cjs → package-C1XvUQFy.cjs} +7 -7
  104. package/dist/{peerTools-C1cduHh1.mjs → peerTools-CeCe-3lk.mjs} +4 -4
  105. package/dist/{peerTools-CqIcCEIg.cjs → peerTools-DPvbcs8V.cjs} +4 -4
  106. package/dist/{persistence-d3ZyER6o.cjs → persistence-2Xp_o6x6.cjs} +3 -3
  107. package/dist/{persistence-C_xFQLsD.mjs → persistence-B9LmhAE2.mjs} +3 -3
  108. package/dist/{piRunnerArgs-aq0zJX1Q.mjs → piRunnerArgs-7FaTyNOq.mjs} +1 -1
  109. package/dist/{piRunnerArgs-DSxolPlV.cjs → piRunnerArgs-DI29dDNo.cjs} +1 -1
  110. package/dist/{piRuntime-BnNl5Lmb.mjs → piRuntime-0qEK5AqE.mjs} +1 -1
  111. package/dist/{piRuntime-Dne1LPu-.cjs → piRuntime-R8XVChxK.cjs} +1 -1
  112. package/dist/{piTerminal-fjado4cR.cjs → piTerminal-Ccj0KNPr.cjs} +17 -17
  113. package/dist/{piTerminal-CKWxWtW-.mjs → piTerminal-zcQKc8Sp.mjs} +17 -17
  114. package/dist/precheckCompat-CWOi5c9L.cjs +29 -0
  115. package/dist/precheckCompat-DeEbilbr.mjs +26 -0
  116. package/dist/rateLimitWindows-C2Jk3Ih7.cjs +258 -0
  117. package/dist/rateLimitWindows-Dhfhbtqu.mjs +248 -0
  118. package/dist/{registerCommonHandlers-Dausbdsb.cjs → registerCommonHandlers-Aha_KfM3.cjs} +2 -2
  119. package/dist/{registerCommonHandlers-bSskMveZ.mjs → registerCommonHandlers-DdfGsFbM.mjs} +2 -2
  120. package/dist/{registerKillSessionHandler-CgKyzwqw.cjs → registerKillSessionHandler-CjitOpUA.cjs} +6 -6
  121. package/dist/{registerKillSessionHandler-Ben5lAsN.mjs → registerKillSessionHandler-DboQlGcH.mjs} +6 -6
  122. package/dist/{remoteSessionClient-DnCIuZpQ.mjs → remoteSessionClient-B2DtWuNP.mjs} +5 -5
  123. package/dist/{remoteSessionClient-BkJt8SHa.cjs → remoteSessionClient-BwI8rpQw.cjs} +5 -5
  124. package/dist/{tools-BTBgpiRc.cjs → reportProgressTool-B-Rcy0s3.cjs} +73 -9
  125. package/dist/{tools-gUjkPpCw.mjs → reportProgressTool-DnAD8wOa.mjs} +67 -10
  126. package/dist/{run-B8dxbDsg.cjs → run-Bh66Xs40.cjs} +289 -133
  127. package/dist/{run-BEYMVE4J.mjs → run-DPEwJpQR.mjs} +287 -131
  128. package/dist/{runClaude-Cy_HzLyO.cjs → runClaude-C-lJdAKD.cjs} +25 -20
  129. package/dist/{runClaude-Dd_P1c0f.mjs → runClaude-DLr_nBzw.mjs} +25 -20
  130. package/dist/{runClaudeDeps-JG7EUH7B.mjs → runClaudeDeps-C7JV7nXG.mjs} +47 -37
  131. package/dist/{runClaudeDeps-dxv910DR.cjs → runClaudeDeps-vWWLod7J.cjs} +44 -35
  132. package/dist/{runGemini-DY1IDW_f.cjs → runGemini-o-CUSayc.cjs} +42 -35
  133. package/dist/{runGemini-CpaBuvoW.mjs → runGemini-tH6sLw-G.mjs} +42 -35
  134. package/dist/{runOpenClaw-C7vrDQbq.mjs → runOpenClaw-C5DZvVhn.mjs} +18 -18
  135. package/dist/{runOpenClaw-C0VARcYj.cjs → runOpenClaw-D24f35l0.cjs} +18 -18
  136. package/dist/{sandbox-DRUJZuaM.mjs → sandbox-BaL1aslA.mjs} +4 -4
  137. package/dist/{sandbox-Bx9-M9rN.cjs → sandbox-TJZJ6ngw.cjs} +4 -4
  138. package/dist/selfCheck-DPi4lqme.mjs +84 -0
  139. package/dist/{selfCheck-Ba1sECTO.cjs → selfCheck-Dugi0Nk_.cjs} +34 -34
  140. package/dist/{send-Dqdpx-w5.cjs → send-CkWOSYmU.cjs} +8 -8
  141. package/dist/{send-BrzkbMy2.mjs → send-DDcJ3ayi.mjs} +8 -8
  142. package/dist/{server-CfB8EWCg.cjs → server-7qFQ8J2u.cjs} +6 -6
  143. package/dist/{server-CPMPoEAA.mjs → server-CUjRvQSd.mjs} +4 -4
  144. package/dist/{sessionLock-BsP3Y_nG.cjs → sessionLock-DfhNICyS.cjs} +2 -2
  145. package/dist/{sessionLock-DukLVzAQ.mjs → sessionLock-DqVyHFAQ.mjs} +2 -2
  146. package/dist/{sessionModeFile-JWWF6Nn7.cjs → sessionModeFile-CIznKD7O.cjs} +1 -1
  147. package/dist/{sessionModeFile-CSvi4H_t.mjs → sessionModeFile-M4OpiyrF.mjs} +1 -1
  148. package/dist/{sessionOps-BlMg1uAa.mjs → sessionOps-BnaEaOKs.mjs} +4 -4
  149. package/dist/{sessionOps-HuoMXcIZ.cjs → sessionOps-DOyy4gkY.cjs} +4 -4
  150. package/dist/{sessionScanner-Ct-JoNHP.mjs → sessionScanner-CcuOn9uU.mjs} +75 -19
  151. package/dist/{sessionScanner-BWU6KvZw.cjs → sessionScanner-Cu1yKlj4.cjs} +75 -19
  152. package/dist/{sessions-AjflCj5y.cjs → sessions-BQgk5Kw8.cjs} +9 -9
  153. package/dist/{sessions-3Hw1xXMV.mjs → sessions-C9O91rL1.mjs} +9 -9
  154. package/dist/{setupOfflineReconnection-B_9xp36H.mjs → setupOfflineReconnection-Byy8aeKT.mjs} +2 -2
  155. package/dist/{setupOfflineReconnection-Cxh9Sz9M.cjs → setupOfflineReconnection-DFmQ8s6I.cjs} +2 -2
  156. package/dist/{spawn-CN8PH11G.cjs → spawn-BS7LPmSm.cjs} +13 -12
  157. package/dist/{spawn-BXEVKCQK.mjs → spawn-EZ2yrtWd.mjs} +13 -12
  158. package/dist/{spawnAgents-Czi2VDzj.mjs → spawnAgents-HDaE3C0-.mjs} +1 -1
  159. package/dist/{spawnAgents-McixdtV1.cjs → spawnAgents-vglexX9N.cjs} +1 -1
  160. package/dist/{spawnHappyCLI-BFN0h2fK.mjs → spawnHappyCLI-BAa49m0q.mjs} +1 -1
  161. package/dist/{spawnHappyCLI-Cj-9-d_7.cjs → spawnHappyCLI-DyaldIe5.cjs} +1 -1
  162. package/dist/specialCommands-CCWtwIGZ.mjs +93 -0
  163. package/dist/specialCommands-DouFaJ_0.cjs +96 -0
  164. package/dist/{startFileWatcher-BfMu444W.cjs → startFileWatcher-DQbbypJv.cjs} +1 -1
  165. package/dist/{startFileWatcher-Csql7gdv.mjs → startFileWatcher-Dfs4whzr.mjs} +1 -1
  166. package/dist/{streamRelay-C0AffuX6.cjs → streamRelay-Ce9sgcOV.cjs} +1 -1
  167. package/dist/{streamRelay-BzMEEvJU.mjs → streamRelay-Iogsh51a.mjs} +1 -1
  168. package/dist/{sync-SCvDzRy6.mjs → sync-BLpH13Kb.mjs} +1 -1
  169. package/dist/{sync--uxtLWbo.cjs → sync-x_lI_3j_.cjs} +1 -1
  170. package/dist/{systemPrompt-C1tRiZ-u.cjs → systemPrompt-4erwILTB.cjs} +3 -3
  171. package/dist/{systemPrompt-D0KMySrK.mjs → systemPrompt-BanyDihy.mjs} +3 -3
  172. package/dist/{teams-By-hcvMF.mjs → teams-D6BOT3lR.mjs} +7 -7
  173. package/dist/{teams-CYDIFXEC.cjs → teams-DzetlGWC.cjs} +7 -7
  174. package/dist/{time-CRvAaC5H.mjs → time-CfDKj6Bx.mjs} +1 -1
  175. package/dist/{time-C7BplxuS.cjs → time-T0YmeOhS.cjs} +1 -1
  176. package/dist/{titleGenerator-CUG-n2r3.mjs → titleGenerator-ChImQ4q-.mjs} +1 -1
  177. package/dist/{titleGenerator-Kw3sTnNQ.cjs → titleGenerator-CoMxqKfP.cjs} +2 -2
  178. package/dist/{todo-B7a7J5Ng.cjs → todo-CZZebKZg.cjs} +6 -6
  179. package/dist/{todo-yuIsUvU8.mjs → todo-SVtYxGON.mjs} +6 -6
  180. package/dist/{tools-RvMKw7yx.mjs → tools-3X2z3YDe.mjs} +1 -1
  181. package/dist/{tools-D7UeLMZ7.cjs → tools-IJ0TAcJs.cjs} +1 -1
  182. package/dist/transcriptCursor-B7T_gkQ0.mjs +102 -0
  183. package/dist/transcriptCursor-DcXGLeSc.cjs +106 -0
  184. package/dist/{uninstall-D5D16-KM.cjs → uninstall-CqqCWj7w.cjs} +3 -3
  185. package/dist/{uninstall-Dx9FmLXs.mjs → uninstall-CypD-kr1.mjs} +3 -3
  186. package/package.json +7 -7
  187. package/scripts/terminal_status_forwarder.cjs +89 -0
  188. package/dist/selfCheck-DdT8r263.mjs +0 -84
  189. package/dist/specialCommands-BSqhYg5X.mjs +0 -52
  190. package/dist/specialCommands-DSsTeRej.cjs +0 -54
@@ -1,12 +1,12 @@
1
1
  import chalk from 'chalk';
2
2
  import { homedir } from 'os';
3
3
  import { join } from 'path';
4
- import { readCredentialsForConfiguredRelay } from './persistence-C_xFQLsD.mjs';
5
- import { A as ApiClient } from './api-Yoh_zKdR.mjs';
6
- import { f as ensurePrivateDirectorySync, w as writePrivateFileSync } from './configuration-CiBUH72C.mjs';
4
+ import { readCredentialsForConfiguredRelay } from './persistence-B9LmhAE2.mjs';
5
+ import { A as ApiClient } from './api-Cmz3XS4P.mjs';
6
+ import { f as ensurePrivateDirectorySync, w as writePrivateFileSync } from './configuration-D2v3puap.mjs';
7
7
  import { createServer } from 'http';
8
8
  import { randomBytes, createHash } from 'crypto';
9
- import { o as openBrowser } from './browser-DydXWySF.mjs';
9
+ import { o as openBrowser } from './browser-DDFi1T8C.mjs';
10
10
  import { exec } from 'child_process';
11
11
  import { promisify } from 'util';
12
12
  import 'node:fs/promises';
@@ -15,28 +15,28 @@ import 'zod';
15
15
  import './authRelay-DSAvg1uv.mjs';
16
16
  import 'node:crypto';
17
17
  import 'tweetnacl';
18
- import './logger-8dtZPn3n.mjs';
18
+ import './logger-BpQcwNnt.mjs';
19
19
  import 'node:util';
20
20
  import 'node:path';
21
21
  import 'node:os';
22
- import './package-tVYgFJoK.mjs';
22
+ import './package-BqwrPxL0.mjs';
23
23
  import 'axios';
24
- import './lidState-BbR6y9rq.mjs';
24
+ import './lidState-BfximpjX.mjs';
25
25
  import 'node:events';
26
26
  import 'socket.io-client';
27
- import './attachmentLimits-B8nzhw-i.mjs';
28
- import './index-vVWpCoTr.mjs';
27
+ import './attachmentLimits-C1PCCM79.mjs';
28
+ import './index-B0HEEYGh.mjs';
29
29
  import '@paralleldrive/cuid2';
30
30
  import './limits-DIo7rEBR.mjs';
31
- import './time-CRvAaC5H.mjs';
32
- import './registerCommonHandlers-bSskMveZ.mjs';
31
+ import './time-CfDKj6Bx.mjs';
32
+ import './registerCommonHandlers-DdfGsFbM.mjs';
33
33
  import 'fs/promises';
34
34
  import 'cross-spawn';
35
35
  import './projectPath-BTBIMB57.mjs';
36
36
  import 'url';
37
- import './sync-SCvDzRy6.mjs';
37
+ import './sync-BLpH13Kb.mjs';
38
38
  import './backgroundTaskActivity-8PdPxrvy.mjs';
39
- import './controlClient-DzmCQrY_.mjs';
39
+ import './controlClient-BMUJfUeF.mjs';
40
40
  import './contentLogMetadata-BlWI0egu.mjs';
41
41
  import 'open';
42
42
 
@@ -5,7 +5,7 @@ var node_fs = require('node:fs');
5
5
  var path = require('node:path');
6
6
  var node_crypto = require('node:crypto');
7
7
  var z = require('zod');
8
- var configuration = require('./configuration-PXAE4-FP.cjs');
8
+ var configuration = require('./configuration-B0cb3xA3.cjs');
9
9
 
10
10
  const TeamScopeSchema = z.z.object({
11
11
  serverUrl: z.z.string(),
@@ -3,7 +3,7 @@ import { constants } from 'node:fs';
3
3
  import { isAbsolute, join, dirname } from 'node:path';
4
4
  import { randomUUID } from 'node:crypto';
5
5
  import { z } from 'zod';
6
- import { n as normalizeHttpEndpoint, c as configuration } from './configuration-CiBUH72C.mjs';
6
+ import { n as normalizeHttpEndpoint, c as configuration } from './configuration-D2v3puap.mjs';
7
7
 
8
8
  const TeamScopeSchema = z.object({
9
9
  serverUrl: z.string(),
@@ -1,6 +1,6 @@
1
- import { l as logger } from './logger-8dtZPn3n.mjs';
2
- import { readDaemonState, clearDaemonState } from './persistence-C_xFQLsD.mjs';
3
- import { c as configuration } from './configuration-CiBUH72C.mjs';
1
+ import { l as logger } from './logger-BpQcwNnt.mjs';
2
+ import { readDaemonState, clearDaemonState } from './persistence-B9LmhAE2.mjs';
3
+ import { c as configuration } from './configuration-D2v3puap.mjs';
4
4
 
5
5
  function daemonControlHeaders(controlToken) {
6
6
  return {
@@ -123,6 +123,13 @@ async function notifyDaemonTurnEvent(sessionId, event) {
123
123
  async function notifyDaemonBackgroundTasks(sessionId, backgroundTasks) {
124
124
  return daemonPost("/session-event", { sessionId, event: "background_tasks", backgroundTasks });
125
125
  }
126
+ function reportRateLimitsToDaemon(report) {
127
+ void daemonPost("/rate-limits", report).then((result) => {
128
+ if (result?.error) logger.debug(`[CONTROL CLIENT] rate-limits not recorded: ${result.error}`);
129
+ }).catch((error) => {
130
+ logger.debug("[CONTROL CLIENT] rate-limits failed:", error);
131
+ });
132
+ }
126
133
  function reportSessionEditToDaemon(edit) {
127
134
  void daemonPost("/session-edit", edit).then((result) => {
128
135
  if (result?.error) logger.debug(`[CONTROL CLIENT] session-edit not recorded: ${result.error}`);
@@ -151,8 +158,8 @@ async function pushClipboardViaDaemon(text, terminalId) {
151
158
  }
152
159
  return result;
153
160
  }
154
- async function pushFilePreviewViaDaemon(terminalId, path, mode = "file") {
155
- const result = await daemonPost("/file-preview", { terminalId, path, mode });
161
+ async function pushFilePreviewViaDaemon(terminalId, path, mode = "file", intent) {
162
+ const result = await daemonPost("/file-preview", { terminalId, path, mode, ...intent ? { intent } : {} });
156
163
  if (result?.error) return { delivered: false, error: result.error };
157
164
  return { delivered: result?.delivered === true, ...result?.delivered === true ? {} : { error: "preview was not delivered" } };
158
165
  }
@@ -257,4 +264,4 @@ async function waitForProcessDeath(pid, timeout) {
257
264
  throw new Error("Process did not die within timeout");
258
265
  }
259
266
 
260
- export { stopDaemon as a, pushFilePreviewViaDaemon as b, checkIfDaemonRunningAndCleanupStaleState as c, setTerminalTitleViaDaemon as d, spawnDaemonSession as e, listDaemonPeers as f, reportSessionEditToDaemon as g, notifyDaemonTurnEvent as h, isDaemonRunningCurrentlyInstalledHappyVersion as i, notifyDaemonBackgroundTasks as j, notifyDaemonSessionEvent as k, listDaemonSessions as l, notifyDaemonClaudeAuthFailed as m, notifyDaemonSessionStarted as n, cleanupDaemonState as o, pushClipboardViaDaemon as p, resumeDaemonSession as r, stopDaemonSession as s };
267
+ export { stopDaemon as a, pushFilePreviewViaDaemon as b, checkIfDaemonRunningAndCleanupStaleState as c, setTerminalTitleViaDaemon as d, spawnDaemonSession as e, listDaemonPeers as f, resumeDaemonSession as g, reportSessionEditToDaemon as h, isDaemonRunningCurrentlyInstalledHappyVersion as i, notifyDaemonTurnEvent as j, notifyDaemonBackgroundTasks as k, listDaemonSessions as l, notifyDaemonSessionEvent as m, notifyDaemonSessionStarted as n, notifyDaemonClaudeAuthFailed as o, pushClipboardViaDaemon as p, cleanupDaemonState as q, reportRateLimitsToDaemon as r, stopDaemonSession as s };
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var logger = require('./logger-B1k7eZnq.cjs');
4
- var persistence = require('./persistence-d3ZyER6o.cjs');
5
- var configuration = require('./configuration-PXAE4-FP.cjs');
3
+ var logger = require('./logger-JTcJU-uL.cjs');
4
+ var persistence = require('./persistence-2Xp_o6x6.cjs');
5
+ var configuration = require('./configuration-B0cb3xA3.cjs');
6
6
 
7
7
  function daemonControlHeaders(controlToken) {
8
8
  return {
@@ -125,6 +125,13 @@ async function notifyDaemonTurnEvent(sessionId, event) {
125
125
  async function notifyDaemonBackgroundTasks(sessionId, backgroundTasks) {
126
126
  return daemonPost("/session-event", { sessionId, event: "background_tasks", backgroundTasks });
127
127
  }
128
+ function reportRateLimitsToDaemon(report) {
129
+ void daemonPost("/rate-limits", report).then((result) => {
130
+ if (result?.error) logger.logger.debug(`[CONTROL CLIENT] rate-limits not recorded: ${result.error}`);
131
+ }).catch((error) => {
132
+ logger.logger.debug("[CONTROL CLIENT] rate-limits failed:", error);
133
+ });
134
+ }
128
135
  function reportSessionEditToDaemon(edit) {
129
136
  void daemonPost("/session-edit", edit).then((result) => {
130
137
  if (result?.error) logger.logger.debug(`[CONTROL CLIENT] session-edit not recorded: ${result.error}`);
@@ -153,8 +160,8 @@ async function pushClipboardViaDaemon(text, terminalId) {
153
160
  }
154
161
  return result;
155
162
  }
156
- async function pushFilePreviewViaDaemon(terminalId, path, mode = "file") {
157
- const result = await daemonPost("/file-preview", { terminalId, path, mode });
163
+ async function pushFilePreviewViaDaemon(terminalId, path, mode = "file", intent) {
164
+ const result = await daemonPost("/file-preview", { terminalId, path, mode, ...intent ? { intent } : {} });
158
165
  if (result?.error) return { delivered: false, error: result.error };
159
166
  return { delivered: result?.delivered === true, ...result?.delivered === true ? {} : { error: "preview was not delivered" } };
160
167
  }
@@ -271,6 +278,7 @@ exports.notifyDaemonSessionStarted = notifyDaemonSessionStarted;
271
278
  exports.notifyDaemonTurnEvent = notifyDaemonTurnEvent;
272
279
  exports.pushClipboardViaDaemon = pushClipboardViaDaemon;
273
280
  exports.pushFilePreviewViaDaemon = pushFilePreviewViaDaemon;
281
+ exports.reportRateLimitsToDaemon = reportRateLimitsToDaemon;
274
282
  exports.reportSessionEditToDaemon = reportSessionEditToDaemon;
275
283
  exports.resumeDaemonSession = resumeDaemonSession;
276
284
  exports.setTerminalTitleViaDaemon = setTerminalTitleViaDaemon;
@@ -1,8 +1,8 @@
1
1
  import os from 'node:os';
2
2
  import { resolve } from 'node:path';
3
- import { c as configuration } from './configuration-CiBUH72C.mjs';
3
+ import { c as configuration } from './configuration-D2v3puap.mjs';
4
4
  import { p as projectPath } from './projectPath-BTBIMB57.mjs';
5
- import { p as packageJson } from './package-tVYgFJoK.mjs';
5
+ import { p as packageJson } from './package-BqwrPxL0.mjs';
6
6
 
7
7
  const SPAWN_ORIGIN_TAG_MAX = 24;
8
8
  function spawnOriginTags(env = process.env, flavor = void 0) {
@@ -2,9 +2,9 @@
2
2
 
3
3
  var os = require('node:os');
4
4
  var path = require('node:path');
5
- var configuration = require('./configuration-PXAE4-FP.cjs');
5
+ var configuration = require('./configuration-B0cb3xA3.cjs');
6
6
  var projectPath = require('./projectPath-ChLhdOyt.cjs');
7
- var _package = require('./package-CC_txQ31.cjs');
7
+ var _package = require('./package-C1XvUQFy.cjs');
8
8
 
9
9
  const SPAWN_ORIGIN_TAG_MAX = 24;
10
10
  function spawnOriginTags(env = process.env, flavor = void 0) {
@@ -1,23 +1,23 @@
1
- import { C as ContextUsageSchema } from './index-vVWpCoTr.mjs';
1
+ import { C as ContextUsageSchema } from './index-B0HEEYGh.mjs';
2
2
  import { unlink, mkdir, open, rename } from 'node:fs/promises';
3
3
  import { randomUUID } from 'node:crypto';
4
4
  import { constants } from 'node:fs';
5
5
  import { dirname } from 'node:path';
6
6
  import { z } from 'zod';
7
- import { T as TeamConnectionPreflightError, c as createTeamsClient } from './client-Do5CHQnZ.mjs';
8
- import { t as teamScopePath } from './context-BpEYcuLv.mjs';
9
- import { g as waitForSessionKey, e as sendUserMessage } from './sessionOps-BlMg1uAa.mjs';
7
+ import { T as TeamConnectionPreflightError, c as createTeamsClient } from './client-CbK33y_s.mjs';
8
+ import { t as teamScopePath } from './context-DjfqLWzE.mjs';
9
+ import { g as waitForSessionKey, e as sendUserMessage } from './sessionOps-BnaEaOKs.mjs';
10
10
  import { T as TEAM_SKILL } from './resources-BdFBQi8r.mjs';
11
- import { T as TEAM_TOOL_NAMES, r as registerTeamsTools } from './tools-RvMKw7yx.mjs';
12
- import { A as AUTOMATION_TOOL_NAMES, r as registerAutomationTools } from './tools-gUjkPpCw.mjs';
13
- import { S as SESSION_PEER_TOOL_NAMES, r as registerSessionPeerTools, a as createSessionPeerToolExecutor } from './peerTools-C1cduHh1.mjs';
11
+ import { T as TEAM_TOOL_NAMES, r as registerTeamsTools } from './tools-3X2z3YDe.mjs';
12
+ import { c as createSelfReportState, A as AUTOMATION_TOOL_NAMES, r as registerAutomationTools, a as registerReportProgressTool, n as normalizeAttention, b as normalizePhase, d as normalizeProgress, s as shouldAcceptSelfReport } from './reportProgressTool-DnAD8wOa.mjs';
13
+ import { S as SESSION_PEER_TOOL_NAMES, r as registerSessionPeerTools, a as createSessionPeerToolExecutor } from './peerTools-CeCe-3lk.mjs';
14
14
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
15
15
  import { createServer } from 'node:http';
16
16
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
17
- import { l as logger } from './logger-8dtZPn3n.mjs';
17
+ import { l as logger } from './logger-BpQcwNnt.mjs';
18
18
  import { C as CLIPBOARD_TOOL_NAME, a as CLIPBOARD_TOOL_TITLE, b as CLIPBOARD_TOOL_DESCRIPTION, c as CLIPBOARD_MAX_BYTES } from './limits-DIo7rEBR.mjs';
19
- import { A as ASSISTANT_TOOL_NAMES, a as registerAssistantTools } from './assistantTools-BWfAV349.mjs';
20
- import { P as PREVIEW_TOOL_NAME, R as REPORT_PROGRESS_TOOL_NAME, a as PREVIEW_TOOL_TITLE, b as PREVIEW_TOOL_DESCRIPTION, c as REPORT_PROGRESS_TOOL_TITLE, d as REPORT_PROGRESS_TOOL_DESCRIPTION } from './agentGuidance-CQuNlNx8.mjs';
19
+ import { A as ASSISTANT_TOOL_NAMES, a as registerAssistantTools, c as checkDownloadTarget } from './downloadTarget-DjSwMHun.mjs';
20
+ import { P as PREVIEW_TOOL_NAME, R as REPORT_PROGRESS_TOOL_NAME, a as PREVIEW_TOOL_TITLE, b as PREVIEW_TOOL_DESCRIPTION, c as PREVIEW_DOWNLOAD_PARAM_DESCRIPTION } from './agentGuidance-BDYt2Qy2.mjs';
21
21
  import { c as checkPreviewPath } from './previewPath-CXN4Vag0.mjs';
22
22
  import { createHash } from 'crypto';
23
23
 
@@ -128,29 +128,6 @@ This session is now connected as the team lead. Call team_inspect to read the au
128
128
  };
129
129
  }
130
130
 
131
- const SELF_REPORT_MIN_INTERVAL_MS = 30 * 1e3;
132
- const SELF_REPORT_FRESH_MS = 15 * 60 * 1e3;
133
- const PROGRESS_MAX_CHARS = 200;
134
- function createSelfReportState() {
135
- return { lastAcceptedAt: 0 };
136
- }
137
- function shouldAcceptSelfReport(state, now, attention) {
138
- if (state.lastAcceptedAt === 0) return true;
139
- if (attention !== void 0 && attention !== state.lastAttention) return true;
140
- return now - state.lastAcceptedAt >= SELF_REPORT_MIN_INTERVAL_MS;
141
- }
142
- function isSelfReportFresh(state, now) {
143
- if (state.lastAcceptedAt === 0) return false;
144
- const age = now - state.lastAcceptedAt;
145
- return age >= 0 && age < SELF_REPORT_FRESH_MS;
146
- }
147
- function normalizeProgress(value) {
148
- if (typeof value !== "string") return null;
149
- const flat = value.replace(/\s+/g, " ").trim();
150
- if (!flat) return null;
151
- return flat.length > PROGRESS_MAX_CHARS ? flat.slice(0, PROGRESS_MAX_CHARS) : flat;
152
- }
153
-
154
131
  function createMcpServer(handlers, options, sessionId, client) {
155
132
  const mcp = new McpServer({
156
133
  name: "Very Happy Tools",
@@ -222,17 +199,20 @@ function createMcpServer(handlers, options, sessionId, client) {
222
199
  title: PREVIEW_TOOL_TITLE,
223
200
  inputSchema: {
224
201
  path: z.string().describe("Absolute path (or ~/\u2026) of the file to show the user"),
225
- mode: z.enum(["file", "diff"]).optional().describe("'file' (default) renders the file; 'diff' is reserved and currently falls back to 'file'")
202
+ mode: z.enum(["file", "diff"]).optional().describe("'file' (default) renders the file; 'diff' is reserved and currently falls back to 'file'"),
203
+ // B-562: optional; old web clients ignore the resulting intent and just preview.
204
+ download: z.boolean().optional().describe(PREVIEW_DOWNLOAD_PARAM_DESCRIPTION)
226
205
  }
227
206
  }, async (args) => {
228
- const response = await handlers.openPreview(args.path, args.mode ?? "file");
207
+ const response = await handlers.openPreview(args.path, args.mode ?? "file", args.download === true);
229
208
  logger.debug("[happyMCP] open_preview response:", response);
230
209
  if (response.delivered) {
210
+ const target = response.resolved ?? args.path;
231
211
  return {
232
212
  content: [{
233
213
  type: "text",
234
214
  // 明说不保证用户看到了——否则 claude 会基于「已预览」做后续推断(spec 风险 8)
235
- text: `Asked the user's open web client(s) to preview ${response.resolved ?? args.path}. This does not confirm they looked at it.`
215
+ text: (args.download === true ? `Asked the user's open web client(s) to offer ${target} for download. This does not confirm they downloaded it.` : `Asked the user's open web client(s) to preview ${target}. This does not confirm they looked at it.`) + (response.note ? ` ${response.note}` : "")
236
216
  }],
237
217
  isError: false
238
218
  };
@@ -242,15 +222,8 @@ function createMcpServer(handlers, options, sessionId, client) {
242
222
  isError: true
243
223
  };
244
224
  });
245
- mcp.registerTool(REPORT_PROGRESS_TOOL_NAME, {
246
- description: REPORT_PROGRESS_TOOL_DESCRIPTION,
247
- title: REPORT_PROGRESS_TOOL_TITLE,
248
- inputSchema: {
249
- progress: z.string().describe("One short line describing the current state of this task"),
250
- attention: z.enum(["none", "review", "blocked"]).optional().describe("'blocked' = cannot proceed without the user; 'review' = wants their eyes; 'none' = ordinary progress")
251
- }
252
- }, async (args) => {
253
- const response = await handlers.reportProgress(args.progress, args.attention ?? "none");
225
+ registerReportProgressTool(mcp, async (args) => {
226
+ const response = await handlers.reportProgress(String(args.progress ?? ""), normalizeAttention(args.attention), normalizePhase(args.phase));
254
227
  logger.debug("[happyMCP] report_progress response:", response);
255
228
  if (response.accepted) {
256
229
  return { content: [{ type: "text", text: "Board updated." }], isError: false };
@@ -265,39 +238,50 @@ function createMcpServer(handlers, options, sessionId, client) {
265
238
  }
266
239
  return mcp;
267
240
  }
241
+ function withoutPhase(board) {
242
+ if (!board) return {};
243
+ const { phase: _phase, ...rest } = board;
244
+ return rest;
245
+ }
268
246
  async function startHappyServer(client, options) {
269
247
  logger.debug(`[happyMCP] server:start sessionId=${client.sessionId} assistant=${!!options?.assistant}`);
270
248
  const selfReportState = options?.selfReportState ?? createSelfReportState();
271
249
  const handlers = {
272
- openPreview: async (path, mode) => {
250
+ openPreview: async (path, mode, download = false) => {
273
251
  const verdict = checkPreviewPath(path);
274
252
  if (verdict.deniedReason) {
275
253
  logger.debug(`[happyMCP] open_preview denied: ${verdict.deniedReason}`);
276
254
  return { delivered: false, error: verdict.deniedReason };
277
255
  }
256
+ const target = download ? await checkDownloadTarget(verdict.resolved) : null;
257
+ if (target?.error) return { delivered: false, error: target.error };
278
258
  try {
279
- const result = client.pushFilePreview(verdict.resolved, mode);
280
- return { delivered: result.delivered, resolved: verdict.resolved, error: result.error };
259
+ const result = client.pushFilePreview(verdict.resolved, mode, download ? "download" : void 0);
260
+ return { delivered: result.delivered, resolved: verdict.resolved, error: result.error, note: target?.note ?? void 0 };
281
261
  } catch (error) {
282
262
  return { delivered: false, error: String(error) };
283
263
  }
284
264
  },
285
- reportProgress: async (progress, attention) => {
265
+ reportProgress: async (progress, attention, phase) => {
286
266
  const text = normalizeProgress(progress);
287
267
  if (!text) {
288
268
  return { accepted: false, error: "progress must be a non-empty one-line string" };
289
269
  }
290
270
  const now = Date.now();
291
- if (!shouldAcceptSelfReport(selfReportState, now, attention)) {
271
+ if (!shouldAcceptSelfReport(selfReportState, now, attention, phase)) {
292
272
  return { accepted: false };
293
273
  }
294
274
  selfReportState.lastAcceptedAt = now;
295
275
  selfReportState.lastAttention = attention;
276
+ selfReportState.lastPhase = phase;
296
277
  try {
297
278
  client.updateMetadata((metadata) => ({
298
279
  ...metadata,
299
280
  board: {
300
- ...metadata?.board,
281
+ // B-556: a report without phase must not keep the previous one
282
+ // (a stale label next to fresh text); taskId etc. are kept.
283
+ ...withoutPhase(metadata?.board),
284
+ ...phase ? { phase } : {},
301
285
  attention,
302
286
  progress: text,
303
287
  analyzedAt: now,
@@ -499,4 +483,4 @@ function hashObject(obj, options, encoding = "hex") {
499
483
  return createHash("sha256").update(jsonString).digest(encoding);
500
484
  }
501
485
 
502
- export { createSelfReportState as c, hashObject as h, isSelfReportFresh as i, startHappyServer as s };
486
+ export { hashObject as h, startHappyServer as s };
@@ -1,25 +1,25 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-DqlyNgt4.cjs');
3
+ var index = require('./index-C9hI8a10.cjs');
4
4
  var promises = require('node:fs/promises');
5
5
  var node_crypto = require('node:crypto');
6
6
  var node_fs = require('node:fs');
7
7
  var path = require('node:path');
8
8
  var z = require('zod');
9
- var client = require('./client-C1GAIJ04.cjs');
10
- var context = require('./context-DhvXl1oC.cjs');
11
- var sessionOps = require('./sessionOps-HuoMXcIZ.cjs');
9
+ var client = require('./client-JISJx2f-.cjs');
10
+ var context = require('./context-BFUpYT39.cjs');
11
+ var sessionOps = require('./sessionOps-DOyy4gkY.cjs');
12
12
  var resources = require('./resources-JDPugcDq.cjs');
13
- var tools = require('./tools-D7UeLMZ7.cjs');
14
- var tools$1 = require('./tools-BTBgpiRc.cjs');
15
- var peerTools = require('./peerTools-CqIcCEIg.cjs');
13
+ var tools = require('./tools-IJ0TAcJs.cjs');
14
+ var reportProgressTool = require('./reportProgressTool-B-Rcy0s3.cjs');
15
+ var peerTools = require('./peerTools-DPvbcs8V.cjs');
16
16
  var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
17
17
  var node_http = require('node:http');
18
18
  var streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
19
- var logger = require('./logger-B1k7eZnq.cjs');
19
+ var logger = require('./logger-JTcJU-uL.cjs');
20
20
  var limits = require('./limits-C-a7gr04.cjs');
21
- var assistantTools = require('./assistantTools-D3cZvgUX.cjs');
22
- var agentGuidance = require('./agentGuidance-B5NATuFa.cjs');
21
+ var downloadTarget = require('./downloadTarget-CiQqRIc-.cjs');
22
+ var agentGuidance = require('./agentGuidance-BtBx2xxE.cjs');
23
23
  var previewPath = require('./previewPath-B0rBdhy1.cjs');
24
24
  var crypto = require('crypto');
25
25
 
@@ -130,36 +130,13 @@ This session is now connected as the team lead. Call team_inspect to read the au
130
130
  };
131
131
  }
132
132
 
133
- const SELF_REPORT_MIN_INTERVAL_MS = 30 * 1e3;
134
- const SELF_REPORT_FRESH_MS = 15 * 60 * 1e3;
135
- const PROGRESS_MAX_CHARS = 200;
136
- function createSelfReportState() {
137
- return { lastAcceptedAt: 0 };
138
- }
139
- function shouldAcceptSelfReport(state, now, attention) {
140
- if (state.lastAcceptedAt === 0) return true;
141
- if (attention !== void 0 && attention !== state.lastAttention) return true;
142
- return now - state.lastAcceptedAt >= SELF_REPORT_MIN_INTERVAL_MS;
143
- }
144
- function isSelfReportFresh(state, now) {
145
- if (state.lastAcceptedAt === 0) return false;
146
- const age = now - state.lastAcceptedAt;
147
- return age >= 0 && age < SELF_REPORT_FRESH_MS;
148
- }
149
- function normalizeProgress(value) {
150
- if (typeof value !== "string") return null;
151
- const flat = value.replace(/\s+/g, " ").trim();
152
- if (!flat) return null;
153
- return flat.length > PROGRESS_MAX_CHARS ? flat.slice(0, PROGRESS_MAX_CHARS) : flat;
154
- }
155
-
156
133
  function createMcpServer(handlers, options, sessionId, client) {
157
134
  const mcp = new mcp_js.McpServer({
158
135
  name: "Very Happy Tools",
159
136
  version: "1.0.0"
160
137
  });
161
138
  tools.registerTeamsTools(mcp, sessionId);
162
- tools$1.registerAutomationTools(mcp);
139
+ reportProgressTool.registerAutomationTools(mcp);
163
140
  if (client) peerTools.registerSessionPeerTools(mcp, peerTools.createSessionPeerToolExecutor(client));
164
141
  mcp.registerTool("change_title", {
165
142
  description: "Change the title of the current chat session",
@@ -224,17 +201,20 @@ function createMcpServer(handlers, options, sessionId, client) {
224
201
  title: agentGuidance.PREVIEW_TOOL_TITLE,
225
202
  inputSchema: {
226
203
  path: z.z.string().describe("Absolute path (or ~/\u2026) of the file to show the user"),
227
- mode: z.z.enum(["file", "diff"]).optional().describe("'file' (default) renders the file; 'diff' is reserved and currently falls back to 'file'")
204
+ mode: z.z.enum(["file", "diff"]).optional().describe("'file' (default) renders the file; 'diff' is reserved and currently falls back to 'file'"),
205
+ // B-562: optional; old web clients ignore the resulting intent and just preview.
206
+ download: z.z.boolean().optional().describe(agentGuidance.PREVIEW_DOWNLOAD_PARAM_DESCRIPTION)
228
207
  }
229
208
  }, async (args) => {
230
- const response = await handlers.openPreview(args.path, args.mode ?? "file");
209
+ const response = await handlers.openPreview(args.path, args.mode ?? "file", args.download === true);
231
210
  logger.logger.debug("[happyMCP] open_preview response:", response);
232
211
  if (response.delivered) {
212
+ const target = response.resolved ?? args.path;
233
213
  return {
234
214
  content: [{
235
215
  type: "text",
236
216
  // 明说不保证用户看到了——否则 claude 会基于「已预览」做后续推断(spec 风险 8)
237
- text: `Asked the user's open web client(s) to preview ${response.resolved ?? args.path}. This does not confirm they looked at it.`
217
+ text: (args.download === true ? `Asked the user's open web client(s) to offer ${target} for download. This does not confirm they downloaded it.` : `Asked the user's open web client(s) to preview ${target}. This does not confirm they looked at it.`) + (response.note ? ` ${response.note}` : "")
238
218
  }],
239
219
  isError: false
240
220
  };
@@ -244,15 +224,8 @@ function createMcpServer(handlers, options, sessionId, client) {
244
224
  isError: true
245
225
  };
246
226
  });
247
- mcp.registerTool(agentGuidance.REPORT_PROGRESS_TOOL_NAME, {
248
- description: agentGuidance.REPORT_PROGRESS_TOOL_DESCRIPTION,
249
- title: agentGuidance.REPORT_PROGRESS_TOOL_TITLE,
250
- inputSchema: {
251
- progress: z.z.string().describe("One short line describing the current state of this task"),
252
- attention: z.z.enum(["none", "review", "blocked"]).optional().describe("'blocked' = cannot proceed without the user; 'review' = wants their eyes; 'none' = ordinary progress")
253
- }
254
- }, async (args) => {
255
- const response = await handlers.reportProgress(args.progress, args.attention ?? "none");
227
+ reportProgressTool.registerReportProgressTool(mcp, async (args) => {
228
+ const response = await handlers.reportProgress(String(args.progress ?? ""), reportProgressTool.normalizeAttention(args.attention), reportProgressTool.normalizePhase(args.phase));
256
229
  logger.logger.debug("[happyMCP] report_progress response:", response);
257
230
  if (response.accepted) {
258
231
  return { content: [{ type: "text", text: "Board updated." }], isError: false };
@@ -263,43 +236,54 @@ function createMcpServer(handlers, options, sessionId, client) {
263
236
  };
264
237
  });
265
238
  if (options?.assistant && !process.env.VH_TEAM_SCOPE_FILE) {
266
- assistantTools.registerAssistantTools(mcp);
239
+ downloadTarget.registerAssistantTools(mcp);
267
240
  }
268
241
  return mcp;
269
242
  }
243
+ function withoutPhase(board) {
244
+ if (!board) return {};
245
+ const { phase: _phase, ...rest } = board;
246
+ return rest;
247
+ }
270
248
  async function startHappyServer(client, options) {
271
249
  logger.logger.debug(`[happyMCP] server:start sessionId=${client.sessionId} assistant=${!!options?.assistant}`);
272
- const selfReportState = options?.selfReportState ?? createSelfReportState();
250
+ const selfReportState = options?.selfReportState ?? reportProgressTool.createSelfReportState();
273
251
  const handlers = {
274
- openPreview: async (path, mode) => {
252
+ openPreview: async (path, mode, download = false) => {
275
253
  const verdict = previewPath.checkPreviewPath(path);
276
254
  if (verdict.deniedReason) {
277
255
  logger.logger.debug(`[happyMCP] open_preview denied: ${verdict.deniedReason}`);
278
256
  return { delivered: false, error: verdict.deniedReason };
279
257
  }
258
+ const target = download ? await downloadTarget.checkDownloadTarget(verdict.resolved) : null;
259
+ if (target?.error) return { delivered: false, error: target.error };
280
260
  try {
281
- const result = client.pushFilePreview(verdict.resolved, mode);
282
- return { delivered: result.delivered, resolved: verdict.resolved, error: result.error };
261
+ const result = client.pushFilePreview(verdict.resolved, mode, download ? "download" : void 0);
262
+ return { delivered: result.delivered, resolved: verdict.resolved, error: result.error, note: target?.note ?? void 0 };
283
263
  } catch (error) {
284
264
  return { delivered: false, error: String(error) };
285
265
  }
286
266
  },
287
- reportProgress: async (progress, attention) => {
288
- const text = normalizeProgress(progress);
267
+ reportProgress: async (progress, attention, phase) => {
268
+ const text = reportProgressTool.normalizeProgress(progress);
289
269
  if (!text) {
290
270
  return { accepted: false, error: "progress must be a non-empty one-line string" };
291
271
  }
292
272
  const now = Date.now();
293
- if (!shouldAcceptSelfReport(selfReportState, now, attention)) {
273
+ if (!reportProgressTool.shouldAcceptSelfReport(selfReportState, now, attention, phase)) {
294
274
  return { accepted: false };
295
275
  }
296
276
  selfReportState.lastAcceptedAt = now;
297
277
  selfReportState.lastAttention = attention;
278
+ selfReportState.lastPhase = phase;
298
279
  try {
299
280
  client.updateMetadata((metadata) => ({
300
281
  ...metadata,
301
282
  board: {
302
- ...metadata?.board,
283
+ // B-556: a report without phase must not keep the previous one
284
+ // (a stale label next to fresh text); taskId etc. are kept.
285
+ ...withoutPhase(metadata?.board),
286
+ ...phase ? { phase } : {},
303
287
  attention,
304
288
  progress: text,
305
289
  analyzedAt: now,
@@ -403,9 +387,9 @@ async function startHappyServer(client, options) {
403
387
  agentGuidance.PREVIEW_TOOL_NAME,
404
388
  agentGuidance.REPORT_PROGRESS_TOOL_NAME,
405
389
  ...tools.TEAM_TOOL_NAMES,
406
- ...tools$1.AUTOMATION_TOOL_NAMES,
390
+ ...reportProgressTool.AUTOMATION_TOOL_NAMES,
407
391
  ...peerTools.SESSION_PEER_TOOL_NAMES,
408
- ...options?.assistant && !process.env.VH_TEAM_SCOPE_FILE ? assistantTools.ASSISTANT_TOOL_NAMES : []
392
+ ...options?.assistant && !process.env.VH_TEAM_SCOPE_FILE ? downloadTarget.ASSISTANT_TOOL_NAMES : []
409
393
  ],
410
394
  stop: () => {
411
395
  logger.logger.debug(`[happyMCP] server:stop sessionId=${client.sessionId}`);
@@ -501,7 +485,5 @@ function hashObject(obj, options, encoding = "hex") {
501
485
  return crypto.createHash("sha256").update(jsonString).digest(encoding);
502
486
  }
503
487
 
504
- exports.createSelfReportState = createSelfReportState;
505
488
  exports.hashObject = hashObject;
506
- exports.isSelfReportFresh = isSelfReportFresh;
507
489
  exports.startHappyServer = startHappyServer;
@@ -1,12 +1,12 @@
1
1
  import chalk from 'chalk';
2
- import { c as configuration } from './configuration-CiBUH72C.mjs';
3
- import { readSettings, readCredentials, readDaemonState } from './persistence-C_xFQLsD.mjs';
4
- import { c as checkIfDaemonRunningAndCleanupStaleState } from './controlClient-DzmCQrY_.mjs';
2
+ import { c as configuration } from './configuration-D2v3puap.mjs';
3
+ import { readSettings, readCredentials, readDaemonState } from './persistence-B9LmhAE2.mjs';
4
+ import { c as checkIfDaemonRunningAndCleanupStaleState } from './controlClient-BMUJfUeF.mjs';
5
5
  import { findAllHappyProcesses } from './doctor-BPkYWSuq.mjs';
6
6
  import { statSync, realpathSync, existsSync, readdirSync } from 'node:fs';
7
7
  import { isAbsolute, resolve, dirname, basename, delimiter, join } from 'node:path';
8
8
  import { p as projectPath } from './projectPath-BTBIMB57.mjs';
9
- import { p as packageJson } from './package-tVYgFJoK.mjs';
9
+ import { p as packageJson } from './package-BqwrPxL0.mjs';
10
10
  import { s as shareableSettingsSummary, c as collectRuntimeReadiness, S as SUPPORTED_NODE_LABEL, r as resolveClaudeCredentialReadiness, a as toolProbeLabel, b as daemonReadiness, d as daemonEndpointsMatch } from './doctorReadiness-C208SMN9.mjs';
11
11
  import { c as credentialRelayProblem } from './authRelay-DSAvg1uv.mjs';
12
12
  import { d as deriveLocalCliUpdateSummary } from './cliUpdate-Y34VGe9Y.mjs';
@@ -310,8 +310,8 @@ ${typeLabels[type] || type}:`));
310
310
  }
311
311
  console.log(chalk.gray(" An external claude command is only needed for native terminal/mirror use."));
312
312
  try {
313
- const { resolveAgentHomesForCli } = await import('./agentHome-DM0urHEI.mjs');
314
- const { describeAgentHome } = await import('./index-OEGj3BxE.mjs');
313
+ const { resolveAgentHomesForCli } = await import('./agentHome-2IbIjKCa.mjs');
314
+ const { describeAgentHome } = await import('./index-DQplgo0W.mjs');
315
315
  const homes = await resolveAgentHomesForCli();
316
316
  console.log(chalk.green(`\u2713 Claude config dir: ${describeAgentHome(homes.claudeConfigDir)}`));
317
317
  console.log(chalk.green(`\u2713 Codex home: ${describeAgentHome(homes.codexHome)}`));
@@ -1,14 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  var chalk = require('chalk');
4
- var configuration = require('./configuration-PXAE4-FP.cjs');
5
- var persistence = require('./persistence-d3ZyER6o.cjs');
6
- var controlClient = require('./controlClient-DI-Er-Ww.cjs');
4
+ var configuration = require('./configuration-B0cb3xA3.cjs');
5
+ var persistence = require('./persistence-2Xp_o6x6.cjs');
6
+ var controlClient = require('./controlClient-CmnHGcyl.cjs');
7
7
  var doctor$1 = require('./doctor-u46qYYKX.cjs');
8
8
  var node_fs = require('node:fs');
9
9
  var path = require('node:path');
10
10
  var projectPath = require('./projectPath-ChLhdOyt.cjs');
11
- var _package = require('./package-CC_txQ31.cjs');
11
+ var _package = require('./package-C1XvUQFy.cjs');
12
12
  var doctorReadiness = require('./doctorReadiness-BCZGcN0a.cjs');
13
13
  var authRelay = require('./authRelay-BdYkC1Po.cjs');
14
14
  var cliUpdate = require('./cliUpdate-DsKXPFYp.cjs');
@@ -312,8 +312,8 @@ ${typeLabels[type] || type}:`));
312
312
  }
313
313
  console.log(chalk.gray(" An external claude command is only needed for native terminal/mirror use."));
314
314
  try {
315
- const { resolveAgentHomesForCli } = await Promise.resolve().then(function () { return require('./agentHome-DtsPKfTS.cjs'); });
316
- const { describeAgentHome } = await Promise.resolve().then(function () { return require('./index-DaTxsAC3.cjs'); });
315
+ const { resolveAgentHomesForCli } = await Promise.resolve().then(function () { return require('./agentHome-KVWj6nCl.cjs'); });
316
+ const { describeAgentHome } = await Promise.resolve().then(function () { return require('./index-DEKIgZUo.cjs'); });
317
317
  const homes = await resolveAgentHomesForCli();
318
318
  console.log(chalk.green(`\u2713 Claude config dir: ${describeAgentHome(homes.claudeConfigDir)}`));
319
319
  console.log(chalk.green(`\u2713 Codex home: ${describeAgentHome(homes.codexHome)}`));