very-happy-cli 0.2.160 → 0.2.162
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--TmFHgRH.mjs} +3 -3
- package/dist/{AcpBackend-Bm2rdke8.cjs → AcpBackend-9asD_DL7.cjs} +3 -3
- package/dist/{AcpSessionManager-CoMWFVw3.mjs → AcpSessionManager-BSIBnWUb.mjs} +1 -1
- package/dist/{AcpSessionManager-BAY1Pggx.cjs → AcpSessionManager-BvIuBzoO.cjs} +1 -1
- package/dist/{BasePermissionHandler-CFHAxumV.cjs → BasePermissionHandler-D4B-NNu2.cjs} +1 -1
- package/dist/{BasePermissionHandler-m3WVholL.mjs → BasePermissionHandler-DUBySe0f.mjs} +1 -1
- package/dist/{BaseReasoningProcessor-CYrKBXGm.mjs → BaseReasoningProcessor-9TybUGTq.mjs} +1 -1
- package/dist/{BaseReasoningProcessor-BFa9_rZA.cjs → BaseReasoningProcessor-CqLl-ikP.cjs} +1 -1
- package/dist/{agentHome-CboCeKWq.cjs → agentHome-BohNUYnE.cjs} +4 -4
- package/dist/{agentHome-Dj1C43aJ.mjs → agentHome-DQrq_FG1.mjs} +4 -4
- package/dist/{api-CgundNNX.cjs → api-CQnLOqRS.cjs} +10 -10
- package/dist/{api-CLMUr-SX.mjs → api-D57dsd6_.mjs} +10 -10
- package/dist/{apiMachine-B9dLW_p5.mjs → apiMachine-78Aqzg--.mjs} +21 -14
- package/dist/{apiMachine-Bn8482VM.cjs → apiMachine-fFFaWxYy.cjs} +33 -26
- package/dist/{assistantTools-BTqPnlFl.cjs → assistantTools-CwESq24n.cjs} +6 -6
- package/dist/{assistantTools-D6tuc6o4.mjs → assistantTools-mEz6uNqL.mjs} +6 -6
- package/dist/{attachmentContent-DpiTJZb4.cjs → attachmentContent-GHOk6Muq.cjs} +2 -2
- package/dist/{attachmentContent-_kxRznNf.mjs → attachmentContent-s1xPha4Q.mjs} +2 -2
- package/dist/{attachmentLimits-yba1uHFO.mjs → attachmentLimits-D5pgmASK.mjs} +1 -1
- package/dist/{attachmentLimits-CzVrqgLR.cjs → attachmentLimits-DzlBPyJP.cjs} +1 -1
- package/dist/{auth-BDOVh5h5.cjs → auth-B8EagV6G.cjs} +8 -8
- package/dist/{auth-PYHZQNPp.mjs → auth-BOaHWquu.mjs} +8 -8
- package/dist/{auth-ba4WMYrN.cjs → auth-BbSdXMQ_.cjs} +5 -5
- package/dist/{auth-Cwutmdsa.mjs → auth-C8V7-oUT.mjs} +5 -5
- package/dist/{auto-BOX_fgmR.cjs → auto-Bw_h0yVc.cjs} +15 -14
- package/dist/{auto-BXu14yP_.mjs → auto-CWDOX35m.mjs} +15 -14
- package/dist/{bootstrap-hxXPCFMx.mjs → bootstrap-BKmsYSwh.mjs} +2 -2
- package/dist/{bootstrap-B5G1TijC.cjs → bootstrap-DvZjEa9_.cjs} +2 -2
- package/dist/{browser-Y6Bl8L_O.cjs → browser-CBZj-1Wx.cjs} +1 -1
- package/dist/{browser-jh2P0UVZ.mjs → browser-CrMAr5fI.mjs} +1 -1
- package/dist/{claudeLocal-CRGG4Pea.cjs → claudeLocal-Bpw-u9et.cjs} +5 -5
- package/dist/{claudeLocal-BaY4fZKi.mjs → claudeLocal-dhdlcQ6F.mjs} +5 -5
- package/dist/{claudeLocalLauncher-D4T7MTqd.mjs → claudeLocalLauncher-BFfGT4eY.mjs} +10 -10
- package/dist/{claudeLocalLauncher-DyEbVzUN.cjs → claudeLocalLauncher-DWFWuLhY.cjs} +10 -10
- package/dist/{codexThreadFork-BH9IZPqD.cjs → claudeSessionFork-D9-mANmu.cjs} +1 -137
- package/dist/{codexThreadFork-slzAseLx.mjs → claudeSessionFork-_DUrXaqd.mjs} +2 -134
- package/dist/{client-BPNbmtvO.cjs → client-CVQJWqjx.cjs} +2 -2
- package/dist/{client-3Ac-O4pw.cjs → client-DiBTHWNU.cjs} +3 -3
- package/dist/{client-CeGKqqcJ.mjs → client-Dk7x-s-O.mjs} +3 -3
- package/dist/{client-ClR0K8zX.mjs → client-DwqHDsLb.mjs} +2 -2
- package/dist/codex/happyMcpStdioBridge.cjs +15 -15
- package/dist/codex/happyMcpStdioBridge.mjs +15 -15
- package/dist/{codexAppServerClient-I3teiV-N.mjs → codexAppServerClient-C2ybs2mZ.mjs} +2 -2
- package/dist/{codexAppServerClient-q2FjnRcK.cjs → codexAppServerClient-DlKv5TjG.cjs} +2 -2
- package/dist/{codexCommand-4zcccIoq.cjs → codexCommand-4vLE31fj.cjs} +45 -40
- package/dist/{codexCommand-Cc9gcbdX.mjs → codexCommand-DnmFr9Qx.mjs} +45 -40
- package/dist/codexThreadFork-DNekT4nQ.cjs +138 -0
- package/dist/codexThreadFork-R76RU5H0.mjs +133 -0
- package/dist/{config-Ci9Kpgwa.cjs → config-Btd4B05_.cjs} +3 -3
- package/dist/{config-CTx_jb-C.mjs → config-CSOG_ZcP.mjs} +3 -3
- package/dist/{configuration-RfeNjFmd.mjs → configuration-A5gW_0GE.mjs} +1 -1
- package/dist/{configuration-BSYpcPwE.cjs → configuration-UsI0sxEv.cjs} +1 -1
- package/dist/{connect-C2CiOUFs.cjs → connect-C9yxp8Om.cjs} +13 -13
- package/dist/{connect-BpOdzNbE.mjs → connect-DWYj8LP_.mjs} +13 -13
- package/dist/{context-DsDr6E2t.cjs → context-0FjjA4vJ.cjs} +1 -1
- package/dist/{context-H0Bcb9S_.mjs → context-BXnxalWW.mjs} +1 -1
- package/dist/{controlClient-Bcwv3D21.cjs → controlClient-BXktrQ4z.cjs} +3 -3
- package/dist/{controlClient-BGbDcgWS.mjs → controlClient-CYzHrh3e.mjs} +3 -3
- package/dist/{createSessionMetadata-CVVkGjxV.mjs → createSessionMetadata-Dyg33ZlU.mjs} +2 -2
- package/dist/{createSessionMetadata-BJxEnM-o.cjs → createSessionMetadata-EX1eAlHx.cjs} +2 -2
- package/dist/{deterministicJson-CzkFJWw1.mjs → deterministicJson-DiR7EOMO.mjs} +9 -9
- package/dist/{deterministicJson-C5CYTVpm.cjs → deterministicJson-eha_oMZ2.cjs} +9 -9
- package/dist/{doctor-D2YJ-Yn2.cjs → doctor-DunLBgVi.cjs} +6 -6
- package/dist/{doctor-DOvByjbk.mjs → doctor-FuCvKdRa.mjs} +6 -6
- package/dist/{ensureDaemonRunning-BCwNrMyv.cjs → ensureDaemonRunning-B4dZFmUy.cjs} +5 -5
- package/dist/{ensureDaemonRunning-Dqa2pOjY.mjs → ensureDaemonRunning-EZkb-CAF.mjs} +5 -5
- package/dist/{handleResumeCommand-C2cKchpX.cjs → handleResumeCommand-CKMIw4pE.cjs} +5 -5
- package/dist/{handleResumeCommand-BvXYf5El.mjs → handleResumeCommand-CsXendKb.mjs} +5 -5
- package/dist/{index-DMZqWwsP.mjs → index-9L39wqYR.mjs} +37 -37
- package/dist/{index-qdS1friN.mjs → index-BBg9j0XK.mjs} +8 -1
- package/dist/{index-B6pAdvJx.cjs → index-BOhgL3rh.cjs} +36 -36
- package/dist/{index-Bu5Zi_a9.cjs → index-CZWAiydF.cjs} +4 -4
- package/dist/{index-DVkMGPyS.mjs → index-CvXcVQ06.mjs} +3 -3
- package/dist/{index-DA7yINuk.cjs → index-DJ-oV52i.cjs} +8 -1
- package/dist/{index-DKLU_fD0.mjs → index-DK2JpTJf.mjs} +4 -4
- package/dist/{index-DDeHXrIX.cjs → index-DRhWHEuW.cjs} +3 -3
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{install-CFY3tYtJ.mjs → install-B2duVo9a.mjs} +3 -3
- package/dist/{install-BgoC2e_2.cjs → install-C8WyZI9K.cjs} +3 -3
- package/dist/lib.cjs +12 -12
- package/dist/lib.d.cts +5 -0
- package/dist/lib.d.mts +5 -0
- package/dist/lib.mjs +12 -12
- package/dist/{lidState-CeEt442o.mjs → lidState-CigXWxhe.mjs} +1 -1
- package/dist/{lidState-BeDfxxEX.cjs → lidState-Ds-6ytZV.cjs} +1 -1
- package/dist/{localHappyAgentAuth-C-HQyiv6.mjs → localHappyAgentAuth-CaCyKzYp.mjs} +1 -1
- package/dist/{localHappyAgentAuth-D6rFhaoc.cjs → localHappyAgentAuth-l0Na-5Ys.cjs} +1 -1
- package/dist/{logger-CS0mw3fa.cjs → logger-7ucWm9wp.cjs} +2 -2
- package/dist/{logger-6HYUEXNk.mjs → logger-CGE4C8ho.mjs} +2 -2
- package/dist/{machineMetadata-DyDbODYd.cjs → machineMetadata-lMPtpF16.cjs} +3 -3
- package/dist/{machineMetadata-oOzBfDfs.mjs → machineMetadata-ue1nkowa.mjs} +3 -3
- package/dist/{main-BwNIAI1A.mjs → main-3fIFXD-t.mjs} +44 -44
- package/dist/{main-BkxJP6JQ.cjs → main-CFI0datL.cjs} +44 -44
- package/dist/{mcp-B1A4I3TK.mjs → mcp-DARQBZ7l.mjs} +14 -14
- package/dist/{mcp-Hszd7qpS.cjs → mcp-DfxLAc1G.cjs} +14 -14
- package/dist/{package-BwMrPwqH.cjs → package-D1A-8ZJy.cjs} +7 -7
- package/dist/{package-BhaKlnxz.mjs → package-DQsvY1XN.mjs} +7 -7
- package/dist/{peerTools-BTqw97Gb.mjs → peerTools-D19hhSQF.mjs} +4 -4
- package/dist/{peerTools-BvKtHXj8.cjs → peerTools-DLwNaEEV.cjs} +4 -4
- package/dist/{permissionMode-Cr5JCbB7.mjs → permissionMode-CH4FoZfU.mjs} +1 -1
- package/dist/{persistence-HGW_ZVs9.mjs → persistence-Cw8aLoyL.mjs} +3 -3
- package/dist/{persistence-yKTH3-5X.cjs → persistence-i0nQMLlk.cjs} +3 -3
- package/dist/{piRunnerArgs-BuX1UFWy.mjs → piRunnerArgs-58t454gw.mjs} +1 -1
- package/dist/{piRunnerArgs-BNloJCCg.cjs → piRunnerArgs-BUyxPxjZ.cjs} +1 -1
- package/dist/{piRuntime-CSGkwCKQ.mjs → piRuntime-DVPixFjl.mjs} +1 -1
- package/dist/{piRuntime-C_H7MJCM.cjs → piRuntime-Dff73XCb.cjs} +1 -1
- package/dist/{piTerminal-DNCZ6yTM.cjs → piTerminal-Dz1RrO70.cjs} +16 -16
- package/dist/{piTerminal-C8a1OrNQ.mjs → piTerminal-gHWFAyzq.mjs} +16 -16
- package/dist/{registerCommonHandlers-DskirN-_.cjs → registerCommonHandlers-CMROPdJz.cjs} +2 -2
- package/dist/{registerCommonHandlers-Ccvsz7Ou.mjs → registerCommonHandlers-Ckv5boQI.mjs} +2 -2
- package/dist/{registerKillSessionHandler-DZeLXWcB.cjs → registerKillSessionHandler-CA9-oelM.cjs} +19 -10
- package/dist/{registerKillSessionHandler-GYvHdipX.mjs → registerKillSessionHandler-Cll4-o8Y.mjs} +19 -10
- package/dist/{remoteSessionClient-CYnXRynE.mjs → remoteSessionClient-BMjsbuBh.mjs} +5 -5
- package/dist/{remoteSessionClient-B0LraSB9.cjs → remoteSessionClient-DX9jHLeW.cjs} +5 -5
- package/dist/{run-CJzxoHVh.cjs → run-CjbGo2wb.cjs} +36 -32
- package/dist/{run-D3ifupU3.mjs → run-CrunzDlt.mjs} +35 -31
- package/dist/{runClaude-Da3RirzE.cjs → runClaude-KN-4Y4LH.cjs} +184 -140
- package/dist/{runClaude-Ba01qT-u.mjs → runClaude-WDBWRtnF.mjs} +185 -141
- package/dist/{runClaudeDeps-DOzEBMls.cjs → runClaudeDeps-DW-8lnHv.cjs} +821 -125
- package/dist/{runClaudeDeps-DOt79DjU.mjs → runClaudeDeps-QaEx8y5r.mjs} +811 -129
- package/dist/{runGemini-DSr9LIxL.cjs → runGemini-Djmwjdv1.cjs} +32 -32
- package/dist/{runGemini-BGeTz57m.mjs → runGemini-Nf6SKBpw.mjs} +32 -32
- package/dist/{runOpenClaw-CogSedIc.mjs → runOpenClaw-9nHtmYbN.mjs} +18 -18
- package/dist/{runOpenClaw-B1mTxN35.cjs → runOpenClaw-CAqP5KFH.cjs} +18 -18
- package/dist/{sandbox-CG7IyDTU.cjs → sandbox-C8Dd8GPM.cjs} +4 -4
- package/dist/{sandbox-DTe6d54R.mjs → sandbox-SP0THMt0.mjs} +4 -4
- package/dist/selfCheck-7FaZtVu2.mjs +84 -0
- package/dist/{selfCheck-Dc-mNSLb.cjs → selfCheck-D9ZXrK7h.cjs} +34 -34
- package/dist/{send-CBXJKc6O.mjs → send-DOx9aQsx.mjs} +8 -8
- package/dist/{send-B7J_eaG3.cjs → send-LPk6Q5HI.cjs} +8 -8
- package/dist/{server-DcVBv04l.mjs → server-BZNi8Hq_.mjs} +4 -4
- package/dist/{server-CZTP_iOn.cjs → server-CxT8jNyn.cjs} +6 -6
- package/dist/{sessionLock-D-EG2CfG.mjs → sessionLock-CfLqJfeI.mjs} +2 -2
- package/dist/{sessionLock-Bys1PNSo.cjs → sessionLock-y9rnA4LK.cjs} +2 -2
- package/dist/{sessionModeFile-RSm0NQkH.cjs → sessionModeFile-B5YeoQJh.cjs} +1 -1
- package/dist/{sessionModeFile-DMl3dw3r.mjs → sessionModeFile-BKxgNH3P.mjs} +1 -1
- package/dist/{sessionOps-SuHW8Dfe.mjs → sessionOps-CdwVPSZz.mjs} +4 -4
- package/dist/{sessionOps-Dn8z85h_.cjs → sessionOps-GsELm2PZ.cjs} +4 -4
- package/dist/{sessionScanner-CX3onqXh.mjs → sessionScanner-Cdukzo70.mjs} +3 -3
- package/dist/{sessionScanner-BOrGjMXL.cjs → sessionScanner-aLEv7mD3.cjs} +3 -3
- package/dist/{sessions-D74aJbhL.cjs → sessions-CfG4WGN0.cjs} +9 -9
- package/dist/{sessions-BEG_HTSi.mjs → sessions-Dne-OiRL.mjs} +9 -9
- package/dist/{setupOfflineReconnection-ByElY60m.cjs → setupOfflineReconnection-CFwltTcP.cjs} +2 -2
- package/dist/{setupOfflineReconnection-DpvWTt69.mjs → setupOfflineReconnection-DiQma2Cc.mjs} +2 -2
- package/dist/{spawn-DgR0RKRs.cjs → spawn-BI_sdgWs.cjs} +24 -15
- package/dist/{spawn-B7yro0b2.mjs → spawn-DkgP2BGF.mjs} +22 -14
- package/dist/{spawnAgents-DZzZ9jMI.mjs → spawnAgents-Y1LjnCt9.mjs} +1 -1
- package/dist/{spawnAgents-BGQiEF-w.cjs → spawnAgents-iSu1Xzs5.cjs} +1 -1
- package/dist/{spawnHappyCLI-B2H5s4B_.mjs → spawnHappyCLI-9mx4lPxh.mjs} +1 -1
- package/dist/{spawnHappyCLI-DBhwZT7O.cjs → spawnHappyCLI-BRdx0sAX.cjs} +1 -1
- package/dist/{startFileWatcher-B4VsLgjD.cjs → startFileWatcher-C2HC2_Dg.cjs} +1 -1
- package/dist/{startFileWatcher-DErVWZE4.mjs → startFileWatcher-COD5UKNs.mjs} +1 -1
- package/dist/{streamRelay-FPVbHpbM.mjs → streamRelay-BLgU9X3R.mjs} +1 -1
- package/dist/{streamRelay-BiKw59Cc.cjs → streamRelay-DnObXZZj.cjs} +1 -1
- package/dist/{sync-C8gyQFMc.mjs → sync-BpLasLu2.mjs} +1 -1
- package/dist/{sync-DccIKZ5_.cjs → sync-Dj92ZJ8Y.cjs} +1 -1
- package/dist/{systemPrompt-BwTPWfMu.cjs → systemPrompt-CyEz_IfR.cjs} +2 -2
- package/dist/{systemPrompt-DX521JJz.mjs → systemPrompt-DsQoUgQw.mjs} +2 -2
- package/dist/{teams-C32F1hqd.mjs → teams-BETNMjpZ.mjs} +6 -6
- package/dist/{teams-Dl8g8kTI.cjs → teams-Ctx9zXn4.cjs} +6 -6
- package/dist/{time-DCuTyook.cjs → time-CLwVAz6s.cjs} +1 -1
- package/dist/{time-D0XyHOid.mjs → time-CVvxdEDh.mjs} +1 -1
- package/dist/{titleGenerator-CQ8CoGhg.mjs → titleGenerator-B4AW3dLr.mjs} +12 -2
- package/dist/{titleGenerator-ChzMJsyg.cjs → titleGenerator-FDpdizn7.cjs} +13 -3
- package/dist/{todo-BvUOTa8G.cjs → todo-C3tyFeq1.cjs} +6 -6
- package/dist/{todo-CZ6cFrrn.mjs → todo-Jk4Vs7hP.mjs} +6 -6
- package/dist/{tools-BZtHF_qQ.mjs → tools-BA1qkiV1.mjs} +2 -2
- package/dist/{tools-DQj0AeLk.cjs → tools-CGxq3I52.cjs} +2 -2
- package/dist/{tools-Be3AoAwu.cjs → tools-O5beDK-s.cjs} +1 -1
- package/dist/{tools-DkluDcG4.mjs → tools-_kFe4m_l.mjs} +1 -1
- package/dist/{uninstall-BkLzaJ6I.mjs → uninstall-C_mdAZlm.mjs} +3 -3
- package/dist/{uninstall-x-TUtf5H.cjs → uninstall-DHKF90lo.cjs} +3 -3
- package/package.json +7 -7
- package/scripts/session_hook_forwarder.cjs +9 -2
- package/dist/selfCheck-C9mVrQwf.mjs +0 -84
|
@@ -1,46 +1,48 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var logger = require('./logger-
|
|
4
|
-
var controlClient = require('./controlClient-
|
|
3
|
+
var logger = require('./logger-7ucWm9wp.cjs');
|
|
4
|
+
var controlClient = require('./controlClient-BXktrQ4z.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-CyEz_IfR.cjs');
|
|
12
12
|
var path$1 = require('node:path');
|
|
13
13
|
var specialCommands = require('./specialCommands-DSsTeRej.cjs');
|
|
14
14
|
require('axios');
|
|
15
15
|
require('node:events');
|
|
16
16
|
require('socket.io-client');
|
|
17
|
-
var attachmentLimits = require('./attachmentLimits-
|
|
17
|
+
var attachmentLimits = require('./attachmentLimits-DzlBPyJP.cjs');
|
|
18
18
|
require('tweetnacl');
|
|
19
|
-
var configuration = require('./configuration-
|
|
20
|
-
require('./index-
|
|
21
|
-
require('./registerCommonHandlers-
|
|
19
|
+
var configuration = require('./configuration-UsI0sxEv.cjs');
|
|
20
|
+
require('./index-DJ-oV52i.cjs');
|
|
21
|
+
require('./registerCommonHandlers-CMROPdJz.cjs');
|
|
22
22
|
require('os');
|
|
23
23
|
require('child_process');
|
|
24
24
|
require('@paralleldrive/cuid2');
|
|
25
|
-
require('./persistence-
|
|
25
|
+
require('./persistence-i0nQMLlk.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-CLwVAz6s.cjs');
|
|
32
|
+
var node_fs = require('node:fs');
|
|
33
|
+
var deterministicJson = require('./deterministicJson-eha_oMZ2.cjs');
|
|
34
|
+
var sessionScanner = require('./sessionScanner-aLEv7mD3.cjs');
|
|
33
35
|
var node_child_process = require('node:child_process');
|
|
34
|
-
var streamRelay = require('./streamRelay-
|
|
35
|
-
var attachmentContent = require('./attachmentContent-
|
|
36
|
-
var
|
|
37
|
-
var
|
|
38
|
-
var
|
|
36
|
+
var streamRelay = require('./streamRelay-DnObXZZj.cjs');
|
|
37
|
+
var attachmentContent = require('./attachmentContent-GHOk6Muq.cjs');
|
|
38
|
+
var promises = require('node:fs/promises');
|
|
39
|
+
var claudeSessionFork = require('./claudeSessionFork-D9-mANmu.cjs');
|
|
40
|
+
var registerKillSessionHandler = require('./registerKillSessionHandler-CA9-oelM.cjs');
|
|
41
|
+
var doctor = require('./doctor-DunLBgVi.cjs');
|
|
39
42
|
var node_http = require('node:http');
|
|
40
43
|
var editPaths = require('./editPaths-Bqp4OFPw.cjs');
|
|
41
|
-
var node_fs = require('node:fs');
|
|
42
44
|
var projectPath = require('./projectPath-ChLhdOyt.cjs');
|
|
43
|
-
var titleGenerator = require('./titleGenerator-
|
|
45
|
+
var titleGenerator = require('./titleGenerator-FDpdizn7.cjs');
|
|
44
46
|
var oneShotPrompts = require('./oneShotPrompts-CL0dip9C.cjs');
|
|
45
47
|
require('node:util');
|
|
46
48
|
require('./smallFastModel-D_uxGMo3.cjs');
|
|
@@ -48,34 +50,34 @@ require('./trimIdent-4gvk9Wk6.cjs');
|
|
|
48
50
|
require('node:os');
|
|
49
51
|
require('./agentGuidance-B5NATuFa.cjs');
|
|
50
52
|
require('zod');
|
|
51
|
-
require('./package-
|
|
52
|
-
require('node:fs/promises');
|
|
53
|
+
require('./package-D1A-8ZJy.cjs');
|
|
53
54
|
require('util');
|
|
54
55
|
require('crypto');
|
|
55
56
|
require('path');
|
|
56
57
|
require('cross-spawn');
|
|
57
58
|
require('./authRelay-BdYkC1Po.cjs');
|
|
58
|
-
require('./
|
|
59
|
-
require('./
|
|
60
|
-
require('./
|
|
61
|
-
require('./context-DsDr6E2t.cjs');
|
|
62
|
-
require('./sessionOps-Dn8z85h_.cjs');
|
|
59
|
+
require('./client-DiBTHWNU.cjs');
|
|
60
|
+
require('./context-0FjjA4vJ.cjs');
|
|
61
|
+
require('./sessionOps-GsELm2PZ.cjs');
|
|
63
62
|
require('./resources-JDPugcDq.cjs');
|
|
64
|
-
require('./tools-
|
|
65
|
-
require('./tools-
|
|
66
|
-
require('./client-
|
|
67
|
-
require('./peerTools-
|
|
63
|
+
require('./tools-O5beDK-s.cjs');
|
|
64
|
+
require('./tools-CGxq3I52.cjs');
|
|
65
|
+
require('./client-CVQJWqjx.cjs');
|
|
66
|
+
require('./peerTools-DLwNaEEV.cjs');
|
|
68
67
|
require('./ids-B6ZC0HGt.cjs');
|
|
69
|
-
require('./remoteSessionClient-
|
|
68
|
+
require('./remoteSessionClient-DX9jHLeW.cjs');
|
|
70
69
|
require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
71
70
|
require('@modelcontextprotocol/sdk/server/streamableHttp.js');
|
|
72
71
|
require('./limits-C-a7gr04.cjs');
|
|
73
|
-
require('./assistantTools-
|
|
72
|
+
require('./assistantTools-CwESq24n.cjs');
|
|
74
73
|
require('./terminals-B_bfC9c2.cjs');
|
|
75
74
|
require('./terminalTitleSuggest-DhvRFX3H.cjs');
|
|
76
75
|
require('./tmuxSocket-D-Xt6Vn-.cjs');
|
|
77
|
-
require('./bootstrap-
|
|
76
|
+
require('./bootstrap-DvZjEa9_.cjs');
|
|
78
77
|
require('./previewPath-B0rBdhy1.cjs');
|
|
78
|
+
require('./sync-Dj92ZJ8Y.cjs');
|
|
79
|
+
require('./startFileWatcher-C2HC2_Dg.cjs');
|
|
80
|
+
require('node:readline');
|
|
79
81
|
require('./doctor-u46qYYKX.cjs');
|
|
80
82
|
require('ps-list');
|
|
81
83
|
require('./doctorReadiness-BCZGcN0a.cjs');
|
|
@@ -143,6 +145,20 @@ class Session {
|
|
|
143
145
|
steerHandler = null;
|
|
144
146
|
/** B-482: the live remote Query's in-process side-question entry; null between Queries and in local mode. */
|
|
145
147
|
sideQuestionLive = null;
|
|
148
|
+
/** B-515: consumed by the first remote launch; later launches never prewarm. */
|
|
149
|
+
claudePrewarm = null;
|
|
150
|
+
/** Hand the prewarm lease to the first remote launch — once per process. */
|
|
151
|
+
takeClaudePrewarm = () => {
|
|
152
|
+
const factory = this.claudePrewarm;
|
|
153
|
+
this.claudePrewarm = null;
|
|
154
|
+
if (!factory || this.sessionId) return null;
|
|
155
|
+
try {
|
|
156
|
+
return factory();
|
|
157
|
+
} catch (error) {
|
|
158
|
+
logger.logger.debug("[Session] Claude prewarm setup failed:", error);
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
146
162
|
/** Callbacks to be notified when session ID is found/changed */
|
|
147
163
|
sessionFoundCallbacks = [];
|
|
148
164
|
/** Keep alive interval reference for cleanup */
|
|
@@ -163,6 +179,7 @@ class Session {
|
|
|
163
179
|
this._onAbort = opts.onAbort;
|
|
164
180
|
this.hookSettingsPath = opts.hookSettingsPath;
|
|
165
181
|
this.jsRuntime = opts.jsRuntime ?? "node";
|
|
182
|
+
this.claudePrewarm = opts.claudePrewarm ?? null;
|
|
166
183
|
try {
|
|
167
184
|
this.notificationProducer = opts.api.notificationProducer(
|
|
168
185
|
opts.client.sessionId,
|
|
@@ -697,6 +714,285 @@ function modelSwitchFailureNotice(model, error) {
|
|
|
697
714
|
return `\u26A0\uFE0F Could not switch to model "${name}" \u2014 continuing with the previous model. ${detail}`;
|
|
698
715
|
}
|
|
699
716
|
|
|
717
|
+
const SDK_TIMING_FIELDS = ["ttft_ms", "time_to_request_ms", "time_to_request_from_spawn_ms"];
|
|
718
|
+
function delta(from, to) {
|
|
719
|
+
if (typeof from !== "number" || typeof to !== "number" || to < from) return "-";
|
|
720
|
+
return `${Math.round(to - from)}ms`;
|
|
721
|
+
}
|
|
722
|
+
function sdkField(result, key) {
|
|
723
|
+
if (!result || typeof result !== "object") return "-";
|
|
724
|
+
const value = result[key];
|
|
725
|
+
return typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}` : "-";
|
|
726
|
+
}
|
|
727
|
+
function formatClaudeTimingLine(input) {
|
|
728
|
+
const m = input.marks;
|
|
729
|
+
const sdk = SDK_TIMING_FIELDS.map((key) => `${key}=${sdkField(input.result, key)}`).join(",");
|
|
730
|
+
return [
|
|
731
|
+
"[CLAUDE TIMING]",
|
|
732
|
+
`turn=${input.turn}`,
|
|
733
|
+
`firstTurnOfProcess=${input.firstTurnOfProcess}`,
|
|
734
|
+
`pushed\u2192spawn=${delta(m.pushedAt, m.spawnAt)}`,
|
|
735
|
+
`spawn\u2192handshake=${delta(m.spawnAt, m.handshakeAt)}`,
|
|
736
|
+
`handshake\u2192init=${delta(m.handshakeAt, m.initAt)}`,
|
|
737
|
+
`init\u2192firstAssistant=${delta(m.initAt, m.firstAssistantAt)}`,
|
|
738
|
+
`pushed\u2192firstAssistant=${delta(m.pushedAt, m.firstAssistantAt)}`,
|
|
739
|
+
`sdk{${sdk}}`,
|
|
740
|
+
...input.prewarm ? [`prewarm=${input.prewarm}`] : []
|
|
741
|
+
].join(" ");
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function claudeModeHash(mode) {
|
|
745
|
+
return deterministicJson.hashObject({
|
|
746
|
+
isPlan: mode.permissionMode === "plan",
|
|
747
|
+
fallbackModel: mode.fallbackModel,
|
|
748
|
+
customSystemPrompt: mode.customSystemPrompt,
|
|
749
|
+
appendSystemPrompt: mode.appendSystemPrompt,
|
|
750
|
+
allowedTools: mode.allowedTools,
|
|
751
|
+
disallowedTools: mode.disallowedTools,
|
|
752
|
+
effort: mode.effort
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
const CLAUDE_PREWARM_IDLE_MS = 15 * 60 * 1e3;
|
|
757
|
+
const CLAUDE_PREWARM_MAX_CONCURRENT = 2;
|
|
758
|
+
const CLAUDE_PREWARM_ADOPT_TIMEOUT_MS = 5e3;
|
|
759
|
+
const PREWARM_HOOK_SOURCE_PREFIX = "prewarm-";
|
|
760
|
+
const BAD_AUTH_STATUSES = /* @__PURE__ */ new Set(["not-logged-in", "error", "claude-missing"]);
|
|
761
|
+
const RESUME_ARGS = /* @__PURE__ */ new Set(["--resume", "-r", "--continue", "-c", "--fork-session", "--session-id"]);
|
|
762
|
+
const CLAUDE_PREWARM_MAX_CONSECUTIVE_MISSES = 5;
|
|
763
|
+
function claudePrewarmSessionEligibility(input) {
|
|
764
|
+
const { env } = input;
|
|
765
|
+
const no = (reason) => ({ eligible: false, reason });
|
|
766
|
+
if (env.HAPPY_CLAUDE_PREWARM === "0") return no("env-off");
|
|
767
|
+
if (input.setting === "off") return no("setting-off");
|
|
768
|
+
if (input.startedBy !== "daemon") return no("not-daemon");
|
|
769
|
+
if (input.startingMode !== "remote") return no("not-remote");
|
|
770
|
+
if (env.HAPPY_RECONNECT_SESSION_ID) return no("reconnect");
|
|
771
|
+
if (env.HAPPY_FORK_CLAUDE_SESSION_ID || env.HAPPY_FORKED_FROM_SESSION_ID) return no("fork");
|
|
772
|
+
if (env.HAPPY_IMPORTED_FROM_CLAUDE_SESSION_ID) return no("import");
|
|
773
|
+
if (env.HAPPY_SESSION_VARIANT === "assistant") return no("assistant");
|
|
774
|
+
if (env.VH_TEAM_OPERATION_ID) return no("teams");
|
|
775
|
+
if (env.VH_AUTOMATION_RUN_ID) return no("automation");
|
|
776
|
+
if (env.HAPPY_SPAWNED_BY) return no("spawned-by");
|
|
777
|
+
if (env.HAPPY_FIRST_MESSAGE_FROM_CLI === "1") return no("cli-first-message");
|
|
778
|
+
if (input.claudeArgs?.some((arg) => RESUME_ARGS.has(arg))) return no("resume-args");
|
|
779
|
+
if (env.HAPPY_CLAUDE_AUTH_STATUS && BAD_AUTH_STATUSES.has(env.HAPPY_CLAUDE_AUTH_STATUS)) return no("claude-auth");
|
|
780
|
+
return { eligible: true };
|
|
781
|
+
}
|
|
782
|
+
function claudePrewarmEligibility(input) {
|
|
783
|
+
const session = claudePrewarmSessionEligibility(input);
|
|
784
|
+
if (!session.eligible) return session;
|
|
785
|
+
if (!input.cache?.appendSystemPrompt) return { eligible: false, reason: "no-cached-system-prompt" };
|
|
786
|
+
if (input.cache.consecutiveMisses >= CLAUDE_PREWARM_MAX_CONSECUTIVE_MISSES) return { eligible: false, reason: "recent-misses" };
|
|
787
|
+
return { eligible: true };
|
|
788
|
+
}
|
|
789
|
+
function prewarmCacheFile(happyHomeDir) {
|
|
790
|
+
return path$1.join(happyHomeDir, "claude-prewarm.json");
|
|
791
|
+
}
|
|
792
|
+
function readPrewarmCache(file) {
|
|
793
|
+
try {
|
|
794
|
+
const raw = JSON.parse(node_fs.readFileSync(file, "utf8"));
|
|
795
|
+
if (typeof raw?.appendSystemPrompt !== "string" || raw.appendSystemPrompt.length === 0) return null;
|
|
796
|
+
const misses = typeof raw.consecutiveMisses === "number" && Number.isFinite(raw.consecutiveMisses) && raw.consecutiveMisses > 0 ? Math.floor(raw.consecutiveMisses) : 0;
|
|
797
|
+
return {
|
|
798
|
+
appendSystemPrompt: raw.appendSystemPrompt,
|
|
799
|
+
...typeof raw.effort === "string" || raw.effort === null ? { effort: raw.effort } : {},
|
|
800
|
+
consecutiveMisses: misses
|
|
801
|
+
};
|
|
802
|
+
} catch {
|
|
803
|
+
return null;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
function writePrewarmCache(file, cache) {
|
|
807
|
+
try {
|
|
808
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
809
|
+
node_fs.writeFileSync(tmp, JSON.stringify({ ...cache, updatedAt: Date.now() }), { mode: 384 });
|
|
810
|
+
node_fs.renameSync(tmp, file);
|
|
811
|
+
return true;
|
|
812
|
+
} catch {
|
|
813
|
+
return false;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
function prewarmPredictionMeta(cache) {
|
|
817
|
+
return {
|
|
818
|
+
appendSystemPrompt: cache.appendSystemPrompt,
|
|
819
|
+
...cache.effort !== void 0 ? { effort: cache.effort } : {}
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
function evaluatePrewarmPrediction(input) {
|
|
823
|
+
const outcome = input.predicted === null ? "no-prediction" : claudeModeHash(input.predicted) === claudeModeHash(input.actual) ? "hit" : "miss";
|
|
824
|
+
const append = input.meta?.appendSystemPrompt;
|
|
825
|
+
const misses = outcome === "miss" ? (input.previous?.consecutiveMisses ?? 0) + 1 : 0;
|
|
826
|
+
if (typeof append !== "string" || append.length === 0) {
|
|
827
|
+
return { outcome, next: input.previous ? { ...input.previous, consecutiveMisses: misses } : null };
|
|
828
|
+
}
|
|
829
|
+
const hasEffort = !!input.meta && Object.prototype.hasOwnProperty.call(input.meta, "effort");
|
|
830
|
+
return {
|
|
831
|
+
outcome,
|
|
832
|
+
next: {
|
|
833
|
+
appendSystemPrompt: append,
|
|
834
|
+
...hasEffort ? { effort: input.meta.effort ?? null } : {},
|
|
835
|
+
consecutiveMisses: misses
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
function prewarmSlotDir(happyHomeDir) {
|
|
840
|
+
return path$1.join(happyHomeDir, "tmp", "claude-prewarm");
|
|
841
|
+
}
|
|
842
|
+
function acquirePrewarmSlot(dir, opts = {}) {
|
|
843
|
+
const max = opts.max ?? CLAUDE_PREWARM_MAX_CONCURRENT;
|
|
844
|
+
const pid = opts.pid ?? process.pid;
|
|
845
|
+
const isAlive = opts.isAlive ?? pidAlive;
|
|
846
|
+
const now = opts.now ?? Date.now();
|
|
847
|
+
const staleMs = opts.staleMs ?? CLAUDE_PREWARM_IDLE_MS + 6e4;
|
|
848
|
+
try {
|
|
849
|
+
node_fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
850
|
+
} catch {
|
|
851
|
+
return null;
|
|
852
|
+
}
|
|
853
|
+
for (let i = 0; i < max; i++) {
|
|
854
|
+
const path = path$1.join(dir, `slot-${i}.lock`);
|
|
855
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
856
|
+
try {
|
|
857
|
+
node_fs.writeFileSync(path, String(pid), { flag: "wx", mode: 384 });
|
|
858
|
+
let released = false;
|
|
859
|
+
return {
|
|
860
|
+
path,
|
|
861
|
+
release: () => {
|
|
862
|
+
if (released) return;
|
|
863
|
+
released = true;
|
|
864
|
+
try {
|
|
865
|
+
if (node_fs.readFileSync(path, "utf8").trim() === String(pid)) node_fs.unlinkSync(path);
|
|
866
|
+
} catch {
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
} catch (error) {
|
|
871
|
+
if (error?.code !== "EEXIST") return null;
|
|
872
|
+
if (!slotIsStale(path, { isAlive, now, staleMs }) || attempt > 0) break;
|
|
873
|
+
try {
|
|
874
|
+
node_fs.unlinkSync(path);
|
|
875
|
+
} catch {
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
return null;
|
|
881
|
+
}
|
|
882
|
+
function slotIsStale(path, opts) {
|
|
883
|
+
try {
|
|
884
|
+
const owner = Number(node_fs.readFileSync(path, "utf8").trim());
|
|
885
|
+
if (!Number.isInteger(owner) || owner <= 0 || !opts.isAlive(owner)) return true;
|
|
886
|
+
return opts.now - node_fs.statSync(path).mtimeMs > opts.staleMs;
|
|
887
|
+
} catch {
|
|
888
|
+
return !node_fs.existsSync(path);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
function pidAlive(pid) {
|
|
892
|
+
try {
|
|
893
|
+
process.kill(pid, 0);
|
|
894
|
+
return true;
|
|
895
|
+
} catch (error) {
|
|
896
|
+
return error?.code === "EPERM";
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
class PrewarmHookGate {
|
|
900
|
+
next = 0;
|
|
901
|
+
adopted = /* @__PURE__ */ new Set();
|
|
902
|
+
newTag() {
|
|
903
|
+
return `${PREWARM_HOOK_SOURCE_PREFIX}${process.pid}-${this.next++}`;
|
|
904
|
+
}
|
|
905
|
+
adopt(tag) {
|
|
906
|
+
this.adopted.add(tag);
|
|
907
|
+
}
|
|
908
|
+
/** Untagged hooks (the ordinary per-process settings file) always pass. */
|
|
909
|
+
accepts(source) {
|
|
910
|
+
if (!source || !source.startsWith(PREWARM_HOOK_SOURCE_PREFIX)) return true;
|
|
911
|
+
return this.adopted.has(source);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
function decideWarmAdoption(input) {
|
|
915
|
+
if (input.specialCommand === "clear") return { adopt: false, reason: "clear" };
|
|
916
|
+
if (input.specialCommand === "compact") return { adopt: false, reason: "compact" };
|
|
917
|
+
if (claudeModeHash(input.predicted) !== claudeModeHash(input.actual)) return { adopt: false, reason: "mode-mismatch" };
|
|
918
|
+
const warmPermission = permissionMode.mapToClaudeMode(input.predicted.permissionMode);
|
|
919
|
+
const wantedPermission = permissionMode.mapToClaudeMode(input.actual.permissionMode);
|
|
920
|
+
return {
|
|
921
|
+
adopt: true,
|
|
922
|
+
...warmPermission !== wantedPermission ? { setPermissionMode: wantedPermission } : {},
|
|
923
|
+
switchModel: needsModelSwitch(input.predicted.model, input.actual.model)
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
function formatPrewarmLine(event, detail) {
|
|
927
|
+
if (event === "discarded" || event === "skipped") {
|
|
928
|
+
return `[CLAUDE PREWARM] ${event}(${typeof detail === "string" ? detail : "unknown"})`;
|
|
929
|
+
}
|
|
930
|
+
const fields = detail && typeof detail === "object" ? Object.entries(detail).filter(([, v]) => v !== void 0).map(([k, v]) => ` ${k}=${v}`).join("") : "";
|
|
931
|
+
return `[CLAUDE PREWARM] ${event}${fields}`;
|
|
932
|
+
}
|
|
933
|
+
const liveLeases = /* @__PURE__ */ new Set();
|
|
934
|
+
let exitHookInstalled = false;
|
|
935
|
+
function disposeAllClaudePrewarms(reason) {
|
|
936
|
+
for (const lease of [...liveLeases]) lease.discard(reason);
|
|
937
|
+
}
|
|
938
|
+
function createClaudePrewarmLease(input) {
|
|
939
|
+
let state = "warm";
|
|
940
|
+
let teardown = null;
|
|
941
|
+
const lease = {
|
|
942
|
+
mode: input.mode,
|
|
943
|
+
hookSettingsPath: input.hookSettingsPath,
|
|
944
|
+
tag: input.tag,
|
|
945
|
+
idleMs: input.idleMs ?? CLAUDE_PREWARM_IDLE_MS,
|
|
946
|
+
adoptTimeoutMs: input.adoptTimeoutMs ?? CLAUDE_PREWARM_ADOPT_TIMEOUT_MS,
|
|
947
|
+
adopt: () => {
|
|
948
|
+
if (state !== "warm") return;
|
|
949
|
+
state = "adopted";
|
|
950
|
+
teardown = null;
|
|
951
|
+
input.gate.adopt(input.tag);
|
|
952
|
+
input.slot.release();
|
|
953
|
+
liveLeases.delete(lease);
|
|
954
|
+
},
|
|
955
|
+
discard: (reason) => {
|
|
956
|
+
if (state !== "warm") return;
|
|
957
|
+
state = "closed";
|
|
958
|
+
const t = teardown;
|
|
959
|
+
teardown = null;
|
|
960
|
+
liveLeases.delete(lease);
|
|
961
|
+
try {
|
|
962
|
+
t?.(reason);
|
|
963
|
+
} catch {
|
|
964
|
+
}
|
|
965
|
+
input.slot.release();
|
|
966
|
+
input.cleanupHookSettings();
|
|
967
|
+
input.log(formatPrewarmLine("discarded", reason));
|
|
968
|
+
},
|
|
969
|
+
setTeardown: (next) => {
|
|
970
|
+
if (state === "warm") teardown = next;
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
liveLeases.add(lease);
|
|
974
|
+
if (!exitHookInstalled) {
|
|
975
|
+
exitHookInstalled = true;
|
|
976
|
+
process.once("exit", () => disposeAllClaudePrewarms("exit"));
|
|
977
|
+
}
|
|
978
|
+
return lease;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
function withTimeout(promise, ms) {
|
|
982
|
+
promise.catch(() => {
|
|
983
|
+
});
|
|
984
|
+
let timer;
|
|
985
|
+
const timeout = new Promise((_, reject) => {
|
|
986
|
+
timer = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);
|
|
987
|
+
});
|
|
988
|
+
return Promise.race([promise, timeout]).finally(() => {
|
|
989
|
+
if (timer) clearTimeout(timer);
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
const PROMPT_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
993
|
+
function promptUuid(uuid) {
|
|
994
|
+
return uuid && PROMPT_UUID_RE.test(uuid) ? { uuid } : {};
|
|
995
|
+
}
|
|
700
996
|
async function claudeRemote(opts) {
|
|
701
997
|
let startFrom = opts.sessionId;
|
|
702
998
|
if (opts.sessionId && !systemPrompt.claudeCheckSession(opts.sessionId, opts.path)) {
|
|
@@ -727,13 +1023,153 @@ async function claudeRemote(opts) {
|
|
|
727
1023
|
process.env[key] = value;
|
|
728
1024
|
});
|
|
729
1025
|
}
|
|
730
|
-
|
|
1026
|
+
let thinking = false;
|
|
1027
|
+
const updateThinking = (newThinking) => {
|
|
1028
|
+
if (thinking !== newThinking) {
|
|
1029
|
+
thinking = newThinking;
|
|
1030
|
+
logger.logger.debug(`[claudeRemote] Thinking state changed to: ${thinking}`);
|
|
1031
|
+
if (opts.onThinkingChange) {
|
|
1032
|
+
opts.onThinkingChange(thinking);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
let callbackDepth = 0;
|
|
1037
|
+
const guardCallback = (callback) => (async (...args) => {
|
|
1038
|
+
callbackDepth++;
|
|
1039
|
+
try {
|
|
1040
|
+
return await callback(...args);
|
|
1041
|
+
} finally {
|
|
1042
|
+
setImmediate(() => {
|
|
1043
|
+
callbackDepth--;
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
});
|
|
1047
|
+
let mode = opts.prewarm?.mode ?? { permissionMode: "default" };
|
|
1048
|
+
const buildSdkOptions = (creationMode, io) => {
|
|
1049
|
+
const sdkOptions = {
|
|
1050
|
+
cwd: opts.path,
|
|
1051
|
+
resume: startFrom ?? void 0,
|
|
1052
|
+
mcpServers: opts.mcpServers,
|
|
1053
|
+
permissionMode: permissionMode.mapToClaudeMode(creationMode.permissionMode),
|
|
1054
|
+
// This is only the SDK safety opt-in; permissionMode/canUseTool still
|
|
1055
|
+
// enforce the selected policy. It must be enabled at Query creation so
|
|
1056
|
+
// a later explicit live switch to bypassPermissions can succeed.
|
|
1057
|
+
allowDangerouslySkipPermissions: true,
|
|
1058
|
+
model: creationMode.model,
|
|
1059
|
+
fallbackModel: creationMode.fallbackModel,
|
|
1060
|
+
customSystemPrompt: creationMode.customSystemPrompt ? creationMode.customSystemPrompt + "\n\n" + systemPrompt.systemPrompt : void 0,
|
|
1061
|
+
appendSystemPrompt: creationMode.appendSystemPrompt ? creationMode.appendSystemPrompt + "\n\n" + systemPrompt.systemPrompt : systemPrompt.systemPrompt,
|
|
1062
|
+
allowedTools: creationMode.allowedTools ? creationMode.allowedTools.concat(opts.allowedTools) : opts.allowedTools,
|
|
1063
|
+
additionalDirectories: opts.additionalDirectories,
|
|
1064
|
+
disallowedTools: creationMode.disallowedTools,
|
|
1065
|
+
effort: creationMode.effort,
|
|
1066
|
+
canCallTool: (toolName, input, options) => opts.canCallTool(toolName, input, mode, options),
|
|
1067
|
+
onElicitation: opts.onElicitation,
|
|
1068
|
+
onUserDialog: opts.onUserDialog,
|
|
1069
|
+
supportedDialogKinds: opts.onUserDialog ? ["refusal_fallback_prompt"] : void 0,
|
|
1070
|
+
abort: io.abort,
|
|
1071
|
+
settingsPath: io.settingsPath,
|
|
1072
|
+
// B-309: token-level partials. Without this the SDK emits nothing
|
|
1073
|
+
// between "turn started" and "entire assistant message", which is
|
|
1074
|
+
// exactly why the web used to show a spinner where the terminal shows
|
|
1075
|
+
// the model thinking out loud. The partials do NOT enter the
|
|
1076
|
+
// transcript; they are split off below and relayed on a side channel.
|
|
1077
|
+
// Only pay for them when someone is listening.
|
|
1078
|
+
includePartialMessages: opts.onStreamFrame ? true : void 0
|
|
1079
|
+
};
|
|
1080
|
+
if (sdkOptions.canCallTool) sdkOptions.canCallTool = guardCallback(sdkOptions.canCallTool);
|
|
1081
|
+
if (sdkOptions.onElicitation) sdkOptions.onElicitation = guardCallback(sdkOptions.onElicitation);
|
|
1082
|
+
if (sdkOptions.onUserDialog) sdkOptions.onUserDialog = guardCallback(sdkOptions.onUserDialog);
|
|
1083
|
+
return sdkOptions;
|
|
1084
|
+
};
|
|
1085
|
+
const discoverModels = async (q) => {
|
|
1086
|
+
if (typeof q.supportedModels !== "function") return void 0;
|
|
1087
|
+
return (await q.supportedModels()).map((model) => ({
|
|
1088
|
+
code: model.value,
|
|
1089
|
+
value: model.displayName,
|
|
1090
|
+
description: model.description,
|
|
1091
|
+
resolvedModel: model.resolvedModel,
|
|
1092
|
+
...model.supportsEffort === false ? { reasoningEfforts: [] } : model.supportedEffortLevels ? { reasoningEfforts: model.supportedEffortLevels } : {}
|
|
1093
|
+
}));
|
|
1094
|
+
};
|
|
1095
|
+
let warm = null;
|
|
1096
|
+
if (opts.prewarm && startFrom) {
|
|
1097
|
+
opts.prewarm.discard("resume");
|
|
1098
|
+
} else if (opts.prewarm && opts.signal?.aborted) {
|
|
1099
|
+
opts.prewarm.discard("aborted");
|
|
1100
|
+
} else if (opts.prewarm) {
|
|
1101
|
+
const lease = opts.prewarm;
|
|
1102
|
+
const abort = new AbortController();
|
|
1103
|
+
const onOuterAbort = () => abort.abort();
|
|
1104
|
+
opts.signal?.addEventListener("abort", onOuterAbort, { once: true });
|
|
1105
|
+
const messages2 = new PushableAsyncIterable();
|
|
1106
|
+
const startedAt = Date.now();
|
|
1107
|
+
try {
|
|
1108
|
+
const response2 = index.query({
|
|
1109
|
+
prompt: messages2,
|
|
1110
|
+
options: buildSdkOptions(lease.mode, { settingsPath: lease.hookSettingsPath, abort: abort.signal })
|
|
1111
|
+
});
|
|
1112
|
+
const handshake = discoverModels(response2).then(
|
|
1113
|
+
(models2) => ({ ok: true, models: models2, at: Date.now() }),
|
|
1114
|
+
() => ({ ok: false, at: Date.now() })
|
|
1115
|
+
);
|
|
1116
|
+
const w = { response: response2, messages: messages2, lease, startedAt, handshake };
|
|
1117
|
+
lease.setTeardown(() => {
|
|
1118
|
+
if (w.idleTimer) clearTimeout(w.idleTimer);
|
|
1119
|
+
try {
|
|
1120
|
+
w.offExit?.();
|
|
1121
|
+
} catch {
|
|
1122
|
+
}
|
|
1123
|
+
opts.signal?.removeEventListener("abort", onOuterAbort);
|
|
1124
|
+
if (warm === w) warm = null;
|
|
1125
|
+
messages2.end();
|
|
1126
|
+
abort.abort();
|
|
1127
|
+
});
|
|
1128
|
+
w.idleTimer = setTimeout(() => lease.discard("idle"), lease.idleMs);
|
|
1129
|
+
w.idleTimer.unref?.();
|
|
1130
|
+
void handshake.then((result) => {
|
|
1131
|
+
if (!result.ok) {
|
|
1132
|
+
lease.discard("handshake-failed");
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
if (warm !== w) return;
|
|
1136
|
+
try {
|
|
1137
|
+
const transport = response2.transport;
|
|
1138
|
+
const off = transport?.onExit?.(() => {
|
|
1139
|
+
if (warm === w) lease.discard("exited");
|
|
1140
|
+
});
|
|
1141
|
+
if (typeof off === "function") w.offExit = off;
|
|
1142
|
+
} catch {
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
warm = w;
|
|
1146
|
+
logger.logger.debug(formatPrewarmLine("started", { tag: lease.tag }));
|
|
1147
|
+
} catch (error) {
|
|
1148
|
+
opts.signal?.removeEventListener("abort", onOuterAbort);
|
|
1149
|
+
logger.logger.debug(`[claudeRemote] prewarm query() threw: ${error instanceof Error ? error.message : String(error)}`);
|
|
1150
|
+
lease.discard("spawn-failed");
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
const discardWarm = (reason) => {
|
|
1154
|
+
warm?.lease.discard(reason);
|
|
1155
|
+
};
|
|
1156
|
+
let initial;
|
|
1157
|
+
try {
|
|
1158
|
+
initial = await opts.nextMessage();
|
|
1159
|
+
} catch (error) {
|
|
1160
|
+
discardWarm("error");
|
|
1161
|
+
throw error;
|
|
1162
|
+
}
|
|
731
1163
|
if (!initial) {
|
|
1164
|
+
discardWarm("exit");
|
|
732
1165
|
return;
|
|
733
1166
|
}
|
|
1167
|
+
let timingTurn = 1;
|
|
1168
|
+
let timingMarks = { pushedAt: initial.enqueuedAt ?? Date.now() };
|
|
734
1169
|
const initialText = typeof initial.message === "string" ? initial.message : initial.message.find((b) => b.type === "text")?.text ?? "";
|
|
735
1170
|
const specialCommand = specialCommands.parseSpecialCommand(initialText);
|
|
736
1171
|
if (specialCommand.type === "clear") {
|
|
1172
|
+
discardWarm("clear");
|
|
737
1173
|
if (opts.onCompletionEvent) {
|
|
738
1174
|
opts.onCompletionEvent("Context was reset");
|
|
739
1175
|
}
|
|
@@ -751,90 +1187,95 @@ async function claudeRemote(opts) {
|
|
|
751
1187
|
opts.onCompletionEvent("Compaction started");
|
|
752
1188
|
}
|
|
753
1189
|
}
|
|
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);
|
|
1190
|
+
let adopted = null;
|
|
1191
|
+
if (warm) {
|
|
1192
|
+
const w = warm;
|
|
1193
|
+
const adoptStart = Date.now();
|
|
1194
|
+
const decision = decideWarmAdoption({ predicted: w.lease.mode, actual: initial.mode, specialCommand: specialCommand.type });
|
|
1195
|
+
let reason = decision.adopt ? null : decision.reason;
|
|
1196
|
+
const hs = reason ? null : await w.handshake;
|
|
1197
|
+
if (!reason) {
|
|
1198
|
+
if (warm !== w) {
|
|
1199
|
+
reason = "closed";
|
|
1200
|
+
} else if (!hs?.ok) {
|
|
1201
|
+
reason = "handshake-failed";
|
|
1202
|
+
} else if (decision.adopt) {
|
|
1203
|
+
try {
|
|
1204
|
+
if (decision.setPermissionMode) {
|
|
1205
|
+
await withTimeout(w.response.setPermissionMode(decision.setPermissionMode), w.lease.adoptTimeoutMs);
|
|
1206
|
+
} else {
|
|
1207
|
+
await withTimeout(w.response.mcpServerStatus(), w.lease.adoptTimeoutMs);
|
|
1208
|
+
}
|
|
1209
|
+
} catch {
|
|
1210
|
+
reason = decision.setPermissionMode ? "set-permission-failed" : "not-alive";
|
|
1211
|
+
}
|
|
1212
|
+
if (!reason && decision.switchModel) {
|
|
1213
|
+
try {
|
|
1214
|
+
await withTimeout(w.response.setModel(modelTarget(initial.mode.model)), w.lease.adoptTimeoutMs);
|
|
1215
|
+
} catch {
|
|
1216
|
+
reason = "set-model-failed";
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
if (!reason && warm !== w) reason = "closed";
|
|
793
1220
|
}
|
|
794
1221
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
1222
|
+
if (reason || !hs?.ok) {
|
|
1223
|
+
w.lease.discard(reason ?? "handshake-failed");
|
|
1224
|
+
warm = null;
|
|
1225
|
+
} else {
|
|
1226
|
+
if (w.idleTimer) clearTimeout(w.idleTimer);
|
|
1227
|
+
try {
|
|
1228
|
+
w.offExit?.();
|
|
1229
|
+
} catch {
|
|
1230
|
+
}
|
|
1231
|
+
warm = null;
|
|
1232
|
+
w.lease.adopt();
|
|
1233
|
+
adopted = { response: w.response, messages: w.messages, models: hs.models };
|
|
1234
|
+
logger.logger.debug(formatPrewarmLine("adopted", {
|
|
1235
|
+
warmForMs: adoptStart - w.startedAt,
|
|
1236
|
+
handshakeWaitMs: Math.max(0, hs.at - adoptStart),
|
|
1237
|
+
adoptMs: Date.now() - adoptStart,
|
|
1238
|
+
setPermissionMode: decision.adopt ? decision.setPermissionMode : void 0,
|
|
1239
|
+
setModel: decision.adopt && decision.switchModel ? true : void 0
|
|
1240
|
+
}));
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
mode = initial.mode;
|
|
1244
|
+
const initialUserMessage = {
|
|
798
1245
|
type: "user",
|
|
799
1246
|
parent_tool_use_id: null,
|
|
800
1247
|
origin: { kind: "human" },
|
|
1248
|
+
...promptUuid(initial.uuid),
|
|
801
1249
|
message: {
|
|
802
1250
|
role: "user",
|
|
803
1251
|
content: initial.message
|
|
804
1252
|
}
|
|
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
|
-
});
|
|
1253
|
+
};
|
|
1254
|
+
let messages;
|
|
1255
|
+
let response;
|
|
824
1256
|
let models;
|
|
825
|
-
if (
|
|
1257
|
+
if (adopted) {
|
|
1258
|
+
messages = adopted.messages;
|
|
1259
|
+
response = adopted.response;
|
|
1260
|
+
models = adopted.models;
|
|
1261
|
+
timingMarks.handshakeAt = Date.now();
|
|
1262
|
+
messages.push(initialUserMessage);
|
|
1263
|
+
} else {
|
|
1264
|
+
messages = new PushableAsyncIterable();
|
|
1265
|
+
messages.push(initialUserMessage);
|
|
1266
|
+
timingMarks.spawnAt = Date.now();
|
|
1267
|
+
response = index.query({
|
|
1268
|
+
prompt: messages,
|
|
1269
|
+
options: buildSdkOptions(initial.mode, { settingsPath: opts.hookSettingsPath, abort: opts.signal })
|
|
1270
|
+
});
|
|
826
1271
|
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
|
-
}));
|
|
1272
|
+
models = await discoverModels(response);
|
|
834
1273
|
} catch (error) {
|
|
835
1274
|
logger.logger.debug("[claudeRemote] Model capability discovery unavailable");
|
|
836
1275
|
}
|
|
1276
|
+
timingMarks.handshakeAt = Date.now();
|
|
837
1277
|
}
|
|
1278
|
+
const prewarmTiming = adopted ? "adopted" : void 0;
|
|
838
1279
|
if (opts.onQueryReady) {
|
|
839
1280
|
opts.onQueryReady({
|
|
840
1281
|
canControl: () => callbackDepth === 0,
|
|
@@ -886,6 +1327,11 @@ async function claudeRemote(opts) {
|
|
|
886
1327
|
if (message.type === "assistant" && message.error) {
|
|
887
1328
|
lastAssistantError = message.error;
|
|
888
1329
|
}
|
|
1330
|
+
if (message.type === "assistant" && timingMarks.firstAssistantAt === void 0) {
|
|
1331
|
+
timingMarks.firstAssistantAt = Date.now();
|
|
1332
|
+
} else if (message.type === "system" && message.subtype === "init" && timingMarks.initAt === void 0) {
|
|
1333
|
+
timingMarks.initAt = Date.now();
|
|
1334
|
+
}
|
|
889
1335
|
if (opts.onStreamFrame && message.type === "system") {
|
|
890
1336
|
const subtype = message.subtype;
|
|
891
1337
|
if (subtype === "thinking_tokens") {
|
|
@@ -935,6 +1381,15 @@ async function claudeRemote(opts) {
|
|
|
935
1381
|
if (message.type === "result") {
|
|
936
1382
|
updateThinking(false);
|
|
937
1383
|
logger.logger.debug("[claudeRemote] Result received");
|
|
1384
|
+
logger.logger.debug(formatClaudeTimingLine({
|
|
1385
|
+
turn: timingTurn,
|
|
1386
|
+
firstTurnOfProcess: timingTurn === 1,
|
|
1387
|
+
marks: timingMarks,
|
|
1388
|
+
result: message,
|
|
1389
|
+
prewarm: timingTurn === 1 ? prewarmTiming : void 0
|
|
1390
|
+
}));
|
|
1391
|
+
timingTurn++;
|
|
1392
|
+
timingMarks = {};
|
|
938
1393
|
const denials = message.permission_denials;
|
|
939
1394
|
if (denials && denials.length > 0) {
|
|
940
1395
|
logger.logger.warn(`[claudeRemote] ${denials.length} tool call(s) auto-denied by Claude Code policy: ${denials.map((d) => d.tool_name ?? "?").join(", ")}`);
|
|
@@ -974,10 +1429,12 @@ async function claudeRemote(opts) {
|
|
|
974
1429
|
}
|
|
975
1430
|
mode = next.mode;
|
|
976
1431
|
updateThinking(true);
|
|
1432
|
+
timingMarks = { pushedAt: next.enqueuedAt ?? Date.now() };
|
|
977
1433
|
messages.push({
|
|
978
1434
|
type: "user",
|
|
979
1435
|
parent_tool_use_id: null,
|
|
980
1436
|
origin: { kind: "human" },
|
|
1437
|
+
...promptUuid(next.uuid),
|
|
981
1438
|
message: { role: "user", content: next.message }
|
|
982
1439
|
});
|
|
983
1440
|
}).catch(() => {
|
|
@@ -2355,6 +2812,146 @@ class LaunchModeGate {
|
|
|
2355
2812
|
}
|
|
2356
2813
|
}
|
|
2357
2814
|
|
|
2815
|
+
class ConversationRewindError extends Error {
|
|
2816
|
+
constructor(code, message) {
|
|
2817
|
+
super(message);
|
|
2818
|
+
this.code = code;
|
|
2819
|
+
this.name = "ConversationRewindError";
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
function transcriptPromptText(parsed) {
|
|
2823
|
+
if (parsed?.type !== "user" || parsed.isSidechain || parsed.isMeta || parsed.isSynthetic) return null;
|
|
2824
|
+
const content = parsed.message?.content;
|
|
2825
|
+
if (typeof content === "string") return content.trim() ? content : null;
|
|
2826
|
+
if (!Array.isArray(content) || content.some((block) => block?.type === "tool_result")) return null;
|
|
2827
|
+
const text = content.filter((block) => block?.type === "text" && typeof block.text === "string").map((block) => block.text).join("\n");
|
|
2828
|
+
if (!text.trim()) return content.length > 0 ? "" : null;
|
|
2829
|
+
return text;
|
|
2830
|
+
}
|
|
2831
|
+
function isConversationEntry(parsed) {
|
|
2832
|
+
return !parsed?.isSidechain && !parsed?.isMeta && !parsed?.isSynthetic && (parsed?.type === "user" || parsed?.type === "assistant");
|
|
2833
|
+
}
|
|
2834
|
+
function resolveRewindTarget(entries, target) {
|
|
2835
|
+
for (const uuid of target.uuids) {
|
|
2836
|
+
const index = entries.findIndex((entry) => entry.parsed?.uuid === uuid && transcriptPromptText(entry.parsed) !== null);
|
|
2837
|
+
if (index >= 0) return index;
|
|
2838
|
+
}
|
|
2839
|
+
const wanted = target.text?.trim();
|
|
2840
|
+
if (!wanted) throw new ConversationRewindError("not-found", "This message is not in the agent conversation");
|
|
2841
|
+
const matches = [];
|
|
2842
|
+
entries.forEach((entry, index) => {
|
|
2843
|
+
if (transcriptPromptText(entry.parsed)?.trim() === wanted) matches.push(index);
|
|
2844
|
+
});
|
|
2845
|
+
if (matches.length === 1) return matches[0];
|
|
2846
|
+
if (matches.length === 0) throw new ConversationRewindError("not-found", "This message is not in the agent conversation");
|
|
2847
|
+
throw new ConversationRewindError("ambiguous", "Several earlier messages have the same text; cannot tell which one to change");
|
|
2848
|
+
}
|
|
2849
|
+
function rewindTranscriptLines(lines, action, target) {
|
|
2850
|
+
const entries = [];
|
|
2851
|
+
for (const line of lines) {
|
|
2852
|
+
if (!line) continue;
|
|
2853
|
+
let parsed = null;
|
|
2854
|
+
try {
|
|
2855
|
+
parsed = JSON.parse(line);
|
|
2856
|
+
} catch {
|
|
2857
|
+
}
|
|
2858
|
+
entries.push({ line, parsed });
|
|
2859
|
+
}
|
|
2860
|
+
const cut = resolveRewindTarget(entries, target);
|
|
2861
|
+
let end = entries.length;
|
|
2862
|
+
for (let i = cut + 1; i < entries.length; i++) {
|
|
2863
|
+
if (transcriptPromptText(entries[i].parsed) !== null) {
|
|
2864
|
+
end = i;
|
|
2865
|
+
break;
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
const before = entries.slice(0, cut);
|
|
2869
|
+
const after = action === "delete" ? entries.slice(end) : [];
|
|
2870
|
+
if (![...before, ...after].some((entry) => isConversationEntry(entry.parsed))) return null;
|
|
2871
|
+
if (before.some((entry) => isConversationEntry(entry.parsed)) && !before.some((entry) => transcriptPromptText(entry.parsed) !== null)) {
|
|
2872
|
+
throw new ConversationRewindError("unsafe", "Cannot safely rewind: earlier history has no user prompt");
|
|
2873
|
+
}
|
|
2874
|
+
if (after.length === 0) return before.map((entry) => entry.line);
|
|
2875
|
+
const dropped = /* @__PURE__ */ new Set();
|
|
2876
|
+
for (const entry of entries.slice(cut, end)) {
|
|
2877
|
+
if (typeof entry.parsed?.uuid === "string") dropped.add(entry.parsed.uuid);
|
|
2878
|
+
}
|
|
2879
|
+
const reparentTo = typeof entries[cut].parsed?.parentUuid === "string" ? entries[cut].parsed.parentUuid : null;
|
|
2880
|
+
const relinked = after.map((entry) => {
|
|
2881
|
+
const parsed = entry.parsed;
|
|
2882
|
+
if (!parsed || typeof parsed !== "object") return entry.line;
|
|
2883
|
+
let next = parsed;
|
|
2884
|
+
for (const key of ["parentUuid", "logicalParentUuid"]) {
|
|
2885
|
+
if (typeof parsed[key] === "string" && dropped.has(parsed[key])) {
|
|
2886
|
+
next = next === parsed ? { ...parsed } : next;
|
|
2887
|
+
next[key] = reparentTo;
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
return next === parsed ? entry.line : JSON.stringify(next);
|
|
2891
|
+
});
|
|
2892
|
+
return [...before.map((entry) => entry.line), ...relinked];
|
|
2893
|
+
}
|
|
2894
|
+
async function rewindClaudeTranscript(projectDir, claudeSessionId, action, target) {
|
|
2895
|
+
const source = path$1.join(projectDir, `${claudeSessionId}.jsonl`);
|
|
2896
|
+
let raw;
|
|
2897
|
+
try {
|
|
2898
|
+
raw = await promises.readFile(source, "utf-8");
|
|
2899
|
+
} catch (error) {
|
|
2900
|
+
if (error.code === "ENOENT") throw new claudeSessionFork.ForkSourceMissingError(source);
|
|
2901
|
+
throw error;
|
|
2902
|
+
}
|
|
2903
|
+
const kept = rewindTranscriptLines(raw.split("\n"), action, target);
|
|
2904
|
+
if (kept === null) return null;
|
|
2905
|
+
const newId = node_crypto.randomUUID();
|
|
2906
|
+
const destination = path$1.join(projectDir, `${newId}.jsonl`);
|
|
2907
|
+
const temporary = `${destination}.tmp-${process.pid}`;
|
|
2908
|
+
try {
|
|
2909
|
+
await promises.writeFile(temporary, kept.join("\n") + "\n", { encoding: "utf-8", flag: "wx" });
|
|
2910
|
+
await promises.rename(temporary, destination);
|
|
2911
|
+
} catch (error) {
|
|
2912
|
+
await promises.unlink(temporary).catch(() => void 0);
|
|
2913
|
+
throw error;
|
|
2914
|
+
}
|
|
2915
|
+
return newId;
|
|
2916
|
+
}
|
|
2917
|
+
|
|
2918
|
+
const STOP_WAIT_MS = 8e3;
|
|
2919
|
+
function createConversationRewind(deps) {
|
|
2920
|
+
let inFlight = false;
|
|
2921
|
+
const rewrite = deps.rewrite ?? rewindClaudeTranscript;
|
|
2922
|
+
return async (input) => {
|
|
2923
|
+
const request = input && typeof input === "object" ? input : {};
|
|
2924
|
+
const action = request.action;
|
|
2925
|
+
const sourceId = typeof request.sourceId === "string" && request.sourceId.length > 0 && request.sourceId.length <= 200 ? request.sourceId : void 0;
|
|
2926
|
+
const text = typeof request.text === "string" && request.text.length <= 2e5 ? request.text : void 0;
|
|
2927
|
+
if (action !== "edit" && action !== "delete" || !sourceId && !text?.trim()) {
|
|
2928
|
+
return { ok: false, code: "invalid", error: "Invalid rewind request" };
|
|
2929
|
+
}
|
|
2930
|
+
if (inFlight) return { ok: false, code: "busy", error: "Another edit is still being applied" };
|
|
2931
|
+
inFlight = true;
|
|
2932
|
+
try {
|
|
2933
|
+
if (deps.isThinking()) {
|
|
2934
|
+
await deps.stopTurn();
|
|
2935
|
+
if (!await deps.waitIdle(STOP_WAIT_MS)) {
|
|
2936
|
+
return { ok: false, code: "running", error: "The agent did not stop; try again after it finishes" };
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
const current = deps.claudeSessionId();
|
|
2940
|
+
if (!current) return { ok: false, code: "no-conversation", error: "The agent has no conversation to change yet" };
|
|
2941
|
+
const uuids = sourceId ? [sourceId, ...deps.aliases(sourceId)] : [];
|
|
2942
|
+
const next = await rewrite(deps.projectDir(), current, action, { uuids, text });
|
|
2943
|
+
await deps.switchConversation(next);
|
|
2944
|
+
return { ok: true, action, freshConversation: next === null };
|
|
2945
|
+
} catch (error) {
|
|
2946
|
+
if (error instanceof ConversationRewindError) return { ok: false, code: error.code, error: error.message };
|
|
2947
|
+
if (error instanceof claudeSessionFork.ForkSourceMissingError) return { ok: false, code: "no-conversation", error: "The agent conversation file is missing on this machine" };
|
|
2948
|
+
throw error;
|
|
2949
|
+
} finally {
|
|
2950
|
+
inFlight = false;
|
|
2951
|
+
}
|
|
2952
|
+
};
|
|
2953
|
+
}
|
|
2954
|
+
|
|
2358
2955
|
const ABORT_INTERRUPT_GRACE_MS = 4e3;
|
|
2359
2956
|
async function claudeRemoteLauncher(session, onPermissionModeChange, onEffectivePermissionMode, onPromptFinalized) {
|
|
2360
2957
|
logger.logger.debug("[claudeRemoteLauncher] Starting remote launcher");
|
|
@@ -2449,6 +3046,31 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
2449
3046
|
await turnSteering.steer();
|
|
2450
3047
|
});
|
|
2451
3048
|
session.client.rpcHandlerManager.registerHandler("switch", doSwitch);
|
|
3049
|
+
const promptAliases = /* @__PURE__ */ new Map();
|
|
3050
|
+
const promptUuidFor = (sourceIds) => {
|
|
3051
|
+
const [first, ...rest] = sourceIds ?? [];
|
|
3052
|
+
if (first) for (const id of rest) promptAliases.set(id, first);
|
|
3053
|
+
if (promptAliases.size > 2e3) promptAliases.delete(promptAliases.keys().next().value);
|
|
3054
|
+
return first;
|
|
3055
|
+
};
|
|
3056
|
+
let silentRelaunch = false;
|
|
3057
|
+
session.client.rpcHandlerManager.registerHandler("conversation-rewind", createConversationRewind({
|
|
3058
|
+
claudeSessionId: () => session.sessionId,
|
|
3059
|
+
projectDir: () => path.getProjectPath(session.path),
|
|
3060
|
+
isThinking: () => session.thinking,
|
|
3061
|
+
stopTurn: doAbort,
|
|
3062
|
+
waitIdle: waitForThinkingToStop,
|
|
3063
|
+
aliases: (sourceId) => {
|
|
3064
|
+
const alias = promptAliases.get(sourceId);
|
|
3065
|
+
return alias ? [alias] : [];
|
|
3066
|
+
},
|
|
3067
|
+
switchConversation: async (claudeSessionId) => {
|
|
3068
|
+
if (claudeSessionId) session.onSessionFound(claudeSessionId);
|
|
3069
|
+
else session.clearSessionId();
|
|
3070
|
+
silentRelaunch = true;
|
|
3071
|
+
await abort();
|
|
3072
|
+
}
|
|
3073
|
+
}));
|
|
2452
3074
|
let livePermissionModeHandler = null;
|
|
2453
3075
|
let idlePermissionModeHandler = null;
|
|
2454
3076
|
session.client.rpcHandlerManager.registerHandler(
|
|
@@ -2634,10 +3256,13 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
2634
3256
|
permissionHandler.setOnModeChanged((nextMode) => {
|
|
2635
3257
|
commitPermissionMode(nextMode);
|
|
2636
3258
|
});
|
|
3259
|
+
let launchPrewarm = null;
|
|
2637
3260
|
try {
|
|
2638
3261
|
const attachmentDirectory = attachmentContent.chatAttachmentDirectory(configuration.configuration.happyHomeDir, session.client.sessionId);
|
|
2639
3262
|
await configuration.ensurePrivateDirectory(attachmentDirectory);
|
|
3263
|
+
launchPrewarm = session.takeClaudePrewarm();
|
|
2640
3264
|
const remoteResult = await claudeRemote({
|
|
3265
|
+
prewarm: launchPrewarm ?? void 0,
|
|
2641
3266
|
sessionId: session.sessionId,
|
|
2642
3267
|
path: session.path,
|
|
2643
3268
|
additionalDirectories: [attachmentDirectory],
|
|
@@ -2669,7 +3294,8 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
2669
3294
|
}) : [];
|
|
2670
3295
|
modeGate.park({
|
|
2671
3296
|
message: parkedStaged.length > 0 ? attachmentContent.appendStagedAttachmentsToPrompt(msg.message, parkedStaged) : msg.message,
|
|
2672
|
-
mode: msg.mode
|
|
3297
|
+
mode: msg.mode,
|
|
3298
|
+
uuid: promptUuidFor(msg.sourceIds)
|
|
2673
3299
|
});
|
|
2674
3300
|
return null;
|
|
2675
3301
|
}
|
|
@@ -2686,13 +3312,17 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
2686
3312
|
onPromptFinalized?.(withAttachments);
|
|
2687
3313
|
return {
|
|
2688
3314
|
message: withAttachments,
|
|
2689
|
-
mode: msg.mode
|
|
3315
|
+
mode: msg.mode,
|
|
3316
|
+
enqueuedAt: msg.enqueuedAt,
|
|
3317
|
+
uuid: promptUuidFor(msg.sourceIds)
|
|
2690
3318
|
};
|
|
2691
3319
|
}
|
|
2692
3320
|
onPromptFinalized?.(msg.message);
|
|
2693
3321
|
return {
|
|
2694
3322
|
message: msg.message,
|
|
2695
|
-
mode: msg.mode
|
|
3323
|
+
mode: msg.mode,
|
|
3324
|
+
enqueuedAt: msg.enqueuedAt,
|
|
3325
|
+
uuid: promptUuidFor(msg.sourceIds)
|
|
2696
3326
|
};
|
|
2697
3327
|
}
|
|
2698
3328
|
return null;
|
|
@@ -2793,7 +3423,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
2793
3423
|
signal: abortController.signal
|
|
2794
3424
|
});
|
|
2795
3425
|
session.consumeOneTimeFlags();
|
|
2796
|
-
if (!exitReason && abortController.signal.aborted) {
|
|
3426
|
+
if (!exitReason && abortController.signal.aborted && !silentRelaunch) {
|
|
2797
3427
|
session.client.closeClaudeSessionTurn("cancelled");
|
|
2798
3428
|
session.client.sendSessionEvent({ type: "message", message: "Aborted by user" });
|
|
2799
3429
|
}
|
|
@@ -2810,6 +3440,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
2810
3440
|
continue;
|
|
2811
3441
|
}
|
|
2812
3442
|
} finally {
|
|
3443
|
+
launchPrewarm?.discard("launch-ended");
|
|
2813
3444
|
runtimeControls.setQuery(null);
|
|
2814
3445
|
backgroundTasks.reset();
|
|
2815
3446
|
session.setBackgroundTasks([]);
|
|
@@ -2835,6 +3466,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
2835
3466
|
streamRelay$1.endTurn();
|
|
2836
3467
|
streamRelay$1.dispose();
|
|
2837
3468
|
abortController = null;
|
|
3469
|
+
silentRelaunch = false;
|
|
2838
3470
|
abortFuture?.resolve(void 0);
|
|
2839
3471
|
abortFuture = null;
|
|
2840
3472
|
logger.logger.debug("[remote]: launch done");
|
|
@@ -2883,7 +3515,8 @@ async function loop(opts) {
|
|
|
2883
3515
|
onModeChange: opts.onModeChange,
|
|
2884
3516
|
onAbort: opts.onAbort,
|
|
2885
3517
|
hookSettingsPath: opts.hookSettingsPath,
|
|
2886
|
-
jsRuntime: opts.jsRuntime
|
|
3518
|
+
jsRuntime: opts.jsRuntime,
|
|
3519
|
+
claudePrewarm: opts.claudePrewarm
|
|
2887
3520
|
});
|
|
2888
3521
|
opts.onSessionReady?.(session);
|
|
2889
3522
|
let mode = opts.startingMode ?? "local";
|
|
@@ -2891,7 +3524,7 @@ async function loop(opts) {
|
|
|
2891
3524
|
logger.logger.debug(`[loop] Iteration with mode: ${mode}`);
|
|
2892
3525
|
switch (mode) {
|
|
2893
3526
|
case "local": {
|
|
2894
|
-
const { claudeLocalLauncher } = await Promise.resolve().then(function () { return require('./claudeLocalLauncher-
|
|
3527
|
+
const { claudeLocalLauncher } = await Promise.resolve().then(function () { return require('./claudeLocalLauncher-DWFWuLhY.cjs'); });
|
|
2895
3528
|
const result = await claudeLocalLauncher(session);
|
|
2896
3529
|
switch (result.type) {
|
|
2897
3530
|
case "switch":
|
|
@@ -2919,18 +3552,18 @@ async function loop(opts) {
|
|
|
2919
3552
|
}
|
|
2920
3553
|
}
|
|
2921
3554
|
|
|
2922
|
-
function
|
|
2923
|
-
return
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
3555
|
+
function parseSessionHookTarget(url) {
|
|
3556
|
+
if (!url) return null;
|
|
3557
|
+
let parsed;
|
|
3558
|
+
try {
|
|
3559
|
+
parsed = new URL(url, "http://127.0.0.1");
|
|
3560
|
+
} catch {
|
|
3561
|
+
return null;
|
|
3562
|
+
}
|
|
3563
|
+
if (parsed.pathname !== "/hook/session-start") return null;
|
|
3564
|
+
const source = parsed.searchParams.get("source");
|
|
3565
|
+
return source && /^[A-Za-z0-9_.-]{1,64}$/.test(source) ? { source } : {};
|
|
2932
3566
|
}
|
|
2933
|
-
|
|
2934
3567
|
function hookRequestLogMetadata(body, data) {
|
|
2935
3568
|
return {
|
|
2936
3569
|
bodyBytes: Buffer.byteLength(body, "utf8"),
|
|
@@ -2952,7 +3585,8 @@ async function startHookServer(options) {
|
|
|
2952
3585
|
const { onSessionHook } = options;
|
|
2953
3586
|
return new Promise((resolve, reject) => {
|
|
2954
3587
|
const server = node_http.createServer(async (req, res) => {
|
|
2955
|
-
|
|
3588
|
+
const hookMeta = req.method === "POST" ? parseSessionHookTarget(req.url) : null;
|
|
3589
|
+
if (hookMeta) {
|
|
2956
3590
|
const timeout = setTimeout(() => {
|
|
2957
3591
|
if (!res.headersSent) {
|
|
2958
3592
|
logger.logger.debug("[hookServer] Request timeout");
|
|
@@ -2976,7 +3610,7 @@ async function startHookServer(options) {
|
|
|
2976
3610
|
const sessionId = data?.session_id || data?.sessionId;
|
|
2977
3611
|
if (sessionId && data) {
|
|
2978
3612
|
logger.logger.debug(`[hookServer] Session hook received session ID: ${sessionId}`);
|
|
2979
|
-
onSessionHook(sessionId, data);
|
|
3613
|
+
onSessionHook(sessionId, data, hookMeta);
|
|
2980
3614
|
} else {
|
|
2981
3615
|
logger.logger.debug("[hookServer] Session hook received but no session_id found in data");
|
|
2982
3616
|
}
|
|
@@ -3015,13 +3649,16 @@ async function startHookServer(options) {
|
|
|
3015
3649
|
});
|
|
3016
3650
|
}
|
|
3017
3651
|
|
|
3018
|
-
function generateHookSettingsFile(port) {
|
|
3652
|
+
function generateHookSettingsFile(port, source) {
|
|
3019
3653
|
const hooksDir = path$1.join(configuration.configuration.happyHomeDir, "tmp", "hooks");
|
|
3020
3654
|
node_fs.mkdirSync(hooksDir, { recursive: true });
|
|
3021
|
-
const filename = `session-hook-${process.pid}.json`;
|
|
3655
|
+
const filename = source ? `session-hook-${process.pid}-${source}.json` : `session-hook-${process.pid}.json`;
|
|
3022
3656
|
const filepath = path$1.join(hooksDir, filename);
|
|
3023
3657
|
const forwarderScript = path$1.resolve(projectPath.projectPath(), "scripts", "session_hook_forwarder.cjs");
|
|
3024
|
-
|
|
3658
|
+
if (source !== void 0 && !/^[A-Za-z0-9_.-]{1,64}$/.test(source)) {
|
|
3659
|
+
throw new Error("invalid hook source tag");
|
|
3660
|
+
}
|
|
3661
|
+
const hookCommand = source ? `node "${forwarderScript}" ${port} ${source}` : `node "${forwarderScript}" ${port}`;
|
|
3025
3662
|
const settings = {
|
|
3026
3663
|
hooks: {
|
|
3027
3664
|
SessionStart: [
|
|
@@ -3619,31 +4256,90 @@ function withAssistantDenylist(current, isAssistant) {
|
|
|
3619
4256
|
return [...merged];
|
|
3620
4257
|
}
|
|
3621
4258
|
|
|
4259
|
+
const VALID_EFFORTS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh", "max"]);
|
|
4260
|
+
const has = (meta, key) => !!meta && Object.prototype.hasOwnProperty.call(meta, key);
|
|
4261
|
+
function resolveMessageMode(current, meta, ctx) {
|
|
4262
|
+
const next = { ...current };
|
|
4263
|
+
const result = {};
|
|
4264
|
+
let permissionMode$1 = current.permissionMode;
|
|
4265
|
+
if (!ctx.staleModeSnapshot && meta?.permissionMode) {
|
|
4266
|
+
permissionMode$1 = permissionMode.resolveRemoteClaudePermissionMode(current.permissionMode, meta.permissionMode, ctx.sandboxEnabled);
|
|
4267
|
+
next.permissionMode = permissionMode$1;
|
|
4268
|
+
result.publishPermissionMode = permissionMode$1;
|
|
4269
|
+
}
|
|
4270
|
+
if (has(meta, "model")) next.model = meta.model || void 0;
|
|
4271
|
+
if (has(meta, "customSystemPrompt")) next.customSystemPrompt = meta.customSystemPrompt || void 0;
|
|
4272
|
+
if (has(meta, "fallbackModel")) next.fallbackModel = meta.fallbackModel || void 0;
|
|
4273
|
+
if (has(meta, "appendSystemPrompt")) next.appendSystemPrompt = meta.appendSystemPrompt || void 0;
|
|
4274
|
+
if (has(meta, "allowedTools")) next.allowedTools = meta.allowedTools || void 0;
|
|
4275
|
+
if (has(meta, "disallowedTools")) {
|
|
4276
|
+
next.disallowedTools = withAssistantDenylist(meta.disallowedTools || void 0, ctx.isAssistantVariant);
|
|
4277
|
+
}
|
|
4278
|
+
if (has(meta, "effort")) {
|
|
4279
|
+
const incoming = meta.effort;
|
|
4280
|
+
if (incoming === null || incoming === void 0) {
|
|
4281
|
+
next.effort = void 0;
|
|
4282
|
+
} else if (typeof incoming === "string" && VALID_EFFORTS.has(incoming)) {
|
|
4283
|
+
next.effort = incoming;
|
|
4284
|
+
} else {
|
|
4285
|
+
result.ignoredEffort = String(incoming);
|
|
4286
|
+
}
|
|
4287
|
+
}
|
|
4288
|
+
return {
|
|
4289
|
+
...result,
|
|
4290
|
+
next,
|
|
4291
|
+
mode: {
|
|
4292
|
+
permissionMode: permissionMode$1 || "default",
|
|
4293
|
+
model: next.model,
|
|
4294
|
+
fallbackModel: next.fallbackModel,
|
|
4295
|
+
customSystemPrompt: next.customSystemPrompt,
|
|
4296
|
+
appendSystemPrompt: next.appendSystemPrompt,
|
|
4297
|
+
allowedTools: next.allowedTools,
|
|
4298
|
+
disallowedTools: next.disallowedTools,
|
|
4299
|
+
effort: next.effort
|
|
4300
|
+
}
|
|
4301
|
+
};
|
|
4302
|
+
}
|
|
4303
|
+
|
|
3622
4304
|
exports.reportSessionEditToDaemon = controlClient.reportSessionEditToDaemon;
|
|
3623
4305
|
exports.claudeCheckSession = systemPrompt.claudeCheckSession;
|
|
3624
4306
|
exports.parseSpecialCommand = specialCommands.parseSpecialCommand;
|
|
3625
4307
|
exports.contentLogMetadata = contentLogMetadata.contentLogMetadata;
|
|
3626
4308
|
exports.RawJSONLinesSchema = types.RawJSONLinesSchema;
|
|
3627
4309
|
exports.getProjectPath = path.getProjectPath;
|
|
4310
|
+
exports.createSelfReportState = deterministicJson.createSelfReportState;
|
|
4311
|
+
exports.startHappyServer = deterministicJson.startHappyServer;
|
|
3628
4312
|
exports.createSessionScanner = sessionScanner.createSessionScanner;
|
|
3629
4313
|
exports.MessageQueue2 = registerKillSessionHandler.MessageQueue2;
|
|
3630
4314
|
exports.registerKillSessionHandler = registerKillSessionHandler.registerKillSessionHandler;
|
|
3631
|
-
exports.createSelfReportState = deterministicJson.createSelfReportState;
|
|
3632
|
-
exports.startHappyServer = deterministicJson.startHappyServer;
|
|
3633
4315
|
exports.getEnvironmentInfo = doctor.getEnvironmentInfo;
|
|
3634
4316
|
exports.EditReportThrottle = editPaths.EditReportThrottle;
|
|
3635
4317
|
exports.extractClaudeEditPaths = editPaths.extractClaudeEditPaths;
|
|
3636
4318
|
exports.TitleGenerator = titleGenerator.TitleGenerator;
|
|
3637
4319
|
exports.BoardAnalyzer = BoardAnalyzer;
|
|
3638
4320
|
exports.FileRateLimiter = FileRateLimiter;
|
|
4321
|
+
exports.PrewarmHookGate = PrewarmHookGate;
|
|
3639
4322
|
exports.SessionExitGate = SessionExitGate;
|
|
4323
|
+
exports.acquirePrewarmSlot = acquirePrewarmSlot;
|
|
3640
4324
|
exports.claudeModeHash = claudeModeHash;
|
|
4325
|
+
exports.claudePrewarmEligibility = claudePrewarmEligibility;
|
|
4326
|
+
exports.claudePrewarmSessionEligibility = claudePrewarmSessionEligibility;
|
|
3641
4327
|
exports.cleanupHookSettingsFile = cleanupHookSettingsFile;
|
|
4328
|
+
exports.createClaudePrewarmLease = createClaudePrewarmLease;
|
|
4329
|
+
exports.disposeAllClaudePrewarms = disposeAllClaudePrewarms;
|
|
4330
|
+
exports.evaluatePrewarmPrediction = evaluatePrewarmPrediction;
|
|
3642
4331
|
exports.exitIntentFromArchiveFlag = exitIntentFromArchiveFlag;
|
|
4332
|
+
exports.formatPrewarmLine = formatPrewarmLine;
|
|
3643
4333
|
exports.generateHookSettingsFile = generateHookSettingsFile;
|
|
3644
4334
|
exports.loop = loop;
|
|
4335
|
+
exports.prewarmCacheFile = prewarmCacheFile;
|
|
4336
|
+
exports.prewarmPredictionMeta = prewarmPredictionMeta;
|
|
4337
|
+
exports.prewarmSlotDir = prewarmSlotDir;
|
|
4338
|
+
exports.readPrewarmCache = readPrewarmCache;
|
|
3645
4339
|
exports.registerSideQuestionHandler = registerSideQuestionHandler;
|
|
4340
|
+
exports.resolveMessageMode = resolveMessageMode;
|
|
3646
4341
|
exports.settleSessionOnExit = settleSessionOnExit;
|
|
3647
4342
|
exports.startHookServer = startHookServer;
|
|
3648
4343
|
exports.withAssistantDenylist = withAssistantDenylist;
|
|
4344
|
+
exports.writePrewarmCache = writePrewarmCache;
|
|
3649
4345
|
exports.writeSideQuestionSettingsFile = writeSideQuestionSettingsFile;
|