very-happy-cli 0.2.159 → 0.2.160
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-DUYFlyfN.cjs → AcpBackend-Bm2rdke8.cjs} +78 -76
- package/dist/{AcpBackend-VsfkZiVF.mjs → AcpBackend-mzv8Dhba.mjs} +4 -2
- package/dist/{AcpSessionManager-Bdv8LWXh.cjs → AcpSessionManager-BAY1Pggx.cjs} +9 -9
- package/dist/{AcpSessionManager-rYtVb0kN.mjs → AcpSessionManager-CoMWFVw3.mjs} +1 -1
- package/dist/BasePermissionHandler-CFHAxumV.cjs +157 -0
- package/dist/BasePermissionHandler-m3WVholL.mjs +155 -0
- package/dist/BaseReasoningProcessor-BFa9_rZA.cjs +200 -0
- package/dist/BaseReasoningProcessor-CYrKBXGm.mjs +198 -0
- package/dist/RemoteModeDisplay-D-HewyXg.mjs +150 -0
- package/dist/RemoteModeDisplay-NC1gPHtj.cjs +153 -0
- package/dist/agentAttachments-Dbw8iMCZ.cjs +20 -0
- package/dist/agentAttachments-M_B5qEF2.mjs +18 -0
- package/dist/agentGuidance-B5NATuFa.cjs +28 -0
- package/dist/agentGuidance-CQuNlNx8.mjs +20 -0
- package/dist/{agentHome-CHh4lmjM.cjs → agentHome-CboCeKWq.cjs} +14 -28
- package/dist/{agentHome-CvsJyeQB.mjs → agentHome-Dj1C43aJ.mjs} +8 -22
- package/dist/api-CLMUr-SX.mjs +3339 -0
- package/dist/api-CgundNNX.cjs +3346 -0
- package/dist/{types-Dh-s4Lqs.mjs → apiMachine-B9dLW_p5.mjs} +9116 -16205
- package/dist/{types-BbvK1Tr_.cjs → apiMachine-Bn8482VM.cjs} +9104 -16247
- package/dist/assistantTools-BTqPnlFl.cjs +380 -0
- package/dist/assistantTools-D6tuc6o4.mjs +376 -0
- package/dist/attachmentContent-DpiTJZb4.cjs +88 -0
- package/dist/attachmentContent-_kxRznNf.mjs +82 -0
- package/dist/attachmentLimits-CzVrqgLR.cjs +354 -0
- package/dist/attachmentLimits-yba1uHFO.mjs +348 -0
- package/dist/auth-BDOVh5h5.cjs +220 -0
- package/dist/auth-Cwutmdsa.mjs +225 -0
- package/dist/auth-PYHZQNPp.mjs +218 -0
- package/dist/auth-ba4WMYrN.cjs +227 -0
- package/dist/authRelay-BdYkC1Po.cjs +156 -0
- package/dist/authRelay-DSAvg1uv.mjs +143 -0
- package/dist/{auto-DKmEls8Z.cjs → auto-BOX_fgmR.cjs} +70 -79
- package/dist/{auto-nb8GhRRy.mjs → auto-BXu14yP_.mjs} +27 -36
- package/dist/backgroundTaskActivity-8PdPxrvy.mjs +149 -0
- package/dist/backgroundTaskActivity-CBvUdj39.cjs +157 -0
- package/dist/bootstrap-B5G1TijC.cjs +116 -0
- package/dist/bootstrap-hxXPCFMx.mjs +112 -0
- package/dist/browser-Y6Bl8L_O.cjs +22 -0
- package/dist/browser-jh2P0UVZ.mjs +20 -0
- package/dist/claudeCliPath-BqkaH2oR.mjs +8 -0
- package/dist/claudeCliPath-U4HHmV4r.cjs +10 -0
- package/dist/claudeLocal-BaY4fZKi.mjs +339 -0
- package/dist/claudeLocal-CRGG4Pea.cjs +343 -0
- package/dist/claudeLocalLauncher-D4T7MTqd.mjs +152 -0
- package/dist/claudeLocalLauncher-DyEbVzUN.cjs +154 -0
- package/dist/cliUpdate-DsKXPFYp.cjs +120 -0
- package/dist/cliUpdate-Y34VGe9Y.mjs +112 -0
- package/dist/client-3Ac-O4pw.cjs +104 -0
- package/dist/client-BPNbmtvO.cjs +119 -0
- package/dist/client-CeGKqqcJ.mjs +100 -0
- package/dist/client-ClR0K8zX.mjs +112 -0
- package/dist/codex/happyMcpStdioBridge.cjs +33 -14
- package/dist/codex/happyMcpStdioBridge.mjs +26 -7
- package/dist/codexAppServerClient-I3teiV-N.mjs +1088 -0
- package/dist/codexAppServerClient-q2FjnRcK.cjs +1090 -0
- package/dist/codexCommand-4zcccIoq.cjs +2088 -0
- package/dist/codexCommand-Cc9gcbdX.mjs +2086 -0
- package/dist/codexThreadFork-BH9IZPqD.cjs +350 -0
- package/dist/codexThreadFork-slzAseLx.mjs +338 -0
- package/dist/{config-ClLtM6F3.mjs → config-CTx_jb-C.mjs} +7 -40
- package/dist/{config-DLx-vW3I.cjs → config-Ci9Kpgwa.cjs} +26 -59
- package/dist/configuration-BSYpcPwE.cjs +181 -0
- package/dist/configuration-RfeNjFmd.mjs +170 -0
- package/dist/connect-BpOdzNbE.mjs +682 -0
- package/dist/connect-C2CiOUFs.cjs +684 -0
- package/dist/constants-BC4St0xd.mjs +11 -0
- package/dist/constants-VJ0N6WuG.cjs +17 -0
- package/dist/contentLogMetadata-BlWI0egu.mjs +51 -0
- package/dist/contentLogMetadata-ZSFk_NjQ.cjs +54 -0
- package/dist/context-DsDr6E2t.cjs +69 -0
- package/dist/context-H0Bcb9S_.mjs +65 -0
- package/dist/controlClient-BGbDcgWS.mjs +260 -0
- package/dist/controlClient-Bcwv3D21.cjs +279 -0
- package/dist/createSessionMetadata-BJxEnM-o.cjs +58 -0
- package/dist/createSessionMetadata-CVVkGjxV.mjs +54 -0
- package/dist/defaultPermissionMode-BnxJPVHT.mjs +4 -0
- package/dist/defaultPermissionMode-CxmTXUQR.cjs +7 -0
- package/dist/detectCLI-CSGMlV51.mjs +58 -0
- package/dist/detectCLI-DR9ZaN6B.cjs +61 -0
- package/dist/deterministicJson-C5CYTVpm.cjs +507 -0
- package/dist/deterministicJson-CzkFJWw1.mjs +502 -0
- package/dist/doctor-BPkYWSuq.mjs +75 -0
- package/dist/doctor-D2YJ-Yn2.cjs +395 -0
- package/dist/doctor-DOvByjbk.mjs +391 -0
- package/dist/doctor-u46qYYKX.cjs +79 -0
- package/dist/doctorReadiness-BCZGcN0a.cjs +151 -0
- package/dist/doctorReadiness-C208SMN9.mjs +142 -0
- package/dist/editPaths-BVfS_FFL.mjs +68 -0
- package/dist/editPaths-Bqp4OFPw.cjs +73 -0
- package/dist/ensureDaemonRunning-BCwNrMyv.cjs +64 -0
- package/dist/ensureDaemonRunning-Dqa2pOjY.mjs +61 -0
- package/dist/handleResumeCommand-BvXYf5El.mjs +240 -0
- package/dist/handleResumeCommand-C2cKchpX.cjs +245 -0
- package/dist/ids-B6ZC0HGt.cjs +13 -0
- package/dist/ids-DU6sLx4C.mjs +10 -0
- package/dist/index-B6UGRQ7h.mjs +102 -0
- package/dist/{index-BEOMECtE.cjs → index-B6pAdvJx.cjs} +121 -91
- package/dist/index-Bu5Zi_a9.cjs +182 -0
- package/dist/index-D3kI0hDR.cjs +107 -0
- package/dist/index-DA7yINuk.cjs +994 -0
- package/dist/index-DDeHXrIX.cjs +71 -0
- package/dist/index-DKLU_fD0.mjs +158 -0
- package/dist/{index-2mCaeKyf.mjs → index-DMZqWwsP.mjs} +68 -38
- package/dist/index-DVkMGPyS.mjs +68 -0
- package/dist/index-qdS1friN.mjs +949 -0
- package/dist/index.cjs +5 -46
- package/dist/index.mjs +5 -46
- package/dist/{install-BPhJppvd.mjs → install-BO_W7VhL.mjs} +37 -37
- package/dist/install-BgoC2e_2.cjs +88 -0
- package/dist/install-CFY3tYtJ.mjs +86 -0
- package/dist/{install-BOHrUaFM.cjs → install-Cs5qAPrB.cjs} +38 -38
- package/dist/{installPiTools-DuZ6jZvX.cjs → installPiTools-BKnXjrVu.cjs} +2 -3
- package/dist/{installPiTools-Cj7yU9Fc.mjs → installPiTools-B_CdM5_2.mjs} +1 -2
- package/dist/{installTerminalHooks-Cou3WUf3.cjs → installTerminalHooks-BQZbvxsZ.cjs} +5 -40
- package/dist/{installTerminalHooks-WeznjkuC.mjs → installTerminalHooks-By7gBMEF.mjs} +3 -38
- package/dist/lib.cjs +28 -19
- package/dist/lib.d.cts +12 -2
- package/dist/lib.d.mts +12 -2
- package/dist/lib.mjs +23 -14
- package/dist/lidState-BeDfxxEX.cjs +305 -0
- package/dist/lidState-CeEt442o.mjs +297 -0
- package/dist/limits-C-a7gr04.cjs +43 -0
- package/dist/limits-DIo7rEBR.mjs +36 -0
- package/dist/localHappyAgentAuth-C-HQyiv6.mjs +82 -0
- package/dist/localHappyAgentAuth-D6rFhaoc.cjs +86 -0
- package/dist/logger-6HYUEXNk.mjs +271 -0
- package/dist/logger-CS0mw3fa.cjs +275 -0
- package/dist/loginShellEnv-BkuYtExZ.cjs +182 -0
- package/dist/loginShellEnv-Dw8M7tkI.mjs +167 -0
- package/dist/machineMetadata-DyDbODYd.cjs +41 -0
- package/dist/machineMetadata-oOzBfDfs.mjs +38 -0
- package/dist/main-BkxJP6JQ.cjs +941 -0
- package/dist/main-BwNIAI1A.mjs +939 -0
- package/dist/manager-BQ4flvQZ.mjs +101 -0
- package/dist/manager-Cly8xVIR.cjs +105 -0
- package/dist/{mcp-Dy3f_K0h.mjs → mcp-B1A4I3TK.mjs} +27 -33
- package/dist/{mcp-CPYbtsYG.cjs → mcp-Hszd7qpS.cjs} +42 -48
- package/dist/messageBuffer-BWlGgR3A.mjs +71 -0
- package/dist/messageBuffer-fJMH6uY8.cjs +73 -0
- package/dist/mirrorProtocol-BNLtoWjO.mjs +170 -0
- package/dist/mirrorProtocol-BUtmg1ws.cjs +186 -0
- package/dist/oneShotPrompts-CL0dip9C.cjs +16 -0
- package/dist/oneShotPrompts-DT4p6RNd.mjs +12 -0
- package/dist/package-BhaKlnxz.mjs +171 -0
- package/dist/package-BwMrPwqH.cjs +173 -0
- package/dist/path-B7zW-WwE.cjs +18 -0
- package/dist/path-D2wdaNSk.mjs +15 -0
- package/dist/peerTools-BTqw97Gb.mjs +272 -0
- package/dist/peerTools-BvKtHXj8.cjs +283 -0
- package/dist/permissionMode-Cr5JCbB7.mjs +80 -0
- package/dist/permissionMode-CrV-XuMs.cjs +87 -0
- package/dist/persistence-HGW_ZVs9.mjs +372 -0
- package/dist/persistence-yKTH3-5X.cjs +414 -0
- package/dist/piExtension.mjs +2 -1
- package/dist/piRunnerArgs-BNloJCCg.cjs +66 -0
- package/dist/piRunnerArgs-BuX1UFWy.mjs +59 -0
- package/dist/{piRuntime-kLZNpAAl.mjs → piRuntime-CSGkwCKQ.mjs} +2 -2
- package/dist/{piRuntime-NtF0YqjH.cjs → piRuntime-C_H7MJCM.cjs} +4 -4
- package/dist/{piTerminal-B0fEOV_2.mjs → piTerminal-C8a1OrNQ.mjs} +32 -35
- package/dist/{piTerminal-9J0GAKzb.cjs → piTerminal-DNCZ6yTM.cjs} +32 -35
- package/dist/previewPath-B0rBdhy1.cjs +83 -0
- package/dist/previewPath-CXN4Vag0.mjs +81 -0
- package/dist/projectPath-BTBIMB57.mjs +10 -0
- package/dist/projectPath-ChLhdOyt.cjs +13 -0
- package/dist/registerCommonHandlers-Ccvsz7Ou.mjs +536 -0
- package/dist/registerCommonHandlers-DskirN-_.cjs +538 -0
- package/dist/registerKillSessionHandler-DZeLXWcB.cjs +361 -0
- package/dist/registerKillSessionHandler-GYvHdipX.mjs +358 -0
- package/dist/remoteSessionClient-B0LraSB9.cjs +634 -0
- package/dist/remoteSessionClient-CYnXRynE.mjs +612 -0
- package/dist/resources-BdFBQi8r.mjs +117 -0
- package/dist/resources-JDPugcDq.cjs +120 -0
- package/dist/run-CJzxoHVh.cjs +5762 -0
- package/dist/run-D3ifupU3.mjs +5739 -0
- package/dist/runClaude-Ba01qT-u.mjs +848 -0
- package/dist/runClaude-Da3RirzE.cjs +850 -0
- package/dist/runClaudeDeps-DOt79DjU.mjs +3624 -0
- package/dist/runClaudeDeps-DOzEBMls.cjs +3649 -0
- package/dist/{runGemini-DV6Ouadt.mjs → runGemini-BGeTz57m.mjs} +58 -31
- package/dist/{runGemini-F-mqx3_K.cjs → runGemini-DSr9LIxL.cjs} +202 -175
- package/dist/{runOpenClaw-Qqo9j63M.cjs → runOpenClaw-B1mTxN35.cjs} +64 -65
- package/dist/{runOpenClaw-D7MlPS5n.mjs → runOpenClaw-CogSedIc.mjs} +31 -32
- package/dist/sandbox-CG7IyDTU.cjs +187 -0
- package/dist/sandbox-DTe6d54R.mjs +180 -0
- package/dist/selfCheck-C9mVrQwf.mjs +84 -0
- package/dist/selfCheck-Dc-mNSLb.cjs +87 -0
- package/dist/{send-4qJTCAYW.cjs → send-B7J_eaG3.cjs} +16 -9
- package/dist/{send-CLhYXNgy.mjs → send-CBXJKc6O.mjs} +12 -5
- package/dist/server-CZTP_iOn.cjs +407 -0
- package/dist/server-DcVBv04l.mjs +404 -0
- package/dist/sessionLock-Bys1PNSo.cjs +205 -0
- package/dist/sessionLock-D-EG2CfG.mjs +197 -0
- package/dist/sessionModeFile-DMl3dw3r.mjs +32 -0
- package/dist/sessionModeFile-RSm0NQkH.cjs +36 -0
- package/dist/sessionOps-Dn8z85h_.cjs +783 -0
- package/dist/sessionOps-SuHW8Dfe.mjs +760 -0
- package/dist/sessionScanner-BOrGjMXL.cjs +209 -0
- package/dist/sessionScanner-CX3onqXh.mjs +206 -0
- package/dist/{sessions-CzIH2rGp.mjs → sessions-BEG_HTSi.mjs} +17 -8
- package/dist/{sessions-Bh1pyddi.cjs → sessions-D74aJbhL.cjs} +37 -28
- package/dist/setupOfflineReconnection-ByElY60m.cjs +74 -0
- package/dist/setupOfflineReconnection-DpvWTt69.mjs +72 -0
- package/dist/smallFastModel-BLNgMrwR.mjs +18 -0
- package/dist/smallFastModel-D_uxGMo3.cjs +21 -0
- package/dist/{spawn-CPIWlPOM.mjs → spawn-B7yro0b2.mjs} +26 -38
- package/dist/{spawn-CmFOSVdW.cjs → spawn-DgR0RKRs.cjs} +52 -64
- package/dist/spawnAgents-BGQiEF-w.cjs +52 -0
- package/dist/spawnAgents-DZzZ9jMI.mjs +45 -0
- package/dist/spawnHappyCLI-B2H5s4B_.mjs +64 -0
- package/dist/spawnHappyCLI-DBhwZT7O.cjs +66 -0
- package/dist/specialCommands-BSqhYg5X.mjs +52 -0
- package/dist/specialCommands-DSsTeRej.cjs +54 -0
- package/dist/startFileWatcher-B4VsLgjD.cjs +71 -0
- package/dist/startFileWatcher-DErVWZE4.mjs +69 -0
- package/dist/startupPlan-BLMbfQIH.cjs +12 -0
- package/dist/startupPlan-DFMyNgAs.mjs +10 -0
- package/dist/streamRelay-BiKw59Cc.cjs +233 -0
- package/dist/streamRelay-FPVbHpbM.mjs +231 -0
- package/dist/sync-C8gyQFMc.mjs +69 -0
- package/dist/sync-DccIKZ5_.cjs +71 -0
- package/dist/systemPrompt-BwTPWfMu.cjs +97 -0
- package/dist/systemPrompt-DX521JJz.mjs +94 -0
- package/dist/{teams-CEahj4cm.mjs → teams-C32F1hqd.mjs} +9 -40
- package/dist/{teams-CB1R9-Z9.cjs → teams-Dl8g8kTI.cjs} +14 -45
- package/dist/template-BaHAmH2K.cjs +129 -0
- package/dist/template-CiOPa2rd.mjs +121 -0
- package/dist/{terminalTitleSuggest-DKgX3osW.mjs → terminalTitleSuggest-CeKsX_V6.mjs} +1 -9
- package/dist/{terminalTitleSuggest-Dji8I0Jy.cjs → terminalTitleSuggest-DhvRFX3H.cjs} +0 -10
- package/dist/terminals-B_bfC9c2.cjs +250 -0
- package/dist/terminals-Dlg0x3nY.mjs +235 -0
- package/dist/time-D0XyHOid.mjs +38 -0
- package/dist/time-DCuTyook.cjs +42 -0
- package/dist/titleGenerator-CQ8CoGhg.mjs +166 -0
- package/dist/titleGenerator-ChzMJsyg.cjs +172 -0
- package/dist/tmuxSocket-B8Yx20sT.mjs +19 -0
- package/dist/tmuxSocket-D-Xt6Vn-.cjs +24 -0
- package/dist/{todo-DqyRI4wP.cjs → todo-BvUOTa8G.cjs} +15 -12
- package/dist/{todo-Cknp5D4U.mjs → todo-CZ6cFrrn.mjs} +11 -8
- package/dist/tools-BZtHF_qQ.mjs +177 -0
- package/dist/tools-Be3AoAwu.cjs +63 -0
- package/dist/tools-DQj0AeLk.cjs +180 -0
- package/dist/tools-DkluDcG4.mjs +60 -0
- package/dist/trimIdent-4gvk9Wk6.cjs +22 -0
- package/dist/trimIdent-BAjmv_TG.mjs +20 -0
- package/dist/types-CRS-srZK.cjs +66 -0
- package/dist/types-CkqAACXx.mjs +64 -0
- package/dist/uninstall-BkLzaJ6I.mjs +47 -0
- package/dist/uninstall-x-TUtf5H.cjs +49 -0
- package/package.json +7 -7
- package/dist/agentGuidance-BRDN1NoZ.cjs +0 -2217
- package/dist/agentGuidance-KgvYuF3R.mjs +0 -2145
- package/dist/index-BF6WfgV5.mjs +0 -19624
- package/dist/index-C-JazrMB.mjs +0 -52
- package/dist/index-blDSadUR.cjs +0 -58
- package/dist/index-rH3DrQ5B.cjs +0 -19688
- package/dist/limits-BH5CV5vR.cjs +0 -2683
- package/dist/limits-CjRj8IX5.mjs +0 -2558
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var spawn = require('cross-spawn');
|
|
4
|
+
var path = require('node:path');
|
|
5
|
+
var projectPath = require('./projectPath-ChLhdOyt.cjs');
|
|
6
|
+
var logger = require('./logger-CS0mw3fa.cjs');
|
|
7
|
+
var node_fs = require('node:fs');
|
|
8
|
+
|
|
9
|
+
let cachedRuntime = null;
|
|
10
|
+
function getRuntime() {
|
|
11
|
+
if (cachedRuntime) return cachedRuntime;
|
|
12
|
+
if (typeof globalThis.Bun !== "undefined") {
|
|
13
|
+
cachedRuntime = "bun";
|
|
14
|
+
return cachedRuntime;
|
|
15
|
+
}
|
|
16
|
+
if (typeof globalThis.Deno !== "undefined") {
|
|
17
|
+
cachedRuntime = "deno";
|
|
18
|
+
return cachedRuntime;
|
|
19
|
+
}
|
|
20
|
+
if (process?.versions?.bun) {
|
|
21
|
+
cachedRuntime = "bun";
|
|
22
|
+
return cachedRuntime;
|
|
23
|
+
}
|
|
24
|
+
if (process?.versions?.deno) {
|
|
25
|
+
cachedRuntime = "deno";
|
|
26
|
+
return cachedRuntime;
|
|
27
|
+
}
|
|
28
|
+
if (process?.versions?.node) {
|
|
29
|
+
cachedRuntime = "node";
|
|
30
|
+
return cachedRuntime;
|
|
31
|
+
}
|
|
32
|
+
cachedRuntime = "unknown";
|
|
33
|
+
return cachedRuntime;
|
|
34
|
+
}
|
|
35
|
+
const isBun = () => getRuntime() === "bun";
|
|
36
|
+
|
|
37
|
+
function spawnHappyCLI(args, options = {}) {
|
|
38
|
+
const projectRoot = projectPath.projectPath();
|
|
39
|
+
const entrypoint = path.join(projectRoot, "dist", "index.mjs");
|
|
40
|
+
let directory;
|
|
41
|
+
if ("cwd" in options) {
|
|
42
|
+
directory = options.cwd;
|
|
43
|
+
} else {
|
|
44
|
+
directory = process.cwd();
|
|
45
|
+
}
|
|
46
|
+
const fullCommand = `happy ${args.join(" ")}`;
|
|
47
|
+
logger.logger.debug(`[SPAWN HAPPY CLI] Spawning: ${fullCommand} in ${directory}`);
|
|
48
|
+
const nodeArgs = [
|
|
49
|
+
"--no-warnings",
|
|
50
|
+
"--no-deprecation",
|
|
51
|
+
entrypoint,
|
|
52
|
+
...args
|
|
53
|
+
];
|
|
54
|
+
if (!node_fs.existsSync(entrypoint)) {
|
|
55
|
+
const errorMessage = `Entrypoint ${entrypoint} does not exist`;
|
|
56
|
+
logger.logger.debug(`[SPAWN HAPPY CLI] ${errorMessage}`);
|
|
57
|
+
throw new Error(errorMessage);
|
|
58
|
+
}
|
|
59
|
+
const runtime = isBun() ? "bun" : "node";
|
|
60
|
+
return spawn.spawn(runtime, nodeArgs, {
|
|
61
|
+
windowsHide: true,
|
|
62
|
+
...options
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
exports.spawnHappyCLI = spawnHappyCLI;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
function parseCompact(message) {
|
|
2
|
+
const trimmed = message.trim();
|
|
3
|
+
if (trimmed === "/compact") {
|
|
4
|
+
return {
|
|
5
|
+
isCompact: true,
|
|
6
|
+
originalMessage: trimmed
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
if (trimmed.startsWith("/compact ")) {
|
|
10
|
+
return {
|
|
11
|
+
isCompact: true,
|
|
12
|
+
originalMessage: trimmed
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
isCompact: false,
|
|
17
|
+
originalMessage: message
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function parseClear(message) {
|
|
21
|
+
const trimmed = message.trim();
|
|
22
|
+
return {
|
|
23
|
+
isClear: trimmed === "/clear"
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function parseSpecialCommand(message) {
|
|
27
|
+
const compactResult = parseCompact(message);
|
|
28
|
+
if (compactResult.isCompact) {
|
|
29
|
+
return {
|
|
30
|
+
type: "compact",
|
|
31
|
+
originalMessage: compactResult.originalMessage
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const clearResult = parseClear(message);
|
|
35
|
+
if (clearResult.isClear) {
|
|
36
|
+
return {
|
|
37
|
+
type: "clear"
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const trimmed = message.trim().toLowerCase();
|
|
41
|
+
if (trimmed === "/mcp") {
|
|
42
|
+
return { type: "mcp" };
|
|
43
|
+
}
|
|
44
|
+
if (trimmed === "/skills") {
|
|
45
|
+
return { type: "skills" };
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
type: null
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { parseSpecialCommand as p };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function parseCompact(message) {
|
|
4
|
+
const trimmed = message.trim();
|
|
5
|
+
if (trimmed === "/compact") {
|
|
6
|
+
return {
|
|
7
|
+
isCompact: true,
|
|
8
|
+
originalMessage: trimmed
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
if (trimmed.startsWith("/compact ")) {
|
|
12
|
+
return {
|
|
13
|
+
isCompact: true,
|
|
14
|
+
originalMessage: trimmed
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
isCompact: false,
|
|
19
|
+
originalMessage: message
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function parseClear(message) {
|
|
23
|
+
const trimmed = message.trim();
|
|
24
|
+
return {
|
|
25
|
+
isClear: trimmed === "/clear"
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function parseSpecialCommand(message) {
|
|
29
|
+
const compactResult = parseCompact(message);
|
|
30
|
+
if (compactResult.isCompact) {
|
|
31
|
+
return {
|
|
32
|
+
type: "compact",
|
|
33
|
+
originalMessage: compactResult.originalMessage
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const clearResult = parseClear(message);
|
|
37
|
+
if (clearResult.isClear) {
|
|
38
|
+
return {
|
|
39
|
+
type: "clear"
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const trimmed = message.trim().toLowerCase();
|
|
43
|
+
if (trimmed === "/mcp") {
|
|
44
|
+
return { type: "mcp" };
|
|
45
|
+
}
|
|
46
|
+
if (trimmed === "/skills") {
|
|
47
|
+
return { type: "skills" };
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
type: null
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exports.parseSpecialCommand = parseSpecialCommand;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var logger = require('./logger-CS0mw3fa.cjs');
|
|
4
|
+
var fs = require('fs/promises');
|
|
5
|
+
|
|
6
|
+
function startFileWatcher(file, onFileChange, options = {}) {
|
|
7
|
+
const abortController = new AbortController();
|
|
8
|
+
const missingFileTimeoutMs = options.missingFileTimeoutMs ?? 6e4;
|
|
9
|
+
const wait = (ms) => new Promise((resolve) => {
|
|
10
|
+
if (abortController.signal.aborted) {
|
|
11
|
+
resolve();
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const timer = setTimeout(() => {
|
|
15
|
+
abortController.signal.removeEventListener("abort", onAbort);
|
|
16
|
+
resolve();
|
|
17
|
+
}, ms);
|
|
18
|
+
const onAbort = () => {
|
|
19
|
+
clearTimeout(timer);
|
|
20
|
+
resolve();
|
|
21
|
+
};
|
|
22
|
+
abortController.signal.addEventListener("abort", onAbort, { once: true });
|
|
23
|
+
});
|
|
24
|
+
void (async () => {
|
|
25
|
+
let missingSince = null;
|
|
26
|
+
let failureCount = 0;
|
|
27
|
+
while (true) {
|
|
28
|
+
try {
|
|
29
|
+
logger.logger.debug(`[FILE_WATCHER] Starting watcher for ${file}`);
|
|
30
|
+
const watcher = fs.watch(file, { persistent: true, signal: abortController.signal });
|
|
31
|
+
for await (const event of watcher) {
|
|
32
|
+
if (abortController.signal.aborted) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
missingSince = null;
|
|
36
|
+
failureCount = 0;
|
|
37
|
+
logger.logger.debug(`[FILE_WATCHER] File changed: ${file}`);
|
|
38
|
+
onFileChange(file);
|
|
39
|
+
}
|
|
40
|
+
} catch (e) {
|
|
41
|
+
if (abortController.signal.aborted) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const isMissing = e?.code === "ENOENT";
|
|
45
|
+
if (isMissing) {
|
|
46
|
+
const now = Date.now();
|
|
47
|
+
if (missingSince === null) {
|
|
48
|
+
missingSince = now;
|
|
49
|
+
}
|
|
50
|
+
const absentMs = now - missingSince;
|
|
51
|
+
if (absentMs >= missingFileTimeoutMs) {
|
|
52
|
+
logger.logger.debug(`[FILE_WATCHER] Giving up on ${file}: never appeared after ${Math.round(absentMs / 1e3)}s`);
|
|
53
|
+
options.onGaveUp?.();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
missingSince = null;
|
|
58
|
+
}
|
|
59
|
+
failureCount++;
|
|
60
|
+
const backoffMs = Math.min(1e3 * 2 ** Math.min(failureCount - 1, 4), 15e3);
|
|
61
|
+
logger.logger.debug(`[FILE_WATCHER] Watch error: ${e.message}, retrying in ${backoffMs}ms`);
|
|
62
|
+
await wait(backoffMs);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
})();
|
|
66
|
+
return () => {
|
|
67
|
+
abortController.abort();
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
exports.startFileWatcher = startFileWatcher;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { l as logger } from './logger-6HYUEXNk.mjs';
|
|
2
|
+
import { watch } from 'fs/promises';
|
|
3
|
+
|
|
4
|
+
function startFileWatcher(file, onFileChange, options = {}) {
|
|
5
|
+
const abortController = new AbortController();
|
|
6
|
+
const missingFileTimeoutMs = options.missingFileTimeoutMs ?? 6e4;
|
|
7
|
+
const wait = (ms) => new Promise((resolve) => {
|
|
8
|
+
if (abortController.signal.aborted) {
|
|
9
|
+
resolve();
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const timer = setTimeout(() => {
|
|
13
|
+
abortController.signal.removeEventListener("abort", onAbort);
|
|
14
|
+
resolve();
|
|
15
|
+
}, ms);
|
|
16
|
+
const onAbort = () => {
|
|
17
|
+
clearTimeout(timer);
|
|
18
|
+
resolve();
|
|
19
|
+
};
|
|
20
|
+
abortController.signal.addEventListener("abort", onAbort, { once: true });
|
|
21
|
+
});
|
|
22
|
+
void (async () => {
|
|
23
|
+
let missingSince = null;
|
|
24
|
+
let failureCount = 0;
|
|
25
|
+
while (true) {
|
|
26
|
+
try {
|
|
27
|
+
logger.debug(`[FILE_WATCHER] Starting watcher for ${file}`);
|
|
28
|
+
const watcher = watch(file, { persistent: true, signal: abortController.signal });
|
|
29
|
+
for await (const event of watcher) {
|
|
30
|
+
if (abortController.signal.aborted) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
missingSince = null;
|
|
34
|
+
failureCount = 0;
|
|
35
|
+
logger.debug(`[FILE_WATCHER] File changed: ${file}`);
|
|
36
|
+
onFileChange(file);
|
|
37
|
+
}
|
|
38
|
+
} catch (e) {
|
|
39
|
+
if (abortController.signal.aborted) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const isMissing = e?.code === "ENOENT";
|
|
43
|
+
if (isMissing) {
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
if (missingSince === null) {
|
|
46
|
+
missingSince = now;
|
|
47
|
+
}
|
|
48
|
+
const absentMs = now - missingSince;
|
|
49
|
+
if (absentMs >= missingFileTimeoutMs) {
|
|
50
|
+
logger.debug(`[FILE_WATCHER] Giving up on ${file}: never appeared after ${Math.round(absentMs / 1e3)}s`);
|
|
51
|
+
options.onGaveUp?.();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
missingSince = null;
|
|
56
|
+
}
|
|
57
|
+
failureCount++;
|
|
58
|
+
const backoffMs = Math.min(1e3 * 2 ** Math.min(failureCount - 1, 4), 15e3);
|
|
59
|
+
logger.debug(`[FILE_WATCHER] Watch error: ${e.message}, retrying in ${backoffMs}ms`);
|
|
60
|
+
await wait(backoffMs);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
})();
|
|
64
|
+
return () => {
|
|
65
|
+
abortController.abort();
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { startFileWatcher as s };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function planClaudeStartup(input) {
|
|
4
|
+
const daemonSpawned = input.startedBy === "daemon";
|
|
5
|
+
return {
|
|
6
|
+
registerMachine: !daemonSpawned,
|
|
7
|
+
ensureDaemonRunning: !daemonSpawned,
|
|
8
|
+
sessionClientBeforeWebhook: !input.reconnect
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
exports.planClaudeStartup = planClaudeStartup;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
function planClaudeStartup(input) {
|
|
2
|
+
const daemonSpawned = input.startedBy === "daemon";
|
|
3
|
+
return {
|
|
4
|
+
registerMachine: !daemonSpawned,
|
|
5
|
+
ensureDaemonRunning: !daemonSpawned,
|
|
6
|
+
sessionClientBeforeWebhook: !input.reconnect
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { planClaudeStartup as p };
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var index = require('./index-DA7yINuk.cjs');
|
|
4
|
+
|
|
5
|
+
const STREAM_FLUSH_MS = 80;
|
|
6
|
+
const PROGRESS_FLUSH_MS = 250;
|
|
7
|
+
const STREAM_FLUSH_MAX_BYTES = 16 * 1024;
|
|
8
|
+
class StreamRelay {
|
|
9
|
+
send;
|
|
10
|
+
setTimer;
|
|
11
|
+
clearTimer;
|
|
12
|
+
now;
|
|
13
|
+
/** The block currently accumulating deltas. At most one is open at a time
|
|
14
|
+
* in practice; a switch flushes the previous one first, so out-of-order
|
|
15
|
+
* SDK frames degrade to "slightly chunkier", never to interleaved text. */
|
|
16
|
+
pending = null;
|
|
17
|
+
flushHandle = null;
|
|
18
|
+
progress = {};
|
|
19
|
+
progressDirty = false;
|
|
20
|
+
progressHandle = null;
|
|
21
|
+
/** Message id of the block currently open, so `content_block_delta` (which
|
|
22
|
+
* carries only an index) can be attributed. Reset per assistant message. */
|
|
23
|
+
currentMid = null;
|
|
24
|
+
openBlocks = /* @__PURE__ */ new Set();
|
|
25
|
+
/** True while nothing has been ingested since the last sweep. Both the SDK
|
|
26
|
+
* `result` frame and the launcher's `finally` call endTurn (the second is
|
|
27
|
+
* the safety net for turns that die before producing a result), so
|
|
28
|
+
* without this a normal turn would emit two sweeps. */
|
|
29
|
+
idleSinceTurnEnd = true;
|
|
30
|
+
constructor(options) {
|
|
31
|
+
this.send = options.send;
|
|
32
|
+
this.setTimer = options.setTimer ?? ((fn, ms) => setTimeout(fn, ms));
|
|
33
|
+
this.clearTimer = options.clearTimer ?? ((handle) => clearTimeout(handle));
|
|
34
|
+
this.now = options.now ?? (() => Date.now());
|
|
35
|
+
}
|
|
36
|
+
/** Feed one SDK frame. Unknown shapes are ignored, never thrown on: this
|
|
37
|
+
* channel must not be able to take a turn down. */
|
|
38
|
+
ingest(message) {
|
|
39
|
+
this.idleSinceTurnEnd = false;
|
|
40
|
+
try {
|
|
41
|
+
if (message.type === "stream_event") {
|
|
42
|
+
this.ingestStreamEvent(message.event);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (message.type === "system" && message.subtype === "thinking_tokens") {
|
|
46
|
+
if (typeof message.estimated_tokens === "number") {
|
|
47
|
+
this.setProgress({ thinkingTokens: message.estimated_tokens });
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (message.type === "system" && message.subtype === "status") {
|
|
52
|
+
const status = message.status === "requesting" || message.status === "compacting" ? message.status : void 0;
|
|
53
|
+
this.progress.status = status;
|
|
54
|
+
this.progressDirty = true;
|
|
55
|
+
this.scheduleProgress();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** The turn produced its result. Flushes everything and tells the web to
|
|
62
|
+
* sweep drafts that no persisted message ever claimed. */
|
|
63
|
+
endTurn() {
|
|
64
|
+
if (this.idleSinceTurnEnd) {
|
|
65
|
+
this.clearTimers();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.idleSinceTurnEnd = true;
|
|
69
|
+
this.flushPending();
|
|
70
|
+
this.closeOpenBlocks();
|
|
71
|
+
this.flushProgress();
|
|
72
|
+
this.progress = {};
|
|
73
|
+
this.currentMid = null;
|
|
74
|
+
this.send({ t: "turn-end" });
|
|
75
|
+
}
|
|
76
|
+
/** Release timers without emitting anything (session teardown). */
|
|
77
|
+
dispose() {
|
|
78
|
+
this.clearTimers();
|
|
79
|
+
this.pending = null;
|
|
80
|
+
this.openBlocks.clear();
|
|
81
|
+
}
|
|
82
|
+
clearTimers() {
|
|
83
|
+
if (this.flushHandle !== null) this.clearTimer(this.flushHandle);
|
|
84
|
+
if (this.progressHandle !== null) this.clearTimer(this.progressHandle);
|
|
85
|
+
this.flushHandle = null;
|
|
86
|
+
this.progressHandle = null;
|
|
87
|
+
}
|
|
88
|
+
ingestStreamEvent(event) {
|
|
89
|
+
const e = event;
|
|
90
|
+
if (!e || typeof e.type !== "string") return;
|
|
91
|
+
if (e.type === "message_start") {
|
|
92
|
+
const mid = e.message?.id;
|
|
93
|
+
this.flushPending();
|
|
94
|
+
this.closeOpenBlocks();
|
|
95
|
+
this.currentMid = typeof mid === "string" && mid.length > 0 ? mid : null;
|
|
96
|
+
const usage = e.message?.usage;
|
|
97
|
+
if (usage || ["inputTokens", "cacheTokens", "outputTokens", "thinkingTokens"].some((key) => key in this.progress)) {
|
|
98
|
+
const count = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : 0;
|
|
99
|
+
this.setProgress({
|
|
100
|
+
inputTokens: count(usage?.input_tokens),
|
|
101
|
+
cacheTokens: count(usage?.cache_creation_input_tokens) + count(usage?.cache_read_input_tokens),
|
|
102
|
+
outputTokens: count(usage?.output_tokens),
|
|
103
|
+
thinkingTokens: 0
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (e.type === "content_block_start") {
|
|
109
|
+
const kind = e.content_block?.type === "thinking" ? "thinking" : e.content_block?.type === "text" ? "text" : null;
|
|
110
|
+
if (!kind || !this.currentMid || typeof e.index !== "number") return;
|
|
111
|
+
this.openBlock(this.currentMid, e.index, kind);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (e.type === "content_block_delta") {
|
|
115
|
+
const delta = e.delta;
|
|
116
|
+
const text = delta?.type === "text_delta" ? delta.text : delta?.type === "thinking_delta" ? delta.thinking : null;
|
|
117
|
+
if (typeof text !== "string" || text.length === 0) return;
|
|
118
|
+
if (!this.currentMid || typeof e.index !== "number") return;
|
|
119
|
+
this.appendDelta(this.currentMid, e.index, text);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (e.type === "content_block_stop") {
|
|
123
|
+
if (!this.currentMid || typeof e.index !== "number") return;
|
|
124
|
+
this.closeBlock(this.currentMid, e.index);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (e.type === "message_delta") {
|
|
128
|
+
const outputTokens = e.usage?.output_tokens;
|
|
129
|
+
if (typeof outputTokens === "number") {
|
|
130
|
+
this.setProgress({ outputTokens });
|
|
131
|
+
}
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// ---- Block-level API (see module comment) --------------------------------
|
|
136
|
+
/** Open a draft block. A different `mid` than the one currently open closes
|
|
137
|
+
* whatever the previous message left open, exactly like the SDK's
|
|
138
|
+
* `message_start` does. Re-opening an already open block is a no-op. */
|
|
139
|
+
openBlock(mid, idx, kind) {
|
|
140
|
+
this.idleSinceTurnEnd = false;
|
|
141
|
+
if (this.currentMid !== mid) {
|
|
142
|
+
this.flushPending();
|
|
143
|
+
this.closeOpenBlocks();
|
|
144
|
+
this.currentMid = mid;
|
|
145
|
+
}
|
|
146
|
+
if (this.openBlocks.has(idx)) return;
|
|
147
|
+
this.flushPending();
|
|
148
|
+
this.openBlocks.add(idx);
|
|
149
|
+
this.send({ t: "block-start", mid, idx, kind });
|
|
150
|
+
}
|
|
151
|
+
/** Append text to an OPEN block; deltas for a block that was never opened
|
|
152
|
+
* (or belongs to another message) are dropped — the SDK path relies on
|
|
153
|
+
* this to ignore `input_json_delta` for tool_use blocks. */
|
|
154
|
+
appendDelta(mid, idx, text) {
|
|
155
|
+
this.idleSinceTurnEnd = false;
|
|
156
|
+
if (text.length === 0) return;
|
|
157
|
+
if (this.currentMid !== mid || !this.openBlocks.has(idx)) return;
|
|
158
|
+
if (this.pending && (this.pending.mid !== mid || this.pending.idx !== idx)) {
|
|
159
|
+
this.flushPending();
|
|
160
|
+
}
|
|
161
|
+
if (!this.pending) {
|
|
162
|
+
this.pending = { mid, idx, text: "", bytes: 0 };
|
|
163
|
+
}
|
|
164
|
+
this.pending.text += text;
|
|
165
|
+
this.pending.bytes += Buffer.byteLength(text, "utf8");
|
|
166
|
+
if (this.pending.bytes >= STREAM_FLUSH_MAX_BYTES || this.pending.text.length >= index.STREAM_DELTA_MAX_CHARS) {
|
|
167
|
+
this.flushPending();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (this.flushHandle === null) {
|
|
171
|
+
this.flushHandle = this.setTimer(() => {
|
|
172
|
+
this.flushHandle = null;
|
|
173
|
+
this.flushPending();
|
|
174
|
+
}, STREAM_FLUSH_MS);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Close an open block: pending text goes out first, then `block-end`. */
|
|
178
|
+
closeBlock(mid, idx) {
|
|
179
|
+
this.idleSinceTurnEnd = false;
|
|
180
|
+
if (this.currentMid !== mid || !this.openBlocks.has(idx)) return;
|
|
181
|
+
this.flushPending();
|
|
182
|
+
this.openBlocks.delete(idx);
|
|
183
|
+
this.send({ t: "block-end", mid, idx });
|
|
184
|
+
}
|
|
185
|
+
/** Merge quantified progress; flushed on the progress cadence. */
|
|
186
|
+
setProgress(patch) {
|
|
187
|
+
this.idleSinceTurnEnd = false;
|
|
188
|
+
this.progress = { ...this.progress, ...patch };
|
|
189
|
+
this.progressDirty = true;
|
|
190
|
+
this.scheduleProgress();
|
|
191
|
+
}
|
|
192
|
+
// -------------------------------------------------------------------------
|
|
193
|
+
flushPending() {
|
|
194
|
+
if (this.flushHandle !== null) {
|
|
195
|
+
this.clearTimer(this.flushHandle);
|
|
196
|
+
this.flushHandle = null;
|
|
197
|
+
}
|
|
198
|
+
const pending = this.pending;
|
|
199
|
+
this.pending = null;
|
|
200
|
+
if (!pending || pending.text.length === 0) return;
|
|
201
|
+
this.send({ t: "block-delta", mid: pending.mid, idx: pending.idx, text: pending.text });
|
|
202
|
+
}
|
|
203
|
+
/** Close blocks the SDK never stopped (interrupt, error, message switch) so
|
|
204
|
+
* the web's draft does not keep a blinking cursor forever. */
|
|
205
|
+
closeOpenBlocks() {
|
|
206
|
+
if (!this.currentMid || this.openBlocks.size === 0) {
|
|
207
|
+
this.openBlocks.clear();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
for (const idx of [...this.openBlocks].sort((a, b) => a - b)) {
|
|
211
|
+
this.send({ t: "block-end", mid: this.currentMid, idx });
|
|
212
|
+
}
|
|
213
|
+
this.openBlocks.clear();
|
|
214
|
+
}
|
|
215
|
+
scheduleProgress() {
|
|
216
|
+
if (this.progressHandle !== null) return;
|
|
217
|
+
this.progressHandle = this.setTimer(() => {
|
|
218
|
+
this.progressHandle = null;
|
|
219
|
+
this.flushProgress();
|
|
220
|
+
}, PROGRESS_FLUSH_MS);
|
|
221
|
+
}
|
|
222
|
+
flushProgress() {
|
|
223
|
+
if (this.progressHandle !== null) {
|
|
224
|
+
this.clearTimer(this.progressHandle);
|
|
225
|
+
this.progressHandle = null;
|
|
226
|
+
}
|
|
227
|
+
if (!this.progressDirty) return;
|
|
228
|
+
this.progressDirty = false;
|
|
229
|
+
this.send({ t: "progress", ...this.progress });
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
exports.StreamRelay = StreamRelay;
|