very-happy-cli 0.2.160 → 0.2.161

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 (162) hide show
  1. package/dist/{AcpBackend-mzv8Dhba.mjs → AcpBackend-6U6pQgx1.mjs} +3 -3
  2. package/dist/{AcpBackend-Bm2rdke8.cjs → AcpBackend-Ba98QDif.cjs} +3 -3
  3. package/dist/{BasePermissionHandler-CFHAxumV.cjs → BasePermissionHandler-2R0uH2CI.cjs} +1 -1
  4. package/dist/{BasePermissionHandler-m3WVholL.mjs → BasePermissionHandler-BvvhBTja.mjs} +1 -1
  5. package/dist/{BaseReasoningProcessor-CYrKBXGm.mjs → BaseReasoningProcessor-DyhO1uoU.mjs} +1 -1
  6. package/dist/{BaseReasoningProcessor-BFa9_rZA.cjs → BaseReasoningProcessor-fsVNmCEF.cjs} +1 -1
  7. package/dist/{agentHome-Dj1C43aJ.mjs → agentHome-Ck1i1TQB.mjs} +4 -4
  8. package/dist/{agentHome-CboCeKWq.cjs → agentHome-DvNnGphb.cjs} +4 -4
  9. package/dist/{api-CgundNNX.cjs → api-B2vLMS-z.cjs} +8 -8
  10. package/dist/{api-CLMUr-SX.mjs → api-SffjRQ1b.mjs} +8 -8
  11. package/dist/{apiMachine-B9dLW_p5.mjs → apiMachine-BpW9t8MO.mjs} +11 -11
  12. package/dist/{apiMachine-Bn8482VM.cjs → apiMachine-gFA54X7y.cjs} +11 -11
  13. package/dist/{assistantTools-BTqPnlFl.cjs → assistantTools-BfA0R3_m.cjs} +6 -6
  14. package/dist/{assistantTools-D6tuc6o4.mjs → assistantTools-CgiTbnWb.mjs} +6 -6
  15. package/dist/{attachmentContent-_kxRznNf.mjs → attachmentContent-CSGxr71v.mjs} +1 -1
  16. package/dist/{attachmentContent-DpiTJZb4.cjs → attachmentContent-DMMZzevR.cjs} +1 -1
  17. package/dist/{auth-ba4WMYrN.cjs → auth-Bt4ceBBy.cjs} +5 -5
  18. package/dist/{auth-Cwutmdsa.mjs → auth-CYHjQ8oQ.mjs} +5 -5
  19. package/dist/{auth-PYHZQNPp.mjs → auth-DdyVZSo6.mjs} +8 -8
  20. package/dist/{auth-BDOVh5h5.cjs → auth-x4CEoysH.cjs} +8 -8
  21. package/dist/{auto-BOX_fgmR.cjs → auto-BDXDUnjB.cjs} +12 -12
  22. package/dist/{auto-BXu14yP_.mjs → auto-CXLlRi3a.mjs} +12 -12
  23. package/dist/{bootstrap-hxXPCFMx.mjs → bootstrap-BNQq05jR.mjs} +2 -2
  24. package/dist/{bootstrap-B5G1TijC.cjs → bootstrap-CkgIq8N3.cjs} +2 -2
  25. package/dist/{browser-jh2P0UVZ.mjs → browser-9pyhQr1R.mjs} +1 -1
  26. package/dist/{browser-Y6Bl8L_O.cjs → browser-BDOlKWYe.cjs} +1 -1
  27. package/dist/{claudeLocal-CRGG4Pea.cjs → claudeLocal-BDuGFnjJ.cjs} +4 -4
  28. package/dist/{claudeLocal-BaY4fZKi.mjs → claudeLocal-CQa8qnwq.mjs} +4 -4
  29. package/dist/{claudeLocalLauncher-DyEbVzUN.cjs → claudeLocalLauncher-Bd5I2-j6.cjs} +9 -9
  30. package/dist/{claudeLocalLauncher-D4T7MTqd.mjs → claudeLocalLauncher-CDqQI9ak.mjs} +9 -9
  31. package/dist/{client-CeGKqqcJ.mjs → client-Brn-UwVk.mjs} +3 -3
  32. package/dist/{client-ClR0K8zX.mjs → client-CXb1VJui.mjs} +2 -2
  33. package/dist/{client-3Ac-O4pw.cjs → client-C_axwRry.cjs} +3 -3
  34. package/dist/{client-BPNbmtvO.cjs → client-DOBWJL3u.cjs} +2 -2
  35. package/dist/codex/happyMcpStdioBridge.cjs +14 -14
  36. package/dist/codex/happyMcpStdioBridge.mjs +14 -14
  37. package/dist/{codexAppServerClient-q2FjnRcK.cjs → codexAppServerClient-ZzhUTWPo.cjs} +2 -2
  38. package/dist/{codexAppServerClient-I3teiV-N.mjs → codexAppServerClient-oeQKD6Qf.mjs} +2 -2
  39. package/dist/{codexCommand-4zcccIoq.cjs → codexCommand-C7H0NpBe.cjs} +35 -35
  40. package/dist/{codexCommand-Cc9gcbdX.mjs → codexCommand-CJ82bl3l.mjs} +35 -35
  41. package/dist/{codexThreadFork-slzAseLx.mjs → codexThreadFork-BCaEMBiM.mjs} +1 -1
  42. package/dist/{codexThreadFork-BH9IZPqD.cjs → codexThreadFork-BZqF-9bX.cjs} +1 -1
  43. package/dist/{config-CTx_jb-C.mjs → config-BglnktIo.mjs} +3 -3
  44. package/dist/{config-Ci9Kpgwa.cjs → config-CYpL1Ahd.cjs} +3 -3
  45. package/dist/{configuration-RfeNjFmd.mjs → configuration-DoWFJUPm.mjs} +1 -1
  46. package/dist/{configuration-BSYpcPwE.cjs → configuration-v9f8LM9T.cjs} +1 -1
  47. package/dist/{connect-BpOdzNbE.mjs → connect-hgcNjyAB.mjs} +11 -11
  48. package/dist/{connect-C2CiOUFs.cjs → connect-yEvjdRvx.cjs} +11 -11
  49. package/dist/{context-DsDr6E2t.cjs → context-B45vMtSZ.cjs} +1 -1
  50. package/dist/{context-H0Bcb9S_.mjs → context-C9GHPLEm.mjs} +1 -1
  51. package/dist/{controlClient-BGbDcgWS.mjs → controlClient-DjoKTtgK.mjs} +3 -3
  52. package/dist/{controlClient-Bcwv3D21.cjs → controlClient-fEHE85bH.cjs} +3 -3
  53. package/dist/{createSessionMetadata-BJxEnM-o.cjs → createSessionMetadata-BRLB9CNO.cjs} +2 -2
  54. package/dist/{createSessionMetadata-CVVkGjxV.mjs → createSessionMetadata-mIeehclp.mjs} +2 -2
  55. package/dist/{deterministicJson-C5CYTVpm.cjs → deterministicJson-DKDP_mM-.cjs} +8 -8
  56. package/dist/{deterministicJson-CzkFJWw1.mjs → deterministicJson-p835AdAU.mjs} +8 -8
  57. package/dist/{doctor-DOvByjbk.mjs → doctor-BeUuQXFs.mjs} +6 -6
  58. package/dist/{doctor-D2YJ-Yn2.cjs → doctor-hVNnSZJn.cjs} +6 -6
  59. package/dist/{ensureDaemonRunning-Dqa2pOjY.mjs → ensureDaemonRunning-CO7d1gOC.mjs} +5 -5
  60. package/dist/{ensureDaemonRunning-BCwNrMyv.cjs → ensureDaemonRunning-Dg9aZfjs.cjs} +5 -5
  61. package/dist/{handleResumeCommand-BvXYf5El.mjs → handleResumeCommand-BiTPK0qd.mjs} +5 -5
  62. package/dist/{handleResumeCommand-C2cKchpX.cjs → handleResumeCommand-DnVmy7a3.cjs} +5 -5
  63. package/dist/{index-DMZqWwsP.mjs → index-CAFwetLk.mjs} +33 -33
  64. package/dist/{index-DVkMGPyS.mjs → index-Cqx-Raq6.mjs} +3 -3
  65. package/dist/{index-B6pAdvJx.cjs → index-LIn6nCcq.cjs} +32 -32
  66. package/dist/{index-Bu5Zi_a9.cjs → index-Pf2cV9cn.cjs} +4 -4
  67. package/dist/{index-DKLU_fD0.mjs → index-SPGPenK5.mjs} +4 -4
  68. package/dist/{index-DDeHXrIX.cjs → index-gNTWtSKN.cjs} +3 -3
  69. package/dist/index.cjs +2 -2
  70. package/dist/index.mjs +2 -2
  71. package/dist/{install-BgoC2e_2.cjs → install-Bu85vlHD.cjs} +3 -3
  72. package/dist/{install-CFY3tYtJ.mjs → install-ClUUl3yp.mjs} +3 -3
  73. package/dist/lib.cjs +10 -10
  74. package/dist/lib.mjs +10 -10
  75. package/dist/{lidState-CeEt442o.mjs → lidState-C2dI0FAN.mjs} +1 -1
  76. package/dist/{lidState-BeDfxxEX.cjs → lidState-KHHu1015.cjs} +1 -1
  77. package/dist/{localHappyAgentAuth-D6rFhaoc.cjs → localHappyAgentAuth-BXiHPXdC.cjs} +1 -1
  78. package/dist/{localHappyAgentAuth-C-HQyiv6.mjs → localHappyAgentAuth-DCsetiyG.mjs} +1 -1
  79. package/dist/{logger-CS0mw3fa.cjs → logger-Bc8-u1w0.cjs} +2 -2
  80. package/dist/{logger-6HYUEXNk.mjs → logger-fXoNzNuB.mjs} +2 -2
  81. package/dist/{machineMetadata-oOzBfDfs.mjs → machineMetadata-BHjehxJY.mjs} +3 -3
  82. package/dist/{machineMetadata-DyDbODYd.cjs → machineMetadata-BibDMFVx.cjs} +3 -3
  83. package/dist/{main-BwNIAI1A.mjs → main-BktM4A1K.mjs} +44 -44
  84. package/dist/{main-BkxJP6JQ.cjs → main-CLaX-t-b.cjs} +44 -44
  85. package/dist/{mcp-B1A4I3TK.mjs → mcp-CeUd9KDr.mjs} +14 -14
  86. package/dist/{mcp-Hszd7qpS.cjs → mcp-GBfE70nk.cjs} +14 -14
  87. package/dist/{package-BwMrPwqH.cjs → package-Cl5BEP5x.cjs} +7 -7
  88. package/dist/{package-BhaKlnxz.mjs → package-uOg9SCKi.mjs} +7 -7
  89. package/dist/{peerTools-BvKtHXj8.cjs → peerTools-CIeiy9wn.cjs} +4 -4
  90. package/dist/{peerTools-BTqw97Gb.mjs → peerTools-Dz3_7Bkk.mjs} +4 -4
  91. package/dist/{permissionMode-Cr5JCbB7.mjs → permissionMode-CH4FoZfU.mjs} +1 -1
  92. package/dist/{persistence-yKTH3-5X.cjs → persistence-CBNMzSa8.cjs} +3 -3
  93. package/dist/{persistence-HGW_ZVs9.mjs → persistence-oET5n61f.mjs} +3 -3
  94. package/dist/{piRunnerArgs-BNloJCCg.cjs → piRunnerArgs-Bf7RUF__.cjs} +1 -1
  95. package/dist/{piRunnerArgs-BuX1UFWy.mjs → piRunnerArgs-Dk1ncwHF.mjs} +1 -1
  96. package/dist/{piRuntime-C_H7MJCM.cjs → piRuntime-B_6TE9Eb.cjs} +1 -1
  97. package/dist/{piRuntime-CSGkwCKQ.mjs → piRuntime-BwRdhK_N.mjs} +1 -1
  98. package/dist/{piTerminal-C8a1OrNQ.mjs → piTerminal-Bap3R8Re.mjs} +16 -16
  99. package/dist/{piTerminal-DNCZ6yTM.cjs → piTerminal-CagmEoez.cjs} +16 -16
  100. package/dist/{registerCommonHandlers-DskirN-_.cjs → registerCommonHandlers-BjSV2Skz.cjs} +2 -2
  101. package/dist/{registerCommonHandlers-Ccvsz7Ou.mjs → registerCommonHandlers-CrgvJsOy.mjs} +2 -2
  102. package/dist/{registerKillSessionHandler-DZeLXWcB.cjs → registerKillSessionHandler-6TC2S3lf.cjs} +13 -8
  103. package/dist/{registerKillSessionHandler-GYvHdipX.mjs → registerKillSessionHandler-Cbc8Rgtd.mjs} +13 -8
  104. package/dist/{remoteSessionClient-B0LraSB9.cjs → remoteSessionClient-BNx78NLb.cjs} +5 -5
  105. package/dist/{remoteSessionClient-CYnXRynE.mjs → remoteSessionClient-CO7qOjR0.mjs} +5 -5
  106. package/dist/{run-D3ifupU3.mjs → run-2l5vSt2h.mjs} +32 -28
  107. package/dist/{run-CJzxoHVh.cjs → run-D5xAEWSB.cjs} +33 -29
  108. package/dist/{runClaude-Da3RirzE.cjs → runClaude-BX6ixjtW.cjs} +182 -138
  109. package/dist/{runClaude-Ba01qT-u.mjs → runClaude-BgN6xo05.mjs} +183 -139
  110. package/dist/{runClaudeDeps-DOzEBMls.cjs → runClaudeDeps-Bp20MScE.cjs} +638 -119
  111. package/dist/{runClaudeDeps-DOt79DjU.mjs → runClaudeDeps-COBBhD9o.mjs} +628 -123
  112. package/dist/{runGemini-DSr9LIxL.cjs → runGemini-CSMPkt0p.cjs} +30 -30
  113. package/dist/{runGemini-BGeTz57m.mjs → runGemini-Cc2jq-uh.mjs} +30 -30
  114. package/dist/{runOpenClaw-CogSedIc.mjs → runOpenClaw-CIlCwdW2.mjs} +15 -15
  115. package/dist/{runOpenClaw-B1mTxN35.cjs → runOpenClaw-YBwua4Rf.cjs} +15 -15
  116. package/dist/{sandbox-CG7IyDTU.cjs → sandbox-C4gXLP1p.cjs} +4 -4
  117. package/dist/{sandbox-DTe6d54R.mjs → sandbox-CNkwOtHI.mjs} +4 -4
  118. package/dist/{selfCheck-Dc-mNSLb.cjs → selfCheck-CU8xSDsl.cjs} +34 -34
  119. package/dist/selfCheck-hJ6PCh7v.mjs +84 -0
  120. package/dist/{send-CBXJKc6O.mjs → send-CGHcKZ-w.mjs} +8 -8
  121. package/dist/{send-B7J_eaG3.cjs → send-DY9Nr-x4.cjs} +8 -8
  122. package/dist/{server-CZTP_iOn.cjs → server-II51Mimf.cjs} +6 -6
  123. package/dist/{server-DcVBv04l.mjs → server-m2b5pamZ.mjs} +4 -4
  124. package/dist/{sessionLock-Bys1PNSo.cjs → sessionLock-7ePAYDOg.cjs} +2 -2
  125. package/dist/{sessionLock-D-EG2CfG.mjs → sessionLock-Cw6FmbMv.mjs} +2 -2
  126. package/dist/{sessionModeFile-RSm0NQkH.cjs → sessionModeFile-BVCV5f7E.cjs} +1 -1
  127. package/dist/{sessionModeFile-DMl3dw3r.mjs → sessionModeFile-CDmDyRkD.mjs} +1 -1
  128. package/dist/{sessionOps-SuHW8Dfe.mjs → sessionOps-C_f1wKOr.mjs} +4 -4
  129. package/dist/{sessionOps-Dn8z85h_.cjs → sessionOps-DJdExmBy.cjs} +4 -4
  130. package/dist/{sessionScanner-CX3onqXh.mjs → sessionScanner-CaAHLyNV.mjs} +3 -3
  131. package/dist/{sessionScanner-BOrGjMXL.cjs → sessionScanner-D1goKdd3.cjs} +3 -3
  132. package/dist/{sessions-D74aJbhL.cjs → sessions-DGs6ALNo.cjs} +9 -9
  133. package/dist/{sessions-BEG_HTSi.mjs → sessions-DnvmWUel.mjs} +9 -9
  134. package/dist/{setupOfflineReconnection-DpvWTt69.mjs → setupOfflineReconnection-CVViqZft.mjs} +2 -2
  135. package/dist/{setupOfflineReconnection-ByElY60m.cjs → setupOfflineReconnection-R7XuR_sj.cjs} +2 -2
  136. package/dist/{spawn-DgR0RKRs.cjs → spawn-CXTH7qg1.cjs} +19 -11
  137. package/dist/{spawn-B7yro0b2.mjs → spawn-DNYSvFtC.mjs} +19 -12
  138. package/dist/{spawnHappyCLI-DBhwZT7O.cjs → spawnHappyCLI-BhYj84rv.cjs} +1 -1
  139. package/dist/{spawnHappyCLI-B2H5s4B_.mjs → spawnHappyCLI-cqWQbwsb.mjs} +1 -1
  140. package/dist/{startFileWatcher-B4VsLgjD.cjs → startFileWatcher-CKKx-8ZO.cjs} +1 -1
  141. package/dist/{startFileWatcher-DErVWZE4.mjs → startFileWatcher-CdegMbJj.mjs} +1 -1
  142. package/dist/{sync-DccIKZ5_.cjs → sync-CVk4QERO.cjs} +1 -1
  143. package/dist/{sync-C8gyQFMc.mjs → sync-CxD-w_40.mjs} +1 -1
  144. package/dist/{systemPrompt-BwTPWfMu.cjs → systemPrompt-BygJcmbi.cjs} +1 -1
  145. package/dist/{systemPrompt-DX521JJz.mjs → systemPrompt-DmtypUc7.mjs} +1 -1
  146. package/dist/{teams-C32F1hqd.mjs → teams-BOC6nIPL.mjs} +6 -6
  147. package/dist/{teams-Dl8g8kTI.cjs → teams-BsvpOBfn.cjs} +6 -6
  148. package/dist/{time-D0XyHOid.mjs → time-BZNdNiIV.mjs} +1 -1
  149. package/dist/{time-DCuTyook.cjs → time-CNRE4ChD.cjs} +1 -1
  150. package/dist/{titleGenerator-ChzMJsyg.cjs → titleGenerator-CFRhU-xq.cjs} +2 -2
  151. package/dist/{titleGenerator-CQ8CoGhg.mjs → titleGenerator-ox6ptCsp.mjs} +1 -1
  152. package/dist/{todo-BvUOTa8G.cjs → todo-B-KB7oAB.cjs} +5 -5
  153. package/dist/{todo-CZ6cFrrn.mjs → todo-C5KBVbUw.mjs} +5 -5
  154. package/dist/{tools-BZtHF_qQ.mjs → tools-BZabNIid.mjs} +1 -1
  155. package/dist/{tools-DkluDcG4.mjs → tools-BmQQUATY.mjs} +1 -1
  156. package/dist/{tools-DQj0AeLk.cjs → tools-CsSovyNp.cjs} +1 -1
  157. package/dist/{tools-Be3AoAwu.cjs → tools-lMDra4Pv.cjs} +1 -1
  158. package/dist/{uninstall-BkLzaJ6I.mjs → uninstall-B1WLtC1d.mjs} +3 -3
  159. package/dist/{uninstall-x-TUtf5H.cjs → uninstall-fvA5aWpU.cjs} +3 -3
  160. package/package.json +7 -7
  161. package/scripts/session_hook_forwarder.cjs +9 -2
  162. package/dist/selfCheck-C9mVrQwf.mjs +0 -84
@@ -1,14 +1,14 @@
1
1
  'use strict';
2
2
 
3
- var logger = require('./logger-CS0mw3fa.cjs');
4
- var controlClient = require('./controlClient-Bcwv3D21.cjs');
3
+ var logger = require('./logger-Bc8-u1w0.cjs');
4
+ var controlClient = require('./controlClient-fEHE85bH.cjs');
5
5
  var backgroundTaskActivity = require('./backgroundTaskActivity-CBvUdj39.cjs');
6
6
  var node_crypto = require('node:crypto');
7
7
  var messageBuffer = require('./messageBuffer-fJMH6uY8.cjs');
8
8
  var index = require('./index-D3kI0hDR.cjs');
9
9
  var claudeAgentSdk = require('@anthropic-ai/claude-agent-sdk');
10
10
  var permissionMode = require('./permissionMode-CrV-XuMs.cjs');
11
- var systemPrompt = require('./systemPrompt-BwTPWfMu.cjs');
11
+ var systemPrompt = require('./systemPrompt-BygJcmbi.cjs');
12
12
  var path$1 = require('node:path');
13
13
  var specialCommands = require('./specialCommands-DSsTeRej.cjs');
14
14
  require('axios');
@@ -16,31 +16,31 @@ require('node:events');
16
16
  require('socket.io-client');
17
17
  var attachmentLimits = require('./attachmentLimits-CzVrqgLR.cjs');
18
18
  require('tweetnacl');
19
- var configuration = require('./configuration-BSYpcPwE.cjs');
19
+ var configuration = require('./configuration-v9f8LM9T.cjs');
20
20
  require('./index-DA7yINuk.cjs');
21
- require('./registerCommonHandlers-DskirN-_.cjs');
21
+ require('./registerCommonHandlers-BjSV2Skz.cjs');
22
22
  require('os');
23
23
  require('child_process');
24
24
  require('@paralleldrive/cuid2');
25
- require('./persistence-yKTH3-5X.cjs');
25
+ require('./persistence-CBNMzSa8.cjs');
26
26
  var contentLogMetadata = require('./contentLogMetadata-ZSFk_NjQ.cjs');
27
27
  require('chalk');
28
28
  var types = require('./types-CRS-srZK.cjs');
29
29
  var path = require('./path-B7zW-WwE.cjs');
30
30
  var fs = require('fs/promises');
31
- var time = require('./time-DCuTyook.cjs');
32
- var sessionScanner = require('./sessionScanner-BOrGjMXL.cjs');
31
+ var time = require('./time-CNRE4ChD.cjs');
32
+ var node_fs = require('node:fs');
33
+ var deterministicJson = require('./deterministicJson-DKDP_mM-.cjs');
34
+ var sessionScanner = require('./sessionScanner-D1goKdd3.cjs');
33
35
  var node_child_process = require('node:child_process');
34
36
  var streamRelay = require('./streamRelay-BiKw59Cc.cjs');
35
- var attachmentContent = require('./attachmentContent-DpiTJZb4.cjs');
36
- var registerKillSessionHandler = require('./registerKillSessionHandler-DZeLXWcB.cjs');
37
- var deterministicJson = require('./deterministicJson-C5CYTVpm.cjs');
38
- var doctor = require('./doctor-D2YJ-Yn2.cjs');
37
+ var attachmentContent = require('./attachmentContent-DMMZzevR.cjs');
38
+ var registerKillSessionHandler = require('./registerKillSessionHandler-6TC2S3lf.cjs');
39
+ var doctor = require('./doctor-hVNnSZJn.cjs');
39
40
  var node_http = require('node:http');
40
41
  var editPaths = require('./editPaths-Bqp4OFPw.cjs');
41
- var node_fs = require('node:fs');
42
42
  var projectPath = require('./projectPath-ChLhdOyt.cjs');
43
- var titleGenerator = require('./titleGenerator-ChzMJsyg.cjs');
43
+ var titleGenerator = require('./titleGenerator-CFRhU-xq.cjs');
44
44
  var oneShotPrompts = require('./oneShotPrompts-CL0dip9C.cjs');
45
45
  require('node:util');
46
46
  require('./smallFastModel-D_uxGMo3.cjs');
@@ -48,34 +48,34 @@ require('./trimIdent-4gvk9Wk6.cjs');
48
48
  require('node:os');
49
49
  require('./agentGuidance-B5NATuFa.cjs');
50
50
  require('zod');
51
- require('./package-BwMrPwqH.cjs');
51
+ require('./package-Cl5BEP5x.cjs');
52
52
  require('node:fs/promises');
53
53
  require('util');
54
54
  require('crypto');
55
55
  require('path');
56
56
  require('cross-spawn');
57
57
  require('./authRelay-BdYkC1Po.cjs');
58
- require('./sync-DccIKZ5_.cjs');
59
- require('./startFileWatcher-B4VsLgjD.cjs');
60
- require('./client-3Ac-O4pw.cjs');
61
- require('./context-DsDr6E2t.cjs');
62
- require('./sessionOps-Dn8z85h_.cjs');
58
+ require('./client-C_axwRry.cjs');
59
+ require('./context-B45vMtSZ.cjs');
60
+ require('./sessionOps-DJdExmBy.cjs');
63
61
  require('./resources-JDPugcDq.cjs');
64
- require('./tools-Be3AoAwu.cjs');
65
- require('./tools-DQj0AeLk.cjs');
66
- require('./client-BPNbmtvO.cjs');
67
- require('./peerTools-BvKtHXj8.cjs');
62
+ require('./tools-lMDra4Pv.cjs');
63
+ require('./tools-CsSovyNp.cjs');
64
+ require('./client-DOBWJL3u.cjs');
65
+ require('./peerTools-CIeiy9wn.cjs');
68
66
  require('./ids-B6ZC0HGt.cjs');
69
- require('./remoteSessionClient-B0LraSB9.cjs');
67
+ require('./remoteSessionClient-BNx78NLb.cjs');
70
68
  require('@modelcontextprotocol/sdk/server/mcp.js');
71
69
  require('@modelcontextprotocol/sdk/server/streamableHttp.js');
72
70
  require('./limits-C-a7gr04.cjs');
73
- require('./assistantTools-BTqPnlFl.cjs');
71
+ require('./assistantTools-BfA0R3_m.cjs');
74
72
  require('./terminals-B_bfC9c2.cjs');
75
73
  require('./terminalTitleSuggest-DhvRFX3H.cjs');
76
74
  require('./tmuxSocket-D-Xt6Vn-.cjs');
77
- require('./bootstrap-B5G1TijC.cjs');
75
+ require('./bootstrap-CkgIq8N3.cjs');
78
76
  require('./previewPath-B0rBdhy1.cjs');
77
+ require('./sync-CVk4QERO.cjs');
78
+ require('./startFileWatcher-CKKx-8ZO.cjs');
79
79
  require('./doctor-u46qYYKX.cjs');
80
80
  require('ps-list');
81
81
  require('./doctorReadiness-BCZGcN0a.cjs');
@@ -143,6 +143,20 @@ class Session {
143
143
  steerHandler = null;
144
144
  /** B-482: the live remote Query's in-process side-question entry; null between Queries and in local mode. */
145
145
  sideQuestionLive = null;
146
+ /** B-515: consumed by the first remote launch; later launches never prewarm. */
147
+ claudePrewarm = null;
148
+ /** Hand the prewarm lease to the first remote launch — once per process. */
149
+ takeClaudePrewarm = () => {
150
+ const factory = this.claudePrewarm;
151
+ this.claudePrewarm = null;
152
+ if (!factory || this.sessionId) return null;
153
+ try {
154
+ return factory();
155
+ } catch (error) {
156
+ logger.logger.debug("[Session] Claude prewarm setup failed:", error);
157
+ return null;
158
+ }
159
+ };
146
160
  /** Callbacks to be notified when session ID is found/changed */
147
161
  sessionFoundCallbacks = [];
148
162
  /** Keep alive interval reference for cleanup */
@@ -163,6 +177,7 @@ class Session {
163
177
  this._onAbort = opts.onAbort;
164
178
  this.hookSettingsPath = opts.hookSettingsPath;
165
179
  this.jsRuntime = opts.jsRuntime ?? "node";
180
+ this.claudePrewarm = opts.claudePrewarm ?? null;
166
181
  try {
167
182
  this.notificationProducer = opts.api.notificationProducer(
168
183
  opts.client.sessionId,
@@ -697,6 +712,281 @@ function modelSwitchFailureNotice(model, error) {
697
712
  return `\u26A0\uFE0F Could not switch to model "${name}" \u2014 continuing with the previous model. ${detail}`;
698
713
  }
699
714
 
715
+ const SDK_TIMING_FIELDS = ["ttft_ms", "time_to_request_ms", "time_to_request_from_spawn_ms"];
716
+ function delta(from, to) {
717
+ if (typeof from !== "number" || typeof to !== "number" || to < from) return "-";
718
+ return `${Math.round(to - from)}ms`;
719
+ }
720
+ function sdkField(result, key) {
721
+ if (!result || typeof result !== "object") return "-";
722
+ const value = result[key];
723
+ return typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}` : "-";
724
+ }
725
+ function formatClaudeTimingLine(input) {
726
+ const m = input.marks;
727
+ const sdk = SDK_TIMING_FIELDS.map((key) => `${key}=${sdkField(input.result, key)}`).join(",");
728
+ return [
729
+ "[CLAUDE TIMING]",
730
+ `turn=${input.turn}`,
731
+ `firstTurnOfProcess=${input.firstTurnOfProcess}`,
732
+ `pushed\u2192spawn=${delta(m.pushedAt, m.spawnAt)}`,
733
+ `spawn\u2192handshake=${delta(m.spawnAt, m.handshakeAt)}`,
734
+ `handshake\u2192init=${delta(m.handshakeAt, m.initAt)}`,
735
+ `init\u2192firstAssistant=${delta(m.initAt, m.firstAssistantAt)}`,
736
+ `pushed\u2192firstAssistant=${delta(m.pushedAt, m.firstAssistantAt)}`,
737
+ `sdk{${sdk}}`,
738
+ ...input.prewarm ? [`prewarm=${input.prewarm}`] : []
739
+ ].join(" ");
740
+ }
741
+
742
+ function claudeModeHash(mode) {
743
+ return deterministicJson.hashObject({
744
+ isPlan: mode.permissionMode === "plan",
745
+ fallbackModel: mode.fallbackModel,
746
+ customSystemPrompt: mode.customSystemPrompt,
747
+ appendSystemPrompt: mode.appendSystemPrompt,
748
+ allowedTools: mode.allowedTools,
749
+ disallowedTools: mode.disallowedTools,
750
+ effort: mode.effort
751
+ });
752
+ }
753
+
754
+ const CLAUDE_PREWARM_IDLE_MS = 15 * 60 * 1e3;
755
+ const CLAUDE_PREWARM_MAX_CONCURRENT = 2;
756
+ const CLAUDE_PREWARM_ADOPT_TIMEOUT_MS = 5e3;
757
+ const PREWARM_HOOK_SOURCE_PREFIX = "prewarm-";
758
+ const BAD_AUTH_STATUSES = /* @__PURE__ */ new Set(["not-logged-in", "error", "claude-missing"]);
759
+ const RESUME_ARGS = /* @__PURE__ */ new Set(["--resume", "-r", "--continue", "-c", "--fork-session", "--session-id"]);
760
+ const CLAUDE_PREWARM_MAX_CONSECUTIVE_MISSES = 5;
761
+ function claudePrewarmSessionEligibility(input) {
762
+ const { env } = input;
763
+ const no = (reason) => ({ eligible: false, reason });
764
+ if (env.HAPPY_CLAUDE_PREWARM === "0") return no("env-off");
765
+ if (input.setting === "off") return no("setting-off");
766
+ if (input.startedBy !== "daemon") return no("not-daemon");
767
+ if (input.startingMode !== "remote") return no("not-remote");
768
+ if (env.HAPPY_RECONNECT_SESSION_ID) return no("reconnect");
769
+ if (env.HAPPY_FORK_CLAUDE_SESSION_ID || env.HAPPY_FORKED_FROM_SESSION_ID) return no("fork");
770
+ if (env.HAPPY_IMPORTED_FROM_CLAUDE_SESSION_ID) return no("import");
771
+ if (env.HAPPY_SESSION_VARIANT === "assistant") return no("assistant");
772
+ if (env.VH_TEAM_OPERATION_ID) return no("teams");
773
+ if (env.VH_AUTOMATION_RUN_ID) return no("automation");
774
+ if (env.HAPPY_SPAWNED_BY) return no("spawned-by");
775
+ if (env.HAPPY_FIRST_MESSAGE_FROM_CLI === "1") return no("cli-first-message");
776
+ if (input.claudeArgs?.some((arg) => RESUME_ARGS.has(arg))) return no("resume-args");
777
+ if (env.HAPPY_CLAUDE_AUTH_STATUS && BAD_AUTH_STATUSES.has(env.HAPPY_CLAUDE_AUTH_STATUS)) return no("claude-auth");
778
+ return { eligible: true };
779
+ }
780
+ function claudePrewarmEligibility(input) {
781
+ const session = claudePrewarmSessionEligibility(input);
782
+ if (!session.eligible) return session;
783
+ if (!input.cache?.appendSystemPrompt) return { eligible: false, reason: "no-cached-system-prompt" };
784
+ if (input.cache.consecutiveMisses >= CLAUDE_PREWARM_MAX_CONSECUTIVE_MISSES) return { eligible: false, reason: "recent-misses" };
785
+ return { eligible: true };
786
+ }
787
+ function prewarmCacheFile(happyHomeDir) {
788
+ return path$1.join(happyHomeDir, "claude-prewarm.json");
789
+ }
790
+ function readPrewarmCache(file) {
791
+ try {
792
+ const raw = JSON.parse(node_fs.readFileSync(file, "utf8"));
793
+ if (typeof raw?.appendSystemPrompt !== "string" || raw.appendSystemPrompt.length === 0) return null;
794
+ const misses = typeof raw.consecutiveMisses === "number" && Number.isFinite(raw.consecutiveMisses) && raw.consecutiveMisses > 0 ? Math.floor(raw.consecutiveMisses) : 0;
795
+ return {
796
+ appendSystemPrompt: raw.appendSystemPrompt,
797
+ ...typeof raw.effort === "string" || raw.effort === null ? { effort: raw.effort } : {},
798
+ consecutiveMisses: misses
799
+ };
800
+ } catch {
801
+ return null;
802
+ }
803
+ }
804
+ function writePrewarmCache(file, cache) {
805
+ try {
806
+ const tmp = `${file}.${process.pid}.tmp`;
807
+ node_fs.writeFileSync(tmp, JSON.stringify({ ...cache, updatedAt: Date.now() }), { mode: 384 });
808
+ node_fs.renameSync(tmp, file);
809
+ return true;
810
+ } catch {
811
+ return false;
812
+ }
813
+ }
814
+ function prewarmPredictionMeta(cache) {
815
+ return {
816
+ appendSystemPrompt: cache.appendSystemPrompt,
817
+ ...cache.effort !== void 0 ? { effort: cache.effort } : {}
818
+ };
819
+ }
820
+ function evaluatePrewarmPrediction(input) {
821
+ const outcome = input.predicted === null ? "no-prediction" : claudeModeHash(input.predicted) === claudeModeHash(input.actual) ? "hit" : "miss";
822
+ const append = input.meta?.appendSystemPrompt;
823
+ const misses = outcome === "miss" ? (input.previous?.consecutiveMisses ?? 0) + 1 : 0;
824
+ if (typeof append !== "string" || append.length === 0) {
825
+ return { outcome, next: input.previous ? { ...input.previous, consecutiveMisses: misses } : null };
826
+ }
827
+ const hasEffort = !!input.meta && Object.prototype.hasOwnProperty.call(input.meta, "effort");
828
+ return {
829
+ outcome,
830
+ next: {
831
+ appendSystemPrompt: append,
832
+ ...hasEffort ? { effort: input.meta.effort ?? null } : {},
833
+ consecutiveMisses: misses
834
+ }
835
+ };
836
+ }
837
+ function prewarmSlotDir(happyHomeDir) {
838
+ return path$1.join(happyHomeDir, "tmp", "claude-prewarm");
839
+ }
840
+ function acquirePrewarmSlot(dir, opts = {}) {
841
+ const max = opts.max ?? CLAUDE_PREWARM_MAX_CONCURRENT;
842
+ const pid = opts.pid ?? process.pid;
843
+ const isAlive = opts.isAlive ?? pidAlive;
844
+ const now = opts.now ?? Date.now();
845
+ const staleMs = opts.staleMs ?? CLAUDE_PREWARM_IDLE_MS + 6e4;
846
+ try {
847
+ node_fs.mkdirSync(dir, { recursive: true, mode: 448 });
848
+ } catch {
849
+ return null;
850
+ }
851
+ for (let i = 0; i < max; i++) {
852
+ const path = path$1.join(dir, `slot-${i}.lock`);
853
+ for (let attempt = 0; attempt < 2; attempt++) {
854
+ try {
855
+ node_fs.writeFileSync(path, String(pid), { flag: "wx", mode: 384 });
856
+ let released = false;
857
+ return {
858
+ path,
859
+ release: () => {
860
+ if (released) return;
861
+ released = true;
862
+ try {
863
+ if (node_fs.readFileSync(path, "utf8").trim() === String(pid)) node_fs.unlinkSync(path);
864
+ } catch {
865
+ }
866
+ }
867
+ };
868
+ } catch (error) {
869
+ if (error?.code !== "EEXIST") return null;
870
+ if (!slotIsStale(path, { isAlive, now, staleMs }) || attempt > 0) break;
871
+ try {
872
+ node_fs.unlinkSync(path);
873
+ } catch {
874
+ }
875
+ }
876
+ }
877
+ }
878
+ return null;
879
+ }
880
+ function slotIsStale(path, opts) {
881
+ try {
882
+ const owner = Number(node_fs.readFileSync(path, "utf8").trim());
883
+ if (!Number.isInteger(owner) || owner <= 0 || !opts.isAlive(owner)) return true;
884
+ return opts.now - node_fs.statSync(path).mtimeMs > opts.staleMs;
885
+ } catch {
886
+ return !node_fs.existsSync(path);
887
+ }
888
+ }
889
+ function pidAlive(pid) {
890
+ try {
891
+ process.kill(pid, 0);
892
+ return true;
893
+ } catch (error) {
894
+ return error?.code === "EPERM";
895
+ }
896
+ }
897
+ class PrewarmHookGate {
898
+ next = 0;
899
+ adopted = /* @__PURE__ */ new Set();
900
+ newTag() {
901
+ return `${PREWARM_HOOK_SOURCE_PREFIX}${process.pid}-${this.next++}`;
902
+ }
903
+ adopt(tag) {
904
+ this.adopted.add(tag);
905
+ }
906
+ /** Untagged hooks (the ordinary per-process settings file) always pass. */
907
+ accepts(source) {
908
+ if (!source || !source.startsWith(PREWARM_HOOK_SOURCE_PREFIX)) return true;
909
+ return this.adopted.has(source);
910
+ }
911
+ }
912
+ function decideWarmAdoption(input) {
913
+ if (input.specialCommand === "clear") return { adopt: false, reason: "clear" };
914
+ if (input.specialCommand === "compact") return { adopt: false, reason: "compact" };
915
+ if (claudeModeHash(input.predicted) !== claudeModeHash(input.actual)) return { adopt: false, reason: "mode-mismatch" };
916
+ const warmPermission = permissionMode.mapToClaudeMode(input.predicted.permissionMode);
917
+ const wantedPermission = permissionMode.mapToClaudeMode(input.actual.permissionMode);
918
+ return {
919
+ adopt: true,
920
+ ...warmPermission !== wantedPermission ? { setPermissionMode: wantedPermission } : {},
921
+ switchModel: needsModelSwitch(input.predicted.model, input.actual.model)
922
+ };
923
+ }
924
+ function formatPrewarmLine(event, detail) {
925
+ if (event === "discarded" || event === "skipped") {
926
+ return `[CLAUDE PREWARM] ${event}(${typeof detail === "string" ? detail : "unknown"})`;
927
+ }
928
+ const fields = detail && typeof detail === "object" ? Object.entries(detail).filter(([, v]) => v !== void 0).map(([k, v]) => ` ${k}=${v}`).join("") : "";
929
+ return `[CLAUDE PREWARM] ${event}${fields}`;
930
+ }
931
+ const liveLeases = /* @__PURE__ */ new Set();
932
+ let exitHookInstalled = false;
933
+ function disposeAllClaudePrewarms(reason) {
934
+ for (const lease of [...liveLeases]) lease.discard(reason);
935
+ }
936
+ function createClaudePrewarmLease(input) {
937
+ let state = "warm";
938
+ let teardown = null;
939
+ const lease = {
940
+ mode: input.mode,
941
+ hookSettingsPath: input.hookSettingsPath,
942
+ tag: input.tag,
943
+ idleMs: input.idleMs ?? CLAUDE_PREWARM_IDLE_MS,
944
+ adoptTimeoutMs: input.adoptTimeoutMs ?? CLAUDE_PREWARM_ADOPT_TIMEOUT_MS,
945
+ adopt: () => {
946
+ if (state !== "warm") return;
947
+ state = "adopted";
948
+ teardown = null;
949
+ input.gate.adopt(input.tag);
950
+ input.slot.release();
951
+ liveLeases.delete(lease);
952
+ },
953
+ discard: (reason) => {
954
+ if (state !== "warm") return;
955
+ state = "closed";
956
+ const t = teardown;
957
+ teardown = null;
958
+ liveLeases.delete(lease);
959
+ try {
960
+ t?.(reason);
961
+ } catch {
962
+ }
963
+ input.slot.release();
964
+ input.cleanupHookSettings();
965
+ input.log(formatPrewarmLine("discarded", reason));
966
+ },
967
+ setTeardown: (next) => {
968
+ if (state === "warm") teardown = next;
969
+ }
970
+ };
971
+ liveLeases.add(lease);
972
+ if (!exitHookInstalled) {
973
+ exitHookInstalled = true;
974
+ process.once("exit", () => disposeAllClaudePrewarms("exit"));
975
+ }
976
+ return lease;
977
+ }
978
+
979
+ function withTimeout(promise, ms) {
980
+ promise.catch(() => {
981
+ });
982
+ let timer;
983
+ const timeout = new Promise((_, reject) => {
984
+ timer = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);
985
+ });
986
+ return Promise.race([promise, timeout]).finally(() => {
987
+ if (timer) clearTimeout(timer);
988
+ });
989
+ }
700
990
  async function claudeRemote(opts) {
701
991
  let startFrom = opts.sessionId;
702
992
  if (opts.sessionId && !systemPrompt.claudeCheckSession(opts.sessionId, opts.path)) {
@@ -727,13 +1017,153 @@ async function claudeRemote(opts) {
727
1017
  process.env[key] = value;
728
1018
  });
729
1019
  }
730
- const initial = await opts.nextMessage();
1020
+ let thinking = false;
1021
+ const updateThinking = (newThinking) => {
1022
+ if (thinking !== newThinking) {
1023
+ thinking = newThinking;
1024
+ logger.logger.debug(`[claudeRemote] Thinking state changed to: ${thinking}`);
1025
+ if (opts.onThinkingChange) {
1026
+ opts.onThinkingChange(thinking);
1027
+ }
1028
+ }
1029
+ };
1030
+ let callbackDepth = 0;
1031
+ const guardCallback = (callback) => (async (...args) => {
1032
+ callbackDepth++;
1033
+ try {
1034
+ return await callback(...args);
1035
+ } finally {
1036
+ setImmediate(() => {
1037
+ callbackDepth--;
1038
+ });
1039
+ }
1040
+ });
1041
+ let mode = opts.prewarm?.mode ?? { permissionMode: "default" };
1042
+ const buildSdkOptions = (creationMode, io) => {
1043
+ const sdkOptions = {
1044
+ cwd: opts.path,
1045
+ resume: startFrom ?? void 0,
1046
+ mcpServers: opts.mcpServers,
1047
+ permissionMode: permissionMode.mapToClaudeMode(creationMode.permissionMode),
1048
+ // This is only the SDK safety opt-in; permissionMode/canUseTool still
1049
+ // enforce the selected policy. It must be enabled at Query creation so
1050
+ // a later explicit live switch to bypassPermissions can succeed.
1051
+ allowDangerouslySkipPermissions: true,
1052
+ model: creationMode.model,
1053
+ fallbackModel: creationMode.fallbackModel,
1054
+ customSystemPrompt: creationMode.customSystemPrompt ? creationMode.customSystemPrompt + "\n\n" + systemPrompt.systemPrompt : void 0,
1055
+ appendSystemPrompt: creationMode.appendSystemPrompt ? creationMode.appendSystemPrompt + "\n\n" + systemPrompt.systemPrompt : systemPrompt.systemPrompt,
1056
+ allowedTools: creationMode.allowedTools ? creationMode.allowedTools.concat(opts.allowedTools) : opts.allowedTools,
1057
+ additionalDirectories: opts.additionalDirectories,
1058
+ disallowedTools: creationMode.disallowedTools,
1059
+ effort: creationMode.effort,
1060
+ canCallTool: (toolName, input, options) => opts.canCallTool(toolName, input, mode, options),
1061
+ onElicitation: opts.onElicitation,
1062
+ onUserDialog: opts.onUserDialog,
1063
+ supportedDialogKinds: opts.onUserDialog ? ["refusal_fallback_prompt"] : void 0,
1064
+ abort: io.abort,
1065
+ settingsPath: io.settingsPath,
1066
+ // B-309: token-level partials. Without this the SDK emits nothing
1067
+ // between "turn started" and "entire assistant message", which is
1068
+ // exactly why the web used to show a spinner where the terminal shows
1069
+ // the model thinking out loud. The partials do NOT enter the
1070
+ // transcript; they are split off below and relayed on a side channel.
1071
+ // Only pay for them when someone is listening.
1072
+ includePartialMessages: opts.onStreamFrame ? true : void 0
1073
+ };
1074
+ if (sdkOptions.canCallTool) sdkOptions.canCallTool = guardCallback(sdkOptions.canCallTool);
1075
+ if (sdkOptions.onElicitation) sdkOptions.onElicitation = guardCallback(sdkOptions.onElicitation);
1076
+ if (sdkOptions.onUserDialog) sdkOptions.onUserDialog = guardCallback(sdkOptions.onUserDialog);
1077
+ return sdkOptions;
1078
+ };
1079
+ const discoverModels = async (q) => {
1080
+ if (typeof q.supportedModels !== "function") return void 0;
1081
+ return (await q.supportedModels()).map((model) => ({
1082
+ code: model.value,
1083
+ value: model.displayName,
1084
+ description: model.description,
1085
+ resolvedModel: model.resolvedModel,
1086
+ ...model.supportsEffort === false ? { reasoningEfforts: [] } : model.supportedEffortLevels ? { reasoningEfforts: model.supportedEffortLevels } : {}
1087
+ }));
1088
+ };
1089
+ let warm = null;
1090
+ if (opts.prewarm && startFrom) {
1091
+ opts.prewarm.discard("resume");
1092
+ } else if (opts.prewarm && opts.signal?.aborted) {
1093
+ opts.prewarm.discard("aborted");
1094
+ } else if (opts.prewarm) {
1095
+ const lease = opts.prewarm;
1096
+ const abort = new AbortController();
1097
+ const onOuterAbort = () => abort.abort();
1098
+ opts.signal?.addEventListener("abort", onOuterAbort, { once: true });
1099
+ const messages2 = new PushableAsyncIterable();
1100
+ const startedAt = Date.now();
1101
+ try {
1102
+ const response2 = index.query({
1103
+ prompt: messages2,
1104
+ options: buildSdkOptions(lease.mode, { settingsPath: lease.hookSettingsPath, abort: abort.signal })
1105
+ });
1106
+ const handshake = discoverModels(response2).then(
1107
+ (models2) => ({ ok: true, models: models2, at: Date.now() }),
1108
+ () => ({ ok: false, at: Date.now() })
1109
+ );
1110
+ const w = { response: response2, messages: messages2, lease, startedAt, handshake };
1111
+ lease.setTeardown(() => {
1112
+ if (w.idleTimer) clearTimeout(w.idleTimer);
1113
+ try {
1114
+ w.offExit?.();
1115
+ } catch {
1116
+ }
1117
+ opts.signal?.removeEventListener("abort", onOuterAbort);
1118
+ if (warm === w) warm = null;
1119
+ messages2.end();
1120
+ abort.abort();
1121
+ });
1122
+ w.idleTimer = setTimeout(() => lease.discard("idle"), lease.idleMs);
1123
+ w.idleTimer.unref?.();
1124
+ void handshake.then((result) => {
1125
+ if (!result.ok) {
1126
+ lease.discard("handshake-failed");
1127
+ return;
1128
+ }
1129
+ if (warm !== w) return;
1130
+ try {
1131
+ const transport = response2.transport;
1132
+ const off = transport?.onExit?.(() => {
1133
+ if (warm === w) lease.discard("exited");
1134
+ });
1135
+ if (typeof off === "function") w.offExit = off;
1136
+ } catch {
1137
+ }
1138
+ });
1139
+ warm = w;
1140
+ logger.logger.debug(formatPrewarmLine("started", { tag: lease.tag }));
1141
+ } catch (error) {
1142
+ opts.signal?.removeEventListener("abort", onOuterAbort);
1143
+ logger.logger.debug(`[claudeRemote] prewarm query() threw: ${error instanceof Error ? error.message : String(error)}`);
1144
+ lease.discard("spawn-failed");
1145
+ }
1146
+ }
1147
+ const discardWarm = (reason) => {
1148
+ warm?.lease.discard(reason);
1149
+ };
1150
+ let initial;
1151
+ try {
1152
+ initial = await opts.nextMessage();
1153
+ } catch (error) {
1154
+ discardWarm("error");
1155
+ throw error;
1156
+ }
731
1157
  if (!initial) {
1158
+ discardWarm("exit");
732
1159
  return;
733
1160
  }
1161
+ let timingTurn = 1;
1162
+ let timingMarks = { pushedAt: initial.enqueuedAt ?? Date.now() };
734
1163
  const initialText = typeof initial.message === "string" ? initial.message : initial.message.find((b) => b.type === "text")?.text ?? "";
735
1164
  const specialCommand = specialCommands.parseSpecialCommand(initialText);
736
1165
  if (specialCommand.type === "clear") {
1166
+ discardWarm("clear");
737
1167
  if (opts.onCompletionEvent) {
738
1168
  opts.onCompletionEvent("Context was reset");
739
1169
  }
@@ -751,50 +1181,61 @@ async function claudeRemote(opts) {
751
1181
  opts.onCompletionEvent("Compaction started");
752
1182
  }
753
1183
  }
754
- let mode = initial.mode;
755
- const sdkOptions = {
756
- cwd: opts.path,
757
- resume: startFrom ?? void 0,
758
- mcpServers: opts.mcpServers,
759
- permissionMode: permissionMode.mapToClaudeMode(initial.mode.permissionMode),
760
- // This is only the SDK safety opt-in; permissionMode/canUseTool still
761
- // enforce the selected policy. It must be enabled at Query creation so
762
- // a later explicit live switch to bypassPermissions can succeed.
763
- allowDangerouslySkipPermissions: true,
764
- model: initial.mode.model,
765
- fallbackModel: initial.mode.fallbackModel,
766
- customSystemPrompt: initial.mode.customSystemPrompt ? initial.mode.customSystemPrompt + "\n\n" + systemPrompt.systemPrompt : void 0,
767
- appendSystemPrompt: initial.mode.appendSystemPrompt ? initial.mode.appendSystemPrompt + "\n\n" + systemPrompt.systemPrompt : systemPrompt.systemPrompt,
768
- allowedTools: initial.mode.allowedTools ? initial.mode.allowedTools.concat(opts.allowedTools) : opts.allowedTools,
769
- additionalDirectories: opts.additionalDirectories,
770
- disallowedTools: initial.mode.disallowedTools,
771
- effort: initial.mode.effort,
772
- canCallTool: (toolName, input, options) => opts.canCallTool(toolName, input, mode, options),
773
- onElicitation: opts.onElicitation,
774
- onUserDialog: opts.onUserDialog,
775
- supportedDialogKinds: opts.onUserDialog ? ["refusal_fallback_prompt"] : void 0,
776
- abort: opts.signal,
777
- settingsPath: opts.hookSettingsPath,
778
- // B-309: token-level partials. Without this the SDK emits nothing
779
- // between "turn started" and "entire assistant message", which is
780
- // exactly why the web used to show a spinner where the terminal shows
781
- // the model thinking out loud. The partials do NOT enter the
782
- // transcript; they are split off below and relayed on a side channel.
783
- // Only pay for them when someone is listening.
784
- includePartialMessages: opts.onStreamFrame ? true : void 0
785
- };
786
- let thinking = false;
787
- const updateThinking = (newThinking) => {
788
- if (thinking !== newThinking) {
789
- thinking = newThinking;
790
- logger.logger.debug(`[claudeRemote] Thinking state changed to: ${thinking}`);
791
- if (opts.onThinkingChange) {
792
- opts.onThinkingChange(thinking);
1184
+ let adopted = null;
1185
+ if (warm) {
1186
+ const w = warm;
1187
+ const adoptStart = Date.now();
1188
+ const decision = decideWarmAdoption({ predicted: w.lease.mode, actual: initial.mode, specialCommand: specialCommand.type });
1189
+ let reason = decision.adopt ? null : decision.reason;
1190
+ const hs = reason ? null : await w.handshake;
1191
+ if (!reason) {
1192
+ if (warm !== w) {
1193
+ reason = "closed";
1194
+ } else if (!hs?.ok) {
1195
+ reason = "handshake-failed";
1196
+ } else if (decision.adopt) {
1197
+ try {
1198
+ if (decision.setPermissionMode) {
1199
+ await withTimeout(w.response.setPermissionMode(decision.setPermissionMode), w.lease.adoptTimeoutMs);
1200
+ } else {
1201
+ await withTimeout(w.response.mcpServerStatus(), w.lease.adoptTimeoutMs);
1202
+ }
1203
+ } catch {
1204
+ reason = decision.setPermissionMode ? "set-permission-failed" : "not-alive";
1205
+ }
1206
+ if (!reason && decision.switchModel) {
1207
+ try {
1208
+ await withTimeout(w.response.setModel(modelTarget(initial.mode.model)), w.lease.adoptTimeoutMs);
1209
+ } catch {
1210
+ reason = "set-model-failed";
1211
+ }
1212
+ }
1213
+ if (!reason && warm !== w) reason = "closed";
793
1214
  }
794
1215
  }
795
- };
796
- let messages = new PushableAsyncIterable();
797
- messages.push({
1216
+ if (reason || !hs?.ok) {
1217
+ w.lease.discard(reason ?? "handshake-failed");
1218
+ warm = null;
1219
+ } else {
1220
+ if (w.idleTimer) clearTimeout(w.idleTimer);
1221
+ try {
1222
+ w.offExit?.();
1223
+ } catch {
1224
+ }
1225
+ warm = null;
1226
+ w.lease.adopt();
1227
+ adopted = { response: w.response, messages: w.messages, models: hs.models };
1228
+ logger.logger.debug(formatPrewarmLine("adopted", {
1229
+ warmForMs: adoptStart - w.startedAt,
1230
+ handshakeWaitMs: Math.max(0, hs.at - adoptStart),
1231
+ adoptMs: Date.now() - adoptStart,
1232
+ setPermissionMode: decision.adopt ? decision.setPermissionMode : void 0,
1233
+ setModel: decision.adopt && decision.switchModel ? true : void 0
1234
+ }));
1235
+ }
1236
+ }
1237
+ mode = initial.mode;
1238
+ const initialUserMessage = {
798
1239
  type: "user",
799
1240
  parent_tool_use_id: null,
800
1241
  origin: { kind: "human" },
@@ -802,39 +1243,32 @@ async function claudeRemote(opts) {
802
1243
  role: "user",
803
1244
  content: initial.message
804
1245
  }
805
- });
806
- let callbackDepth = 0;
807
- const guardCallback = (callback) => (async (...args) => {
808
- callbackDepth++;
809
- try {
810
- return await callback(...args);
811
- } finally {
812
- setImmediate(() => {
813
- callbackDepth--;
814
- });
815
- }
816
- });
817
- if (sdkOptions.canCallTool) sdkOptions.canCallTool = guardCallback(sdkOptions.canCallTool);
818
- if (sdkOptions.onElicitation) sdkOptions.onElicitation = guardCallback(sdkOptions.onElicitation);
819
- if (sdkOptions.onUserDialog) sdkOptions.onUserDialog = guardCallback(sdkOptions.onUserDialog);
820
- const response = index.query({
821
- prompt: messages,
822
- options: sdkOptions
823
- });
1246
+ };
1247
+ let messages;
1248
+ let response;
824
1249
  let models;
825
- if (typeof response.supportedModels === "function") {
1250
+ if (adopted) {
1251
+ messages = adopted.messages;
1252
+ response = adopted.response;
1253
+ models = adopted.models;
1254
+ timingMarks.handshakeAt = Date.now();
1255
+ messages.push(initialUserMessage);
1256
+ } else {
1257
+ messages = new PushableAsyncIterable();
1258
+ messages.push(initialUserMessage);
1259
+ timingMarks.spawnAt = Date.now();
1260
+ response = index.query({
1261
+ prompt: messages,
1262
+ options: buildSdkOptions(initial.mode, { settingsPath: opts.hookSettingsPath, abort: opts.signal })
1263
+ });
826
1264
  try {
827
- models = (await response.supportedModels()).map((model) => ({
828
- code: model.value,
829
- value: model.displayName,
830
- description: model.description,
831
- resolvedModel: model.resolvedModel,
832
- ...model.supportsEffort === false ? { reasoningEfforts: [] } : model.supportedEffortLevels ? { reasoningEfforts: model.supportedEffortLevels } : {}
833
- }));
1265
+ models = await discoverModels(response);
834
1266
  } catch (error) {
835
1267
  logger.logger.debug("[claudeRemote] Model capability discovery unavailable");
836
1268
  }
1269
+ timingMarks.handshakeAt = Date.now();
837
1270
  }
1271
+ const prewarmTiming = adopted ? "adopted" : void 0;
838
1272
  if (opts.onQueryReady) {
839
1273
  opts.onQueryReady({
840
1274
  canControl: () => callbackDepth === 0,
@@ -886,6 +1320,11 @@ async function claudeRemote(opts) {
886
1320
  if (message.type === "assistant" && message.error) {
887
1321
  lastAssistantError = message.error;
888
1322
  }
1323
+ if (message.type === "assistant" && timingMarks.firstAssistantAt === void 0) {
1324
+ timingMarks.firstAssistantAt = Date.now();
1325
+ } else if (message.type === "system" && message.subtype === "init" && timingMarks.initAt === void 0) {
1326
+ timingMarks.initAt = Date.now();
1327
+ }
889
1328
  if (opts.onStreamFrame && message.type === "system") {
890
1329
  const subtype = message.subtype;
891
1330
  if (subtype === "thinking_tokens") {
@@ -935,6 +1374,15 @@ async function claudeRemote(opts) {
935
1374
  if (message.type === "result") {
936
1375
  updateThinking(false);
937
1376
  logger.logger.debug("[claudeRemote] Result received");
1377
+ logger.logger.debug(formatClaudeTimingLine({
1378
+ turn: timingTurn,
1379
+ firstTurnOfProcess: timingTurn === 1,
1380
+ marks: timingMarks,
1381
+ result: message,
1382
+ prewarm: timingTurn === 1 ? prewarmTiming : void 0
1383
+ }));
1384
+ timingTurn++;
1385
+ timingMarks = {};
938
1386
  const denials = message.permission_denials;
939
1387
  if (denials && denials.length > 0) {
940
1388
  logger.logger.warn(`[claudeRemote] ${denials.length} tool call(s) auto-denied by Claude Code policy: ${denials.map((d) => d.tool_name ?? "?").join(", ")}`);
@@ -974,6 +1422,7 @@ async function claudeRemote(opts) {
974
1422
  }
975
1423
  mode = next.mode;
976
1424
  updateThinking(true);
1425
+ timingMarks = { pushedAt: next.enqueuedAt ?? Date.now() };
977
1426
  messages.push({
978
1427
  type: "user",
979
1428
  parent_tool_use_id: null,
@@ -2634,10 +3083,13 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
2634
3083
  permissionHandler.setOnModeChanged((nextMode) => {
2635
3084
  commitPermissionMode(nextMode);
2636
3085
  });
3086
+ let launchPrewarm = null;
2637
3087
  try {
2638
3088
  const attachmentDirectory = attachmentContent.chatAttachmentDirectory(configuration.configuration.happyHomeDir, session.client.sessionId);
2639
3089
  await configuration.ensurePrivateDirectory(attachmentDirectory);
3090
+ launchPrewarm = session.takeClaudePrewarm();
2640
3091
  const remoteResult = await claudeRemote({
3092
+ prewarm: launchPrewarm ?? void 0,
2641
3093
  sessionId: session.sessionId,
2642
3094
  path: session.path,
2643
3095
  additionalDirectories: [attachmentDirectory],
@@ -2686,13 +3138,15 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
2686
3138
  onPromptFinalized?.(withAttachments);
2687
3139
  return {
2688
3140
  message: withAttachments,
2689
- mode: msg.mode
3141
+ mode: msg.mode,
3142
+ enqueuedAt: msg.enqueuedAt
2690
3143
  };
2691
3144
  }
2692
3145
  onPromptFinalized?.(msg.message);
2693
3146
  return {
2694
3147
  message: msg.message,
2695
- mode: msg.mode
3148
+ mode: msg.mode,
3149
+ enqueuedAt: msg.enqueuedAt
2696
3150
  };
2697
3151
  }
2698
3152
  return null;
@@ -2810,6 +3264,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
2810
3264
  continue;
2811
3265
  }
2812
3266
  } finally {
3267
+ launchPrewarm?.discard("launch-ended");
2813
3268
  runtimeControls.setQuery(null);
2814
3269
  backgroundTasks.reset();
2815
3270
  session.setBackgroundTasks([]);
@@ -2883,7 +3338,8 @@ async function loop(opts) {
2883
3338
  onModeChange: opts.onModeChange,
2884
3339
  onAbort: opts.onAbort,
2885
3340
  hookSettingsPath: opts.hookSettingsPath,
2886
- jsRuntime: opts.jsRuntime
3341
+ jsRuntime: opts.jsRuntime,
3342
+ claudePrewarm: opts.claudePrewarm
2887
3343
  });
2888
3344
  opts.onSessionReady?.(session);
2889
3345
  let mode = opts.startingMode ?? "local";
@@ -2891,7 +3347,7 @@ async function loop(opts) {
2891
3347
  logger.logger.debug(`[loop] Iteration with mode: ${mode}`);
2892
3348
  switch (mode) {
2893
3349
  case "local": {
2894
- const { claudeLocalLauncher } = await Promise.resolve().then(function () { return require('./claudeLocalLauncher-DyEbVzUN.cjs'); });
3350
+ const { claudeLocalLauncher } = await Promise.resolve().then(function () { return require('./claudeLocalLauncher-Bd5I2-j6.cjs'); });
2895
3351
  const result = await claudeLocalLauncher(session);
2896
3352
  switch (result.type) {
2897
3353
  case "switch":
@@ -2919,18 +3375,18 @@ async function loop(opts) {
2919
3375
  }
2920
3376
  }
2921
3377
 
2922
- function claudeModeHash(mode) {
2923
- return deterministicJson.hashObject({
2924
- isPlan: mode.permissionMode === "plan",
2925
- fallbackModel: mode.fallbackModel,
2926
- customSystemPrompt: mode.customSystemPrompt,
2927
- appendSystemPrompt: mode.appendSystemPrompt,
2928
- allowedTools: mode.allowedTools,
2929
- disallowedTools: mode.disallowedTools,
2930
- effort: mode.effort
2931
- });
3378
+ function parseSessionHookTarget(url) {
3379
+ if (!url) return null;
3380
+ let parsed;
3381
+ try {
3382
+ parsed = new URL(url, "http://127.0.0.1");
3383
+ } catch {
3384
+ return null;
3385
+ }
3386
+ if (parsed.pathname !== "/hook/session-start") return null;
3387
+ const source = parsed.searchParams.get("source");
3388
+ return source && /^[A-Za-z0-9_.-]{1,64}$/.test(source) ? { source } : {};
2932
3389
  }
2933
-
2934
3390
  function hookRequestLogMetadata(body, data) {
2935
3391
  return {
2936
3392
  bodyBytes: Buffer.byteLength(body, "utf8"),
@@ -2952,7 +3408,8 @@ async function startHookServer(options) {
2952
3408
  const { onSessionHook } = options;
2953
3409
  return new Promise((resolve, reject) => {
2954
3410
  const server = node_http.createServer(async (req, res) => {
2955
- if (req.method === "POST" && req.url === "/hook/session-start") {
3411
+ const hookMeta = req.method === "POST" ? parseSessionHookTarget(req.url) : null;
3412
+ if (hookMeta) {
2956
3413
  const timeout = setTimeout(() => {
2957
3414
  if (!res.headersSent) {
2958
3415
  logger.logger.debug("[hookServer] Request timeout");
@@ -2976,7 +3433,7 @@ async function startHookServer(options) {
2976
3433
  const sessionId = data?.session_id || data?.sessionId;
2977
3434
  if (sessionId && data) {
2978
3435
  logger.logger.debug(`[hookServer] Session hook received session ID: ${sessionId}`);
2979
- onSessionHook(sessionId, data);
3436
+ onSessionHook(sessionId, data, hookMeta);
2980
3437
  } else {
2981
3438
  logger.logger.debug("[hookServer] Session hook received but no session_id found in data");
2982
3439
  }
@@ -3015,13 +3472,16 @@ async function startHookServer(options) {
3015
3472
  });
3016
3473
  }
3017
3474
 
3018
- function generateHookSettingsFile(port) {
3475
+ function generateHookSettingsFile(port, source) {
3019
3476
  const hooksDir = path$1.join(configuration.configuration.happyHomeDir, "tmp", "hooks");
3020
3477
  node_fs.mkdirSync(hooksDir, { recursive: true });
3021
- const filename = `session-hook-${process.pid}.json`;
3478
+ const filename = source ? `session-hook-${process.pid}-${source}.json` : `session-hook-${process.pid}.json`;
3022
3479
  const filepath = path$1.join(hooksDir, filename);
3023
3480
  const forwarderScript = path$1.resolve(projectPath.projectPath(), "scripts", "session_hook_forwarder.cjs");
3024
- const hookCommand = `node "${forwarderScript}" ${port}`;
3481
+ if (source !== void 0 && !/^[A-Za-z0-9_.-]{1,64}$/.test(source)) {
3482
+ throw new Error("invalid hook source tag");
3483
+ }
3484
+ const hookCommand = source ? `node "${forwarderScript}" ${port} ${source}` : `node "${forwarderScript}" ${port}`;
3025
3485
  const settings = {
3026
3486
  hooks: {
3027
3487
  SessionStart: [
@@ -3619,31 +4079,90 @@ function withAssistantDenylist(current, isAssistant) {
3619
4079
  return [...merged];
3620
4080
  }
3621
4081
 
4082
+ const VALID_EFFORTS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh", "max"]);
4083
+ const has = (meta, key) => !!meta && Object.prototype.hasOwnProperty.call(meta, key);
4084
+ function resolveMessageMode(current, meta, ctx) {
4085
+ const next = { ...current };
4086
+ const result = {};
4087
+ let permissionMode$1 = current.permissionMode;
4088
+ if (!ctx.staleModeSnapshot && meta?.permissionMode) {
4089
+ permissionMode$1 = permissionMode.resolveRemoteClaudePermissionMode(current.permissionMode, meta.permissionMode, ctx.sandboxEnabled);
4090
+ next.permissionMode = permissionMode$1;
4091
+ result.publishPermissionMode = permissionMode$1;
4092
+ }
4093
+ if (has(meta, "model")) next.model = meta.model || void 0;
4094
+ if (has(meta, "customSystemPrompt")) next.customSystemPrompt = meta.customSystemPrompt || void 0;
4095
+ if (has(meta, "fallbackModel")) next.fallbackModel = meta.fallbackModel || void 0;
4096
+ if (has(meta, "appendSystemPrompt")) next.appendSystemPrompt = meta.appendSystemPrompt || void 0;
4097
+ if (has(meta, "allowedTools")) next.allowedTools = meta.allowedTools || void 0;
4098
+ if (has(meta, "disallowedTools")) {
4099
+ next.disallowedTools = withAssistantDenylist(meta.disallowedTools || void 0, ctx.isAssistantVariant);
4100
+ }
4101
+ if (has(meta, "effort")) {
4102
+ const incoming = meta.effort;
4103
+ if (incoming === null || incoming === void 0) {
4104
+ next.effort = void 0;
4105
+ } else if (typeof incoming === "string" && VALID_EFFORTS.has(incoming)) {
4106
+ next.effort = incoming;
4107
+ } else {
4108
+ result.ignoredEffort = String(incoming);
4109
+ }
4110
+ }
4111
+ return {
4112
+ ...result,
4113
+ next,
4114
+ mode: {
4115
+ permissionMode: permissionMode$1 || "default",
4116
+ model: next.model,
4117
+ fallbackModel: next.fallbackModel,
4118
+ customSystemPrompt: next.customSystemPrompt,
4119
+ appendSystemPrompt: next.appendSystemPrompt,
4120
+ allowedTools: next.allowedTools,
4121
+ disallowedTools: next.disallowedTools,
4122
+ effort: next.effort
4123
+ }
4124
+ };
4125
+ }
4126
+
3622
4127
  exports.reportSessionEditToDaemon = controlClient.reportSessionEditToDaemon;
3623
4128
  exports.claudeCheckSession = systemPrompt.claudeCheckSession;
3624
4129
  exports.parseSpecialCommand = specialCommands.parseSpecialCommand;
3625
4130
  exports.contentLogMetadata = contentLogMetadata.contentLogMetadata;
3626
4131
  exports.RawJSONLinesSchema = types.RawJSONLinesSchema;
3627
4132
  exports.getProjectPath = path.getProjectPath;
4133
+ exports.createSelfReportState = deterministicJson.createSelfReportState;
4134
+ exports.startHappyServer = deterministicJson.startHappyServer;
3628
4135
  exports.createSessionScanner = sessionScanner.createSessionScanner;
3629
4136
  exports.MessageQueue2 = registerKillSessionHandler.MessageQueue2;
3630
4137
  exports.registerKillSessionHandler = registerKillSessionHandler.registerKillSessionHandler;
3631
- exports.createSelfReportState = deterministicJson.createSelfReportState;
3632
- exports.startHappyServer = deterministicJson.startHappyServer;
3633
4138
  exports.getEnvironmentInfo = doctor.getEnvironmentInfo;
3634
4139
  exports.EditReportThrottle = editPaths.EditReportThrottle;
3635
4140
  exports.extractClaudeEditPaths = editPaths.extractClaudeEditPaths;
3636
4141
  exports.TitleGenerator = titleGenerator.TitleGenerator;
3637
4142
  exports.BoardAnalyzer = BoardAnalyzer;
3638
4143
  exports.FileRateLimiter = FileRateLimiter;
4144
+ exports.PrewarmHookGate = PrewarmHookGate;
3639
4145
  exports.SessionExitGate = SessionExitGate;
4146
+ exports.acquirePrewarmSlot = acquirePrewarmSlot;
3640
4147
  exports.claudeModeHash = claudeModeHash;
4148
+ exports.claudePrewarmEligibility = claudePrewarmEligibility;
4149
+ exports.claudePrewarmSessionEligibility = claudePrewarmSessionEligibility;
3641
4150
  exports.cleanupHookSettingsFile = cleanupHookSettingsFile;
4151
+ exports.createClaudePrewarmLease = createClaudePrewarmLease;
4152
+ exports.disposeAllClaudePrewarms = disposeAllClaudePrewarms;
4153
+ exports.evaluatePrewarmPrediction = evaluatePrewarmPrediction;
3642
4154
  exports.exitIntentFromArchiveFlag = exitIntentFromArchiveFlag;
4155
+ exports.formatPrewarmLine = formatPrewarmLine;
3643
4156
  exports.generateHookSettingsFile = generateHookSettingsFile;
3644
4157
  exports.loop = loop;
4158
+ exports.prewarmCacheFile = prewarmCacheFile;
4159
+ exports.prewarmPredictionMeta = prewarmPredictionMeta;
4160
+ exports.prewarmSlotDir = prewarmSlotDir;
4161
+ exports.readPrewarmCache = readPrewarmCache;
3645
4162
  exports.registerSideQuestionHandler = registerSideQuestionHandler;
4163
+ exports.resolveMessageMode = resolveMessageMode;
3646
4164
  exports.settleSessionOnExit = settleSessionOnExit;
3647
4165
  exports.startHookServer = startHookServer;
3648
4166
  exports.withAssistantDenylist = withAssistantDenylist;
4167
+ exports.writePrewarmCache = writePrewarmCache;
3649
4168
  exports.writeSideQuestionSettingsFile = writeSideQuestionSettingsFile;