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.
- package/dist/{AcpBackend-mzv8Dhba.mjs → AcpBackend-6U6pQgx1.mjs} +3 -3
- package/dist/{AcpBackend-Bm2rdke8.cjs → AcpBackend-Ba98QDif.cjs} +3 -3
- package/dist/{BasePermissionHandler-CFHAxumV.cjs → BasePermissionHandler-2R0uH2CI.cjs} +1 -1
- package/dist/{BasePermissionHandler-m3WVholL.mjs → BasePermissionHandler-BvvhBTja.mjs} +1 -1
- package/dist/{BaseReasoningProcessor-CYrKBXGm.mjs → BaseReasoningProcessor-DyhO1uoU.mjs} +1 -1
- package/dist/{BaseReasoningProcessor-BFa9_rZA.cjs → BaseReasoningProcessor-fsVNmCEF.cjs} +1 -1
- package/dist/{agentHome-Dj1C43aJ.mjs → agentHome-Ck1i1TQB.mjs} +4 -4
- package/dist/{agentHome-CboCeKWq.cjs → agentHome-DvNnGphb.cjs} +4 -4
- package/dist/{api-CgundNNX.cjs → api-B2vLMS-z.cjs} +8 -8
- package/dist/{api-CLMUr-SX.mjs → api-SffjRQ1b.mjs} +8 -8
- package/dist/{apiMachine-B9dLW_p5.mjs → apiMachine-BpW9t8MO.mjs} +11 -11
- package/dist/{apiMachine-Bn8482VM.cjs → apiMachine-gFA54X7y.cjs} +11 -11
- package/dist/{assistantTools-BTqPnlFl.cjs → assistantTools-BfA0R3_m.cjs} +6 -6
- package/dist/{assistantTools-D6tuc6o4.mjs → assistantTools-CgiTbnWb.mjs} +6 -6
- package/dist/{attachmentContent-_kxRznNf.mjs → attachmentContent-CSGxr71v.mjs} +1 -1
- package/dist/{attachmentContent-DpiTJZb4.cjs → attachmentContent-DMMZzevR.cjs} +1 -1
- package/dist/{auth-ba4WMYrN.cjs → auth-Bt4ceBBy.cjs} +5 -5
- package/dist/{auth-Cwutmdsa.mjs → auth-CYHjQ8oQ.mjs} +5 -5
- package/dist/{auth-PYHZQNPp.mjs → auth-DdyVZSo6.mjs} +8 -8
- package/dist/{auth-BDOVh5h5.cjs → auth-x4CEoysH.cjs} +8 -8
- package/dist/{auto-BOX_fgmR.cjs → auto-BDXDUnjB.cjs} +12 -12
- package/dist/{auto-BXu14yP_.mjs → auto-CXLlRi3a.mjs} +12 -12
- package/dist/{bootstrap-hxXPCFMx.mjs → bootstrap-BNQq05jR.mjs} +2 -2
- package/dist/{bootstrap-B5G1TijC.cjs → bootstrap-CkgIq8N3.cjs} +2 -2
- package/dist/{browser-jh2P0UVZ.mjs → browser-9pyhQr1R.mjs} +1 -1
- package/dist/{browser-Y6Bl8L_O.cjs → browser-BDOlKWYe.cjs} +1 -1
- package/dist/{claudeLocal-CRGG4Pea.cjs → claudeLocal-BDuGFnjJ.cjs} +4 -4
- package/dist/{claudeLocal-BaY4fZKi.mjs → claudeLocal-CQa8qnwq.mjs} +4 -4
- package/dist/{claudeLocalLauncher-DyEbVzUN.cjs → claudeLocalLauncher-Bd5I2-j6.cjs} +9 -9
- package/dist/{claudeLocalLauncher-D4T7MTqd.mjs → claudeLocalLauncher-CDqQI9ak.mjs} +9 -9
- package/dist/{client-CeGKqqcJ.mjs → client-Brn-UwVk.mjs} +3 -3
- package/dist/{client-ClR0K8zX.mjs → client-CXb1VJui.mjs} +2 -2
- package/dist/{client-3Ac-O4pw.cjs → client-C_axwRry.cjs} +3 -3
- package/dist/{client-BPNbmtvO.cjs → client-DOBWJL3u.cjs} +2 -2
- package/dist/codex/happyMcpStdioBridge.cjs +14 -14
- package/dist/codex/happyMcpStdioBridge.mjs +14 -14
- package/dist/{codexAppServerClient-q2FjnRcK.cjs → codexAppServerClient-ZzhUTWPo.cjs} +2 -2
- package/dist/{codexAppServerClient-I3teiV-N.mjs → codexAppServerClient-oeQKD6Qf.mjs} +2 -2
- package/dist/{codexCommand-4zcccIoq.cjs → codexCommand-C7H0NpBe.cjs} +35 -35
- package/dist/{codexCommand-Cc9gcbdX.mjs → codexCommand-CJ82bl3l.mjs} +35 -35
- package/dist/{codexThreadFork-slzAseLx.mjs → codexThreadFork-BCaEMBiM.mjs} +1 -1
- package/dist/{codexThreadFork-BH9IZPqD.cjs → codexThreadFork-BZqF-9bX.cjs} +1 -1
- package/dist/{config-CTx_jb-C.mjs → config-BglnktIo.mjs} +3 -3
- package/dist/{config-Ci9Kpgwa.cjs → config-CYpL1Ahd.cjs} +3 -3
- package/dist/{configuration-RfeNjFmd.mjs → configuration-DoWFJUPm.mjs} +1 -1
- package/dist/{configuration-BSYpcPwE.cjs → configuration-v9f8LM9T.cjs} +1 -1
- package/dist/{connect-BpOdzNbE.mjs → connect-hgcNjyAB.mjs} +11 -11
- package/dist/{connect-C2CiOUFs.cjs → connect-yEvjdRvx.cjs} +11 -11
- package/dist/{context-DsDr6E2t.cjs → context-B45vMtSZ.cjs} +1 -1
- package/dist/{context-H0Bcb9S_.mjs → context-C9GHPLEm.mjs} +1 -1
- package/dist/{controlClient-BGbDcgWS.mjs → controlClient-DjoKTtgK.mjs} +3 -3
- package/dist/{controlClient-Bcwv3D21.cjs → controlClient-fEHE85bH.cjs} +3 -3
- package/dist/{createSessionMetadata-BJxEnM-o.cjs → createSessionMetadata-BRLB9CNO.cjs} +2 -2
- package/dist/{createSessionMetadata-CVVkGjxV.mjs → createSessionMetadata-mIeehclp.mjs} +2 -2
- package/dist/{deterministicJson-C5CYTVpm.cjs → deterministicJson-DKDP_mM-.cjs} +8 -8
- package/dist/{deterministicJson-CzkFJWw1.mjs → deterministicJson-p835AdAU.mjs} +8 -8
- package/dist/{doctor-DOvByjbk.mjs → doctor-BeUuQXFs.mjs} +6 -6
- package/dist/{doctor-D2YJ-Yn2.cjs → doctor-hVNnSZJn.cjs} +6 -6
- package/dist/{ensureDaemonRunning-Dqa2pOjY.mjs → ensureDaemonRunning-CO7d1gOC.mjs} +5 -5
- package/dist/{ensureDaemonRunning-BCwNrMyv.cjs → ensureDaemonRunning-Dg9aZfjs.cjs} +5 -5
- package/dist/{handleResumeCommand-BvXYf5El.mjs → handleResumeCommand-BiTPK0qd.mjs} +5 -5
- package/dist/{handleResumeCommand-C2cKchpX.cjs → handleResumeCommand-DnVmy7a3.cjs} +5 -5
- package/dist/{index-DMZqWwsP.mjs → index-CAFwetLk.mjs} +33 -33
- package/dist/{index-DVkMGPyS.mjs → index-Cqx-Raq6.mjs} +3 -3
- package/dist/{index-B6pAdvJx.cjs → index-LIn6nCcq.cjs} +32 -32
- package/dist/{index-Bu5Zi_a9.cjs → index-Pf2cV9cn.cjs} +4 -4
- package/dist/{index-DKLU_fD0.mjs → index-SPGPenK5.mjs} +4 -4
- package/dist/{index-DDeHXrIX.cjs → index-gNTWtSKN.cjs} +3 -3
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{install-BgoC2e_2.cjs → install-Bu85vlHD.cjs} +3 -3
- package/dist/{install-CFY3tYtJ.mjs → install-ClUUl3yp.mjs} +3 -3
- package/dist/lib.cjs +10 -10
- package/dist/lib.mjs +10 -10
- package/dist/{lidState-CeEt442o.mjs → lidState-C2dI0FAN.mjs} +1 -1
- package/dist/{lidState-BeDfxxEX.cjs → lidState-KHHu1015.cjs} +1 -1
- package/dist/{localHappyAgentAuth-D6rFhaoc.cjs → localHappyAgentAuth-BXiHPXdC.cjs} +1 -1
- package/dist/{localHappyAgentAuth-C-HQyiv6.mjs → localHappyAgentAuth-DCsetiyG.mjs} +1 -1
- package/dist/{logger-CS0mw3fa.cjs → logger-Bc8-u1w0.cjs} +2 -2
- package/dist/{logger-6HYUEXNk.mjs → logger-fXoNzNuB.mjs} +2 -2
- package/dist/{machineMetadata-oOzBfDfs.mjs → machineMetadata-BHjehxJY.mjs} +3 -3
- package/dist/{machineMetadata-DyDbODYd.cjs → machineMetadata-BibDMFVx.cjs} +3 -3
- package/dist/{main-BwNIAI1A.mjs → main-BktM4A1K.mjs} +44 -44
- package/dist/{main-BkxJP6JQ.cjs → main-CLaX-t-b.cjs} +44 -44
- package/dist/{mcp-B1A4I3TK.mjs → mcp-CeUd9KDr.mjs} +14 -14
- package/dist/{mcp-Hszd7qpS.cjs → mcp-GBfE70nk.cjs} +14 -14
- package/dist/{package-BwMrPwqH.cjs → package-Cl5BEP5x.cjs} +7 -7
- package/dist/{package-BhaKlnxz.mjs → package-uOg9SCKi.mjs} +7 -7
- package/dist/{peerTools-BvKtHXj8.cjs → peerTools-CIeiy9wn.cjs} +4 -4
- package/dist/{peerTools-BTqw97Gb.mjs → peerTools-Dz3_7Bkk.mjs} +4 -4
- package/dist/{permissionMode-Cr5JCbB7.mjs → permissionMode-CH4FoZfU.mjs} +1 -1
- package/dist/{persistence-yKTH3-5X.cjs → persistence-CBNMzSa8.cjs} +3 -3
- package/dist/{persistence-HGW_ZVs9.mjs → persistence-oET5n61f.mjs} +3 -3
- package/dist/{piRunnerArgs-BNloJCCg.cjs → piRunnerArgs-Bf7RUF__.cjs} +1 -1
- package/dist/{piRunnerArgs-BuX1UFWy.mjs → piRunnerArgs-Dk1ncwHF.mjs} +1 -1
- package/dist/{piRuntime-C_H7MJCM.cjs → piRuntime-B_6TE9Eb.cjs} +1 -1
- package/dist/{piRuntime-CSGkwCKQ.mjs → piRuntime-BwRdhK_N.mjs} +1 -1
- package/dist/{piTerminal-C8a1OrNQ.mjs → piTerminal-Bap3R8Re.mjs} +16 -16
- package/dist/{piTerminal-DNCZ6yTM.cjs → piTerminal-CagmEoez.cjs} +16 -16
- package/dist/{registerCommonHandlers-DskirN-_.cjs → registerCommonHandlers-BjSV2Skz.cjs} +2 -2
- package/dist/{registerCommonHandlers-Ccvsz7Ou.mjs → registerCommonHandlers-CrgvJsOy.mjs} +2 -2
- package/dist/{registerKillSessionHandler-DZeLXWcB.cjs → registerKillSessionHandler-6TC2S3lf.cjs} +13 -8
- package/dist/{registerKillSessionHandler-GYvHdipX.mjs → registerKillSessionHandler-Cbc8Rgtd.mjs} +13 -8
- package/dist/{remoteSessionClient-B0LraSB9.cjs → remoteSessionClient-BNx78NLb.cjs} +5 -5
- package/dist/{remoteSessionClient-CYnXRynE.mjs → remoteSessionClient-CO7qOjR0.mjs} +5 -5
- package/dist/{run-D3ifupU3.mjs → run-2l5vSt2h.mjs} +32 -28
- package/dist/{run-CJzxoHVh.cjs → run-D5xAEWSB.cjs} +33 -29
- package/dist/{runClaude-Da3RirzE.cjs → runClaude-BX6ixjtW.cjs} +182 -138
- package/dist/{runClaude-Ba01qT-u.mjs → runClaude-BgN6xo05.mjs} +183 -139
- package/dist/{runClaudeDeps-DOzEBMls.cjs → runClaudeDeps-Bp20MScE.cjs} +638 -119
- package/dist/{runClaudeDeps-DOt79DjU.mjs → runClaudeDeps-COBBhD9o.mjs} +628 -123
- package/dist/{runGemini-DSr9LIxL.cjs → runGemini-CSMPkt0p.cjs} +30 -30
- package/dist/{runGemini-BGeTz57m.mjs → runGemini-Cc2jq-uh.mjs} +30 -30
- package/dist/{runOpenClaw-CogSedIc.mjs → runOpenClaw-CIlCwdW2.mjs} +15 -15
- package/dist/{runOpenClaw-B1mTxN35.cjs → runOpenClaw-YBwua4Rf.cjs} +15 -15
- package/dist/{sandbox-CG7IyDTU.cjs → sandbox-C4gXLP1p.cjs} +4 -4
- package/dist/{sandbox-DTe6d54R.mjs → sandbox-CNkwOtHI.mjs} +4 -4
- package/dist/{selfCheck-Dc-mNSLb.cjs → selfCheck-CU8xSDsl.cjs} +34 -34
- package/dist/selfCheck-hJ6PCh7v.mjs +84 -0
- package/dist/{send-CBXJKc6O.mjs → send-CGHcKZ-w.mjs} +8 -8
- package/dist/{send-B7J_eaG3.cjs → send-DY9Nr-x4.cjs} +8 -8
- package/dist/{server-CZTP_iOn.cjs → server-II51Mimf.cjs} +6 -6
- package/dist/{server-DcVBv04l.mjs → server-m2b5pamZ.mjs} +4 -4
- package/dist/{sessionLock-Bys1PNSo.cjs → sessionLock-7ePAYDOg.cjs} +2 -2
- package/dist/{sessionLock-D-EG2CfG.mjs → sessionLock-Cw6FmbMv.mjs} +2 -2
- package/dist/{sessionModeFile-RSm0NQkH.cjs → sessionModeFile-BVCV5f7E.cjs} +1 -1
- package/dist/{sessionModeFile-DMl3dw3r.mjs → sessionModeFile-CDmDyRkD.mjs} +1 -1
- package/dist/{sessionOps-SuHW8Dfe.mjs → sessionOps-C_f1wKOr.mjs} +4 -4
- package/dist/{sessionOps-Dn8z85h_.cjs → sessionOps-DJdExmBy.cjs} +4 -4
- package/dist/{sessionScanner-CX3onqXh.mjs → sessionScanner-CaAHLyNV.mjs} +3 -3
- package/dist/{sessionScanner-BOrGjMXL.cjs → sessionScanner-D1goKdd3.cjs} +3 -3
- package/dist/{sessions-D74aJbhL.cjs → sessions-DGs6ALNo.cjs} +9 -9
- package/dist/{sessions-BEG_HTSi.mjs → sessions-DnvmWUel.mjs} +9 -9
- package/dist/{setupOfflineReconnection-DpvWTt69.mjs → setupOfflineReconnection-CVViqZft.mjs} +2 -2
- package/dist/{setupOfflineReconnection-ByElY60m.cjs → setupOfflineReconnection-R7XuR_sj.cjs} +2 -2
- package/dist/{spawn-DgR0RKRs.cjs → spawn-CXTH7qg1.cjs} +19 -11
- package/dist/{spawn-B7yro0b2.mjs → spawn-DNYSvFtC.mjs} +19 -12
- package/dist/{spawnHappyCLI-DBhwZT7O.cjs → spawnHappyCLI-BhYj84rv.cjs} +1 -1
- package/dist/{spawnHappyCLI-B2H5s4B_.mjs → spawnHappyCLI-cqWQbwsb.mjs} +1 -1
- package/dist/{startFileWatcher-B4VsLgjD.cjs → startFileWatcher-CKKx-8ZO.cjs} +1 -1
- package/dist/{startFileWatcher-DErVWZE4.mjs → startFileWatcher-CdegMbJj.mjs} +1 -1
- package/dist/{sync-DccIKZ5_.cjs → sync-CVk4QERO.cjs} +1 -1
- package/dist/{sync-C8gyQFMc.mjs → sync-CxD-w_40.mjs} +1 -1
- package/dist/{systemPrompt-BwTPWfMu.cjs → systemPrompt-BygJcmbi.cjs} +1 -1
- package/dist/{systemPrompt-DX521JJz.mjs → systemPrompt-DmtypUc7.mjs} +1 -1
- package/dist/{teams-C32F1hqd.mjs → teams-BOC6nIPL.mjs} +6 -6
- package/dist/{teams-Dl8g8kTI.cjs → teams-BsvpOBfn.cjs} +6 -6
- package/dist/{time-D0XyHOid.mjs → time-BZNdNiIV.mjs} +1 -1
- package/dist/{time-DCuTyook.cjs → time-CNRE4ChD.cjs} +1 -1
- package/dist/{titleGenerator-ChzMJsyg.cjs → titleGenerator-CFRhU-xq.cjs} +2 -2
- package/dist/{titleGenerator-CQ8CoGhg.mjs → titleGenerator-ox6ptCsp.mjs} +1 -1
- package/dist/{todo-BvUOTa8G.cjs → todo-B-KB7oAB.cjs} +5 -5
- package/dist/{todo-CZ6cFrrn.mjs → todo-C5KBVbUw.mjs} +5 -5
- package/dist/{tools-BZtHF_qQ.mjs → tools-BZabNIid.mjs} +1 -1
- package/dist/{tools-DkluDcG4.mjs → tools-BmQQUATY.mjs} +1 -1
- package/dist/{tools-DQj0AeLk.cjs → tools-CsSovyNp.cjs} +1 -1
- package/dist/{tools-Be3AoAwu.cjs → tools-lMDra4Pv.cjs} +1 -1
- package/dist/{uninstall-BkLzaJ6I.mjs → uninstall-B1WLtC1d.mjs} +3 -3
- package/dist/{uninstall-x-TUtf5H.cjs → uninstall-fvA5aWpU.cjs} +3 -3
- package/package.json +7 -7
- package/scripts/session_hook_forwarder.cjs +9 -2
- package/dist/selfCheck-C9mVrQwf.mjs +0 -84
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var logger = require('./logger-
|
|
4
|
-
var controlClient = require('./controlClient-
|
|
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-
|
|
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-
|
|
19
|
+
var configuration = require('./configuration-v9f8LM9T.cjs');
|
|
20
20
|
require('./index-DA7yINuk.cjs');
|
|
21
|
-
require('./registerCommonHandlers-
|
|
21
|
+
require('./registerCommonHandlers-BjSV2Skz.cjs');
|
|
22
22
|
require('os');
|
|
23
23
|
require('child_process');
|
|
24
24
|
require('@paralleldrive/cuid2');
|
|
25
|
-
require('./persistence-
|
|
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-
|
|
32
|
-
var
|
|
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-
|
|
36
|
-
var registerKillSessionHandler = require('./registerKillSessionHandler-
|
|
37
|
-
var
|
|
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-
|
|
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-
|
|
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('./
|
|
59
|
-
require('./
|
|
60
|
-
require('./
|
|
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-
|
|
65
|
-
require('./tools-
|
|
66
|
-
require('./client-
|
|
67
|
-
require('./peerTools-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
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
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
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
|
-
|
|
797
|
-
|
|
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
|
|
807
|
-
|
|
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 (
|
|
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 =
|
|
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-
|
|
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
|
|
2923
|
-
return
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|