@zonease/happy 0.6.37 → 0.6.39
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/{types-DYCJXXdA.mjs → api-CIZKyfSn.mjs} +136 -1725
- package/dist/{types-BrTorNAy.cjs → api-CwOCQeLH.cjs} +317 -1961
- package/dist/auth-0VnlXT9f.mjs +181 -0
- package/dist/auth-BE8dD20T.mjs +270 -0
- package/dist/auth-BIleVCw0.cjs +274 -0
- package/dist/auth-Cas9DR3b.cjs +183 -0
- package/dist/browser-Cc08m7of.cjs +22 -0
- package/dist/browser-Dll5hxOV.mjs +20 -0
- package/dist/claudeLocal-CPT3zcIU.mjs +344 -0
- package/dist/claudeLocal-WkgLbl1a.cjs +352 -0
- package/dist/codex/happyMcpStdioBridge.cjs +4 -1
- package/dist/codex/happyMcpStdioBridge.mjs +4 -1
- package/dist/common-BdNgghUJ.mjs +75 -0
- package/dist/common-CZvSRU4p.cjs +83 -0
- package/dist/{config-D_g6ohaV.cjs → config-Draa-5XC.cjs} +21 -34
- package/dist/{config-DPn-cbpz.mjs → config-rTT4qTU5.mjs} +7 -20
- package/dist/connect-BfC1tYP_.mjs +679 -0
- package/dist/connect-CJZ73syK.cjs +681 -0
- package/dist/{constants-B4x1K7by.cjs → constants-E_UWYTo3.cjs} +2 -2
- package/dist/{constants-BO9OAFOT.mjs → constants-pmXZGibX.mjs} +1 -1
- package/dist/controlClient-CM_QcJnB.mjs +159 -0
- package/dist/controlClient-DZMIsKsT.cjs +168 -0
- package/dist/deviceExec-CU1R9CRb.cjs +84 -0
- package/dist/deviceExec-D93AOVV4.mjs +81 -0
- package/dist/diagnose-B3D1a_v0.cjs +60 -0
- package/dist/diagnose-CuRKXxt1.mjs +58 -0
- package/dist/doctor-C08m5Z9f.cjs +78 -0
- package/dist/doctor-Cya9YSA0.cjs +214 -0
- package/dist/doctor-DZYB6IVc.mjs +211 -0
- package/dist/doctor-ON7pN5G5.mjs +74 -0
- package/dist/downloadImage-DfSFLb-h.mjs +887 -0
- package/dist/downloadImage-MQMrUUxS.cjs +897 -0
- package/dist/enroll-BxlbVftP.cjs +115 -0
- package/dist/enroll-C52x8oly.mjs +113 -0
- package/dist/evidence-Ccd9iYcj.mjs +127 -0
- package/dist/evidence-CjWBG5rX.cjs +129 -0
- package/dist/formatImageMessage-B4lSxlk2.mjs +43 -0
- package/dist/formatImageMessage-DbyG8c2j.cjs +46 -0
- package/dist/github-DKcyF1zp.mjs +57 -0
- package/dist/github-h9GhJJ_C.cjs +59 -0
- package/dist/index-CDTNgfUf.cjs +578 -0
- package/dist/index-CPKdvi7J.mjs +554 -0
- package/dist/index.cjs +812 -40
- package/dist/index.mjs +813 -40
- package/dist/install-BokHRgFW.cjs +98 -0
- package/dist/install-C_cp8b2-.cjs +96 -0
- package/dist/install-DAeCn8ae.mjs +94 -0
- package/dist/install-oRAjVLjP.mjs +95 -0
- package/dist/lib.cjs +18 -12
- package/dist/lib.d.cts +16 -16
- package/dist/lib.d.mts +16 -16
- package/dist/lib.mjs +13 -7
- package/dist/{loadableToolOutput-lQH8Kb_w.mjs → loadableToolOutput-Cuygmd4K.mjs} +4 -2
- package/dist/{loadableToolOutput-CasonFIt.cjs → loadableToolOutput-DDCJjywt.cjs} +63 -61
- package/dist/mcpToolSchemas-CjeTfrAs.mjs +62 -0
- package/dist/mcpToolSchemas-DK42yoZ_.cjs +64 -0
- package/dist/persistence-BFjvtUad.mjs +944 -0
- package/dist/persistence-JLUn_Nou.cjs +996 -0
- package/dist/projectPath-BTBIMB57.mjs +10 -0
- package/dist/projectPath-ChLhdOyt.cjs +13 -0
- package/dist/prompt-BTWDZZO0.cjs +25 -0
- package/dist/prompt-BsAZsPbo.mjs +22 -0
- package/dist/release-BMEzNONE.mjs +168 -0
- package/dist/release-EhOJeAZe.cjs +171 -0
- package/dist/run-BDn2aE3Q.cjs +2152 -0
- package/dist/run-DBZqN6Kn.mjs +2128 -0
- package/dist/runClaude-DNHvERX0.mjs +3763 -0
- package/dist/runClaude-uaKxPZPm.cjs +3766 -0
- package/dist/{runCodex-BTt3fxG4.cjs → runCodex-82UrZLme.cjs} +169 -153
- package/dist/{runCodex-BXCB5trB.mjs → runCodex-C-RTM0wA.mjs} +36 -20
- package/dist/{runGemini-37HHbp9n.mjs → runGemini-Bm6-4Xm2.mjs} +34 -17
- package/dist/{runGemini-C-0nSFBv.cjs → runGemini-CXMr4Jwb.cjs} +212 -195
- package/dist/{runOneShot-CXhbFJ2j.cjs → runOneShot-1B6RMYT7.cjs} +31 -55
- package/dist/{runOneShot-USX8QPfE.mjs → runOneShot-ioARRHrx.mjs} +14 -38
- package/dist/{serve-DZAq-_1F.cjs → serve-BtdAhkIE.cjs} +35 -58
- package/dist/{serve-BRedJPzL.mjs → serve-CwibwU6N.mjs} +12 -35
- package/dist/session-2sU4Bu1R.mjs +108 -0
- package/dist/session-D--F87zL.cjs +110 -0
- package/dist/sessionKeyCache-4Tp8pJ3N.cjs +36 -0
- package/dist/sessionKeyCache-D2BwO91C.mjs +33 -0
- package/dist/sessionList-BCSw3qYt.mjs +51 -0
- package/dist/sessionList-ICJsjNtJ.cjs +54 -0
- package/dist/sessionSummary-Bkz52BPh.cjs +393 -0
- package/dist/sessionSummary-lHGBWQSb.mjs +387 -0
- package/dist/spawnHappyCLI-CoORX0YW.mjs +66 -0
- package/dist/spawnHappyCLI-D_V-AAoP.cjs +70 -0
- package/dist/ssh-BTOlhhxi.cjs +333 -0
- package/dist/ssh-DL_AkRAD.mjs +328 -0
- package/dist/systemdScope-BeOtAkhk.mjs +25 -0
- package/dist/systemdScope-DW3-UoKB.cjs +29 -0
- package/dist/task-CQzrHRZe.mjs +165 -0
- package/dist/task-CSpaC9HX.cjs +167 -0
- package/dist/time-Bj2HRkKH.cjs +33 -0
- package/dist/time-DgsBLJA_.mjs +29 -0
- package/dist/trimIdent-4gvk9Wk6.cjs +22 -0
- package/dist/trimIdent-BAjmv_TG.mjs +20 -0
- package/dist/types-BoJh4Qfv.mjs +57 -0
- package/dist/types-DWeB7aqh.cjs +59 -0
- package/dist/uninstall-BiKyRAb1.cjs +77 -0
- package/dist/uninstall-nFMFGUVM.mjs +75 -0
- package/dist/update-BcqRHXf2.mjs +109 -0
- package/dist/update-Dw8pgsAT.cjs +111 -0
- package/dist/workflowCommon-B0d01Y_a.mjs +56 -0
- package/dist/workflowCommon-Bl568-rt.cjs +62 -0
- package/dist/workflowReports-BEWuQesA.cjs +113 -0
- package/dist/workflowReports-Dd8-4-8f.mjs +108 -0
- package/package.json +1 -1
- package/dist/index-BlkHOkB3.cjs +0 -11312
- package/dist/index-DJ2VpGiR.mjs +0 -11272
- package/dist/mcpToolSchemas-CdPXJQmb.mjs +0 -175
- package/dist/mcpToolSchemas-f-kttjFw.cjs +0 -186
|
@@ -1,1050 +1,35 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var axios = require('axios');
|
|
4
|
-
var
|
|
5
|
-
var fs$1 = require('fs');
|
|
6
|
-
var fs = require('node:fs');
|
|
7
|
-
var os = require('node:os');
|
|
8
|
-
var path = require('node:path');
|
|
4
|
+
var logger = require('./persistence-JLUn_Nou.cjs');
|
|
9
5
|
var node_events = require('node:events');
|
|
10
6
|
var socket_ioClient = require('socket.io-client');
|
|
11
7
|
var z = require('zod');
|
|
12
|
-
|
|
8
|
+
require('./index-CDTNgfUf.cjs');
|
|
9
|
+
var time = require('./time-Bj2HRkKH.cjs');
|
|
13
10
|
var node_crypto = require('node:crypto');
|
|
14
|
-
var
|
|
11
|
+
var fs = require('node:fs');
|
|
12
|
+
var path = require('node:path');
|
|
15
13
|
var node_child_process = require('node:child_process');
|
|
16
14
|
var promises = require('node:fs/promises');
|
|
15
|
+
var os = require('node:os');
|
|
17
16
|
var node_util = require('node:util');
|
|
18
17
|
var child_process = require('child_process');
|
|
19
18
|
var util = require('util');
|
|
20
|
-
var fs$
|
|
19
|
+
var fs$1 = require('fs/promises');
|
|
21
20
|
var path$1 = require('path');
|
|
22
|
-
var
|
|
21
|
+
var projectPath = require('./projectPath-ChLhdOyt.cjs');
|
|
23
22
|
var node_module = require('node:module');
|
|
24
23
|
var WebSocket = require('ws');
|
|
25
24
|
var crypto = require('crypto');
|
|
25
|
+
var tweetnacl = require('tweetnacl');
|
|
26
26
|
var base64 = require('@stablelib/base64');
|
|
27
27
|
var node_readline = require('node:readline');
|
|
28
28
|
var expoServerSdk = require('expo-server-sdk');
|
|
29
|
+
var sessionKeyCache = require('./sessionKeyCache-4Tp8pJ3N.cjs');
|
|
30
|
+
var chalk = require('chalk');
|
|
29
31
|
|
|
30
32
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
31
|
-
function _interopNamespaceDefault(e) {
|
|
32
|
-
var n = Object.create(null);
|
|
33
|
-
if (e) {
|
|
34
|
-
Object.keys(e).forEach(function (k) {
|
|
35
|
-
if (k !== 'default') {
|
|
36
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
37
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
38
|
-
enumerable: true,
|
|
39
|
-
get: function () { return e[k]; }
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
n.default = e;
|
|
45
|
-
return Object.freeze(n);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
|
|
49
|
-
|
|
50
|
-
const DEBUG_TRUE_VALUES = /* @__PURE__ */ new Set(["1", "true"]);
|
|
51
|
-
function isDebug() {
|
|
52
|
-
return DEBUG_TRUE_VALUES.has(process.env.DEBUG?.toLowerCase() ?? "");
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
var name = "@zonease/happy";
|
|
56
|
-
var version = "0.6.37";
|
|
57
|
-
var description = "Mobile and Web client for Claude Code, Codex, and Gemini";
|
|
58
|
-
var author = "ZonEaseTech";
|
|
59
|
-
var license = "MIT";
|
|
60
|
-
var type = "module";
|
|
61
|
-
var homepage = "https://github.com/ZonEaseTech/happy-wfs";
|
|
62
|
-
var bugs = "https://github.com/ZonEaseTech/happy-wfs/issues";
|
|
63
|
-
var repository = {
|
|
64
|
-
type: "git",
|
|
65
|
-
url: "git+https://github.com/ZonEaseTech/happy-wfs.git",
|
|
66
|
-
directory: "packages/happy-cli"
|
|
67
|
-
};
|
|
68
|
-
var bin = {
|
|
69
|
-
happy: "./bin/happy.mjs",
|
|
70
|
-
"happy-mcp": "./bin/happy-mcp.mjs"
|
|
71
|
-
};
|
|
72
|
-
var main = "./dist/index.cjs";
|
|
73
|
-
var module$1 = "./dist/index.mjs";
|
|
74
|
-
var types = "./dist/index.d.cts";
|
|
75
|
-
var exports$1 = {
|
|
76
|
-
".": {
|
|
77
|
-
require: {
|
|
78
|
-
types: "./dist/index.d.cts",
|
|
79
|
-
"default": "./dist/index.cjs"
|
|
80
|
-
},
|
|
81
|
-
"import": {
|
|
82
|
-
types: "./dist/index.d.mts",
|
|
83
|
-
"default": "./dist/index.mjs"
|
|
84
|
-
}
|
|
85
|
-
},
|
|
86
|
-
"./lib": {
|
|
87
|
-
require: {
|
|
88
|
-
types: "./dist/lib.d.cts",
|
|
89
|
-
"default": "./dist/lib.cjs"
|
|
90
|
-
},
|
|
91
|
-
"import": {
|
|
92
|
-
types: "./dist/lib.d.mts",
|
|
93
|
-
"default": "./dist/lib.mjs"
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
"./codex/happyMcpStdioBridge": {
|
|
97
|
-
require: {
|
|
98
|
-
types: "./dist/codex/happyMcpStdioBridge.d.cts",
|
|
99
|
-
"default": "./dist/codex/happyMcpStdioBridge.cjs"
|
|
100
|
-
},
|
|
101
|
-
"import": {
|
|
102
|
-
types: "./dist/codex/happyMcpStdioBridge.d.mts",
|
|
103
|
-
"default": "./dist/codex/happyMcpStdioBridge.mjs"
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
var files = [
|
|
108
|
-
"dist",
|
|
109
|
-
"bin",
|
|
110
|
-
"scripts",
|
|
111
|
-
"package.json"
|
|
112
|
-
];
|
|
113
|
-
var scripts = {
|
|
114
|
-
"why do we need to build before running tests / dev?": "We need the binary to be built so we run daemon commands which directly run the binary - we don't want them to go out of sync or have custom spawn logic depending how we started happy",
|
|
115
|
-
typecheck: "tsc --noEmit",
|
|
116
|
-
build: "shx rm -rf dist && tsc --noEmit && pkgroll",
|
|
117
|
-
test: "$npm_execpath run build && vitest run",
|
|
118
|
-
"test:integration": "$npm_execpath run build && vitest run --config vitest.integration.config.ts",
|
|
119
|
-
start: "$npm_execpath run build && node ./bin/happy.mjs",
|
|
120
|
-
dev: "tsx src/index.ts",
|
|
121
|
-
"dev:local-server": "$npm_execpath run build && tsx --env-file .env.dev-local-server src/index.ts",
|
|
122
|
-
"dev:integration-test-env": "$npm_execpath run build && tsx --env-file .env.integration-test src/index.ts",
|
|
123
|
-
prepublishOnly: "$npm_execpath run build && $npm_execpath test",
|
|
124
|
-
release: "$npm_execpath install && release-it",
|
|
125
|
-
postinstall: "node scripts/unpack-tools.cjs",
|
|
126
|
-
"// ==== Dev/Stable Variant Management ====": "",
|
|
127
|
-
stable: "node scripts/env-wrapper.cjs stable",
|
|
128
|
-
"dev:variant": "node scripts/env-wrapper.cjs dev",
|
|
129
|
-
"// ==== Stable Version Quick Commands ====": "",
|
|
130
|
-
"stable:daemon:start": "node scripts/env-wrapper.cjs stable daemon start",
|
|
131
|
-
"stable:daemon:stop": "node scripts/env-wrapper.cjs stable daemon stop",
|
|
132
|
-
"stable:daemon:status": "node scripts/env-wrapper.cjs stable daemon status",
|
|
133
|
-
"stable:auth": "node scripts/env-wrapper.cjs stable auth",
|
|
134
|
-
"// ==== Development Version Quick Commands ====": "",
|
|
135
|
-
"dev:daemon:start": "node scripts/env-wrapper.cjs dev daemon start",
|
|
136
|
-
"dev:daemon:stop": "node scripts/env-wrapper.cjs dev daemon stop",
|
|
137
|
-
"dev:daemon:status": "node scripts/env-wrapper.cjs dev daemon status",
|
|
138
|
-
"dev:auth": "node scripts/env-wrapper.cjs dev auth",
|
|
139
|
-
"// ==== Setup ====": "",
|
|
140
|
-
"setup:dev": "node scripts/setup-dev.cjs",
|
|
141
|
-
doctor: "node scripts/env-wrapper.cjs stable doctor",
|
|
142
|
-
"// ==== Development Linking ====": "",
|
|
143
|
-
"link:dev": "node scripts/link-dev.cjs",
|
|
144
|
-
"unlink:dev": "node scripts/link-dev.cjs unlink"
|
|
145
|
-
};
|
|
146
|
-
var dependencies = {
|
|
147
|
-
"@agentclientprotocol/sdk": "^0.14.1",
|
|
148
|
-
"@paralleldrive/cuid2": "^2.2.2",
|
|
149
|
-
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
150
|
-
"@stablelib/base64": "^2.0.1",
|
|
151
|
-
"@stablelib/hex": "^2.0.1",
|
|
152
|
-
"@types/cross-spawn": "^6.0.6",
|
|
153
|
-
"@types/http-proxy": "^1.17.17",
|
|
154
|
-
"@types/qrcode-terminal": "^0.12.2",
|
|
155
|
-
"@types/react": "^19.2.7",
|
|
156
|
-
"@types/tmp": "^0.2.6",
|
|
157
|
-
"@types/ws": "^8.18.1",
|
|
158
|
-
ai: "^5.0.107",
|
|
159
|
-
axios: "^1.13.2",
|
|
160
|
-
chalk: "^5.6.2",
|
|
161
|
-
"cross-spawn": "^7.0.6",
|
|
162
|
-
"expo-server-sdk": "^3.15.0",
|
|
163
|
-
fastify: "^5.6.2",
|
|
164
|
-
"fastify-type-provider-zod": "4.0.2",
|
|
165
|
-
"http-proxy": "^1.18.1",
|
|
166
|
-
"http-proxy-middleware": "^3.0.5",
|
|
167
|
-
ink: "^6.5.1",
|
|
168
|
-
open: "^10.2.0",
|
|
169
|
-
"ps-list": "^8.1.1",
|
|
170
|
-
"qrcode-terminal": "^0.12.0",
|
|
171
|
-
react: "^19.2.0",
|
|
172
|
-
"socket.io-client": "^4.8.1",
|
|
173
|
-
tar: "^7.5.2",
|
|
174
|
-
tmp: "^0.2.5",
|
|
175
|
-
tweetnacl: "^1.0.3",
|
|
176
|
-
ws: "^8.19.0",
|
|
177
|
-
zod: "3.25.76"
|
|
178
|
-
};
|
|
179
|
-
var devDependencies = {
|
|
180
|
-
"@eslint/compat": "^1",
|
|
181
|
-
"@types/node": ">=20",
|
|
182
|
-
"cross-env": "^10.1.0",
|
|
183
|
-
dotenv: "^16.6.1",
|
|
184
|
-
eslint: "^9",
|
|
185
|
-
"eslint-config-prettier": "^10",
|
|
186
|
-
pkgroll: "^2.14.2",
|
|
187
|
-
"release-it": "^19.0.6",
|
|
188
|
-
shx: "^0.3.3",
|
|
189
|
-
"ts-node": "^10",
|
|
190
|
-
tsx: "^4.20.6",
|
|
191
|
-
typescript: "5.9.3",
|
|
192
|
-
vitest: "^3.2.4",
|
|
193
|
-
"happy-wire": "*"
|
|
194
|
-
};
|
|
195
|
-
var resolutions = {
|
|
196
|
-
"whatwg-url": "14.2.0",
|
|
197
|
-
"parse-path": "7.0.3",
|
|
198
|
-
"@types/parse-path": "7.0.3"
|
|
199
|
-
};
|
|
200
|
-
var publishConfig = {
|
|
201
|
-
registry: "https://registry.npmjs.org",
|
|
202
|
-
access: "public"
|
|
203
|
-
};
|
|
204
|
-
var packageManager = "yarn@1.22.22";
|
|
205
|
-
var optionalDependencies = {
|
|
206
|
-
"node-pty": "^1.0.0",
|
|
207
|
-
"@zonease/happy-tools-arm64-darwin": "1.0.0",
|
|
208
|
-
"@zonease/happy-tools-x64-darwin": "1.0.0",
|
|
209
|
-
"@zonease/happy-tools-arm64-linux": "1.0.0",
|
|
210
|
-
"@zonease/happy-tools-x64-linux": "1.0.0",
|
|
211
|
-
"@zonease/happy-tools-x64-win32": "1.0.0",
|
|
212
|
-
"@zonease/happy-tools-arm64-win32": "1.0.0"
|
|
213
|
-
};
|
|
214
|
-
var packageJson = {
|
|
215
|
-
name: name,
|
|
216
|
-
version: version,
|
|
217
|
-
description: description,
|
|
218
|
-
author: author,
|
|
219
|
-
license: license,
|
|
220
|
-
type: type,
|
|
221
|
-
homepage: homepage,
|
|
222
|
-
bugs: bugs,
|
|
223
|
-
repository: repository,
|
|
224
|
-
bin: bin,
|
|
225
|
-
main: main,
|
|
226
|
-
module: module$1,
|
|
227
|
-
types: types,
|
|
228
|
-
exports: exports$1,
|
|
229
|
-
files: files,
|
|
230
|
-
scripts: scripts,
|
|
231
|
-
dependencies: dependencies,
|
|
232
|
-
devDependencies: devDependencies,
|
|
233
|
-
resolutions: resolutions,
|
|
234
|
-
publishConfig: publishConfig,
|
|
235
|
-
packageManager: packageManager,
|
|
236
|
-
optionalDependencies: optionalDependencies
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
class Configuration {
|
|
240
|
-
serverUrl;
|
|
241
|
-
webappUrl;
|
|
242
|
-
isDaemonProcess;
|
|
243
|
-
// Directories and paths (from persistence)
|
|
244
|
-
happyHomeDir;
|
|
245
|
-
logsDir;
|
|
246
|
-
settingsFile;
|
|
247
|
-
privateKeyFile;
|
|
248
|
-
daemonStateFile;
|
|
249
|
-
daemonLockFile;
|
|
250
|
-
sessionKeysDir;
|
|
251
|
-
currentCliVersion;
|
|
252
|
-
isExperimentalEnabled;
|
|
253
|
-
disableCaffeinate;
|
|
254
|
-
constructor() {
|
|
255
|
-
this.serverUrl = process.env.HAPPY_SERVER_URL || "https://api-happy.zonease.org";
|
|
256
|
-
this.webappUrl = process.env.HAPPY_WEBAPP_URL || "https://happy.zonease.org";
|
|
257
|
-
const args = process.argv.slice(2);
|
|
258
|
-
this.isDaemonProcess = args.length >= 2 && args[0] === "daemon" && args[1] === "start-sync";
|
|
259
|
-
if (process.env.HAPPY_HOME_DIR) {
|
|
260
|
-
const expandedPath = process.env.HAPPY_HOME_DIR.replace(/^~/, os.homedir());
|
|
261
|
-
this.happyHomeDir = expandedPath;
|
|
262
|
-
} else {
|
|
263
|
-
this.happyHomeDir = path.join(os.homedir(), ".happy");
|
|
264
|
-
}
|
|
265
|
-
this.logsDir = path.join(this.happyHomeDir, "logs");
|
|
266
|
-
this.settingsFile = path.join(this.happyHomeDir, "settings.json");
|
|
267
|
-
this.privateKeyFile = path.join(this.happyHomeDir, "access.key");
|
|
268
|
-
this.daemonStateFile = path.join(this.happyHomeDir, "daemon.state.json");
|
|
269
|
-
this.daemonLockFile = path.join(this.happyHomeDir, "daemon.state.json.lock");
|
|
270
|
-
this.sessionKeysDir = path.join(this.happyHomeDir, "session-keys");
|
|
271
|
-
this.isExperimentalEnabled = ["true", "1", "yes"].includes(process.env.HAPPY_EXPERIMENTAL?.toLowerCase() || "");
|
|
272
|
-
this.disableCaffeinate = ["true", "1", "yes"].includes(process.env.HAPPY_DISABLE_CAFFEINATE?.toLowerCase() || "");
|
|
273
|
-
this.currentCliVersion = packageJson.version;
|
|
274
|
-
const variant = process.env.HAPPY_VARIANT || "stable";
|
|
275
|
-
if (variant === "dev" && !this.happyHomeDir.includes("dev")) {
|
|
276
|
-
console.warn('\u26A0\uFE0F WARNING: HAPPY_VARIANT=dev but HAPPY_HOME_DIR does not contain "dev"');
|
|
277
|
-
console.warn(` Current: ${this.happyHomeDir}`);
|
|
278
|
-
console.warn(` Expected: Should contain "dev" (e.g., ~/.happy-dev)`);
|
|
279
|
-
}
|
|
280
|
-
if (!this.isDaemonProcess && variant === "dev") {
|
|
281
|
-
console.log("\x1B[33m\u{1F527} DEV MODE\x1B[0m - Data: " + this.happyHomeDir);
|
|
282
|
-
}
|
|
283
|
-
if (!fs.existsSync(this.happyHomeDir)) {
|
|
284
|
-
fs.mkdirSync(this.happyHomeDir, { recursive: true });
|
|
285
|
-
}
|
|
286
|
-
if (!fs.existsSync(this.logsDir)) {
|
|
287
|
-
fs.mkdirSync(this.logsDir, { recursive: true });
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
const configuration = new Configuration();
|
|
292
|
-
|
|
293
|
-
function createTimestampForFilename(date = /* @__PURE__ */ new Date()) {
|
|
294
|
-
return date.toLocaleString("sv-SE", {
|
|
295
|
-
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
296
|
-
year: "numeric",
|
|
297
|
-
month: "2-digit",
|
|
298
|
-
day: "2-digit",
|
|
299
|
-
hour: "2-digit",
|
|
300
|
-
minute: "2-digit",
|
|
301
|
-
second: "2-digit"
|
|
302
|
-
}).replace(/[: ]/g, "-").replace(/,/g, "") + "-pid-" + process.pid;
|
|
303
|
-
}
|
|
304
|
-
function createTimestampForLogEntry(date = /* @__PURE__ */ new Date()) {
|
|
305
|
-
return date.toLocaleTimeString("en-US", {
|
|
306
|
-
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
307
|
-
hour12: false,
|
|
308
|
-
hour: "2-digit",
|
|
309
|
-
minute: "2-digit",
|
|
310
|
-
second: "2-digit",
|
|
311
|
-
fractionalSecondDigits: 3
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
function getSessionLogPath() {
|
|
315
|
-
const timestamp = createTimestampForFilename();
|
|
316
|
-
const filename = configuration.isDaemonProcess ? `${timestamp}-daemon.log` : `${timestamp}.log`;
|
|
317
|
-
return path.join(configuration.logsDir, filename);
|
|
318
|
-
}
|
|
319
|
-
class Logger {
|
|
320
|
-
constructor(logFilePath = getSessionLogPath()) {
|
|
321
|
-
this.logFilePath = logFilePath;
|
|
322
|
-
if (process.env.DANGEROUSLY_LOG_TO_SERVER_FOR_AI_AUTO_DEBUGGING && process.env.HAPPY_SERVER_URL) {
|
|
323
|
-
this.dangerouslyUnencryptedServerLoggingUrl = process.env.HAPPY_SERVER_URL;
|
|
324
|
-
console.log(chalk.yellow("[REMOTE LOGGING] Sending logs to server for AI debugging"));
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
dangerouslyUnencryptedServerLoggingUrl;
|
|
328
|
-
// Use local timezone for simplicity of locating the logs,
|
|
329
|
-
// in practice you will not need absolute timestamps
|
|
330
|
-
localTimezoneTimestamp() {
|
|
331
|
-
return createTimestampForLogEntry();
|
|
332
|
-
}
|
|
333
|
-
debug(message, ...args) {
|
|
334
|
-
this.logToFile(`[${this.localTimezoneTimestamp()}]`, message, ...args);
|
|
335
|
-
}
|
|
336
|
-
debugLargeJson(message, object, maxStringLength = 100, maxArrayLength = 10) {
|
|
337
|
-
if (!isDebug()) {
|
|
338
|
-
this.debug(`In production, skipping message inspection`);
|
|
339
|
-
}
|
|
340
|
-
const truncateStrings = (obj) => {
|
|
341
|
-
if (typeof obj === "string") {
|
|
342
|
-
return obj.length > maxStringLength ? obj.substring(0, maxStringLength) + "... [truncated for logs]" : obj;
|
|
343
|
-
}
|
|
344
|
-
if (Array.isArray(obj)) {
|
|
345
|
-
const truncatedArray = obj.map((item) => truncateStrings(item)).slice(0, maxArrayLength);
|
|
346
|
-
if (obj.length > maxArrayLength) {
|
|
347
|
-
truncatedArray.push(`... [truncated array for logs up to ${maxArrayLength} items]`);
|
|
348
|
-
}
|
|
349
|
-
return truncatedArray;
|
|
350
|
-
}
|
|
351
|
-
if (obj && typeof obj === "object") {
|
|
352
|
-
const result = {};
|
|
353
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
354
|
-
if (key === "usage") {
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
result[key] = truncateStrings(value);
|
|
358
|
-
}
|
|
359
|
-
return result;
|
|
360
|
-
}
|
|
361
|
-
return obj;
|
|
362
|
-
};
|
|
363
|
-
const truncatedObject = truncateStrings(object);
|
|
364
|
-
const json = JSON.stringify(truncatedObject, null, 2);
|
|
365
|
-
this.logToFile(`[${this.localTimezoneTimestamp()}]`, message, "\n", json);
|
|
366
|
-
}
|
|
367
|
-
info(message, ...args) {
|
|
368
|
-
this.logToConsole("info", "", message, ...args);
|
|
369
|
-
this.debug(message, args);
|
|
370
|
-
}
|
|
371
|
-
infoDeveloper(message, ...args) {
|
|
372
|
-
this.debug(message, ...args);
|
|
373
|
-
if (isDebug()) {
|
|
374
|
-
this.logToConsole("info", "[DEV]", message, ...args);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
warn(message, ...args) {
|
|
378
|
-
this.logToConsole("warn", "", message, ...args);
|
|
379
|
-
this.debug(`[WARN] ${message}`, ...args);
|
|
380
|
-
}
|
|
381
|
-
getLogPath() {
|
|
382
|
-
return this.logFilePath;
|
|
383
|
-
}
|
|
384
|
-
logToConsole(level, prefix, message, ...args) {
|
|
385
|
-
switch (level) {
|
|
386
|
-
case "debug": {
|
|
387
|
-
console.log(chalk.gray(prefix), message, ...args);
|
|
388
|
-
break;
|
|
389
|
-
}
|
|
390
|
-
case "error": {
|
|
391
|
-
console.error(chalk.red(prefix), message, ...args);
|
|
392
|
-
break;
|
|
393
|
-
}
|
|
394
|
-
case "info": {
|
|
395
|
-
console.log(chalk.blue(prefix), message, ...args);
|
|
396
|
-
break;
|
|
397
|
-
}
|
|
398
|
-
case "warn": {
|
|
399
|
-
console.log(chalk.yellow(prefix), message, ...args);
|
|
400
|
-
break;
|
|
401
|
-
}
|
|
402
|
-
default: {
|
|
403
|
-
this.debug("Unknown log level:", level);
|
|
404
|
-
console.log(chalk.blue(prefix), message, ...args);
|
|
405
|
-
break;
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
async sendToRemoteServer(level, message, ...args) {
|
|
410
|
-
if (!this.dangerouslyUnencryptedServerLoggingUrl) return;
|
|
411
|
-
try {
|
|
412
|
-
await fetch(this.dangerouslyUnencryptedServerLoggingUrl + "/logs-combined-from-cli-and-mobile-for-simple-ai-debugging", {
|
|
413
|
-
method: "POST",
|
|
414
|
-
headers: { "Content-Type": "application/json" },
|
|
415
|
-
body: JSON.stringify({
|
|
416
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
417
|
-
level,
|
|
418
|
-
message: `${message} ${args.map(
|
|
419
|
-
(a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)
|
|
420
|
-
).join(" ")}`,
|
|
421
|
-
source: "cli",
|
|
422
|
-
platform: process.platform
|
|
423
|
-
})
|
|
424
|
-
});
|
|
425
|
-
} catch (error) {
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
logToFile(prefix, message, ...args) {
|
|
429
|
-
const logLine = `${prefix} ${message} ${args.map((arg) => {
|
|
430
|
-
if (typeof arg === "string") return arg;
|
|
431
|
-
if (arg instanceof Error) return `${arg.message}
|
|
432
|
-
${arg.stack ?? ""}`;
|
|
433
|
-
return JSON.stringify(arg);
|
|
434
|
-
}).join(" ")}
|
|
435
|
-
`;
|
|
436
|
-
if (this.dangerouslyUnencryptedServerLoggingUrl) {
|
|
437
|
-
let level = "info";
|
|
438
|
-
if (prefix.includes(this.localTimezoneTimestamp())) {
|
|
439
|
-
level = "debug";
|
|
440
|
-
}
|
|
441
|
-
this.sendToRemoteServer(level, message, ...args).catch(() => {
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
try {
|
|
445
|
-
fs$1.appendFileSync(this.logFilePath, logLine);
|
|
446
|
-
} catch (appendError) {
|
|
447
|
-
if (isDebug()) {
|
|
448
|
-
console.error("[DEV MODE ONLY THROWING] Failed to append to log file:", appendError);
|
|
449
|
-
throw appendError;
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
let logger = new Logger();
|
|
455
|
-
async function listDaemonLogFiles(limit = 50) {
|
|
456
|
-
try {
|
|
457
|
-
const logsDir = configuration.logsDir;
|
|
458
|
-
if (!fs.existsSync(logsDir)) {
|
|
459
|
-
return [];
|
|
460
|
-
}
|
|
461
|
-
const logs = fs.readdirSync(logsDir).filter((file) => file.endsWith("-daemon.log")).map((file) => {
|
|
462
|
-
const fullPath = path.join(logsDir, file);
|
|
463
|
-
const stats = fs.statSync(fullPath);
|
|
464
|
-
return { file, path: fullPath, modified: stats.mtime };
|
|
465
|
-
}).sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
466
|
-
try {
|
|
467
|
-
const { readDaemonState } = await Promise.resolve().then(function () { return persistence; });
|
|
468
|
-
const state = await readDaemonState();
|
|
469
|
-
if (!state) {
|
|
470
|
-
return logs;
|
|
471
|
-
}
|
|
472
|
-
if (state.daemonLogPath && fs.existsSync(state.daemonLogPath)) {
|
|
473
|
-
const stats = fs.statSync(state.daemonLogPath);
|
|
474
|
-
const persisted = {
|
|
475
|
-
file: path.basename(state.daemonLogPath),
|
|
476
|
-
path: state.daemonLogPath,
|
|
477
|
-
modified: stats.mtime
|
|
478
|
-
};
|
|
479
|
-
const idx = logs.findIndex((l) => l.path === persisted.path);
|
|
480
|
-
if (idx >= 0) {
|
|
481
|
-
const [found] = logs.splice(idx, 1);
|
|
482
|
-
logs.unshift(found);
|
|
483
|
-
} else {
|
|
484
|
-
logs.unshift(persisted);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
} catch {
|
|
488
|
-
}
|
|
489
|
-
return logs.slice(0, Math.max(0, limit));
|
|
490
|
-
} catch {
|
|
491
|
-
return [];
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
async function getLatestDaemonLog() {
|
|
495
|
-
const [latest] = await listDaemonLogFiles(1);
|
|
496
|
-
return latest || null;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
const sessionRoleSchema = z__namespace.enum(["user", "agent"]);
|
|
500
|
-
const sessionTextEventSchema = z__namespace.object({
|
|
501
|
-
t: z__namespace.literal("text"),
|
|
502
|
-
text: z__namespace.string(),
|
|
503
|
-
thinking: z__namespace.boolean().optional()
|
|
504
|
-
});
|
|
505
|
-
const sessionServiceMessageEventSchema = z__namespace.object({
|
|
506
|
-
t: z__namespace.literal("service"),
|
|
507
|
-
text: z__namespace.string()
|
|
508
|
-
});
|
|
509
|
-
const sessionToolCallStartEventSchema = z__namespace.object({
|
|
510
|
-
t: z__namespace.literal("tool-call-start"),
|
|
511
|
-
call: z__namespace.string(),
|
|
512
|
-
name: z__namespace.string(),
|
|
513
|
-
title: z__namespace.string(),
|
|
514
|
-
description: z__namespace.string(),
|
|
515
|
-
args: z__namespace.record(z__namespace.string(), z__namespace.unknown())
|
|
516
|
-
});
|
|
517
|
-
const sessionToolCallEndEventSchema = z__namespace.object({
|
|
518
|
-
t: z__namespace.literal("tool-call-end"),
|
|
519
|
-
call: z__namespace.string()
|
|
520
|
-
});
|
|
521
|
-
const sessionFileEventSchema = z__namespace.object({
|
|
522
|
-
t: z__namespace.literal("file"),
|
|
523
|
-
ref: z__namespace.string(),
|
|
524
|
-
name: z__namespace.string(),
|
|
525
|
-
size: z__namespace.number(),
|
|
526
|
-
image: z__namespace.object({
|
|
527
|
-
width: z__namespace.number(),
|
|
528
|
-
height: z__namespace.number(),
|
|
529
|
-
thumbhash: z__namespace.string()
|
|
530
|
-
}).optional()
|
|
531
|
-
});
|
|
532
|
-
const sessionTurnStartEventSchema = z__namespace.object({
|
|
533
|
-
t: z__namespace.literal("turn-start")
|
|
534
|
-
});
|
|
535
|
-
const sessionStartEventSchema = z__namespace.object({
|
|
536
|
-
t: z__namespace.literal("start"),
|
|
537
|
-
title: z__namespace.string().optional()
|
|
538
|
-
});
|
|
539
|
-
const sessionTurnEndStatusSchema = z__namespace.enum(["completed", "failed", "cancelled"]);
|
|
540
|
-
const sessionTurnEndEventSchema = z__namespace.object({
|
|
541
|
-
t: z__namespace.literal("turn-end"),
|
|
542
|
-
status: sessionTurnEndStatusSchema
|
|
543
|
-
});
|
|
544
|
-
const sessionStopEventSchema = z__namespace.object({
|
|
545
|
-
t: z__namespace.literal("stop")
|
|
546
|
-
});
|
|
547
|
-
const sessionEventSchema = z__namespace.discriminatedUnion("t", [
|
|
548
|
-
sessionTextEventSchema,
|
|
549
|
-
sessionServiceMessageEventSchema,
|
|
550
|
-
sessionToolCallStartEventSchema,
|
|
551
|
-
sessionToolCallEndEventSchema,
|
|
552
|
-
sessionFileEventSchema,
|
|
553
|
-
sessionTurnStartEventSchema,
|
|
554
|
-
sessionStartEventSchema,
|
|
555
|
-
sessionTurnEndEventSchema,
|
|
556
|
-
sessionStopEventSchema
|
|
557
|
-
]);
|
|
558
|
-
const sessionEnvelopeSchema = z__namespace.object({
|
|
559
|
-
id: z__namespace.string(),
|
|
560
|
-
time: z__namespace.number(),
|
|
561
|
-
role: sessionRoleSchema,
|
|
562
|
-
turn: z__namespace.string().optional(),
|
|
563
|
-
subagent: z__namespace.string().refine((value) => cuid2.isCuid(value), {
|
|
564
|
-
message: "subagent must be a cuid2 value"
|
|
565
|
-
}).optional(),
|
|
566
|
-
ev: sessionEventSchema
|
|
567
|
-
}).superRefine((envelope, ctx) => {
|
|
568
|
-
if (envelope.ev.t === "service" && envelope.role !== "agent") {
|
|
569
|
-
ctx.addIssue({
|
|
570
|
-
code: z__namespace.ZodIssueCode.custom,
|
|
571
|
-
message: 'service events must use role "agent"',
|
|
572
|
-
path: ["role"]
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
if ((envelope.ev.t === "start" || envelope.ev.t === "stop") && envelope.role !== "agent") {
|
|
576
|
-
ctx.addIssue({
|
|
577
|
-
code: z__namespace.ZodIssueCode.custom,
|
|
578
|
-
message: `${envelope.ev.t} events must use role "agent"`,
|
|
579
|
-
path: ["role"]
|
|
580
|
-
});
|
|
581
|
-
}
|
|
582
|
-
});
|
|
583
|
-
const MessageMetaSchema$1 = z__namespace.object({
|
|
584
|
-
sentFrom: z__namespace.string().optional(),
|
|
585
|
-
permissionMode: z__namespace.enum(["default", "acceptEdits", "bypassPermissions", "plan", "read-only", "safe-yolo", "yolo"]).optional(),
|
|
586
|
-
model: z__namespace.string().nullable().optional(),
|
|
587
|
-
fallbackModel: z__namespace.string().nullable().optional(),
|
|
588
|
-
reasoningEffort: z__namespace.string().nullable().optional(),
|
|
589
|
-
customSystemPrompt: z__namespace.string().nullable().optional(),
|
|
590
|
-
appendSystemPrompt: z__namespace.string().nullable().optional(),
|
|
591
|
-
allowedTools: z__namespace.array(z__namespace.string()).nullable().optional(),
|
|
592
|
-
disallowedTools: z__namespace.array(z__namespace.string()).nullable().optional(),
|
|
593
|
-
displayText: z__namespace.string().optional()
|
|
594
|
-
});
|
|
595
|
-
const UserMessageSchema$1 = z__namespace.object({
|
|
596
|
-
role: z__namespace.literal("user"),
|
|
597
|
-
content: z__namespace.object({
|
|
598
|
-
type: z__namespace.literal("text"),
|
|
599
|
-
text: z__namespace.string()
|
|
600
|
-
}),
|
|
601
|
-
localKey: z__namespace.string().optional(),
|
|
602
|
-
meta: MessageMetaSchema$1.optional()
|
|
603
|
-
});
|
|
604
|
-
const AgentMessageSchema$1 = z__namespace.object({
|
|
605
|
-
role: z__namespace.literal("agent"),
|
|
606
|
-
content: z__namespace.object({
|
|
607
|
-
type: z__namespace.string()
|
|
608
|
-
}).passthrough(),
|
|
609
|
-
meta: MessageMetaSchema$1.optional()
|
|
610
|
-
});
|
|
611
|
-
z__namespace.discriminatedUnion("role", [UserMessageSchema$1, AgentMessageSchema$1]);
|
|
612
|
-
const SessionMessageContentSchema = z__namespace.object({
|
|
613
|
-
c: z__namespace.string(),
|
|
614
|
-
t: z__namespace.literal("encrypted")
|
|
615
|
-
});
|
|
616
|
-
const SessionMessageSchema = z__namespace.object({
|
|
617
|
-
id: z__namespace.string(),
|
|
618
|
-
seq: z__namespace.number(),
|
|
619
|
-
localId: z__namespace.string().nullish(),
|
|
620
|
-
content: SessionMessageContentSchema,
|
|
621
|
-
createdAt: z__namespace.number(),
|
|
622
|
-
updatedAt: z__namespace.number()
|
|
623
|
-
});
|
|
624
|
-
const SessionProtocolMessageSchema = z__namespace.object({
|
|
625
|
-
role: z__namespace.literal("session"),
|
|
626
|
-
content: sessionEnvelopeSchema,
|
|
627
|
-
meta: MessageMetaSchema$1.optional()
|
|
628
|
-
});
|
|
629
|
-
z__namespace.discriminatedUnion("role", [
|
|
630
|
-
UserMessageSchema$1,
|
|
631
|
-
AgentMessageSchema$1,
|
|
632
|
-
SessionProtocolMessageSchema
|
|
633
|
-
]);
|
|
634
|
-
const VersionedEncryptedValueSchema = z__namespace.object({
|
|
635
|
-
version: z__namespace.number(),
|
|
636
|
-
value: z__namespace.string()
|
|
637
|
-
});
|
|
638
|
-
const VersionedNullableEncryptedValueSchema = z__namespace.object({
|
|
639
|
-
version: z__namespace.number(),
|
|
640
|
-
value: z__namespace.string().nullable()
|
|
641
|
-
});
|
|
642
|
-
const UpdateNewMessageBodySchema = z__namespace.object({
|
|
643
|
-
t: z__namespace.literal("new-message"),
|
|
644
|
-
sid: z__namespace.string(),
|
|
645
|
-
message: SessionMessageSchema
|
|
646
|
-
});
|
|
647
|
-
const UpdateSessionBodySchema = z__namespace.object({
|
|
648
|
-
t: z__namespace.literal("update-session"),
|
|
649
|
-
id: z__namespace.string(),
|
|
650
|
-
metadata: VersionedEncryptedValueSchema.nullish(),
|
|
651
|
-
agentState: VersionedNullableEncryptedValueSchema.nullish()
|
|
652
|
-
});
|
|
653
|
-
const VersionedMachineEncryptedValueSchema = z__namespace.object({
|
|
654
|
-
version: z__namespace.number(),
|
|
655
|
-
value: z__namespace.string()
|
|
656
|
-
});
|
|
657
|
-
const UpdateMachineBodySchema = z__namespace.object({
|
|
658
|
-
t: z__namespace.literal("update-machine"),
|
|
659
|
-
machineId: z__namespace.string(),
|
|
660
|
-
metadata: VersionedMachineEncryptedValueSchema.nullish(),
|
|
661
|
-
daemonState: VersionedMachineEncryptedValueSchema.nullish(),
|
|
662
|
-
active: z__namespace.boolean().optional(),
|
|
663
|
-
activeAt: z__namespace.number().optional()
|
|
664
|
-
});
|
|
665
|
-
const CoreUpdateBodySchema = z__namespace.discriminatedUnion("t", [
|
|
666
|
-
UpdateNewMessageBodySchema,
|
|
667
|
-
UpdateSessionBodySchema,
|
|
668
|
-
UpdateMachineBodySchema
|
|
669
|
-
]);
|
|
670
|
-
z__namespace.object({
|
|
671
|
-
id: z__namespace.string(),
|
|
672
|
-
seq: z__namespace.number(),
|
|
673
|
-
body: CoreUpdateBodySchema,
|
|
674
|
-
createdAt: z__namespace.number()
|
|
675
|
-
});
|
|
676
|
-
const MODEL_MODE_DEFAULT = "default";
|
|
677
|
-
const MODEL_MODES = [
|
|
678
|
-
MODEL_MODE_DEFAULT,
|
|
679
|
-
"claude-fable-5",
|
|
680
|
-
"claude-fable-5[1m]",
|
|
681
|
-
"claude-opus-5",
|
|
682
|
-
"claude-opus-5[1m]",
|
|
683
|
-
"claude-opus-4-8",
|
|
684
|
-
"claude-opus-4-8[1m]",
|
|
685
|
-
"claude-opus-4-6",
|
|
686
|
-
"claude-opus-4-6[1m]",
|
|
687
|
-
"claude-sonnet-4-6",
|
|
688
|
-
"claude-sonnet-4-6[1m]",
|
|
689
|
-
"claude-haiku-4-5",
|
|
690
|
-
"claude-fable-5-low",
|
|
691
|
-
"claude-fable-5-medium",
|
|
692
|
-
"claude-fable-5-high",
|
|
693
|
-
"claude-fable-5-xhigh",
|
|
694
|
-
"claude-fable-5-max",
|
|
695
|
-
"claude-fable-5[1m]-low",
|
|
696
|
-
"claude-fable-5[1m]-medium",
|
|
697
|
-
"claude-fable-5[1m]-high",
|
|
698
|
-
"claude-fable-5[1m]-xhigh",
|
|
699
|
-
"claude-fable-5[1m]-max",
|
|
700
|
-
"claude-opus-5-low",
|
|
701
|
-
"claude-opus-5-medium",
|
|
702
|
-
"claude-opus-5-high",
|
|
703
|
-
"claude-opus-5-xhigh",
|
|
704
|
-
"claude-opus-5-max",
|
|
705
|
-
"claude-opus-5[1m]-low",
|
|
706
|
-
"claude-opus-5[1m]-medium",
|
|
707
|
-
"claude-opus-5[1m]-high",
|
|
708
|
-
"claude-opus-5[1m]-xhigh",
|
|
709
|
-
"claude-opus-5[1m]-max",
|
|
710
|
-
"claude-opus-4-8-low",
|
|
711
|
-
"claude-opus-4-8-medium",
|
|
712
|
-
"claude-opus-4-8-high",
|
|
713
|
-
"claude-opus-4-8-xhigh",
|
|
714
|
-
"claude-opus-4-8-max",
|
|
715
|
-
"claude-opus-4-8[1m]-low",
|
|
716
|
-
"claude-opus-4-8[1m]-medium",
|
|
717
|
-
"claude-opus-4-8[1m]-high",
|
|
718
|
-
"claude-opus-4-8[1m]-xhigh",
|
|
719
|
-
"claude-opus-4-8[1m]-max",
|
|
720
|
-
"claude-opus-4-6-low",
|
|
721
|
-
"claude-opus-4-6-medium",
|
|
722
|
-
"claude-opus-4-6-high",
|
|
723
|
-
"claude-opus-4-6-max",
|
|
724
|
-
"claude-opus-4-6[1m]-low",
|
|
725
|
-
"claude-opus-4-6[1m]-medium",
|
|
726
|
-
"claude-opus-4-6[1m]-high",
|
|
727
|
-
"claude-opus-4-6[1m]-max",
|
|
728
|
-
"claude-sonnet-4-6-low",
|
|
729
|
-
"claude-sonnet-4-6-medium",
|
|
730
|
-
"claude-sonnet-4-6-high",
|
|
731
|
-
"claude-sonnet-4-6[1m]-low",
|
|
732
|
-
"claude-sonnet-4-6[1m]-medium",
|
|
733
|
-
"claude-sonnet-4-6[1m]-high",
|
|
734
|
-
"claude-haiku-4-5-low",
|
|
735
|
-
"claude-haiku-4-5-medium",
|
|
736
|
-
"claude-haiku-4-5-high",
|
|
737
|
-
"gpt-5.6-sol-low",
|
|
738
|
-
"gpt-5.6-sol-medium",
|
|
739
|
-
"gpt-5.6-sol-high",
|
|
740
|
-
"gpt-5.6-sol-xhigh",
|
|
741
|
-
"gpt-5.6-sol-max",
|
|
742
|
-
"gpt-5.6-terra-low",
|
|
743
|
-
"gpt-5.6-terra-medium",
|
|
744
|
-
"gpt-5.6-terra-high",
|
|
745
|
-
"gpt-5.6-terra-xhigh",
|
|
746
|
-
"gpt-5.6-luna-low",
|
|
747
|
-
"gpt-5.6-luna-medium",
|
|
748
|
-
"gpt-5.6-luna-high",
|
|
749
|
-
"gpt-5.6-luna-xhigh",
|
|
750
|
-
"gpt-5.5-low",
|
|
751
|
-
"gpt-5.5-medium",
|
|
752
|
-
"gpt-5.5-high",
|
|
753
|
-
"gpt-5.5-xhigh",
|
|
754
|
-
"gpt-5.4-low",
|
|
755
|
-
"gpt-5.4-medium",
|
|
756
|
-
"gpt-5.4-high",
|
|
757
|
-
"gpt-5.4-xhigh",
|
|
758
|
-
"gpt-5.3-codex-low",
|
|
759
|
-
"gpt-5.3-codex-medium",
|
|
760
|
-
"gpt-5.3-codex-high",
|
|
761
|
-
"gpt-5.3-codex-xhigh",
|
|
762
|
-
"gpt-5.2-codex-low",
|
|
763
|
-
"gpt-5.2-codex-medium",
|
|
764
|
-
"gpt-5.2-codex-high",
|
|
765
|
-
"gpt-5.2-codex-xhigh",
|
|
766
|
-
"gpt-5.2-low",
|
|
767
|
-
"gpt-5.2-medium",
|
|
768
|
-
"gpt-5.2-high",
|
|
769
|
-
"gpt-5.2-xhigh",
|
|
770
|
-
"gpt-5.1-codex-max-low",
|
|
771
|
-
"gpt-5.1-codex-max-medium",
|
|
772
|
-
"gpt-5.1-codex-max-high",
|
|
773
|
-
"gpt-5.1-codex-max-xhigh",
|
|
774
|
-
"gpt-5.1-codex-mini-medium",
|
|
775
|
-
"gpt-5.1-codex-mini-high",
|
|
776
|
-
"gemini-3-pro-preview",
|
|
777
|
-
"gemini-3-flash-preview",
|
|
778
|
-
"gemini-2.5-pro"
|
|
779
|
-
];
|
|
780
|
-
const CLAUDE_MODEL_MODES = [
|
|
781
|
-
MODEL_MODE_DEFAULT,
|
|
782
|
-
"claude-fable-5",
|
|
783
|
-
"claude-fable-5[1m]",
|
|
784
|
-
"claude-opus-5",
|
|
785
|
-
"claude-opus-5[1m]",
|
|
786
|
-
"claude-opus-4-8",
|
|
787
|
-
"claude-opus-4-8[1m]",
|
|
788
|
-
"claude-opus-4-6",
|
|
789
|
-
"claude-opus-4-6[1m]",
|
|
790
|
-
"claude-sonnet-4-6",
|
|
791
|
-
"claude-sonnet-4-6[1m]",
|
|
792
|
-
"claude-haiku-4-5",
|
|
793
|
-
"claude-fable-5-low",
|
|
794
|
-
"claude-fable-5-medium",
|
|
795
|
-
"claude-fable-5-high",
|
|
796
|
-
"claude-fable-5-xhigh",
|
|
797
|
-
"claude-fable-5-max",
|
|
798
|
-
"claude-fable-5[1m]-low",
|
|
799
|
-
"claude-fable-5[1m]-medium",
|
|
800
|
-
"claude-fable-5[1m]-high",
|
|
801
|
-
"claude-fable-5[1m]-xhigh",
|
|
802
|
-
"claude-fable-5[1m]-max",
|
|
803
|
-
"claude-opus-5-low",
|
|
804
|
-
"claude-opus-5-medium",
|
|
805
|
-
"claude-opus-5-high",
|
|
806
|
-
"claude-opus-5-xhigh",
|
|
807
|
-
"claude-opus-5-max",
|
|
808
|
-
"claude-opus-5[1m]-low",
|
|
809
|
-
"claude-opus-5[1m]-medium",
|
|
810
|
-
"claude-opus-5[1m]-high",
|
|
811
|
-
"claude-opus-5[1m]-xhigh",
|
|
812
|
-
"claude-opus-5[1m]-max",
|
|
813
|
-
"claude-opus-4-8-low",
|
|
814
|
-
"claude-opus-4-8-medium",
|
|
815
|
-
"claude-opus-4-8-high",
|
|
816
|
-
"claude-opus-4-8-xhigh",
|
|
817
|
-
"claude-opus-4-8-max",
|
|
818
|
-
"claude-opus-4-8[1m]-low",
|
|
819
|
-
"claude-opus-4-8[1m]-medium",
|
|
820
|
-
"claude-opus-4-8[1m]-high",
|
|
821
|
-
"claude-opus-4-8[1m]-xhigh",
|
|
822
|
-
"claude-opus-4-8[1m]-max",
|
|
823
|
-
"claude-opus-4-6-low",
|
|
824
|
-
"claude-opus-4-6-medium",
|
|
825
|
-
"claude-opus-4-6-high",
|
|
826
|
-
"claude-opus-4-6-max",
|
|
827
|
-
"claude-opus-4-6[1m]-low",
|
|
828
|
-
"claude-opus-4-6[1m]-medium",
|
|
829
|
-
"claude-opus-4-6[1m]-high",
|
|
830
|
-
"claude-opus-4-6[1m]-max",
|
|
831
|
-
"claude-sonnet-4-6-low",
|
|
832
|
-
"claude-sonnet-4-6-medium",
|
|
833
|
-
"claude-sonnet-4-6-high",
|
|
834
|
-
"claude-sonnet-4-6[1m]-low",
|
|
835
|
-
"claude-sonnet-4-6[1m]-medium",
|
|
836
|
-
"claude-sonnet-4-6[1m]-high",
|
|
837
|
-
"claude-haiku-4-5-low",
|
|
838
|
-
"claude-haiku-4-5-medium",
|
|
839
|
-
"claude-haiku-4-5-high"
|
|
840
|
-
];
|
|
841
|
-
const GEMINI_MODEL_MODES = [
|
|
842
|
-
MODEL_MODE_DEFAULT,
|
|
843
|
-
"gemini-3-pro-preview",
|
|
844
|
-
"gemini-3-flash-preview",
|
|
845
|
-
"gemini-2.5-pro"
|
|
846
|
-
];
|
|
847
|
-
const CODEX_MODEL_MODES = [
|
|
848
|
-
MODEL_MODE_DEFAULT,
|
|
849
|
-
"gpt-5.6-sol-low",
|
|
850
|
-
"gpt-5.6-sol-medium",
|
|
851
|
-
"gpt-5.6-sol-high",
|
|
852
|
-
"gpt-5.6-sol-xhigh",
|
|
853
|
-
"gpt-5.6-sol-max",
|
|
854
|
-
"gpt-5.6-terra-low",
|
|
855
|
-
"gpt-5.6-terra-medium",
|
|
856
|
-
"gpt-5.6-terra-high",
|
|
857
|
-
"gpt-5.6-terra-xhigh",
|
|
858
|
-
"gpt-5.6-luna-low",
|
|
859
|
-
"gpt-5.6-luna-medium",
|
|
860
|
-
"gpt-5.6-luna-high",
|
|
861
|
-
"gpt-5.6-luna-xhigh",
|
|
862
|
-
"gpt-5.5-low",
|
|
863
|
-
"gpt-5.5-medium",
|
|
864
|
-
"gpt-5.5-high",
|
|
865
|
-
"gpt-5.5-xhigh",
|
|
866
|
-
"gpt-5.4-low",
|
|
867
|
-
"gpt-5.4-medium",
|
|
868
|
-
"gpt-5.4-high",
|
|
869
|
-
"gpt-5.4-xhigh",
|
|
870
|
-
"gpt-5.3-codex-low",
|
|
871
|
-
"gpt-5.3-codex-medium",
|
|
872
|
-
"gpt-5.3-codex-high",
|
|
873
|
-
"gpt-5.3-codex-xhigh",
|
|
874
|
-
"gpt-5.2-codex-low",
|
|
875
|
-
"gpt-5.2-codex-medium",
|
|
876
|
-
"gpt-5.2-codex-high",
|
|
877
|
-
"gpt-5.2-codex-xhigh",
|
|
878
|
-
"gpt-5.2-low",
|
|
879
|
-
"gpt-5.2-medium",
|
|
880
|
-
"gpt-5.2-high",
|
|
881
|
-
"gpt-5.2-xhigh",
|
|
882
|
-
"gpt-5.1-codex-max-low",
|
|
883
|
-
"gpt-5.1-codex-max-medium",
|
|
884
|
-
"gpt-5.1-codex-max-high",
|
|
885
|
-
"gpt-5.1-codex-max-xhigh",
|
|
886
|
-
"gpt-5.1-codex-mini-medium",
|
|
887
|
-
"gpt-5.1-codex-mini-high"
|
|
888
|
-
];
|
|
889
|
-
const MODEL_MODE_SET = new Set(MODEL_MODES);
|
|
890
|
-
const CLAUDE_MODEL_MODE_SET = new Set(CLAUDE_MODEL_MODES);
|
|
891
|
-
const GEMINI_MODEL_MODE_SET = new Set(GEMINI_MODEL_MODES);
|
|
892
|
-
const CODEX_MODEL_MODE_SET = new Set(CODEX_MODEL_MODES);
|
|
893
|
-
function isModelMode(value) {
|
|
894
|
-
return MODEL_MODE_SET.has(value);
|
|
895
|
-
}
|
|
896
|
-
function isModelModeForAgent(agent, mode) {
|
|
897
|
-
if (!isModelMode(mode)) return false;
|
|
898
|
-
if (agent === "claude") return CLAUDE_MODEL_MODE_SET.has(mode);
|
|
899
|
-
if (agent === "gemini") return GEMINI_MODEL_MODE_SET.has(mode);
|
|
900
|
-
return CODEX_MODEL_MODE_SET.has(mode);
|
|
901
|
-
}
|
|
902
|
-
const CLAUDE_MODE_TO_SELECTION = {
|
|
903
|
-
"claude-fable-5-low": { family: "claude-fable-5", effort: "low" },
|
|
904
|
-
"claude-fable-5-medium": { family: "claude-fable-5", effort: "medium" },
|
|
905
|
-
"claude-fable-5-high": { family: "claude-fable-5", effort: "high" },
|
|
906
|
-
"claude-fable-5-xhigh": { family: "claude-fable-5", effort: "xhigh" },
|
|
907
|
-
"claude-fable-5-max": { family: "claude-fable-5", effort: "max" },
|
|
908
|
-
"claude-fable-5[1m]-low": { family: "claude-fable-5[1m]", effort: "low" },
|
|
909
|
-
"claude-fable-5[1m]-medium": { family: "claude-fable-5[1m]", effort: "medium" },
|
|
910
|
-
"claude-fable-5[1m]-high": { family: "claude-fable-5[1m]", effort: "high" },
|
|
911
|
-
"claude-fable-5[1m]-xhigh": { family: "claude-fable-5[1m]", effort: "xhigh" },
|
|
912
|
-
"claude-fable-5[1m]-max": { family: "claude-fable-5[1m]", effort: "max" },
|
|
913
|
-
"claude-opus-5-low": { family: "claude-opus-5", effort: "low" },
|
|
914
|
-
"claude-opus-5-medium": { family: "claude-opus-5", effort: "medium" },
|
|
915
|
-
"claude-opus-5-high": { family: "claude-opus-5", effort: "high" },
|
|
916
|
-
"claude-opus-5-xhigh": { family: "claude-opus-5", effort: "xhigh" },
|
|
917
|
-
"claude-opus-5-max": { family: "claude-opus-5", effort: "max" },
|
|
918
|
-
"claude-opus-5[1m]-low": { family: "claude-opus-5[1m]", effort: "low" },
|
|
919
|
-
"claude-opus-5[1m]-medium": { family: "claude-opus-5[1m]", effort: "medium" },
|
|
920
|
-
"claude-opus-5[1m]-high": { family: "claude-opus-5[1m]", effort: "high" },
|
|
921
|
-
"claude-opus-5[1m]-xhigh": { family: "claude-opus-5[1m]", effort: "xhigh" },
|
|
922
|
-
"claude-opus-5[1m]-max": { family: "claude-opus-5[1m]", effort: "max" },
|
|
923
|
-
"claude-opus-4-8-low": { family: "claude-opus-4-8", effort: "low" },
|
|
924
|
-
"claude-opus-4-8-medium": { family: "claude-opus-4-8", effort: "medium" },
|
|
925
|
-
"claude-opus-4-8-high": { family: "claude-opus-4-8", effort: "high" },
|
|
926
|
-
"claude-opus-4-8-xhigh": { family: "claude-opus-4-8", effort: "xhigh" },
|
|
927
|
-
"claude-opus-4-8-max": { family: "claude-opus-4-8", effort: "max" },
|
|
928
|
-
"claude-opus-4-8[1m]-low": { family: "claude-opus-4-8[1m]", effort: "low" },
|
|
929
|
-
"claude-opus-4-8[1m]-medium": { family: "claude-opus-4-8[1m]", effort: "medium" },
|
|
930
|
-
"claude-opus-4-8[1m]-high": { family: "claude-opus-4-8[1m]", effort: "high" },
|
|
931
|
-
"claude-opus-4-8[1m]-xhigh": { family: "claude-opus-4-8[1m]", effort: "xhigh" },
|
|
932
|
-
"claude-opus-4-8[1m]-max": { family: "claude-opus-4-8[1m]", effort: "max" },
|
|
933
|
-
"claude-opus-4-6-low": { family: "claude-opus-4-6", effort: "low" },
|
|
934
|
-
"claude-opus-4-6-medium": { family: "claude-opus-4-6", effort: "medium" },
|
|
935
|
-
"claude-opus-4-6-high": { family: "claude-opus-4-6", effort: "high" },
|
|
936
|
-
"claude-opus-4-6-max": { family: "claude-opus-4-6", effort: "max" },
|
|
937
|
-
"claude-opus-4-6[1m]-low": { family: "claude-opus-4-6[1m]", effort: "low" },
|
|
938
|
-
"claude-opus-4-6[1m]-medium": { family: "claude-opus-4-6[1m]", effort: "medium" },
|
|
939
|
-
"claude-opus-4-6[1m]-high": { family: "claude-opus-4-6[1m]", effort: "high" },
|
|
940
|
-
"claude-opus-4-6[1m]-max": { family: "claude-opus-4-6[1m]", effort: "max" },
|
|
941
|
-
"claude-sonnet-4-6-low": { family: "claude-sonnet-4-6", effort: "low" },
|
|
942
|
-
"claude-sonnet-4-6-medium": { family: "claude-sonnet-4-6", effort: "medium" },
|
|
943
|
-
"claude-sonnet-4-6-high": { family: "claude-sonnet-4-6", effort: "high" },
|
|
944
|
-
"claude-sonnet-4-6[1m]-low": { family: "claude-sonnet-4-6[1m]", effort: "low" },
|
|
945
|
-
"claude-sonnet-4-6[1m]-medium": { family: "claude-sonnet-4-6[1m]", effort: "medium" },
|
|
946
|
-
"claude-sonnet-4-6[1m]-high": { family: "claude-sonnet-4-6[1m]", effort: "high" },
|
|
947
|
-
"claude-haiku-4-5-low": { family: "claude-haiku-4-5", effort: "low" },
|
|
948
|
-
"claude-haiku-4-5-medium": { family: "claude-haiku-4-5", effort: "medium" },
|
|
949
|
-
"claude-haiku-4-5-high": { family: "claude-haiku-4-5", effort: "high" }
|
|
950
|
-
};
|
|
951
|
-
const CODEX_MODE_TO_SELECTION = {
|
|
952
|
-
"gpt-5.6-sol-low": { family: "gpt-5.6-sol", effort: "low" },
|
|
953
|
-
"gpt-5.6-sol-medium": { family: "gpt-5.6-sol", effort: "medium" },
|
|
954
|
-
"gpt-5.6-sol-high": { family: "gpt-5.6-sol", effort: "high" },
|
|
955
|
-
"gpt-5.6-sol-xhigh": { family: "gpt-5.6-sol", effort: "xhigh" },
|
|
956
|
-
"gpt-5.6-sol-max": { family: "gpt-5.6-sol", effort: "max" },
|
|
957
|
-
"gpt-5.6-terra-low": { family: "gpt-5.6-terra", effort: "low" },
|
|
958
|
-
"gpt-5.6-terra-medium": { family: "gpt-5.6-terra", effort: "medium" },
|
|
959
|
-
"gpt-5.6-terra-high": { family: "gpt-5.6-terra", effort: "high" },
|
|
960
|
-
"gpt-5.6-terra-xhigh": { family: "gpt-5.6-terra", effort: "xhigh" },
|
|
961
|
-
"gpt-5.6-luna-low": { family: "gpt-5.6-luna", effort: "low" },
|
|
962
|
-
"gpt-5.6-luna-medium": { family: "gpt-5.6-luna", effort: "medium" },
|
|
963
|
-
"gpt-5.6-luna-high": { family: "gpt-5.6-luna", effort: "high" },
|
|
964
|
-
"gpt-5.6-luna-xhigh": { family: "gpt-5.6-luna", effort: "xhigh" },
|
|
965
|
-
"gpt-5.5-low": { family: "gpt-5.5", effort: "low" },
|
|
966
|
-
"gpt-5.5-medium": { family: "gpt-5.5", effort: "medium" },
|
|
967
|
-
"gpt-5.5-high": { family: "gpt-5.5", effort: "high" },
|
|
968
|
-
"gpt-5.5-xhigh": { family: "gpt-5.5", effort: "xhigh" },
|
|
969
|
-
"gpt-5.4-low": { family: "gpt-5.4", effort: "low" },
|
|
970
|
-
"gpt-5.4-medium": { family: "gpt-5.4", effort: "medium" },
|
|
971
|
-
"gpt-5.4-high": { family: "gpt-5.4", effort: "high" },
|
|
972
|
-
"gpt-5.4-xhigh": { family: "gpt-5.4", effort: "xhigh" },
|
|
973
|
-
"gpt-5.3-codex-low": { family: "gpt-5.3-codex", effort: "low" },
|
|
974
|
-
"gpt-5.3-codex-medium": { family: "gpt-5.3-codex", effort: "medium" },
|
|
975
|
-
"gpt-5.3-codex-high": { family: "gpt-5.3-codex", effort: "high" },
|
|
976
|
-
"gpt-5.3-codex-xhigh": { family: "gpt-5.3-codex", effort: "xhigh" },
|
|
977
|
-
"gpt-5.2-codex-low": { family: "gpt-5.2-codex", effort: "low" },
|
|
978
|
-
"gpt-5.2-codex-medium": { family: "gpt-5.2-codex", effort: "medium" },
|
|
979
|
-
"gpt-5.2-codex-high": { family: "gpt-5.2-codex", effort: "high" },
|
|
980
|
-
"gpt-5.2-codex-xhigh": { family: "gpt-5.2-codex", effort: "xhigh" },
|
|
981
|
-
"gpt-5.2-low": { family: "gpt-5.2", effort: "low" },
|
|
982
|
-
"gpt-5.2-medium": { family: "gpt-5.2", effort: "medium" },
|
|
983
|
-
"gpt-5.2-high": { family: "gpt-5.2", effort: "high" },
|
|
984
|
-
"gpt-5.2-xhigh": { family: "gpt-5.2", effort: "xhigh" },
|
|
985
|
-
"gpt-5.1-codex-max-low": { family: "gpt-5.1-codex-max", effort: "low" },
|
|
986
|
-
"gpt-5.1-codex-max-medium": { family: "gpt-5.1-codex-max", effort: "medium" },
|
|
987
|
-
"gpt-5.1-codex-max-high": { family: "gpt-5.1-codex-max", effort: "high" },
|
|
988
|
-
"gpt-5.1-codex-max-xhigh": { family: "gpt-5.1-codex-max", effort: "xhigh" },
|
|
989
|
-
"gpt-5.1-codex-mini-medium": { family: "gpt-5.1-codex-mini", effort: "medium" },
|
|
990
|
-
"gpt-5.1-codex-mini-high": { family: "gpt-5.1-codex-mini", effort: "high" }
|
|
991
|
-
};
|
|
992
|
-
function parseClaudeModelMode(mode) {
|
|
993
|
-
const entry = CLAUDE_MODE_TO_SELECTION[mode];
|
|
994
|
-
if (entry) return entry;
|
|
995
|
-
if (mode === MODEL_MODE_DEFAULT) return { family: MODEL_MODE_DEFAULT, effort: null };
|
|
996
|
-
return { family: mode, effort: null };
|
|
997
|
-
}
|
|
998
|
-
function parseCodexModelMode(mode) {
|
|
999
|
-
return CODEX_MODE_TO_SELECTION[mode] ?? { family: MODEL_MODE_DEFAULT, effort: "medium" };
|
|
1000
|
-
}
|
|
1001
|
-
const FeishuWebhookConfigSchema = z.z.object({
|
|
1002
|
-
url: z.z.string().url(),
|
|
1003
|
-
secret: z.z.string().optional(),
|
|
1004
|
-
enabled: z.z.boolean()
|
|
1005
|
-
});
|
|
1006
|
-
z.z.object({
|
|
1007
|
-
url: z.z.string().nullable(),
|
|
1008
|
-
secret_set: z.z.boolean(),
|
|
1009
|
-
enabled: z.z.boolean(),
|
|
1010
|
-
lastTestedAt: z.z.number().nullable()
|
|
1011
|
-
});
|
|
1012
|
-
z.z.object({
|
|
1013
|
-
feishu: FeishuWebhookConfigSchema.extend({
|
|
1014
|
-
lastTestedAt: z.z.number().optional()
|
|
1015
|
-
}).optional(),
|
|
1016
|
-
feishuMention: FeishuWebhookConfigSchema.extend({
|
|
1017
|
-
lastTestedAt: z.z.number().optional()
|
|
1018
|
-
}).optional(),
|
|
1019
|
-
/**
|
|
1020
|
-
* The account owner's own Feishu identity (open_id `ou_…` or tenant
|
|
1021
|
-
* user_id). When set, collaboration @ notifications sent to any owner's
|
|
1022
|
-
* mention webhook render this user as a real `<at>` ping instead of
|
|
1023
|
-
* plain text. The ping only fires if the user is in the bot's group.
|
|
1024
|
-
*/
|
|
1025
|
-
feishuUserId: z.z.string().optional()
|
|
1026
|
-
});
|
|
1027
|
-
const MemorySourceSchema = z.z.enum(["manual", "message-pin"]);
|
|
1028
|
-
z.z.object({
|
|
1029
|
-
id: z.z.string(),
|
|
1030
|
-
content: z.z.string().min(1).max(8e3),
|
|
1031
|
-
source: MemorySourceSchema,
|
|
1032
|
-
sourceSessionId: z.z.string().nullable(),
|
|
1033
|
-
sourceMessageId: z.z.string().nullable(),
|
|
1034
|
-
archivedAt: z.z.number().nullable(),
|
|
1035
|
-
createdAt: z.z.number(),
|
|
1036
|
-
updatedAt: z.z.number()
|
|
1037
|
-
});
|
|
1038
|
-
z.z.object({
|
|
1039
|
-
content: z.z.string().min(1).max(8e3),
|
|
1040
|
-
source: MemorySourceSchema.optional().default("manual"),
|
|
1041
|
-
sourceSessionId: z.z.string().optional(),
|
|
1042
|
-
sourceMessageId: z.z.string().optional()
|
|
1043
|
-
});
|
|
1044
|
-
z.z.object({
|
|
1045
|
-
content: z.z.string().min(1).max(8e3)
|
|
1046
|
-
});
|
|
1047
|
-
|
|
1048
33
|
z.z.object({
|
|
1049
34
|
host: z.z.string(),
|
|
1050
35
|
platform: z.z.string(),
|
|
@@ -1150,141 +135,6 @@ const AgentMessageSchema = z.z.object({
|
|
|
1150
135
|
});
|
|
1151
136
|
z.z.union([UserMessageSchema, AgentMessageSchema]);
|
|
1152
137
|
|
|
1153
|
-
function encodeBase64(buffer, variant = "base64") {
|
|
1154
|
-
if (variant === "base64url") {
|
|
1155
|
-
return encodeBase64Url(buffer);
|
|
1156
|
-
}
|
|
1157
|
-
return Buffer.from(buffer).toString("base64");
|
|
1158
|
-
}
|
|
1159
|
-
function encodeBase64Url(buffer) {
|
|
1160
|
-
return Buffer.from(buffer).toString("base64").replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
|
|
1161
|
-
}
|
|
1162
|
-
function decodeBase64(base64, variant = "base64") {
|
|
1163
|
-
if (variant === "base64url") {
|
|
1164
|
-
const base64Standard = base64.replaceAll("-", "+").replaceAll("_", "/") + "=".repeat((4 - base64.length % 4) % 4);
|
|
1165
|
-
return new Uint8Array(Buffer.from(base64Standard, "base64"));
|
|
1166
|
-
}
|
|
1167
|
-
return new Uint8Array(Buffer.from(base64, "base64"));
|
|
1168
|
-
}
|
|
1169
|
-
function getRandomBytes(size) {
|
|
1170
|
-
return new Uint8Array(node_crypto.randomBytes(size));
|
|
1171
|
-
}
|
|
1172
|
-
function libsodiumPublicKeyFromSecretKey(seed) {
|
|
1173
|
-
const hashedSeed = new Uint8Array(node_crypto.createHash("sha512").update(seed).digest());
|
|
1174
|
-
const secretKey = hashedSeed.slice(0, 32);
|
|
1175
|
-
return new Uint8Array(tweetnacl.box.keyPair.fromSecretKey(secretKey).publicKey);
|
|
1176
|
-
}
|
|
1177
|
-
function libsodiumEncryptForPublicKey(data, recipientPublicKey) {
|
|
1178
|
-
const ephemeralKeyPair = tweetnacl.box.keyPair();
|
|
1179
|
-
const nonce = getRandomBytes(tweetnacl.box.nonceLength);
|
|
1180
|
-
const encrypted = tweetnacl.box(data, nonce, recipientPublicKey, ephemeralKeyPair.secretKey);
|
|
1181
|
-
const result = new Uint8Array(ephemeralKeyPair.publicKey.length + nonce.length + encrypted.length);
|
|
1182
|
-
result.set(ephemeralKeyPair.publicKey, 0);
|
|
1183
|
-
result.set(nonce, ephemeralKeyPair.publicKey.length);
|
|
1184
|
-
result.set(encrypted, ephemeralKeyPair.publicKey.length + nonce.length);
|
|
1185
|
-
return result;
|
|
1186
|
-
}
|
|
1187
|
-
function encryptLegacy(data, secret) {
|
|
1188
|
-
const nonce = getRandomBytes(tweetnacl.secretbox.nonceLength);
|
|
1189
|
-
const encrypted = tweetnacl.secretbox(new TextEncoder().encode(JSON.stringify(data)), nonce, secret);
|
|
1190
|
-
const result = new Uint8Array(nonce.length + encrypted.length);
|
|
1191
|
-
result.set(nonce);
|
|
1192
|
-
result.set(encrypted, nonce.length);
|
|
1193
|
-
return result;
|
|
1194
|
-
}
|
|
1195
|
-
function decryptLegacy(data, secret) {
|
|
1196
|
-
const nonce = data.slice(0, tweetnacl.secretbox.nonceLength);
|
|
1197
|
-
const encrypted = data.slice(tweetnacl.secretbox.nonceLength);
|
|
1198
|
-
const decrypted = tweetnacl.secretbox.open(encrypted, nonce, secret);
|
|
1199
|
-
if (!decrypted) {
|
|
1200
|
-
return null;
|
|
1201
|
-
}
|
|
1202
|
-
return JSON.parse(new TextDecoder().decode(decrypted));
|
|
1203
|
-
}
|
|
1204
|
-
function encryptWithDataKey(data, dataKey) {
|
|
1205
|
-
const nonce = getRandomBytes(12);
|
|
1206
|
-
const cipher = node_crypto.createCipheriv("aes-256-gcm", dataKey, nonce);
|
|
1207
|
-
const plaintext = new TextEncoder().encode(JSON.stringify(data));
|
|
1208
|
-
const encrypted = Buffer.concat([
|
|
1209
|
-
cipher.update(plaintext),
|
|
1210
|
-
cipher.final()
|
|
1211
|
-
]);
|
|
1212
|
-
const authTag = cipher.getAuthTag();
|
|
1213
|
-
const bundle = new Uint8Array(12 + encrypted.length + 16 + 1);
|
|
1214
|
-
bundle.set([0], 0);
|
|
1215
|
-
bundle.set(nonce, 1);
|
|
1216
|
-
bundle.set(new Uint8Array(encrypted), 13);
|
|
1217
|
-
bundle.set(new Uint8Array(authTag), 13 + encrypted.length);
|
|
1218
|
-
return bundle;
|
|
1219
|
-
}
|
|
1220
|
-
function decryptWithDataKey(bundle, dataKey) {
|
|
1221
|
-
if (bundle.length < 1) {
|
|
1222
|
-
return null;
|
|
1223
|
-
}
|
|
1224
|
-
if (bundle[0] !== 0) {
|
|
1225
|
-
return null;
|
|
1226
|
-
}
|
|
1227
|
-
if (bundle.length < 12 + 16 + 1) {
|
|
1228
|
-
return null;
|
|
1229
|
-
}
|
|
1230
|
-
const nonce = bundle.slice(1, 13);
|
|
1231
|
-
const authTag = bundle.slice(bundle.length - 16);
|
|
1232
|
-
const ciphertext = bundle.slice(13, bundle.length - 16);
|
|
1233
|
-
try {
|
|
1234
|
-
const decipher = node_crypto.createDecipheriv("aes-256-gcm", dataKey, nonce);
|
|
1235
|
-
decipher.setAuthTag(authTag);
|
|
1236
|
-
const decrypted = Buffer.concat([
|
|
1237
|
-
decipher.update(ciphertext),
|
|
1238
|
-
decipher.final()
|
|
1239
|
-
]);
|
|
1240
|
-
return JSON.parse(new TextDecoder().decode(decrypted));
|
|
1241
|
-
} catch (error) {
|
|
1242
|
-
return null;
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
function encrypt(key, variant, data) {
|
|
1246
|
-
if (variant === "legacy") {
|
|
1247
|
-
return encryptLegacy(data, key);
|
|
1248
|
-
} else {
|
|
1249
|
-
return encryptWithDataKey(data, key);
|
|
1250
|
-
}
|
|
1251
|
-
}
|
|
1252
|
-
function decrypt(key, variant, data) {
|
|
1253
|
-
if (variant === "legacy") {
|
|
1254
|
-
return decryptLegacy(data, key);
|
|
1255
|
-
} else {
|
|
1256
|
-
return decryptWithDataKey(data, key);
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
async function delay(ms) {
|
|
1261
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1262
|
-
}
|
|
1263
|
-
function exponentialBackoffDelay(currentFailureCount, minDelay, maxDelay, maxFailureCount) {
|
|
1264
|
-
let maxDelayRet = minDelay + (maxDelay - minDelay) / maxFailureCount * Math.min(currentFailureCount, maxFailureCount);
|
|
1265
|
-
return Math.round(Math.random() * maxDelayRet);
|
|
1266
|
-
}
|
|
1267
|
-
function createBackoff(opts) {
|
|
1268
|
-
return async (callback) => {
|
|
1269
|
-
let currentFailureCount = 0;
|
|
1270
|
-
const minDelay = 250;
|
|
1271
|
-
const maxDelay = 1e3;
|
|
1272
|
-
const maxFailureCount = 50;
|
|
1273
|
-
while (true) {
|
|
1274
|
-
try {
|
|
1275
|
-
return await callback();
|
|
1276
|
-
} catch (e) {
|
|
1277
|
-
if (currentFailureCount < maxFailureCount) {
|
|
1278
|
-
currentFailureCount++;
|
|
1279
|
-
}
|
|
1280
|
-
let waitForRequest = exponentialBackoffDelay(currentFailureCount, minDelay, maxDelay, maxFailureCount);
|
|
1281
|
-
await delay(waitForRequest);
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
};
|
|
1285
|
-
}
|
|
1286
|
-
let backoff = createBackoff();
|
|
1287
|
-
|
|
1288
138
|
class AsyncLock {
|
|
1289
139
|
permits = 1;
|
|
1290
140
|
promiseResolverQueue = [];
|
|
@@ -1365,7 +215,7 @@ class InvalidateSync {
|
|
|
1365
215
|
this._pendings = [];
|
|
1366
216
|
};
|
|
1367
217
|
_doSync = async () => {
|
|
1368
|
-
await backoff(async () => {
|
|
218
|
+
await time.backoff(async () => {
|
|
1369
219
|
if (this._stopped) {
|
|
1370
220
|
return;
|
|
1371
221
|
}
|
|
@@ -1385,7 +235,7 @@ class InvalidateSync {
|
|
|
1385
235
|
};
|
|
1386
236
|
}
|
|
1387
237
|
|
|
1388
|
-
const diffsDir = path.join(configuration.happyHomeDir, "diffs");
|
|
238
|
+
const diffsDir = path.join(logger.configuration.happyHomeDir, "diffs");
|
|
1389
239
|
function ensureDiffsDir() {
|
|
1390
240
|
if (!fs.existsSync(diffsDir)) {
|
|
1391
241
|
fs.mkdirSync(diffsDir, { recursive: true });
|
|
@@ -1409,9 +259,9 @@ function saveDiffRecords(sessionId, records) {
|
|
|
1409
259
|
}
|
|
1410
260
|
existing.push(...records);
|
|
1411
261
|
fs.writeFileSync(filePath, JSON.stringify(existing), "utf-8");
|
|
1412
|
-
logger.debug(`[DiffStore] Saved ${records.length} record(s) for session ${sessionId}`);
|
|
262
|
+
logger.logger.debug(`[DiffStore] Saved ${records.length} record(s) for session ${sessionId}`);
|
|
1413
263
|
} catch (error) {
|
|
1414
|
-
logger.warn(`[DiffStore] Failed to save diff records:`, error);
|
|
264
|
+
logger.logger.warn(`[DiffStore] Failed to save diff records:`, error);
|
|
1415
265
|
}
|
|
1416
266
|
}
|
|
1417
267
|
function getDiffDetail(sessionId, callId, filePath) {
|
|
@@ -1423,12 +273,12 @@ function getDiffDetail(sessionId, callId, filePath) {
|
|
|
1423
273
|
if (!record) return null;
|
|
1424
274
|
return { diff: record.diff, additions: record.additions, deletions: record.deletions };
|
|
1425
275
|
} catch (error) {
|
|
1426
|
-
logger.warn(`[DiffStore] Failed to get diff detail:`, error);
|
|
276
|
+
logger.logger.warn(`[DiffStore] Failed to get diff detail:`, error);
|
|
1427
277
|
return null;
|
|
1428
278
|
}
|
|
1429
279
|
}
|
|
1430
280
|
|
|
1431
|
-
const toolOutputsDir = path.join(configuration.happyHomeDir, "tool-outputs");
|
|
281
|
+
const toolOutputsDir = path.join(logger.configuration.happyHomeDir, "tool-outputs");
|
|
1432
282
|
function ensureToolOutputsDir() {
|
|
1433
283
|
if (!fs.existsSync(toolOutputsDir)) {
|
|
1434
284
|
fs.mkdirSync(toolOutputsDir, { recursive: true });
|
|
@@ -1451,9 +301,9 @@ function saveToolOutputRecord(sessionId, record) {
|
|
|
1451
301
|
}
|
|
1452
302
|
existing.push(record);
|
|
1453
303
|
fs.writeFileSync(filePath, JSON.stringify(existing), "utf-8");
|
|
1454
|
-
logger.debug(`[ToolOutputStore] Saved output for ${record.toolName} (${record.callId}) in session ${sessionId}`);
|
|
304
|
+
logger.logger.debug(`[ToolOutputStore] Saved output for ${record.toolName} (${record.callId}) in session ${sessionId}`);
|
|
1455
305
|
} catch (error) {
|
|
1456
|
-
logger.warn("[ToolOutputStore] Failed to save tool output record:", error);
|
|
306
|
+
logger.logger.warn("[ToolOutputStore] Failed to save tool output record:", error);
|
|
1457
307
|
}
|
|
1458
308
|
}
|
|
1459
309
|
function getToolOutputRecord(sessionId, callId) {
|
|
@@ -1463,7 +313,7 @@ function getToolOutputRecord(sessionId, callId) {
|
|
|
1463
313
|
const records = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
1464
314
|
return records.find((record) => record.callId === callId) || null;
|
|
1465
315
|
} catch (error) {
|
|
1466
|
-
logger.warn("[ToolOutputStore] Failed to get tool output record:", error);
|
|
316
|
+
logger.logger.warn("[ToolOutputStore] Failed to get tool output record:", error);
|
|
1467
317
|
return null;
|
|
1468
318
|
}
|
|
1469
319
|
}
|
|
@@ -1769,7 +619,7 @@ class RpcHandlerManager {
|
|
|
1769
619
|
this.scopePrefix = config.scopePrefix;
|
|
1770
620
|
this.encryptionKey = config.encryptionKey;
|
|
1771
621
|
this.encryptionVariant = config.encryptionVariant;
|
|
1772
|
-
this.logger = config.logger || ((msg, data) => logger.debug(msg, data));
|
|
622
|
+
this.logger = config.logger || ((msg, data) => logger.logger.debug(msg, data));
|
|
1773
623
|
}
|
|
1774
624
|
/** Encryption key — exposed so feature modules can encrypt outbound non-RPC frames. */
|
|
1775
625
|
getEncryptionKey() {
|
|
@@ -1824,11 +674,11 @@ class RpcHandlerManager {
|
|
|
1824
674
|
if (!handler) {
|
|
1825
675
|
this.logger("[RPC] [ERROR] Method not found", { method: request.method });
|
|
1826
676
|
const errorResponse = { error: "Method not found" };
|
|
1827
|
-
const encryptedError = encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, errorResponse));
|
|
677
|
+
const encryptedError = logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, errorResponse));
|
|
1828
678
|
return encryptedError;
|
|
1829
679
|
}
|
|
1830
680
|
const isPlaintext = typeof request.params !== "string";
|
|
1831
|
-
const decryptedParams = isPlaintext ? request.params : decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(request.params));
|
|
681
|
+
const decryptedParams = isPlaintext ? request.params : logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(request.params));
|
|
1832
682
|
this.logger("[RPC] Calling handler", { method: request.method });
|
|
1833
683
|
const result = await handler(decryptedParams);
|
|
1834
684
|
this.logger("[RPC] Handler returned", { method: request.method, hasResult: result !== void 0 });
|
|
@@ -1839,7 +689,7 @@ class RpcHandlerManager {
|
|
|
1839
689
|
this.logger("[RPC] Handler returned pre-encrypted response", { method: request.method });
|
|
1840
690
|
return result.data;
|
|
1841
691
|
}
|
|
1842
|
-
const encryptedResponse = encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, result));
|
|
692
|
+
const encryptedResponse = logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, result));
|
|
1843
693
|
this.logger("[RPC] Sending encrypted response", { method: request.method, responseLength: encryptedResponse.length });
|
|
1844
694
|
return encryptedResponse;
|
|
1845
695
|
} catch (error) {
|
|
@@ -1850,7 +700,7 @@ class RpcHandlerManager {
|
|
|
1850
700
|
if (typeof request.params !== "string") {
|
|
1851
701
|
return errorResponse;
|
|
1852
702
|
}
|
|
1853
|
-
return encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, errorResponse));
|
|
703
|
+
return logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, errorResponse));
|
|
1854
704
|
}
|
|
1855
705
|
}
|
|
1856
706
|
onSocketConnect(socket) {
|
|
@@ -2500,14 +1350,8 @@ No git repository was found from session cwd or workspace repo metadata. Session
|
|
|
2500
1350
|
};
|
|
2501
1351
|
}
|
|
2502
1352
|
|
|
2503
|
-
const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-BrTorNAy.cjs', document.baseURI).href))));
|
|
2504
|
-
function projectPath() {
|
|
2505
|
-
const path = path$1.resolve(__dirname$1, "..");
|
|
2506
|
-
return path;
|
|
2507
|
-
}
|
|
2508
|
-
|
|
2509
1353
|
function run$1(args, options) {
|
|
2510
|
-
const RUNNER_PATH = path$1.resolve(path$1.join(projectPath(), "scripts", "ripgrep_launcher.cjs"));
|
|
1354
|
+
const RUNNER_PATH = path$1.resolve(path$1.join(projectPath.projectPath(), "scripts", "ripgrep_launcher.cjs"));
|
|
2511
1355
|
return new Promise((resolve2, reject) => {
|
|
2512
1356
|
const child = child_process.spawn("node", [RUNNER_PATH, JSON.stringify(args)], {
|
|
2513
1357
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -2541,7 +1385,7 @@ function toolsPackageName() {
|
|
|
2541
1385
|
return `@zonease/happy-tools-${toolsPlatform()}`;
|
|
2542
1386
|
}
|
|
2543
1387
|
function legacyToolsDir() {
|
|
2544
|
-
return path.resolve(projectPath(), "tools", "unpacked");
|
|
1388
|
+
return path.resolve(projectPath.projectPath(), "tools", "unpacked");
|
|
2545
1389
|
}
|
|
2546
1390
|
let cached$1;
|
|
2547
1391
|
function resolveToolsDir() {
|
|
@@ -2551,7 +1395,7 @@ function resolveToolsDir() {
|
|
|
2551
1395
|
}
|
|
2552
1396
|
function findToolsDir() {
|
|
2553
1397
|
try {
|
|
2554
|
-
const manifest = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('
|
|
1398
|
+
const manifest = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('api-CwOCQeLH.cjs', document.baseURI).href))).resolve(`${toolsPackageName()}/package.json`);
|
|
2555
1399
|
return path.dirname(manifest);
|
|
2556
1400
|
} catch {
|
|
2557
1401
|
}
|
|
@@ -2625,10 +1469,10 @@ function ensureSpawnHelperExecutable() {
|
|
|
2625
1469
|
for (const candidate of candidates) {
|
|
2626
1470
|
if (!fs.existsSync(candidate) || (fs.statSync(candidate).mode & 73) !== 0) continue;
|
|
2627
1471
|
fs.chmodSync(candidate, 493);
|
|
2628
|
-
logger.debug(`[pty] restored exec bit on ${candidate}`);
|
|
1472
|
+
logger.logger.debug(`[pty] restored exec bit on ${candidate}`);
|
|
2629
1473
|
}
|
|
2630
1474
|
} catch (err) {
|
|
2631
|
-
logger.debug("[pty] could not check spawn-helper permissions:", err);
|
|
1475
|
+
logger.logger.debug("[pty] could not check spawn-helper permissions:", err);
|
|
2632
1476
|
}
|
|
2633
1477
|
}
|
|
2634
1478
|
function loadNodePty() {
|
|
@@ -2643,7 +1487,7 @@ function loadNodePty() {
|
|
|
2643
1487
|
return mod;
|
|
2644
1488
|
} catch (err) {
|
|
2645
1489
|
loadError = err instanceof Error ? err : new Error(String(err));
|
|
2646
|
-
logger.debug("[pty] node-pty unavailable:", loadError.message);
|
|
1490
|
+
logger.logger.debug("[pty] node-pty unavailable:", loadError.message);
|
|
2647
1491
|
return null;
|
|
2648
1492
|
}
|
|
2649
1493
|
}
|
|
@@ -2701,7 +1545,7 @@ function spawnShell(opts) {
|
|
|
2701
1545
|
if (!mod) {
|
|
2702
1546
|
const err = new Error(PTY_UNAVAILABLE);
|
|
2703
1547
|
if (loadError) {
|
|
2704
|
-
logger.debug("[pty] underlying load error:", loadError.stack ?? loadError.message);
|
|
1548
|
+
logger.logger.debug("[pty] underlying load error:", loadError.stack ?? loadError.message);
|
|
2705
1549
|
}
|
|
2706
1550
|
throw err;
|
|
2707
1551
|
}
|
|
@@ -2736,7 +1580,7 @@ function spawnShell(opts) {
|
|
|
2736
1580
|
});
|
|
2737
1581
|
const ptyId = node_crypto.randomUUID();
|
|
2738
1582
|
ptys.set(ptyId, term);
|
|
2739
|
-
logger.debug(`[pty] spawned ${ptyId} pid=${term.pid} shell=${shell} cols=${opts.cols} rows=${opts.rows} cwd=${cwd}`);
|
|
1583
|
+
logger.logger.debug(`[pty] spawned ${ptyId} pid=${term.pid} shell=${shell} cols=${opts.cols} rows=${opts.rows} cwd=${cwd}`);
|
|
2740
1584
|
return { ptyId, term };
|
|
2741
1585
|
}
|
|
2742
1586
|
function resizePty(ptyId, cols, rows) {
|
|
@@ -2746,7 +1590,7 @@ function resizePty(ptyId, cols, rows) {
|
|
|
2746
1590
|
term.resize(cols, rows);
|
|
2747
1591
|
return true;
|
|
2748
1592
|
} catch (err) {
|
|
2749
|
-
logger.debug(`[pty] resize ${ptyId} failed:`, err);
|
|
1593
|
+
logger.logger.debug(`[pty] resize ${ptyId} failed:`, err);
|
|
2750
1594
|
return false;
|
|
2751
1595
|
}
|
|
2752
1596
|
}
|
|
@@ -2757,7 +1601,7 @@ function writeToPty(ptyId, data) {
|
|
|
2757
1601
|
term.write(data);
|
|
2758
1602
|
return true;
|
|
2759
1603
|
} catch (err) {
|
|
2760
|
-
logger.debug(`[pty] write ${ptyId} failed:`, err);
|
|
1604
|
+
logger.logger.debug(`[pty] write ${ptyId} failed:`, err);
|
|
2761
1605
|
return false;
|
|
2762
1606
|
}
|
|
2763
1607
|
}
|
|
@@ -2768,7 +1612,7 @@ function closePty(ptyId) {
|
|
|
2768
1612
|
try {
|
|
2769
1613
|
term.kill();
|
|
2770
1614
|
} catch (err) {
|
|
2771
|
-
logger.debug(`[pty] kill ${ptyId} failed (likely already exited):`, err);
|
|
1615
|
+
logger.logger.debug(`[pty] kill ${ptyId} failed (likely already exited):`, err);
|
|
2772
1616
|
}
|
|
2773
1617
|
return true;
|
|
2774
1618
|
}
|
|
@@ -2801,7 +1645,7 @@ function runLoginShell(shell) {
|
|
|
2801
1645
|
(error, stdout) => {
|
|
2802
1646
|
const parsed = parseEnvDump(stdout ?? "");
|
|
2803
1647
|
if (!parsed && error) {
|
|
2804
|
-
logger.debug("[shellEnv] login shell did not return an environment:", error.message);
|
|
1648
|
+
logger.logger.debug("[shellEnv] login shell did not return an environment:", error.message);
|
|
2805
1649
|
}
|
|
2806
1650
|
resolve(parsed);
|
|
2807
1651
|
}
|
|
@@ -2822,7 +1666,7 @@ function resolveLoginShellEnv() {
|
|
|
2822
1666
|
if (!shell) return process.env;
|
|
2823
1667
|
const resolved = await runLoginShell(shell);
|
|
2824
1668
|
if (!resolved) return process.env;
|
|
2825
|
-
logger.debug(`[shellEnv] resolved ${Object.keys(resolved).length} variables from ${shell}`);
|
|
1669
|
+
logger.logger.debug(`[shellEnv] resolved ${Object.keys(resolved).length} variables from ${shell}`);
|
|
2826
1670
|
return { ...resolved, ...daemonOwnedEnv() };
|
|
2827
1671
|
})();
|
|
2828
1672
|
return cached;
|
|
@@ -2871,7 +1715,7 @@ const PTY_OUTPUT_FLUSH_MS = 16;
|
|
|
2871
1715
|
const PTY_OUTPUT_FLUSH_BYTES = 32 * 1024;
|
|
2872
1716
|
function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId) {
|
|
2873
1717
|
rpcHandlerManager.registerHandler("bash", async (data) => {
|
|
2874
|
-
logger.debug("Shell command request:", data.command);
|
|
1718
|
+
logger.logger.debug("Shell command request:", data.command);
|
|
2875
1719
|
if (data.cwd && data.cwd !== "/") {
|
|
2876
1720
|
const validation = validatePath(data.cwd, workingDirectory);
|
|
2877
1721
|
if (!validation.valid) {
|
|
@@ -2888,16 +1732,16 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
2888
1732
|
// fails here with "command not found".
|
|
2889
1733
|
env: await resolveLoginShellEnv()
|
|
2890
1734
|
};
|
|
2891
|
-
logger.debug("Shell command executing...", { cwd: options.cwd, timeout: options.timeout });
|
|
1735
|
+
logger.logger.debug("Shell command executing...", { cwd: options.cwd, timeout: options.timeout });
|
|
2892
1736
|
const { stdout, stderr } = await execAsync(data.command, options);
|
|
2893
|
-
logger.debug("Shell command executed, processing result...");
|
|
1737
|
+
logger.logger.debug("Shell command executed, processing result...");
|
|
2894
1738
|
const result = {
|
|
2895
1739
|
success: true,
|
|
2896
1740
|
stdout: stdout ? stdout.toString() : "",
|
|
2897
1741
|
stderr: stderr ? stderr.toString() : "",
|
|
2898
1742
|
exitCode: 0
|
|
2899
1743
|
};
|
|
2900
|
-
logger.debug("Shell command result:", {
|
|
1744
|
+
logger.logger.debug("Shell command result:", {
|
|
2901
1745
|
success: true,
|
|
2902
1746
|
exitCode: 0,
|
|
2903
1747
|
stdoutLen: result.stdout.length,
|
|
@@ -2914,7 +1758,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
2914
1758
|
exitCode: typeof execError.code === "number" ? execError.code : -1,
|
|
2915
1759
|
error: "Command timed out"
|
|
2916
1760
|
};
|
|
2917
|
-
logger.debug("Shell command timed out:", {
|
|
1761
|
+
logger.logger.debug("Shell command timed out:", {
|
|
2918
1762
|
success: false,
|
|
2919
1763
|
exitCode: result2.exitCode,
|
|
2920
1764
|
error: "Command timed out"
|
|
@@ -2928,7 +1772,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
2928
1772
|
exitCode: typeof execError.code === "number" ? execError.code : 1,
|
|
2929
1773
|
error: execError.message || "Command failed"
|
|
2930
1774
|
};
|
|
2931
|
-
logger.debug("Shell command failed:", {
|
|
1775
|
+
logger.logger.debug("Shell command failed:", {
|
|
2932
1776
|
success: false,
|
|
2933
1777
|
exitCode: result.exitCode,
|
|
2934
1778
|
error: result.error,
|
|
@@ -2939,40 +1783,40 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
2939
1783
|
}
|
|
2940
1784
|
});
|
|
2941
1785
|
rpcHandlerManager.registerHandler("readFile", async (data) => {
|
|
2942
|
-
logger.debug("Read file request:", data.path);
|
|
1786
|
+
logger.logger.debug("Read file request:", data.path);
|
|
2943
1787
|
const validation = validatePath(data.path, workingDirectory);
|
|
2944
1788
|
if (!validation.valid) {
|
|
2945
1789
|
return { success: false, error: validation.error };
|
|
2946
1790
|
}
|
|
2947
1791
|
try {
|
|
2948
|
-
const buffer = await fs$
|
|
1792
|
+
const buffer = await fs$1.readFile(data.path);
|
|
2949
1793
|
const content = buffer.toString("base64");
|
|
2950
1794
|
return { success: true, content };
|
|
2951
1795
|
} catch (error) {
|
|
2952
|
-
logger.debug("Failed to read file:", error);
|
|
1796
|
+
logger.logger.debug("Failed to read file:", error);
|
|
2953
1797
|
return { success: false, error: error instanceof Error ? error.message : "Failed to read file" };
|
|
2954
1798
|
}
|
|
2955
1799
|
});
|
|
2956
1800
|
rpcHandlerManager.registerHandler("writeFile", async (data) => {
|
|
2957
|
-
logger.debug("Write file request:", data.path);
|
|
1801
|
+
logger.logger.debug("Write file request:", data.path);
|
|
2958
1802
|
const absPath = path$1.resolve(workingDirectory, data.path);
|
|
2959
1803
|
const validation = validatePath(data.path, workingDirectory);
|
|
2960
1804
|
if (!validation.valid) {
|
|
2961
|
-
logger.debug("[writeFile] path=%s ok=%s reason=%s", absPath, false, validation.error);
|
|
1805
|
+
logger.logger.debug("[writeFile] path=%s ok=%s reason=%s", absPath, false, validation.error);
|
|
2962
1806
|
return { success: false, error: validation.error };
|
|
2963
1807
|
}
|
|
2964
1808
|
if (!isWritableForSession(absPath)) {
|
|
2965
|
-
logger.debug("[writeFile] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
|
|
1809
|
+
logger.logger.debug("[writeFile] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
|
|
2966
1810
|
return { success: false, error: `Path '${absPath}' is on the system write deny-list` };
|
|
2967
1811
|
}
|
|
2968
1812
|
try {
|
|
2969
1813
|
const buf = Buffer.from(data.content, "base64");
|
|
2970
|
-
await fs$
|
|
2971
|
-
logger.debug("[writeFile] path=%s bytes=%d ok=%s", absPath, buf.length, true);
|
|
1814
|
+
await fs$1.writeFile(absPath, buf);
|
|
1815
|
+
logger.logger.debug("[writeFile] path=%s bytes=%d ok=%s", absPath, buf.length, true);
|
|
2972
1816
|
return { success: true, bytesWritten: buf.length };
|
|
2973
1817
|
} catch (error) {
|
|
2974
1818
|
const message = error instanceof Error ? error.message : "Failed to write file";
|
|
2975
|
-
logger.debug("[writeFile] path=%s ok=%s reason=%s", absPath, false, message);
|
|
1819
|
+
logger.logger.debug("[writeFile] path=%s ok=%s reason=%s", absPath, false, message);
|
|
2976
1820
|
return { success: false, error: message };
|
|
2977
1821
|
}
|
|
2978
1822
|
});
|
|
@@ -3001,10 +1845,10 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3001
1845
|
return { success: false, error: `Path '${paths.absolutePath}' is on the system write deny-list` };
|
|
3002
1846
|
}
|
|
3003
1847
|
try {
|
|
3004
|
-
await fs$
|
|
3005
|
-
await fs$
|
|
3006
|
-
await fs$
|
|
3007
|
-
await fs$
|
|
1848
|
+
await fs$1.mkdir(paths.directory, { recursive: true });
|
|
1849
|
+
await fs$1.rm(paths.tempAbsolutePath, { force: true });
|
|
1850
|
+
await fs$1.rm(paths.absolutePath, { force: true });
|
|
1851
|
+
await fs$1.writeFile(paths.tempAbsolutePath, Buffer.alloc(0));
|
|
3008
1852
|
return {
|
|
3009
1853
|
success: true,
|
|
3010
1854
|
relativePath: paths.relativePath,
|
|
@@ -3033,12 +1877,12 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3033
1877
|
}
|
|
3034
1878
|
try {
|
|
3035
1879
|
const chunk = Buffer.from(data.chunkBase64, "base64");
|
|
3036
|
-
const current = await fs$
|
|
1880
|
+
const current = await fs$1.stat(paths.tempAbsolutePath).catch(() => null);
|
|
3037
1881
|
const currentSize = current?.size ?? 0;
|
|
3038
1882
|
if (currentSize + chunk.length > MAX_SESSION_UPLOAD_FILE_BYTES) {
|
|
3039
1883
|
return { success: false, error: "File exceeds 100MB limit" };
|
|
3040
1884
|
}
|
|
3041
|
-
await fs$
|
|
1885
|
+
await fs$1.appendFile(paths.tempAbsolutePath, chunk);
|
|
3042
1886
|
return {
|
|
3043
1887
|
success: true,
|
|
3044
1888
|
relativePath: paths.relativePath,
|
|
@@ -3074,11 +1918,11 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3074
1918
|
return { success: false, error: `Path '${paths.absolutePath}' is on the system write deny-list` };
|
|
3075
1919
|
}
|
|
3076
1920
|
try {
|
|
3077
|
-
const info = await fs$
|
|
1921
|
+
const info = await fs$1.stat(paths.tempAbsolutePath);
|
|
3078
1922
|
if (info.size !== data.fileSize) {
|
|
3079
1923
|
return { success: false, error: `Upload size mismatch: expected ${data.fileSize}, got ${info.size}` };
|
|
3080
1924
|
}
|
|
3081
|
-
await fs$
|
|
1925
|
+
await fs$1.rename(paths.tempAbsolutePath, paths.absolutePath);
|
|
3082
1926
|
return {
|
|
3083
1927
|
success: true,
|
|
3084
1928
|
relativePath: paths.relativePath,
|
|
@@ -3096,14 +1940,14 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3096
1940
|
uploadId: data.uploadId,
|
|
3097
1941
|
fileName: data.fileName
|
|
3098
1942
|
});
|
|
3099
|
-
await fs$
|
|
1943
|
+
await fs$1.rm(paths.tempAbsolutePath, { force: true });
|
|
3100
1944
|
return { success: true };
|
|
3101
1945
|
} catch (error) {
|
|
3102
1946
|
return { success: false, error: error instanceof Error ? error.message : "Failed to abort upload" };
|
|
3103
1947
|
}
|
|
3104
1948
|
});
|
|
3105
1949
|
rpcHandlerManager.registerHandler("rename", async (data) => {
|
|
3106
|
-
logger.debug("Rename request:", data.from, "->", data.to);
|
|
1950
|
+
logger.logger.debug("Rename request:", data.from, "->", data.to);
|
|
3107
1951
|
const absFrom = path$1.resolve(workingDirectory, data.from);
|
|
3108
1952
|
const absTo = path$1.resolve(workingDirectory, data.to);
|
|
3109
1953
|
const fromValidation = validatePath(data.from, workingDirectory);
|
|
@@ -3115,68 +1959,68 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3115
1959
|
return { success: false, error: toValidation.error };
|
|
3116
1960
|
}
|
|
3117
1961
|
if (!isWritableForSession(absFrom)) {
|
|
3118
|
-
logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, false);
|
|
1962
|
+
logger.logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, false);
|
|
3119
1963
|
return { success: false, error: `Path '${absFrom}' is on the system write deny-list` };
|
|
3120
1964
|
}
|
|
3121
1965
|
if (!isWritableForSession(absTo)) {
|
|
3122
|
-
logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, false);
|
|
1966
|
+
logger.logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, false);
|
|
3123
1967
|
return { success: false, error: `Path '${absTo}' is on the system write deny-list` };
|
|
3124
1968
|
}
|
|
3125
1969
|
try {
|
|
3126
|
-
await fs$
|
|
3127
|
-
logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, true);
|
|
1970
|
+
await fs$1.rename(absFrom, absTo);
|
|
1971
|
+
logger.logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, true);
|
|
3128
1972
|
return { success: true };
|
|
3129
1973
|
} catch (error) {
|
|
3130
1974
|
const message = error instanceof Error ? error.message : "Failed to rename";
|
|
3131
|
-
logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, false);
|
|
1975
|
+
logger.logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, false);
|
|
3132
1976
|
return { success: false, error: message };
|
|
3133
1977
|
}
|
|
3134
1978
|
});
|
|
3135
1979
|
rpcHandlerManager.registerHandler("deleteFile", async (data) => {
|
|
3136
|
-
logger.debug("Delete file request:", data.path);
|
|
1980
|
+
logger.logger.debug("Delete file request:", data.path);
|
|
3137
1981
|
const absPath = path$1.resolve(workingDirectory, data.path);
|
|
3138
1982
|
const validation = validatePath(data.path, workingDirectory);
|
|
3139
1983
|
if (!validation.valid) {
|
|
3140
1984
|
return { success: false, error: validation.error };
|
|
3141
1985
|
}
|
|
3142
1986
|
if (!isWritableForSession(absPath)) {
|
|
3143
|
-
logger.info("[deleteFile] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
|
|
1987
|
+
logger.logger.info("[deleteFile] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
|
|
3144
1988
|
return { success: false, error: `Path '${absPath}' is on the system write deny-list` };
|
|
3145
1989
|
}
|
|
3146
1990
|
try {
|
|
3147
|
-
const st = await fs$
|
|
1991
|
+
const st = await fs$1.lstat(absPath);
|
|
3148
1992
|
if (st.isDirectory()) {
|
|
3149
|
-
logger.info("[deleteFile] path=%s ok=%s reason=%s", absPath, false, "is directory");
|
|
1993
|
+
logger.logger.info("[deleteFile] path=%s ok=%s reason=%s", absPath, false, "is directory");
|
|
3150
1994
|
return { success: false, error: "Not a file, use deleteDirectory" };
|
|
3151
1995
|
}
|
|
3152
|
-
await fs$
|
|
3153
|
-
logger.info("[deleteFile] path=%s ok=%s", absPath, true);
|
|
1996
|
+
await fs$1.unlink(absPath);
|
|
1997
|
+
logger.logger.info("[deleteFile] path=%s ok=%s", absPath, true);
|
|
3154
1998
|
return { success: true };
|
|
3155
1999
|
} catch (error) {
|
|
3156
2000
|
const message = error instanceof Error ? error.message : "Failed to delete file";
|
|
3157
|
-
logger.info("[deleteFile] path=%s ok=%s reason=%s", absPath, false, message);
|
|
2001
|
+
logger.logger.info("[deleteFile] path=%s ok=%s reason=%s", absPath, false, message);
|
|
3158
2002
|
return { success: false, error: message };
|
|
3159
2003
|
}
|
|
3160
2004
|
});
|
|
3161
2005
|
rpcHandlerManager.registerHandler("deleteDirectory", async (data) => {
|
|
3162
|
-
logger.debug("Delete directory request:", data.path);
|
|
2006
|
+
logger.logger.debug("Delete directory request:", data.path);
|
|
3163
2007
|
const absPath = path$1.resolve(workingDirectory, data.path);
|
|
3164
2008
|
const validation = validatePath(data.path, workingDirectory);
|
|
3165
2009
|
if (!validation.valid) {
|
|
3166
2010
|
return { success: false, error: validation.error };
|
|
3167
2011
|
}
|
|
3168
2012
|
if (!isWritableForSession(absPath)) {
|
|
3169
|
-
logger.info("[deleteDirectory] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
|
|
2013
|
+
logger.logger.info("[deleteDirectory] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
|
|
3170
2014
|
return { success: false, error: `Path '${absPath}' is on the system write deny-list` };
|
|
3171
2015
|
}
|
|
3172
2016
|
try {
|
|
3173
|
-
const top = await fs$
|
|
2017
|
+
const top = await fs$1.lstat(absPath);
|
|
3174
2018
|
if (!top.isDirectory()) {
|
|
3175
|
-
logger.info("[deleteDirectory] path=%s ok=%s reason=%s", absPath, false, "not a directory");
|
|
2019
|
+
logger.logger.info("[deleteDirectory] path=%s ok=%s reason=%s", absPath, false, "not a directory");
|
|
3176
2020
|
return { success: false, error: "Not a directory" };
|
|
3177
2021
|
}
|
|
3178
2022
|
async function countEntries(dir) {
|
|
3179
|
-
const entries = await fs$
|
|
2023
|
+
const entries = await fs$1.readdir(dir, { withFileTypes: true });
|
|
3180
2024
|
let n = 0;
|
|
3181
2025
|
for (const entry of entries) {
|
|
3182
2026
|
n += 1;
|
|
@@ -3187,70 +2031,70 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3187
2031
|
return n;
|
|
3188
2032
|
}
|
|
3189
2033
|
const deletedCount = await countEntries(absPath);
|
|
3190
|
-
await fs$
|
|
3191
|
-
logger.info("[deleteDirectory] path=%s deletedCount=%d ok=%s", absPath, deletedCount, true);
|
|
2034
|
+
await fs$1.rm(absPath, { recursive: true, force: false });
|
|
2035
|
+
logger.logger.info("[deleteDirectory] path=%s deletedCount=%d ok=%s", absPath, deletedCount, true);
|
|
3192
2036
|
return { success: true, deletedCount };
|
|
3193
2037
|
} catch (error) {
|
|
3194
2038
|
const message = error instanceof Error ? error.message : "Failed to delete directory";
|
|
3195
|
-
logger.info("[deleteDirectory] path=%s ok=%s reason=%s", absPath, false, message);
|
|
2039
|
+
logger.logger.info("[deleteDirectory] path=%s ok=%s reason=%s", absPath, false, message);
|
|
3196
2040
|
return { success: false, error: message };
|
|
3197
2041
|
}
|
|
3198
2042
|
});
|
|
3199
2043
|
rpcHandlerManager.registerHandler("createFile", async (data) => {
|
|
3200
|
-
logger.debug("Create file request:", data.path);
|
|
2044
|
+
logger.logger.debug("Create file request:", data.path);
|
|
3201
2045
|
const absPath = path$1.resolve(workingDirectory, data.path);
|
|
3202
2046
|
const validation = validatePath(data.path, workingDirectory);
|
|
3203
2047
|
if (!validation.valid) {
|
|
3204
2048
|
return { success: false, error: validation.error };
|
|
3205
2049
|
}
|
|
3206
2050
|
if (!isWritableForSession(absPath)) {
|
|
3207
|
-
logger.info("[createFile] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
|
|
2051
|
+
logger.logger.info("[createFile] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
|
|
3208
2052
|
return { success: false, error: `Path '${absPath}' is on the system write deny-list` };
|
|
3209
2053
|
}
|
|
3210
2054
|
try {
|
|
3211
2055
|
const buf = data.content ? Buffer.from(data.content, "base64") : Buffer.alloc(0);
|
|
3212
|
-
await fs$
|
|
3213
|
-
logger.info("[createFile] path=%s bytes=%d ok=%s", absPath, buf.length, true);
|
|
2056
|
+
await fs$1.writeFile(absPath, buf, { flag: "wx" });
|
|
2057
|
+
logger.logger.info("[createFile] path=%s bytes=%d ok=%s", absPath, buf.length, true);
|
|
3214
2058
|
return { success: true };
|
|
3215
2059
|
} catch (error) {
|
|
3216
2060
|
const errno = error.code;
|
|
3217
2061
|
if (errno === "EEXIST") {
|
|
3218
|
-
logger.info("[createFile] path=%s ok=%s reason=%s", absPath, false, "file exists");
|
|
2062
|
+
logger.logger.info("[createFile] path=%s ok=%s reason=%s", absPath, false, "file exists");
|
|
3219
2063
|
return { success: false, error: "File exists" };
|
|
3220
2064
|
}
|
|
3221
2065
|
const message = error instanceof Error ? error.message : "Failed to create file";
|
|
3222
|
-
logger.info("[createFile] path=%s ok=%s reason=%s", absPath, false, message);
|
|
2066
|
+
logger.logger.info("[createFile] path=%s ok=%s reason=%s", absPath, false, message);
|
|
3223
2067
|
return { success: false, error: message };
|
|
3224
2068
|
}
|
|
3225
2069
|
});
|
|
3226
2070
|
rpcHandlerManager.registerHandler("createDirectory", async (data) => {
|
|
3227
|
-
logger.debug("Create directory request:", data.path);
|
|
2071
|
+
logger.logger.debug("Create directory request:", data.path);
|
|
3228
2072
|
const absPath = path$1.resolve(workingDirectory, data.path);
|
|
3229
2073
|
const validation = validatePath(data.path, workingDirectory);
|
|
3230
2074
|
if (!validation.valid) {
|
|
3231
2075
|
return { success: false, error: validation.error };
|
|
3232
2076
|
}
|
|
3233
2077
|
if (!isWritableForSession(absPath)) {
|
|
3234
|
-
logger.info("[createDirectory] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
|
|
2078
|
+
logger.logger.info("[createDirectory] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
|
|
3235
2079
|
return { success: false, error: `Path '${absPath}' is on the system write deny-list` };
|
|
3236
2080
|
}
|
|
3237
2081
|
try {
|
|
3238
|
-
await fs$
|
|
3239
|
-
logger.info("[createDirectory] path=%s ok=%s", absPath, true);
|
|
2082
|
+
await fs$1.mkdir(absPath);
|
|
2083
|
+
logger.logger.info("[createDirectory] path=%s ok=%s", absPath, true);
|
|
3240
2084
|
return { success: true };
|
|
3241
2085
|
} catch (error) {
|
|
3242
2086
|
const errno = error.code;
|
|
3243
2087
|
if (errno === "EEXIST") {
|
|
3244
|
-
logger.info("[createDirectory] path=%s ok=%s reason=%s", absPath, false, "directory exists");
|
|
2088
|
+
logger.logger.info("[createDirectory] path=%s ok=%s reason=%s", absPath, false, "directory exists");
|
|
3245
2089
|
return { success: false, error: "Directory exists" };
|
|
3246
2090
|
}
|
|
3247
2091
|
const message = error instanceof Error ? error.message : "Failed to create directory";
|
|
3248
|
-
logger.info("[createDirectory] path=%s ok=%s reason=%s", absPath, false, message);
|
|
2092
|
+
logger.logger.info("[createDirectory] path=%s ok=%s reason=%s", absPath, false, message);
|
|
3249
2093
|
return { success: false, error: message };
|
|
3250
2094
|
}
|
|
3251
2095
|
});
|
|
3252
2096
|
rpcHandlerManager.registerHandler("listDirectory", async (data) => {
|
|
3253
|
-
logger.debug("List directory request:", data.path);
|
|
2097
|
+
logger.logger.debug("List directory request:", data.path);
|
|
3254
2098
|
const absPath = path$1.resolve(workingDirectory, data.path);
|
|
3255
2099
|
const validation = validatePath(data.path, workingDirectory);
|
|
3256
2100
|
if (!validation.valid) {
|
|
@@ -3258,7 +2102,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3258
2102
|
}
|
|
3259
2103
|
const hideSystem = data.hideSystem !== false;
|
|
3260
2104
|
try {
|
|
3261
|
-
const rawEntries = await fs$
|
|
2105
|
+
const rawEntries = await fs$1.readdir(absPath, { withFileTypes: true });
|
|
3262
2106
|
const noSymlinks = rawEntries.filter((e) => !e.isSymbolicLink());
|
|
3263
2107
|
const visible = hideSystem ? noSymlinks.filter((e) => !isSystemNoise(e.name)) : noSymlinks;
|
|
3264
2108
|
const entries = await Promise.all(
|
|
@@ -3268,11 +2112,11 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3268
2112
|
let size;
|
|
3269
2113
|
let mtime;
|
|
3270
2114
|
try {
|
|
3271
|
-
const stats = await fs$
|
|
2115
|
+
const stats = await fs$1.stat(fullPath);
|
|
3272
2116
|
size = stats.size;
|
|
3273
2117
|
mtime = stats.mtime.getTime();
|
|
3274
2118
|
} catch (error) {
|
|
3275
|
-
logger.debug(`Failed to stat ${fullPath}:`, error);
|
|
2119
|
+
logger.logger.debug(`Failed to stat ${fullPath}:`, error);
|
|
3276
2120
|
}
|
|
3277
2121
|
return { name: entry.name, path: fullPath, type, size, mtime };
|
|
3278
2122
|
})
|
|
@@ -3284,19 +2128,19 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3284
2128
|
});
|
|
3285
2129
|
return { success: true, entries };
|
|
3286
2130
|
} catch (error) {
|
|
3287
|
-
logger.debug("Failed to list directory:", error);
|
|
2131
|
+
logger.logger.debug("Failed to list directory:", error);
|
|
3288
2132
|
return { success: false, error: error instanceof Error ? error.message : "Failed to list directory" };
|
|
3289
2133
|
}
|
|
3290
2134
|
});
|
|
3291
2135
|
rpcHandlerManager.registerHandler("getDirectoryTree", async (data) => {
|
|
3292
|
-
logger.debug("Get directory tree request:", data.path, "maxDepth:", data.maxDepth);
|
|
2136
|
+
logger.logger.debug("Get directory tree request:", data.path, "maxDepth:", data.maxDepth);
|
|
3293
2137
|
const validation = validatePath(data.path, workingDirectory);
|
|
3294
2138
|
if (!validation.valid) {
|
|
3295
2139
|
return { success: false, error: validation.error };
|
|
3296
2140
|
}
|
|
3297
2141
|
async function buildTree(path, name, currentDepth) {
|
|
3298
2142
|
try {
|
|
3299
|
-
const stats = await fs$
|
|
2143
|
+
const stats = await fs$1.stat(path);
|
|
3300
2144
|
const node = {
|
|
3301
2145
|
name,
|
|
3302
2146
|
path,
|
|
@@ -3305,12 +2149,12 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3305
2149
|
modified: stats.mtime.getTime()
|
|
3306
2150
|
};
|
|
3307
2151
|
if (stats.isDirectory() && currentDepth < data.maxDepth) {
|
|
3308
|
-
const entries = await fs$
|
|
2152
|
+
const entries = await fs$1.readdir(path, { withFileTypes: true });
|
|
3309
2153
|
const children = [];
|
|
3310
2154
|
await Promise.all(
|
|
3311
2155
|
entries.map(async (entry) => {
|
|
3312
2156
|
if (entry.isSymbolicLink()) {
|
|
3313
|
-
logger.debug(`Skipping symlink: ${path$1.join(path, entry.name)}`);
|
|
2157
|
+
logger.logger.debug(`Skipping symlink: ${path$1.join(path, entry.name)}`);
|
|
3314
2158
|
return;
|
|
3315
2159
|
}
|
|
3316
2160
|
const childPath = path$1.join(path, entry.name);
|
|
@@ -3329,7 +2173,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3329
2173
|
}
|
|
3330
2174
|
return node;
|
|
3331
2175
|
} catch (error) {
|
|
3332
|
-
logger.debug(`Failed to process ${path}:`, error instanceof Error ? error.message : String(error));
|
|
2176
|
+
logger.logger.debug(`Failed to process ${path}:`, error instanceof Error ? error.message : String(error));
|
|
3333
2177
|
return null;
|
|
3334
2178
|
}
|
|
3335
2179
|
}
|
|
@@ -3344,12 +2188,12 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3344
2188
|
}
|
|
3345
2189
|
return { success: true, tree };
|
|
3346
2190
|
} catch (error) {
|
|
3347
|
-
logger.debug("Failed to get directory tree:", error);
|
|
2191
|
+
logger.logger.debug("Failed to get directory tree:", error);
|
|
3348
2192
|
return { success: false, error: error instanceof Error ? error.message : "Failed to get directory tree" };
|
|
3349
2193
|
}
|
|
3350
2194
|
});
|
|
3351
2195
|
rpcHandlerManager.registerHandler("ripgrep", async (data) => {
|
|
3352
|
-
logger.debug("Ripgrep request with args:", data.args, "cwd:", data.cwd);
|
|
2196
|
+
logger.logger.debug("Ripgrep request with args:", data.args, "cwd:", data.cwd);
|
|
3353
2197
|
if (data.cwd) {
|
|
3354
2198
|
const validation = validatePath(data.cwd, workingDirectory);
|
|
3355
2199
|
if (!validation.valid) {
|
|
@@ -3365,7 +2209,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3365
2209
|
stderr: result.stderr.toString()
|
|
3366
2210
|
};
|
|
3367
2211
|
} catch (error) {
|
|
3368
|
-
logger.debug("Failed to run ripgrep:", error);
|
|
2212
|
+
logger.logger.debug("Failed to run ripgrep:", error);
|
|
3369
2213
|
return {
|
|
3370
2214
|
success: false,
|
|
3371
2215
|
error: error instanceof Error ? error.message : "Failed to run ripgrep"
|
|
@@ -3373,7 +2217,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3373
2217
|
}
|
|
3374
2218
|
});
|
|
3375
2219
|
rpcHandlerManager.registerHandler("difftastic", async (data) => {
|
|
3376
|
-
logger.debug("Difftastic request with args:", data.args, "cwd:", data.cwd);
|
|
2220
|
+
logger.logger.debug("Difftastic request with args:", data.args, "cwd:", data.cwd);
|
|
3377
2221
|
if (data.cwd) {
|
|
3378
2222
|
const validation = validatePath(data.cwd, workingDirectory);
|
|
3379
2223
|
if (!validation.valid) {
|
|
@@ -3389,7 +2233,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3389
2233
|
stderr: result.stderr.toString()
|
|
3390
2234
|
};
|
|
3391
2235
|
} catch (error) {
|
|
3392
|
-
logger.debug("Failed to run difftastic:", error);
|
|
2236
|
+
logger.logger.debug("Failed to run difftastic:", error);
|
|
3393
2237
|
return {
|
|
3394
2238
|
success: false,
|
|
3395
2239
|
error: error instanceof Error ? error.message : "Failed to run difftastic"
|
|
@@ -3398,7 +2242,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3398
2242
|
});
|
|
3399
2243
|
if (sessionId) {
|
|
3400
2244
|
rpcHandlerManager.registerHandler("getDiffDetail", async (data) => {
|
|
3401
|
-
logger.debug("getDiffDetail request:", data.callId, data.filePath);
|
|
2245
|
+
logger.logger.debug("getDiffDetail request:", data.callId, data.filePath);
|
|
3402
2246
|
const result = getDiffDetail(sessionId, data.callId, data.filePath);
|
|
3403
2247
|
if (!result) {
|
|
3404
2248
|
return { success: false, error: "not_found" };
|
|
@@ -3411,7 +2255,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3411
2255
|
};
|
|
3412
2256
|
});
|
|
3413
2257
|
rpcHandlerManager.registerHandler("getToolOutput", async (data) => {
|
|
3414
|
-
logger.debug("getToolOutput request:", data.callId);
|
|
2258
|
+
logger.logger.debug("getToolOutput request:", data.callId);
|
|
3415
2259
|
const record = getToolOutputRecord(sessionId, data.callId);
|
|
3416
2260
|
if (!record) {
|
|
3417
2261
|
return { success: false, error: "not_found" };
|
|
@@ -3433,7 +2277,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3433
2277
|
if (event === "pty-output" && typeof payload.data === "string") {
|
|
3434
2278
|
const key = rpcHandlerManager.getEncryptionKey();
|
|
3435
2279
|
const variant = rpcHandlerManager.getEncryptionVariant();
|
|
3436
|
-
envelope.data = encodeBase64(encrypt(key, variant, payload.data));
|
|
2280
|
+
envelope.data = logger.encodeBase64(logger.encrypt(key, variant, payload.data));
|
|
3437
2281
|
} else if (event === "pty-exit" && typeof payload.exitCode === "number") {
|
|
3438
2282
|
envelope.exitCode = payload.exitCode;
|
|
3439
2283
|
}
|
|
@@ -3493,7 +2337,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3493
2337
|
outboundStates.delete(ptyId);
|
|
3494
2338
|
};
|
|
3495
2339
|
rpcHandlerManager.registerHandler("pty-start", async (data) => {
|
|
3496
|
-
logger.debug("[pty-start] request", { cols: data.cols, rows: data.rows, cwd: data.cwd });
|
|
2340
|
+
logger.logger.debug("[pty-start] request", { cols: data.cols, rows: data.rows, cwd: data.cwd });
|
|
3497
2341
|
try {
|
|
3498
2342
|
const { ptyId, term } = spawnShell({
|
|
3499
2343
|
cols: data.cols,
|
|
@@ -3515,7 +2359,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3515
2359
|
}
|
|
3516
2360
|
});
|
|
3517
2361
|
const exitDispose = term.onExit(({ exitCode }) => {
|
|
3518
|
-
logger.debug(`[pty-exit] ${ptyId} exitCode=${exitCode}`);
|
|
2362
|
+
logger.logger.debug(`[pty-exit] ${ptyId} exitCode=${exitCode}`);
|
|
3519
2363
|
flushPtyOutput(ptyId);
|
|
3520
2364
|
emitEncrypted("pty-exit", { sessionId, ptyId, exitCode });
|
|
3521
2365
|
cleanupPtyState(ptyId);
|
|
@@ -3532,27 +2376,27 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3532
2376
|
} catch (err) {
|
|
3533
2377
|
const message = err instanceof Error ? err.message : String(err);
|
|
3534
2378
|
if (message === PTY_UNAVAILABLE) {
|
|
3535
|
-
logger.debug("[pty-start] node-pty unavailable on this host");
|
|
2379
|
+
logger.logger.debug("[pty-start] node-pty unavailable on this host");
|
|
3536
2380
|
return { ok: false, error: PTY_UNAVAILABLE };
|
|
3537
2381
|
}
|
|
3538
|
-
logger.debug("[pty-start] spawn failed:", message);
|
|
2382
|
+
logger.logger.debug("[pty-start] spawn failed:", message);
|
|
3539
2383
|
return { ok: false, error: message };
|
|
3540
2384
|
}
|
|
3541
2385
|
});
|
|
3542
2386
|
rpcHandlerManager.registerHandler("pty-resize", async (data) => {
|
|
3543
|
-
logger.debug(`[pty-resize] ${data.ptyId} ${data.cols}x${data.rows}`);
|
|
2387
|
+
logger.logger.debug(`[pty-resize] ${data.ptyId} ${data.cols}x${data.rows}`);
|
|
3544
2388
|
const ok = resizePty(data.ptyId, data.cols, data.rows);
|
|
3545
2389
|
return { ok };
|
|
3546
2390
|
});
|
|
3547
2391
|
rpcHandlerManager.registerHandler("pty-close", async (data) => {
|
|
3548
|
-
logger.debug(`[pty-close] ${data.ptyId}`);
|
|
2392
|
+
logger.logger.debug(`[pty-close] ${data.ptyId}`);
|
|
3549
2393
|
cleanupPtyState(data.ptyId);
|
|
3550
2394
|
const ok = closePty(data.ptyId);
|
|
3551
2395
|
return { ok };
|
|
3552
2396
|
});
|
|
3553
2397
|
rpcHandlerManager.registerSocketEvent("pty-input", (envelope) => {
|
|
3554
2398
|
if (!envelope || typeof envelope !== "object") {
|
|
3555
|
-
logger.debug("[pty-input] unexpected envelope shape, dropping");
|
|
2399
|
+
logger.logger.debug("[pty-input] unexpected envelope shape, dropping");
|
|
3556
2400
|
return;
|
|
3557
2401
|
}
|
|
3558
2402
|
if (envelope.sessionId !== sessionId) return;
|
|
@@ -3561,14 +2405,14 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
3561
2405
|
try {
|
|
3562
2406
|
const key = rpcHandlerManager.getEncryptionKey();
|
|
3563
2407
|
const variant = rpcHandlerManager.getEncryptionVariant();
|
|
3564
|
-
const decoded = decrypt(key, variant, decodeBase64(envelope.data));
|
|
2408
|
+
const decoded = logger.decrypt(key, variant, logger.decodeBase64(envelope.data));
|
|
3565
2409
|
if (typeof decoded !== "string") {
|
|
3566
|
-
logger.debug("[pty-input] decrypted payload not a string, dropping");
|
|
2410
|
+
logger.logger.debug("[pty-input] decrypted payload not a string, dropping");
|
|
3567
2411
|
return;
|
|
3568
2412
|
}
|
|
3569
2413
|
writeToPty(envelope.ptyId, decoded);
|
|
3570
2414
|
} catch (err) {
|
|
3571
|
-
logger.debug("[pty-input] decrypt/dispatch failed:", err);
|
|
2415
|
+
logger.logger.debug("[pty-input] decrypt/dispatch failed:", err);
|
|
3572
2416
|
}
|
|
3573
2417
|
});
|
|
3574
2418
|
}
|
|
@@ -3836,7 +2680,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3836
2680
|
initialTitleSet = false;
|
|
3837
2681
|
queueOrDeliverUserMessage(message, source) {
|
|
3838
2682
|
if (isHumanOnlyMessageRecord(message)) {
|
|
3839
|
-
logger.debug(`[API] Ignoring human-only collaboration message from ${source}`);
|
|
2683
|
+
logger.logger.debug(`[API] Ignoring human-only collaboration message from ${source}`);
|
|
3840
2684
|
return false;
|
|
3841
2685
|
}
|
|
3842
2686
|
if (this.pendingMessageCallback) {
|
|
@@ -3861,7 +2705,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3861
2705
|
scopePrefix: this.sessionId,
|
|
3862
2706
|
encryptionKey: this.encryptionKey,
|
|
3863
2707
|
encryptionVariant: this.encryptionVariant,
|
|
3864
|
-
logger: (msg, data) => logger.debug(msg, data)
|
|
2708
|
+
logger: (msg, data) => logger.logger.debug(msg, data)
|
|
3865
2709
|
});
|
|
3866
2710
|
registerCommonHandlers(this.rpcHandlerManager, this.metadata.path, this.sessionId);
|
|
3867
2711
|
this.autoReviewGuard = this.createAutoReviewGuard();
|
|
@@ -3878,7 +2722,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3878
2722
|
}
|
|
3879
2723
|
});
|
|
3880
2724
|
this.sendSync = new InvalidateSync(() => this.flushOutbox());
|
|
3881
|
-
this.socket = socket_ioClient.io(configuration.serverUrl, {
|
|
2725
|
+
this.socket = socket_ioClient.io(logger.configuration.serverUrl, {
|
|
3882
2726
|
auth: {
|
|
3883
2727
|
token: this.token,
|
|
3884
2728
|
clientType: "session-scoped",
|
|
@@ -3895,18 +2739,18 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3895
2739
|
autoConnect: false
|
|
3896
2740
|
});
|
|
3897
2741
|
this.socket.on("connect", () => {
|
|
3898
|
-
logger.debug("Socket connected successfully");
|
|
2742
|
+
logger.logger.debug("Socket connected successfully");
|
|
3899
2743
|
this.rpcHandlerManager.onSocketConnect(this.socket);
|
|
3900
2744
|
});
|
|
3901
2745
|
this.socket.on("rpc-request", async (data, callback) => {
|
|
3902
2746
|
callback(await this.rpcHandlerManager.handleRequest(data));
|
|
3903
2747
|
});
|
|
3904
2748
|
this.socket.on("disconnect", (reason) => {
|
|
3905
|
-
logger.debug("[API] Socket disconnected:", reason);
|
|
2749
|
+
logger.logger.debug("[API] Socket disconnected:", reason);
|
|
3906
2750
|
this.rpcHandlerManager.onSocketDisconnect();
|
|
3907
2751
|
});
|
|
3908
2752
|
this.socket.on("connect_error", (error) => {
|
|
3909
|
-
logger.debug("[API] Socket connection error:", error);
|
|
2753
|
+
logger.logger.debug("[API] Socket connection error:", error);
|
|
3910
2754
|
this.rpcHandlerManager.onSocketDisconnect();
|
|
3911
2755
|
});
|
|
3912
2756
|
this.socket.on("ephemeral", (payload) => {
|
|
@@ -3939,20 +2783,20 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3939
2783
|
});
|
|
3940
2784
|
};
|
|
3941
2785
|
try {
|
|
3942
|
-
logger.debugLargeJson("[SOCKET] [UPDATE] Received update:", data);
|
|
2786
|
+
logger.logger.debugLargeJson("[SOCKET] [UPDATE] Received update:", data);
|
|
3943
2787
|
if (!data.body) {
|
|
3944
|
-
logger.debug("[SOCKET] [UPDATE] [ERROR] No body in update!");
|
|
2788
|
+
logger.logger.debug("[SOCKET] [UPDATE] [ERROR] No body in update!");
|
|
3945
2789
|
return;
|
|
3946
2790
|
}
|
|
3947
2791
|
if (data.body.t === "new-message" && data.body.message.content.t === "encrypted") {
|
|
3948
|
-
const body = decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(data.body.message.content.c));
|
|
3949
|
-
logger.debugLargeJson("[SOCKET] [UPDATE] Received update:", body);
|
|
2792
|
+
const body = logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(data.body.message.content.c));
|
|
2793
|
+
logger.logger.debugLargeJson("[SOCKET] [UPDATE] Received update:", body);
|
|
3950
2794
|
const userResult = UserMessageSchema.safeParse(body);
|
|
3951
2795
|
if (userResult.success) {
|
|
3952
2796
|
if (isHumanOnlyMessageRecord(body)) {
|
|
3953
|
-
logger.debug("[SOCKET] [UPDATE] Ignoring human-only collaboration message");
|
|
2797
|
+
logger.logger.debug("[SOCKET] [UPDATE] Ignoring human-only collaboration message");
|
|
3954
2798
|
} else if (userResult.data.meta?.sentFrom === "cli") {
|
|
3955
|
-
logger.debug("[SOCKET] [UPDATE] Ignoring echo of CLI-originated user message");
|
|
2799
|
+
logger.logger.debug("[SOCKET] [UPDATE] Ignoring echo of CLI-originated user message");
|
|
3956
2800
|
} else {
|
|
3957
2801
|
this.maybeSetInitialTitleFromUserText(userResult.data.content.text);
|
|
3958
2802
|
if (this.queueOrDeliverUserMessage(userResult.data, "socket-update")) {
|
|
@@ -3971,22 +2815,22 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3971
2815
|
if (data.body.metadata && data.body.metadata.version > this.metadataVersion) {
|
|
3972
2816
|
this.metadata = adoptServerSessionMetadata(
|
|
3973
2817
|
this.metadata,
|
|
3974
|
-
decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(data.body.metadata.value))
|
|
2818
|
+
logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(data.body.metadata.value))
|
|
3975
2819
|
);
|
|
3976
2820
|
this.metadataVersion = data.body.metadata.version;
|
|
3977
2821
|
this.syncedModel = this.metadata?.model?.trim() || null;
|
|
3978
2822
|
}
|
|
3979
2823
|
if (data.body.agentState && data.body.agentState.version > this.agentStateVersion) {
|
|
3980
|
-
this.agentState = data.body.agentState.value ? decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(data.body.agentState.value)) : null;
|
|
2824
|
+
this.agentState = data.body.agentState.value ? logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(data.body.agentState.value)) : null;
|
|
3981
2825
|
this.agentStateVersion = data.body.agentState.version;
|
|
3982
2826
|
}
|
|
3983
2827
|
} else if (data.body.t === "update-machine") {
|
|
3984
|
-
logger.debug(`[SOCKET] WARNING: Session client received unexpected machine update - ignoring`);
|
|
2828
|
+
logger.logger.debug(`[SOCKET] WARNING: Session client received unexpected machine update - ignoring`);
|
|
3985
2829
|
} else {
|
|
3986
2830
|
this.emit("message", data.body);
|
|
3987
2831
|
}
|
|
3988
2832
|
} catch (error) {
|
|
3989
|
-
logger.debug("[SOCKET] [UPDATE] [ERROR] Error handling update", { error });
|
|
2833
|
+
logger.logger.debug("[SOCKET] [UPDATE] [ERROR] Error handling update", { error });
|
|
3990
2834
|
if (data?.body?.t === "new-message") {
|
|
3991
2835
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3992
2836
|
emitMessageReceipt({
|
|
@@ -4000,7 +2844,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4000
2844
|
}
|
|
4001
2845
|
});
|
|
4002
2846
|
this.socket.on("error", (error) => {
|
|
4003
|
-
logger.debug("[API] Socket error:", error);
|
|
2847
|
+
logger.logger.debug("[API] Socket error:", error);
|
|
4004
2848
|
});
|
|
4005
2849
|
this.socket.connect();
|
|
4006
2850
|
}
|
|
@@ -4015,7 +2859,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4015
2859
|
}
|
|
4016
2860
|
async orchestratorSubmit(body) {
|
|
4017
2861
|
const response = await axios.post(
|
|
4018
|
-
`${configuration.serverUrl}/v1/orchestrator/submit`,
|
|
2862
|
+
`${logger.configuration.serverUrl}/v1/orchestrator/submit`,
|
|
4019
2863
|
body,
|
|
4020
2864
|
{
|
|
4021
2865
|
headers: this.orchestratorHeaders(),
|
|
@@ -4026,7 +2870,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4026
2870
|
}
|
|
4027
2871
|
async orchestratorGetContext() {
|
|
4028
2872
|
const response = await axios.get(
|
|
4029
|
-
`${configuration.serverUrl}/v1/orchestrator/context`,
|
|
2873
|
+
`${logger.configuration.serverUrl}/v1/orchestrator/context`,
|
|
4030
2874
|
{
|
|
4031
2875
|
headers: this.orchestratorHeaders(),
|
|
4032
2876
|
timeout: 3e4
|
|
@@ -4036,7 +2880,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4036
2880
|
}
|
|
4037
2881
|
async orchestratorGetRun(runId, includeTasks = true) {
|
|
4038
2882
|
const response = await axios.get(
|
|
4039
|
-
`${configuration.serverUrl}/v1/orchestrator/runs/${encodeURIComponent(runId)}`,
|
|
2883
|
+
`${logger.configuration.serverUrl}/v1/orchestrator/runs/${encodeURIComponent(runId)}`,
|
|
4040
2884
|
{
|
|
4041
2885
|
headers: this.orchestratorHeaders(),
|
|
4042
2886
|
params: { includeTasks },
|
|
@@ -4047,7 +2891,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4047
2891
|
}
|
|
4048
2892
|
async orchestratorListRuns(query = {}) {
|
|
4049
2893
|
const response = await axios.get(
|
|
4050
|
-
`${configuration.serverUrl}/v1/orchestrator/runs`,
|
|
2894
|
+
`${logger.configuration.serverUrl}/v1/orchestrator/runs`,
|
|
4051
2895
|
{
|
|
4052
2896
|
headers: this.orchestratorHeaders(),
|
|
4053
2897
|
params: query,
|
|
@@ -4058,7 +2902,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4058
2902
|
}
|
|
4059
2903
|
async orchestratorPend(runId, query = {}) {
|
|
4060
2904
|
const response = await axios.get(
|
|
4061
|
-
`${configuration.serverUrl}/v1/orchestrator/runs/${encodeURIComponent(runId)}/pend`,
|
|
2905
|
+
`${logger.configuration.serverUrl}/v1/orchestrator/runs/${encodeURIComponent(runId)}/pend`,
|
|
4062
2906
|
{
|
|
4063
2907
|
headers: this.orchestratorHeaders(),
|
|
4064
2908
|
params: query,
|
|
@@ -4069,7 +2913,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4069
2913
|
}
|
|
4070
2914
|
async orchestratorSendMessage(body) {
|
|
4071
2915
|
const response = await axios.post(
|
|
4072
|
-
`${configuration.serverUrl}/v1/orchestrator/tasks/${encodeURIComponent(body.taskId)}/send-message`,
|
|
2916
|
+
`${logger.configuration.serverUrl}/v1/orchestrator/tasks/${encodeURIComponent(body.taskId)}/send-message`,
|
|
4073
2917
|
{
|
|
4074
2918
|
message: body.message
|
|
4075
2919
|
},
|
|
@@ -4082,7 +2926,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4082
2926
|
}
|
|
4083
2927
|
async orchestratorCancel(runId, body) {
|
|
4084
2928
|
const response = await axios.post(
|
|
4085
|
-
`${configuration.serverUrl}/v1/orchestrator/runs/${encodeURIComponent(runId)}/cancel`,
|
|
2929
|
+
`${logger.configuration.serverUrl}/v1/orchestrator/runs/${encodeURIComponent(runId)}/cancel`,
|
|
4086
2930
|
body ?? {},
|
|
4087
2931
|
{
|
|
4088
2932
|
headers: this.orchestratorHeaders(),
|
|
@@ -4321,7 +3165,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4321
3165
|
for (let offset = 0; offset < batch.length; offset += OUTBOX_FLUSH_BATCH_SIZE) {
|
|
4322
3166
|
const chunk = batch.slice(offset, offset + OUTBOX_FLUSH_BATCH_SIZE);
|
|
4323
3167
|
await axios.post(
|
|
4324
|
-
`${configuration.serverUrl}/v3/sessions/${encodeURIComponent(this.sessionId)}/messages`,
|
|
3168
|
+
`${logger.configuration.serverUrl}/v3/sessions/${encodeURIComponent(this.sessionId)}/messages`,
|
|
4325
3169
|
{
|
|
4326
3170
|
messages: chunk
|
|
4327
3171
|
},
|
|
@@ -4341,7 +3185,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4341
3185
|
* This is the parallel reliable path alongside the fast-path socket emit.
|
|
4342
3186
|
*/
|
|
4343
3187
|
enqueueMessage(content) {
|
|
4344
|
-
const encrypted = encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, content));
|
|
3188
|
+
const encrypted = logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, content));
|
|
4345
3189
|
this.pendingOutbox.push({
|
|
4346
3190
|
content: encrypted,
|
|
4347
3191
|
localId: node_crypto.randomUUID()
|
|
@@ -4358,7 +3202,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4358
3202
|
const messages = await this.fetchRecentReviewMessages(80);
|
|
4359
3203
|
return messages.some((message) => message.role === "user" && normalizeAutoReviewTextForDedupe(message.text) === normalized);
|
|
4360
3204
|
} catch (error) {
|
|
4361
|
-
logger.debug("[AUTO_REVIEW] Failed to check duplicate follow-up messages:", error);
|
|
3205
|
+
logger.logger.debug("[AUTO_REVIEW] Failed to check duplicate follow-up messages:", error);
|
|
4362
3206
|
return false;
|
|
4363
3207
|
}
|
|
4364
3208
|
}
|
|
@@ -4380,9 +3224,9 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4380
3224
|
displayText: trimmed
|
|
4381
3225
|
}
|
|
4382
3226
|
};
|
|
4383
|
-
const encrypted = encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, content));
|
|
3227
|
+
const encrypted = logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, content));
|
|
4384
3228
|
await axios.post(
|
|
4385
|
-
`${configuration.serverUrl}/v3/sessions/${encodeURIComponent(this.sessionId)}/send`,
|
|
3229
|
+
`${logger.configuration.serverUrl}/v3/sessions/${encodeURIComponent(this.sessionId)}/send`,
|
|
4386
3230
|
{
|
|
4387
3231
|
content: encrypted,
|
|
4388
3232
|
localId,
|
|
@@ -4399,7 +3243,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4399
3243
|
}
|
|
4400
3244
|
async fetchRecentReviewMessages(limit = 200) {
|
|
4401
3245
|
const response = await axios.get(
|
|
4402
|
-
`${configuration.serverUrl}/v3/sessions/${encodeURIComponent(this.sessionId)}/messages`,
|
|
3246
|
+
`${logger.configuration.serverUrl}/v3/sessions/${encodeURIComponent(this.sessionId)}/messages`,
|
|
4403
3247
|
{
|
|
4404
3248
|
params: { limit },
|
|
4405
3249
|
headers: { "Authorization": `Bearer ${this.token}` },
|
|
@@ -4412,7 +3256,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4412
3256
|
const encrypted = row?.content?.t === "encrypted" ? row.content.c : null;
|
|
4413
3257
|
if (!encrypted) continue;
|
|
4414
3258
|
try {
|
|
4415
|
-
const decrypted = decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(encrypted));
|
|
3259
|
+
const decrypted = logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(encrypted));
|
|
4416
3260
|
if (isHumanOnlyMessageRecord(decrypted)) {
|
|
4417
3261
|
continue;
|
|
4418
3262
|
}
|
|
@@ -4420,7 +3264,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4420
3264
|
const text = extractPlainTextForAutoReview(decrypted);
|
|
4421
3265
|
if (text) result.push({ role, text });
|
|
4422
3266
|
} catch (error) {
|
|
4423
|
-
logger.debug("[AUTO_REVIEW] Failed to decrypt review history message:", error);
|
|
3267
|
+
logger.logger.debug("[AUTO_REVIEW] Failed to decrypt review history message:", error);
|
|
4424
3268
|
}
|
|
4425
3269
|
}
|
|
4426
3270
|
return result;
|
|
@@ -4431,13 +3275,13 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4431
3275
|
const isSidechain = body.isSidechain === true;
|
|
4432
3276
|
this.sendUsageData(body.message.usage, isSidechain ? void 0 : body.message.model);
|
|
4433
3277
|
} catch (error) {
|
|
4434
|
-
logger.debug("[SOCKET] Failed to send usage data:", error);
|
|
3278
|
+
logger.logger.debug("[SOCKET] Failed to send usage data:", error);
|
|
4435
3279
|
}
|
|
4436
3280
|
}
|
|
4437
3281
|
if (body.type === "summary" && "summary" in body && "leafUuid" in body) {
|
|
4438
3282
|
this.updateMetadata((metadata) => {
|
|
4439
3283
|
if (metadata.summaryPinned) {
|
|
4440
|
-
logger.debug("[SOCKET] Skipping summary update: title is pinned by user");
|
|
3284
|
+
logger.logger.debug("[SOCKET] Skipping summary update: title is pinned by user");
|
|
4441
3285
|
return metadata;
|
|
4442
3286
|
}
|
|
4443
3287
|
const newSummary = body.summary;
|
|
@@ -4445,7 +3289,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4445
3289
|
const dirName = metadata.path?.split(/[\\/]/).filter(Boolean).pop();
|
|
4446
3290
|
const isNewSummaryDirName = dirName && newSummary === dirName;
|
|
4447
3291
|
if (isNewSummaryDirName && currentSummary && currentSummary !== dirName) {
|
|
4448
|
-
logger.debug("[SOCKET] Skipping summary update: new summary is directory name but current title is better", {
|
|
3292
|
+
logger.logger.debug("[SOCKET] Skipping summary update: new summary is directory name but current title is better", {
|
|
4449
3293
|
newSummary,
|
|
4450
3294
|
currentSummary,
|
|
4451
3295
|
dirName
|
|
@@ -4471,18 +3315,18 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4471
3315
|
if (content.role === "agent") {
|
|
4472
3316
|
this.autoReviewGuard.onAgentText(extractPlainTextForAutoReview(content), String(body.uuid || node_crypto.randomUUID()));
|
|
4473
3317
|
}
|
|
4474
|
-
logger.debugLargeJson("[SOCKET] Sending message through socket:", content);
|
|
3318
|
+
logger.logger.debugLargeJson("[SOCKET] Sending message through socket:", content);
|
|
4475
3319
|
this.enqueueMessage(content);
|
|
4476
3320
|
this.postSendProcessing(body);
|
|
4477
3321
|
}
|
|
4478
3322
|
async sendClaudeSessionMessageBatch(messages, mode = "append") {
|
|
4479
3323
|
if (!this.socket.connected) {
|
|
4480
|
-
logger.debug("[API] Socket not connected, cannot send Claude session message batch. Messages will be lost:", { count: messages.length });
|
|
3324
|
+
logger.logger.debug("[API] Socket not connected, cannot send Claude session message batch. Messages will be lost:", { count: messages.length });
|
|
4481
3325
|
return { result: "error" };
|
|
4482
3326
|
}
|
|
4483
3327
|
const payload = messages.map((item) => {
|
|
4484
3328
|
const content = this.buildMessageContent(item.message);
|
|
4485
|
-
const encrypted = encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, content));
|
|
3329
|
+
const encrypted = logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, content));
|
|
4486
3330
|
return {
|
|
4487
3331
|
message: encrypted,
|
|
4488
3332
|
localId: item.localId ?? null
|
|
@@ -4537,7 +3381,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4537
3381
|
sentFrom: "cli"
|
|
4538
3382
|
}
|
|
4539
3383
|
};
|
|
4540
|
-
logger.debug(`[SOCKET] Sending ACP message from ${provider}:`, { type: body.type, hasMessage: "message" in body });
|
|
3384
|
+
logger.logger.debug(`[SOCKET] Sending ACP message from ${provider}:`, { type: body.type, hasMessage: "message" in body });
|
|
4541
3385
|
this.autoReviewGuard.onAgentText(normalizeReviewableAgentText(body), `${provider}-${Date.now()}`);
|
|
4542
3386
|
this.enqueueMessage(content);
|
|
4543
3387
|
}
|
|
@@ -4548,17 +3392,17 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4548
3392
|
*/
|
|
4549
3393
|
async sendBackfillBatch(messages, mode = "append") {
|
|
4550
3394
|
if (!this.socket.connected) {
|
|
4551
|
-
logger.debug(`[API] Socket not connected, cannot send backfill batch (${messages.length} messages)`);
|
|
3395
|
+
logger.logger.debug(`[API] Socket not connected, cannot send backfill batch (${messages.length} messages)`);
|
|
4552
3396
|
return { result: "error" };
|
|
4553
3397
|
}
|
|
4554
3398
|
const payload = messages.map((item) => {
|
|
4555
|
-
const encrypted = encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, item.content));
|
|
3399
|
+
const encrypted = logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, item.content));
|
|
4556
3400
|
return {
|
|
4557
3401
|
message: encrypted,
|
|
4558
3402
|
localId: item.localId
|
|
4559
3403
|
};
|
|
4560
3404
|
});
|
|
4561
|
-
logger.debug(`[SOCKET] Sending backfill batch: ${messages.length} messages, mode=${mode}`);
|
|
3405
|
+
logger.logger.debug(`[SOCKET] Sending backfill batch: ${messages.length} messages, mode=${mode}`);
|
|
4562
3406
|
const response = await this.socket.emitWithAck("message-batch", {
|
|
4563
3407
|
sid: this.sessionId,
|
|
4564
3408
|
messages: payload,
|
|
@@ -4575,7 +3419,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4575
3419
|
data: event
|
|
4576
3420
|
}
|
|
4577
3421
|
};
|
|
4578
|
-
const encrypted = encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, content));
|
|
3422
|
+
const encrypted = logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, content));
|
|
4579
3423
|
this.socket.emit("message", {
|
|
4580
3424
|
sid: this.sessionId,
|
|
4581
3425
|
message: encrypted
|
|
@@ -4585,8 +3429,8 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4585
3429
|
* Send a ping message to keep the connection alive
|
|
4586
3430
|
*/
|
|
4587
3431
|
keepAlive(thinking, mode) {
|
|
4588
|
-
if (isDebug()) {
|
|
4589
|
-
logger.debug(`[API] Sending keep alive message: ${thinking}`);
|
|
3432
|
+
if (logger.isDebug()) {
|
|
3433
|
+
logger.logger.debug(`[API] Sending keep alive message: ${thinking}`);
|
|
4590
3434
|
}
|
|
4591
3435
|
this.socket.volatile.emit("session-alive", {
|
|
4592
3436
|
sid: this.sessionId,
|
|
@@ -4605,7 +3449,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4605
3449
|
* Send a generic usage report to the server for any provider
|
|
4606
3450
|
*/
|
|
4607
3451
|
sendUsageReport(report) {
|
|
4608
|
-
logger.debugLargeJson("[SOCKET] Sending usage report:", report);
|
|
3452
|
+
logger.logger.debugLargeJson("[SOCKET] Sending usage report:", report);
|
|
4609
3453
|
this.socket.emit("usage-report", {
|
|
4610
3454
|
key: report.key,
|
|
4611
3455
|
sessionId: this.sessionId,
|
|
@@ -4613,7 +3457,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4613
3457
|
cost: report.cost
|
|
4614
3458
|
}, (response) => {
|
|
4615
3459
|
if (!response?.success) {
|
|
4616
|
-
logger.debug("[SOCKET] Usage report rejected by server", {
|
|
3460
|
+
logger.logger.debug("[SOCKET] Usage report rejected by server", {
|
|
4617
3461
|
key: report.key,
|
|
4618
3462
|
sessionId: this.sessionId,
|
|
4619
3463
|
error: response?.error || "unknown error"
|
|
@@ -4700,22 +3544,22 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4700
3544
|
}
|
|
4701
3545
|
async updateMetadataAsync(handler) {
|
|
4702
3546
|
await this.metadataLock.inLock(async () => {
|
|
4703
|
-
await backoff(async () => {
|
|
3547
|
+
await time.backoff(async () => {
|
|
4704
3548
|
const base = this.metadata;
|
|
4705
3549
|
if (!base) {
|
|
4706
|
-
logger.debug("[API] skipping metadata update: no local metadata to build on");
|
|
3550
|
+
logger.logger.debug("[API] skipping metadata update: no local metadata to build on");
|
|
4707
3551
|
return;
|
|
4708
3552
|
}
|
|
4709
3553
|
const updated = adoptServerSessionMetadata(base, handler(base));
|
|
4710
|
-
const answer = await this.socket.emitWithAck("update-metadata", { sid: this.sessionId, expectedVersion: this.metadataVersion, metadata: encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, updated)) });
|
|
3554
|
+
const answer = await this.socket.emitWithAck("update-metadata", { sid: this.sessionId, expectedVersion: this.metadataVersion, metadata: logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, updated)) });
|
|
4711
3555
|
if (answer.result === "success") {
|
|
4712
|
-
this.metadata = adoptServerSessionMetadata(this.metadata, decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.metadata)));
|
|
3556
|
+
this.metadata = adoptServerSessionMetadata(this.metadata, logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(answer.metadata)));
|
|
4713
3557
|
this.metadataVersion = answer.version;
|
|
4714
3558
|
this.syncedModel = this.metadata?.model?.trim() || null;
|
|
4715
3559
|
} else if (answer.result === "version-mismatch") {
|
|
4716
3560
|
if (answer.version > this.metadataVersion) {
|
|
4717
3561
|
this.metadataVersion = answer.version;
|
|
4718
|
-
this.metadata = adoptServerSessionMetadata(this.metadata, decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.metadata)));
|
|
3562
|
+
this.metadata = adoptServerSessionMetadata(this.metadata, logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(answer.metadata)));
|
|
4719
3563
|
this.syncedModel = this.metadata?.model?.trim() || null;
|
|
4720
3564
|
}
|
|
4721
3565
|
throw new Error("Metadata version mismatch");
|
|
@@ -4728,19 +3572,19 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4728
3572
|
* @param handler - Handler function that returns the updated agent state
|
|
4729
3573
|
*/
|
|
4730
3574
|
updateAgentState(handler) {
|
|
4731
|
-
logger.debugLargeJson("Updating agent state", this.agentState);
|
|
3575
|
+
logger.logger.debugLargeJson("Updating agent state", this.agentState);
|
|
4732
3576
|
this.agentStateLock.inLock(async () => {
|
|
4733
|
-
await backoff(async () => {
|
|
3577
|
+
await time.backoff(async () => {
|
|
4734
3578
|
let updated = handler(this.agentState || {});
|
|
4735
|
-
const answer = await this.socket.emitWithAck("update-state", { sid: this.sessionId, expectedVersion: this.agentStateVersion, agentState: updated ? encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, updated)) : null });
|
|
3579
|
+
const answer = await this.socket.emitWithAck("update-state", { sid: this.sessionId, expectedVersion: this.agentStateVersion, agentState: updated ? logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, updated)) : null });
|
|
4736
3580
|
if (answer.result === "success") {
|
|
4737
|
-
this.agentState = answer.agentState ? decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.agentState)) : null;
|
|
3581
|
+
this.agentState = answer.agentState ? logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(answer.agentState)) : null;
|
|
4738
3582
|
this.agentStateVersion = answer.version;
|
|
4739
|
-
logger.debug("Agent state updated", this.agentState);
|
|
3583
|
+
logger.logger.debug("Agent state updated", this.agentState);
|
|
4740
3584
|
} else if (answer.result === "version-mismatch") {
|
|
4741
3585
|
if (answer.version > this.agentStateVersion) {
|
|
4742
3586
|
this.agentStateVersion = answer.version;
|
|
4743
|
-
this.agentState = answer.agentState ? decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.agentState)) : null;
|
|
3587
|
+
this.agentState = answer.agentState ? logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(answer.agentState)) : null;
|
|
4744
3588
|
}
|
|
4745
3589
|
throw new Error("Agent state version mismatch");
|
|
4746
3590
|
} else if (answer.result === "error") ;
|
|
@@ -4755,7 +3599,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4755
3599
|
try {
|
|
4756
3600
|
await this.sendSync.invalidateAndAwait();
|
|
4757
3601
|
} catch (error) {
|
|
4758
|
-
logger.debug("[API] flush: outbox flush failed, some messages may be lost:", error);
|
|
3602
|
+
logger.logger.debug("[API] flush: outbox flush failed, some messages may be lost:", error);
|
|
4759
3603
|
}
|
|
4760
3604
|
if (!this.socket.connected) {
|
|
4761
3605
|
return;
|
|
@@ -4770,387 +3614,17 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4770
3614
|
});
|
|
4771
3615
|
}
|
|
4772
3616
|
async close() {
|
|
4773
|
-
logger.debug("[API] socket.close() called");
|
|
3617
|
+
logger.logger.debug("[API] socket.close() called");
|
|
4774
3618
|
try {
|
|
4775
3619
|
await this.sendSync.invalidateAndAwait();
|
|
4776
3620
|
} catch (error) {
|
|
4777
|
-
logger.debug("[API] close: final outbox flush failed:", error);
|
|
3621
|
+
logger.logger.debug("[API] close: final outbox flush failed:", error);
|
|
4778
3622
|
}
|
|
4779
3623
|
this.sendSync.stop();
|
|
4780
3624
|
this.socket.close();
|
|
4781
3625
|
}
|
|
4782
3626
|
}
|
|
4783
3627
|
|
|
4784
|
-
const AnthropicConfigSchema = z__namespace.object({
|
|
4785
|
-
baseUrl: z__namespace.string().url().optional(),
|
|
4786
|
-
authToken: z__namespace.string().optional(),
|
|
4787
|
-
model: z__namespace.string().optional()
|
|
4788
|
-
});
|
|
4789
|
-
const OpenAIConfigSchema = z__namespace.object({
|
|
4790
|
-
apiKey: z__namespace.string().optional(),
|
|
4791
|
-
baseUrl: z__namespace.string().url().optional(),
|
|
4792
|
-
model: z__namespace.string().optional()
|
|
4793
|
-
});
|
|
4794
|
-
const AzureOpenAIConfigSchema = z__namespace.object({
|
|
4795
|
-
apiKey: z__namespace.string().optional(),
|
|
4796
|
-
endpoint: z__namespace.string().url().optional(),
|
|
4797
|
-
apiVersion: z__namespace.string().optional(),
|
|
4798
|
-
deploymentName: z__namespace.string().optional()
|
|
4799
|
-
});
|
|
4800
|
-
const TogetherAIConfigSchema = z__namespace.object({
|
|
4801
|
-
apiKey: z__namespace.string().optional(),
|
|
4802
|
-
model: z__namespace.string().optional()
|
|
4803
|
-
});
|
|
4804
|
-
const TmuxConfigSchema = z__namespace.object({
|
|
4805
|
-
sessionName: z__namespace.string().optional(),
|
|
4806
|
-
tmpDir: z__namespace.string().optional(),
|
|
4807
|
-
updateEnvironment: z__namespace.boolean().optional()
|
|
4808
|
-
});
|
|
4809
|
-
const EnvironmentVariableSchema = z__namespace.object({
|
|
4810
|
-
name: z__namespace.string().regex(/^[A-Z_][A-Z0-9_]*$/, "Invalid environment variable name"),
|
|
4811
|
-
value: z__namespace.string()
|
|
4812
|
-
});
|
|
4813
|
-
const ProfileCompatibilitySchema = z__namespace.object({
|
|
4814
|
-
claude: z__namespace.boolean().default(true),
|
|
4815
|
-
codex: z__namespace.boolean().default(true),
|
|
4816
|
-
gemini: z__namespace.boolean().default(true)
|
|
4817
|
-
});
|
|
4818
|
-
const AIBackendProfileSchema = z__namespace.object({
|
|
4819
|
-
id: z__namespace.string().uuid(),
|
|
4820
|
-
name: z__namespace.string().min(1).max(100),
|
|
4821
|
-
description: z__namespace.string().max(500).optional(),
|
|
4822
|
-
// Agent-specific configurations
|
|
4823
|
-
anthropicConfig: AnthropicConfigSchema.optional(),
|
|
4824
|
-
openaiConfig: OpenAIConfigSchema.optional(),
|
|
4825
|
-
azureOpenAIConfig: AzureOpenAIConfigSchema.optional(),
|
|
4826
|
-
togetherAIConfig: TogetherAIConfigSchema.optional(),
|
|
4827
|
-
// Tmux configuration
|
|
4828
|
-
tmuxConfig: TmuxConfigSchema.optional(),
|
|
4829
|
-
// Environment variables (validated)
|
|
4830
|
-
environmentVariables: z__namespace.array(EnvironmentVariableSchema).default([]),
|
|
4831
|
-
// Default session type for this profile
|
|
4832
|
-
defaultSessionType: z__namespace.enum(["simple", "worktree"]).optional(),
|
|
4833
|
-
// Default permission mode for this profile (supports both Claude and Codex modes)
|
|
4834
|
-
defaultPermissionMode: z__namespace.enum([
|
|
4835
|
-
"default",
|
|
4836
|
-
"acceptEdits",
|
|
4837
|
-
"bypassPermissions",
|
|
4838
|
-
"plan",
|
|
4839
|
-
// Claude modes
|
|
4840
|
-
"read-only",
|
|
4841
|
-
"safe-yolo",
|
|
4842
|
-
"yolo"
|
|
4843
|
-
// Codex modes
|
|
4844
|
-
]).optional(),
|
|
4845
|
-
// Default model mode for this profile
|
|
4846
|
-
defaultModelMode: z__namespace.string().optional(),
|
|
4847
|
-
// Compatibility metadata
|
|
4848
|
-
compatibility: ProfileCompatibilitySchema.default({ claude: true, codex: true, gemini: true }),
|
|
4849
|
-
// Built-in profile indicator
|
|
4850
|
-
isBuiltIn: z__namespace.boolean().default(false),
|
|
4851
|
-
// Metadata
|
|
4852
|
-
createdAt: z__namespace.number().default(() => Date.now()),
|
|
4853
|
-
updatedAt: z__namespace.number().default(() => Date.now()),
|
|
4854
|
-
version: z__namespace.string().default("1.0.0")
|
|
4855
|
-
});
|
|
4856
|
-
function validateProfileForAgent(profile, agent) {
|
|
4857
|
-
return profile.compatibility[agent];
|
|
4858
|
-
}
|
|
4859
|
-
function getProfileEnvironmentVariables(profile) {
|
|
4860
|
-
const envVars = {};
|
|
4861
|
-
profile.environmentVariables.forEach((envVar) => {
|
|
4862
|
-
envVars[envVar.name] = envVar.value;
|
|
4863
|
-
});
|
|
4864
|
-
if (profile.anthropicConfig) {
|
|
4865
|
-
if (profile.anthropicConfig.baseUrl) envVars.ANTHROPIC_BASE_URL = profile.anthropicConfig.baseUrl;
|
|
4866
|
-
if (profile.anthropicConfig.authToken) envVars.ANTHROPIC_AUTH_TOKEN = profile.anthropicConfig.authToken;
|
|
4867
|
-
if (profile.anthropicConfig.model) envVars.ANTHROPIC_MODEL = profile.anthropicConfig.model;
|
|
4868
|
-
}
|
|
4869
|
-
if (profile.openaiConfig) {
|
|
4870
|
-
if (profile.openaiConfig.apiKey) envVars.OPENAI_API_KEY = profile.openaiConfig.apiKey;
|
|
4871
|
-
if (profile.openaiConfig.baseUrl) envVars.OPENAI_BASE_URL = profile.openaiConfig.baseUrl;
|
|
4872
|
-
if (profile.openaiConfig.model) envVars.OPENAI_MODEL = profile.openaiConfig.model;
|
|
4873
|
-
}
|
|
4874
|
-
if (profile.azureOpenAIConfig) {
|
|
4875
|
-
if (profile.azureOpenAIConfig.apiKey) envVars.AZURE_OPENAI_API_KEY = profile.azureOpenAIConfig.apiKey;
|
|
4876
|
-
if (profile.azureOpenAIConfig.endpoint) envVars.AZURE_OPENAI_ENDPOINT = profile.azureOpenAIConfig.endpoint;
|
|
4877
|
-
if (profile.azureOpenAIConfig.apiVersion) envVars.AZURE_OPENAI_API_VERSION = profile.azureOpenAIConfig.apiVersion;
|
|
4878
|
-
if (profile.azureOpenAIConfig.deploymentName) envVars.AZURE_OPENAI_DEPLOYMENT_NAME = profile.azureOpenAIConfig.deploymentName;
|
|
4879
|
-
}
|
|
4880
|
-
if (profile.togetherAIConfig) {
|
|
4881
|
-
if (profile.togetherAIConfig.apiKey) envVars.TOGETHER_API_KEY = profile.togetherAIConfig.apiKey;
|
|
4882
|
-
if (profile.togetherAIConfig.model) envVars.TOGETHER_MODEL = profile.togetherAIConfig.model;
|
|
4883
|
-
}
|
|
4884
|
-
if (profile.tmuxConfig) {
|
|
4885
|
-
if (profile.tmuxConfig.sessionName !== void 0) envVars.TMUX_SESSION_NAME = profile.tmuxConfig.sessionName;
|
|
4886
|
-
if (profile.tmuxConfig.tmpDir) envVars.TMUX_TMPDIR = profile.tmuxConfig.tmpDir;
|
|
4887
|
-
if (profile.tmuxConfig.updateEnvironment !== void 0) {
|
|
4888
|
-
envVars.TMUX_UPDATE_ENVIRONMENT = profile.tmuxConfig.updateEnvironment.toString();
|
|
4889
|
-
}
|
|
4890
|
-
}
|
|
4891
|
-
return envVars;
|
|
4892
|
-
}
|
|
4893
|
-
const SUPPORTED_SCHEMA_VERSION = 2;
|
|
4894
|
-
const defaultSettings = {
|
|
4895
|
-
schemaVersion: SUPPORTED_SCHEMA_VERSION,
|
|
4896
|
-
onboardingCompleted: false,
|
|
4897
|
-
profiles: [],
|
|
4898
|
-
localEnvironmentVariables: {}
|
|
4899
|
-
};
|
|
4900
|
-
function migrateSettings(raw, fromVersion) {
|
|
4901
|
-
let migrated = { ...raw };
|
|
4902
|
-
if (fromVersion < 2) {
|
|
4903
|
-
if (!migrated.profiles) {
|
|
4904
|
-
migrated.profiles = [];
|
|
4905
|
-
}
|
|
4906
|
-
if (!migrated.localEnvironmentVariables) {
|
|
4907
|
-
migrated.localEnvironmentVariables = {};
|
|
4908
|
-
}
|
|
4909
|
-
migrated.schemaVersion = 2;
|
|
4910
|
-
}
|
|
4911
|
-
return migrated;
|
|
4912
|
-
}
|
|
4913
|
-
async function readSettings() {
|
|
4914
|
-
if (!fs.existsSync(configuration.settingsFile)) {
|
|
4915
|
-
return { ...defaultSettings };
|
|
4916
|
-
}
|
|
4917
|
-
try {
|
|
4918
|
-
const content = await promises.readFile(configuration.settingsFile, "utf8");
|
|
4919
|
-
const raw = JSON.parse(content);
|
|
4920
|
-
const schemaVersion = raw.schemaVersion ?? 1;
|
|
4921
|
-
if (schemaVersion > SUPPORTED_SCHEMA_VERSION) {
|
|
4922
|
-
logger.warn(
|
|
4923
|
-
`\u26A0\uFE0F Settings schema v${schemaVersion} > supported v${SUPPORTED_SCHEMA_VERSION}. Update happy-cli for full functionality.`
|
|
4924
|
-
);
|
|
4925
|
-
}
|
|
4926
|
-
const migrated = migrateSettings(raw, schemaVersion);
|
|
4927
|
-
if (migrated.profiles && Array.isArray(migrated.profiles)) {
|
|
4928
|
-
const validProfiles = [];
|
|
4929
|
-
for (const profile of migrated.profiles) {
|
|
4930
|
-
try {
|
|
4931
|
-
const validated = AIBackendProfileSchema.parse(profile);
|
|
4932
|
-
validProfiles.push(validated);
|
|
4933
|
-
} catch (error) {
|
|
4934
|
-
logger.warn(
|
|
4935
|
-
`\u26A0\uFE0F Invalid profile "${profile?.name || profile?.id || "unknown"}" - skipping. Error: ${error.message}`
|
|
4936
|
-
);
|
|
4937
|
-
}
|
|
4938
|
-
}
|
|
4939
|
-
migrated.profiles = validProfiles;
|
|
4940
|
-
}
|
|
4941
|
-
return { ...defaultSettings, ...migrated };
|
|
4942
|
-
} catch (error) {
|
|
4943
|
-
logger.warn(`Failed to read settings: ${error.message}`);
|
|
4944
|
-
return { ...defaultSettings };
|
|
4945
|
-
}
|
|
4946
|
-
}
|
|
4947
|
-
async function updateSettings(updater) {
|
|
4948
|
-
const LOCK_RETRY_INTERVAL_MS = 100;
|
|
4949
|
-
const MAX_LOCK_ATTEMPTS = 50;
|
|
4950
|
-
const STALE_LOCK_TIMEOUT_MS = 1e4;
|
|
4951
|
-
const lockFile = configuration.settingsFile + ".lock";
|
|
4952
|
-
const tmpFile = configuration.settingsFile + ".tmp";
|
|
4953
|
-
let fileHandle;
|
|
4954
|
-
let attempts = 0;
|
|
4955
|
-
while (attempts < MAX_LOCK_ATTEMPTS) {
|
|
4956
|
-
try {
|
|
4957
|
-
fileHandle = await promises.open(lockFile, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY);
|
|
4958
|
-
break;
|
|
4959
|
-
} catch (err) {
|
|
4960
|
-
if (err.code === "EEXIST") {
|
|
4961
|
-
attempts++;
|
|
4962
|
-
await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_INTERVAL_MS));
|
|
4963
|
-
try {
|
|
4964
|
-
const stats = await promises.stat(lockFile);
|
|
4965
|
-
if (Date.now() - stats.mtimeMs > STALE_LOCK_TIMEOUT_MS) {
|
|
4966
|
-
await promises.unlink(lockFile).catch(() => {
|
|
4967
|
-
});
|
|
4968
|
-
}
|
|
4969
|
-
} catch {
|
|
4970
|
-
}
|
|
4971
|
-
} else {
|
|
4972
|
-
throw err;
|
|
4973
|
-
}
|
|
4974
|
-
}
|
|
4975
|
-
}
|
|
4976
|
-
if (!fileHandle) {
|
|
4977
|
-
throw new Error(`Failed to acquire settings lock after ${MAX_LOCK_ATTEMPTS * LOCK_RETRY_INTERVAL_MS / 1e3} seconds`);
|
|
4978
|
-
}
|
|
4979
|
-
try {
|
|
4980
|
-
const current = await readSettings() || { ...defaultSettings };
|
|
4981
|
-
const updated = await updater(current);
|
|
4982
|
-
if (!fs.existsSync(configuration.happyHomeDir)) {
|
|
4983
|
-
await promises.mkdir(configuration.happyHomeDir, { recursive: true });
|
|
4984
|
-
}
|
|
4985
|
-
await promises.writeFile(tmpFile, JSON.stringify(updated, null, 2));
|
|
4986
|
-
await promises.rename(tmpFile, configuration.settingsFile);
|
|
4987
|
-
return updated;
|
|
4988
|
-
} finally {
|
|
4989
|
-
await fileHandle.close();
|
|
4990
|
-
await promises.unlink(lockFile).catch(() => {
|
|
4991
|
-
});
|
|
4992
|
-
}
|
|
4993
|
-
}
|
|
4994
|
-
const credentialsSchema = z__namespace.object({
|
|
4995
|
-
token: z__namespace.string(),
|
|
4996
|
-
secret: z__namespace.string().base64().nullish(),
|
|
4997
|
-
// Legacy
|
|
4998
|
-
encryption: z__namespace.object({
|
|
4999
|
-
publicKey: z__namespace.string().base64(),
|
|
5000
|
-
machineKey: z__namespace.string().base64()
|
|
5001
|
-
}).nullish()
|
|
5002
|
-
});
|
|
5003
|
-
async function readCredentials() {
|
|
5004
|
-
if (!fs.existsSync(configuration.privateKeyFile)) {
|
|
5005
|
-
return null;
|
|
5006
|
-
}
|
|
5007
|
-
try {
|
|
5008
|
-
const keyBase64 = await promises.readFile(configuration.privateKeyFile, "utf8");
|
|
5009
|
-
const credentials = credentialsSchema.parse(JSON.parse(keyBase64));
|
|
5010
|
-
if (credentials.secret) {
|
|
5011
|
-
return {
|
|
5012
|
-
token: credentials.token,
|
|
5013
|
-
encryption: {
|
|
5014
|
-
type: "legacy",
|
|
5015
|
-
secret: new Uint8Array(Buffer.from(credentials.secret, "base64"))
|
|
5016
|
-
}
|
|
5017
|
-
};
|
|
5018
|
-
} else if (credentials.encryption) {
|
|
5019
|
-
return {
|
|
5020
|
-
token: credentials.token,
|
|
5021
|
-
encryption: {
|
|
5022
|
-
type: "dataKey",
|
|
5023
|
-
publicKey: new Uint8Array(Buffer.from(credentials.encryption.publicKey, "base64")),
|
|
5024
|
-
machineKey: new Uint8Array(Buffer.from(credentials.encryption.machineKey, "base64"))
|
|
5025
|
-
}
|
|
5026
|
-
};
|
|
5027
|
-
}
|
|
5028
|
-
} catch {
|
|
5029
|
-
return null;
|
|
5030
|
-
}
|
|
5031
|
-
return null;
|
|
5032
|
-
}
|
|
5033
|
-
async function writeCredentialsLegacy(credentials) {
|
|
5034
|
-
if (!fs.existsSync(configuration.happyHomeDir)) {
|
|
5035
|
-
await promises.mkdir(configuration.happyHomeDir, { recursive: true });
|
|
5036
|
-
}
|
|
5037
|
-
await promises.writeFile(configuration.privateKeyFile, JSON.stringify({
|
|
5038
|
-
secret: encodeBase64(credentials.secret),
|
|
5039
|
-
token: credentials.token
|
|
5040
|
-
}, null, 2));
|
|
5041
|
-
}
|
|
5042
|
-
async function writeCredentialsDataKey(credentials) {
|
|
5043
|
-
if (!fs.existsSync(configuration.happyHomeDir)) {
|
|
5044
|
-
await promises.mkdir(configuration.happyHomeDir, { recursive: true });
|
|
5045
|
-
}
|
|
5046
|
-
await promises.writeFile(configuration.privateKeyFile, JSON.stringify({
|
|
5047
|
-
encryption: { publicKey: encodeBase64(credentials.publicKey), machineKey: encodeBase64(credentials.machineKey) },
|
|
5048
|
-
token: credentials.token
|
|
5049
|
-
}, null, 2));
|
|
5050
|
-
}
|
|
5051
|
-
async function clearCredentials() {
|
|
5052
|
-
if (fs.existsSync(configuration.privateKeyFile)) {
|
|
5053
|
-
await promises.unlink(configuration.privateKeyFile);
|
|
5054
|
-
}
|
|
5055
|
-
}
|
|
5056
|
-
async function clearMachineId() {
|
|
5057
|
-
await updateSettings((settings) => ({
|
|
5058
|
-
...settings,
|
|
5059
|
-
machineId: void 0
|
|
5060
|
-
}));
|
|
5061
|
-
}
|
|
5062
|
-
async function readDaemonState() {
|
|
5063
|
-
try {
|
|
5064
|
-
if (!fs.existsSync(configuration.daemonStateFile)) {
|
|
5065
|
-
return null;
|
|
5066
|
-
}
|
|
5067
|
-
const content = await promises.readFile(configuration.daemonStateFile, "utf-8");
|
|
5068
|
-
return JSON.parse(content);
|
|
5069
|
-
} catch (error) {
|
|
5070
|
-
console.error(`[PERSISTENCE] Daemon state file corrupted: ${configuration.daemonStateFile}`, error);
|
|
5071
|
-
return null;
|
|
5072
|
-
}
|
|
5073
|
-
}
|
|
5074
|
-
function writeDaemonState(state) {
|
|
5075
|
-
fs.writeFileSync(configuration.daemonStateFile, JSON.stringify(state, null, 2), "utf-8");
|
|
5076
|
-
}
|
|
5077
|
-
async function clearDaemonState() {
|
|
5078
|
-
if (fs.existsSync(configuration.daemonStateFile)) {
|
|
5079
|
-
await promises.unlink(configuration.daemonStateFile);
|
|
5080
|
-
}
|
|
5081
|
-
if (fs.existsSync(configuration.daemonLockFile)) {
|
|
5082
|
-
try {
|
|
5083
|
-
await promises.unlink(configuration.daemonLockFile);
|
|
5084
|
-
} catch {
|
|
5085
|
-
}
|
|
5086
|
-
}
|
|
5087
|
-
}
|
|
5088
|
-
async function acquireDaemonLock(maxAttempts = 5, delayIncrementMs = 200) {
|
|
5089
|
-
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
5090
|
-
try {
|
|
5091
|
-
const fileHandle = await promises.open(
|
|
5092
|
-
configuration.daemonLockFile,
|
|
5093
|
-
fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY
|
|
5094
|
-
);
|
|
5095
|
-
await fileHandle.writeFile(String(process.pid));
|
|
5096
|
-
return fileHandle;
|
|
5097
|
-
} catch (error) {
|
|
5098
|
-
if (error.code === "EEXIST") {
|
|
5099
|
-
try {
|
|
5100
|
-
const lockPid = fs.readFileSync(configuration.daemonLockFile, "utf-8").trim();
|
|
5101
|
-
if (lockPid && !isNaN(Number(lockPid))) {
|
|
5102
|
-
try {
|
|
5103
|
-
process.kill(Number(lockPid), 0);
|
|
5104
|
-
} catch {
|
|
5105
|
-
fs.unlinkSync(configuration.daemonLockFile);
|
|
5106
|
-
continue;
|
|
5107
|
-
}
|
|
5108
|
-
}
|
|
5109
|
-
} catch {
|
|
5110
|
-
}
|
|
5111
|
-
}
|
|
5112
|
-
if (attempt === maxAttempts) {
|
|
5113
|
-
return null;
|
|
5114
|
-
}
|
|
5115
|
-
const delayMs = attempt * delayIncrementMs;
|
|
5116
|
-
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
5117
|
-
}
|
|
5118
|
-
}
|
|
5119
|
-
return null;
|
|
5120
|
-
}
|
|
5121
|
-
async function releaseDaemonLock(lockHandle) {
|
|
5122
|
-
try {
|
|
5123
|
-
await lockHandle.close();
|
|
5124
|
-
} catch {
|
|
5125
|
-
}
|
|
5126
|
-
try {
|
|
5127
|
-
if (fs.existsSync(configuration.daemonLockFile)) {
|
|
5128
|
-
fs.unlinkSync(configuration.daemonLockFile);
|
|
5129
|
-
}
|
|
5130
|
-
} catch {
|
|
5131
|
-
}
|
|
5132
|
-
}
|
|
5133
|
-
|
|
5134
|
-
var persistence = /*#__PURE__*/Object.freeze({
|
|
5135
|
-
__proto__: null,
|
|
5136
|
-
AIBackendProfileSchema: AIBackendProfileSchema,
|
|
5137
|
-
SUPPORTED_SCHEMA_VERSION: SUPPORTED_SCHEMA_VERSION,
|
|
5138
|
-
acquireDaemonLock: acquireDaemonLock,
|
|
5139
|
-
clearCredentials: clearCredentials,
|
|
5140
|
-
clearDaemonState: clearDaemonState,
|
|
5141
|
-
clearMachineId: clearMachineId,
|
|
5142
|
-
getProfileEnvironmentVariables: getProfileEnvironmentVariables,
|
|
5143
|
-
readCredentials: readCredentials,
|
|
5144
|
-
readDaemonState: readDaemonState,
|
|
5145
|
-
readSettings: readSettings,
|
|
5146
|
-
releaseDaemonLock: releaseDaemonLock,
|
|
5147
|
-
updateSettings: updateSettings,
|
|
5148
|
-
validateProfileForAgent: validateProfileForAgent,
|
|
5149
|
-
writeCredentialsDataKey: writeCredentialsDataKey,
|
|
5150
|
-
writeCredentialsLegacy: writeCredentialsLegacy,
|
|
5151
|
-
writeDaemonState: writeDaemonState
|
|
5152
|
-
});
|
|
5153
|
-
|
|
5154
3628
|
function buildRunningDaemonState(previousState, currentRuntimeState, opts = {}) {
|
|
5155
3629
|
const currentHttpPort = currentRuntimeState?.httpPort;
|
|
5156
3630
|
const currentStartedAt = currentRuntimeState?.startedAt;
|
|
@@ -5216,11 +3690,11 @@ class OpenClawTunnelManager {
|
|
|
5216
3690
|
this.tunnels.set(tunnelId, tunnel);
|
|
5217
3691
|
return new Promise((resolve) => {
|
|
5218
3692
|
try {
|
|
5219
|
-
logger.debug(`[OpenClawTunnel] Connecting to ${config.url}`);
|
|
3693
|
+
logger.logger.debug(`[OpenClawTunnel] Connecting to ${config.url}`);
|
|
5220
3694
|
const ws = new WebSocket(config.url);
|
|
5221
3695
|
tunnel.ws = ws;
|
|
5222
3696
|
ws.on("open", () => {
|
|
5223
|
-
logger.debug(`[OpenClawTunnel] WebSocket opened for tunnel ${tunnelId}`);
|
|
3697
|
+
logger.logger.debug(`[OpenClawTunnel] WebSocket opened for tunnel ${tunnelId}`);
|
|
5224
3698
|
});
|
|
5225
3699
|
ws.on("message", async (data) => {
|
|
5226
3700
|
const result = await this.handleMessage(tunnelId, tunnel, data.toString());
|
|
@@ -5229,7 +3703,7 @@ class OpenClawTunnelManager {
|
|
|
5229
3703
|
}
|
|
5230
3704
|
});
|
|
5231
3705
|
ws.on("error", (error) => {
|
|
5232
|
-
logger.debug(`[OpenClawTunnel] WebSocket error for tunnel ${tunnelId}:`, error);
|
|
3706
|
+
logger.logger.debug(`[OpenClawTunnel] WebSocket error for tunnel ${tunnelId}:`, error);
|
|
5233
3707
|
tunnel.status = "error";
|
|
5234
3708
|
this.failAllPending(tunnel, new Error("WebSocket error"));
|
|
5235
3709
|
resolve({
|
|
@@ -5240,7 +3714,7 @@ class OpenClawTunnelManager {
|
|
|
5240
3714
|
});
|
|
5241
3715
|
ws.on("close", (code, reason) => {
|
|
5242
3716
|
const reasonStr = reason?.toString() || "";
|
|
5243
|
-
logger.debug(`[OpenClawTunnel] WebSocket closed for tunnel ${tunnelId}: ${code} ${reasonStr}`);
|
|
3717
|
+
logger.logger.debug(`[OpenClawTunnel] WebSocket closed for tunnel ${tunnelId}: ${code} ${reasonStr}`);
|
|
5244
3718
|
const isPairingRequired = reasonStr.includes("unauthorized") || reasonStr.includes("NOT_PAIRED");
|
|
5245
3719
|
this.failAllPending(tunnel, new Error(reasonStr || "Connection closed"));
|
|
5246
3720
|
if (tunnel.status === "connecting") {
|
|
@@ -5372,7 +3846,7 @@ class OpenClawTunnelManager {
|
|
|
5372
3846
|
tunnel.ws = null;
|
|
5373
3847
|
}
|
|
5374
3848
|
this.tunnels.delete(tunnelId);
|
|
5375
|
-
logger.debug(`[OpenClawTunnel] Closed tunnel ${tunnelId}`);
|
|
3849
|
+
logger.logger.debug(`[OpenClawTunnel] Closed tunnel ${tunnelId}`);
|
|
5376
3850
|
return true;
|
|
5377
3851
|
}
|
|
5378
3852
|
async handleMessage(tunnelId, tunnel, data) {
|
|
@@ -5380,7 +3854,7 @@ class OpenClawTunnelManager {
|
|
|
5380
3854
|
try {
|
|
5381
3855
|
frame = JSON.parse(data);
|
|
5382
3856
|
} catch {
|
|
5383
|
-
logger.debug(`[OpenClawTunnel] Invalid JSON: ${data.slice(0, 100)}`);
|
|
3857
|
+
logger.logger.debug(`[OpenClawTunnel] Invalid JSON: ${data.slice(0, 100)}`);
|
|
5384
3858
|
return null;
|
|
5385
3859
|
}
|
|
5386
3860
|
if (frame.type === "res") {
|
|
@@ -5405,7 +3879,7 @@ class OpenClawTunnelManager {
|
|
|
5405
3879
|
if (frame.event === "connect.challenge" && !tunnel.connectSent) {
|
|
5406
3880
|
const nonce = payload?.nonce;
|
|
5407
3881
|
if (nonce) {
|
|
5408
|
-
logger.debug(`[OpenClawTunnel] Received challenge nonce for tunnel ${tunnelId}`);
|
|
3882
|
+
logger.logger.debug(`[OpenClawTunnel] Received challenge nonce for tunnel ${tunnelId}`);
|
|
5409
3883
|
tunnel.connectNonce = nonce;
|
|
5410
3884
|
}
|
|
5411
3885
|
return this.sendConnect(tunnelId, tunnel);
|
|
@@ -5485,7 +3959,7 @@ class OpenClawTunnelManager {
|
|
|
5485
3959
|
tunnel.mainSessionKey = result.snapshot?.sessionDefaults?.mainSessionKey ?? null;
|
|
5486
3960
|
tunnel.serverHost = result.server?.host ?? null;
|
|
5487
3961
|
tunnel.deviceToken = result.auth?.deviceToken ?? null;
|
|
5488
|
-
logger.debug(`[OpenClawTunnel] Connected tunnel ${tunnelId}, server: ${tunnel.serverHost}`);
|
|
3962
|
+
logger.logger.debug(`[OpenClawTunnel] Connected tunnel ${tunnelId}, server: ${tunnel.serverHost}`);
|
|
5489
3963
|
resolve({
|
|
5490
3964
|
ok: true,
|
|
5491
3965
|
status: "connected",
|
|
@@ -5603,7 +4077,7 @@ function registerOpenClawHandlers(rpcManager, encryptionContext) {
|
|
|
5603
4077
|
if (Array.isArray(payload.messages) && payload.messages.length > 0) {
|
|
5604
4078
|
return {
|
|
5605
4079
|
__preEncrypted: true,
|
|
5606
|
-
data: encodeBase64(encryptLegacy(result, encryptionContext.key))
|
|
4080
|
+
data: logger.encodeBase64(logger.encryptLegacy(result, encryptionContext.key))
|
|
5607
4081
|
};
|
|
5608
4082
|
}
|
|
5609
4083
|
}
|
|
@@ -5655,7 +4129,7 @@ const SESSION_CACHE_REFRESH_MODES = /* @__PURE__ */ new Set([
|
|
|
5655
4129
|
"background"
|
|
5656
4130
|
]);
|
|
5657
4131
|
function getSessionMetadataCachePath(cacheFileName) {
|
|
5658
|
-
return path.join(configuration.happyHomeDir, cacheFileName);
|
|
4132
|
+
return path.join(logger.configuration.happyHomeDir, cacheFileName);
|
|
5659
4133
|
}
|
|
5660
4134
|
function getCacheLockPath(cachePath) {
|
|
5661
4135
|
return `${cachePath}.lock`;
|
|
@@ -6702,7 +5176,7 @@ const GeminiSessionLineSchema = z.z.discriminatedUnion("type", [
|
|
|
6702
5176
|
|
|
6703
5177
|
const SESSIONS_DIR_NAME = "gemini_sessions";
|
|
6704
5178
|
function getGeminiSessionsDir() {
|
|
6705
|
-
return path.join(configuration.happyHomeDir, SESSIONS_DIR_NAME);
|
|
5179
|
+
return path.join(logger.configuration.happyHomeDir, SESSIONS_DIR_NAME);
|
|
6706
5180
|
}
|
|
6707
5181
|
function getGeminiSessionFilePath(sessionId) {
|
|
6708
5182
|
return path.join(getGeminiSessionsDir(), `${sessionId}.jsonl`);
|
|
@@ -6722,9 +5196,9 @@ class GeminiSessionWriter {
|
|
|
6722
5196
|
value: meta ?? {},
|
|
6723
5197
|
timestamp: Date.now()
|
|
6724
5198
|
});
|
|
6725
|
-
logger.debug(`[GeminiSessionWriter] Initialized: ${this.filePath}`);
|
|
5199
|
+
logger.logger.debug(`[GeminiSessionWriter] Initialized: ${this.filePath}`);
|
|
6726
5200
|
} catch (error) {
|
|
6727
|
-
logger.debug(`[GeminiSessionWriter] Failed to init:`, error);
|
|
5201
|
+
logger.logger.debug(`[GeminiSessionWriter] Failed to init:`, error);
|
|
6728
5202
|
}
|
|
6729
5203
|
}
|
|
6730
5204
|
getFilePath() {
|
|
@@ -6783,7 +5257,7 @@ class GeminiSessionWriter {
|
|
|
6783
5257
|
*/
|
|
6784
5258
|
appendLine(line) {
|
|
6785
5259
|
this.writePromise = this.writePromise.then(() => promises.appendFile(this.filePath, JSON.stringify(line) + "\n", "utf-8")).catch((error) => {
|
|
6786
|
-
logger.debug(`[GeminiSessionWriter] Write failed:`, error);
|
|
5260
|
+
logger.logger.debug(`[GeminiSessionWriter] Write failed:`, error);
|
|
6787
5261
|
});
|
|
6788
5262
|
}
|
|
6789
5263
|
}
|
|
@@ -6794,7 +5268,7 @@ async function readGeminiSessionLog(sessionId) {
|
|
|
6794
5268
|
try {
|
|
6795
5269
|
content = await promises.readFile(filePath, "utf-8");
|
|
6796
5270
|
} catch (error) {
|
|
6797
|
-
logger.debug(`[GeminiSessionReader] Session file not found: ${filePath}`);
|
|
5271
|
+
logger.logger.debug(`[GeminiSessionReader] Session file not found: ${filePath}`);
|
|
6798
5272
|
return [];
|
|
6799
5273
|
}
|
|
6800
5274
|
const lines = content.split("\n");
|
|
@@ -6807,10 +5281,10 @@ async function readGeminiSessionLog(sessionId) {
|
|
|
6807
5281
|
if (result.success) {
|
|
6808
5282
|
entries.push(result.data);
|
|
6809
5283
|
} else {
|
|
6810
|
-
logger.debug(`[GeminiSessionReader] Skipping invalid line: ${line.substring(0, 100)}`);
|
|
5284
|
+
logger.logger.debug(`[GeminiSessionReader] Skipping invalid line: ${line.substring(0, 100)}`);
|
|
6811
5285
|
}
|
|
6812
5286
|
} catch {
|
|
6813
|
-
logger.debug(`[GeminiSessionReader] Skipping non-JSON line: ${line.substring(0, 100)}`);
|
|
5287
|
+
logger.logger.debug(`[GeminiSessionReader] Skipping non-JSON line: ${line.substring(0, 100)}`);
|
|
6814
5288
|
}
|
|
6815
5289
|
}
|
|
6816
5290
|
return entries;
|
|
@@ -7032,7 +5506,7 @@ async function forkAndTruncateGeminiSession(sessionId, truncateBeforeUuid) {
|
|
|
7032
5506
|
return { success: false, errorMessage: truncateResult.errorMessage };
|
|
7033
5507
|
}
|
|
7034
5508
|
}
|
|
7035
|
-
logger.debug(`[GeminiSessionFork] Forked ${sessionId} -> ${newSessionId}`);
|
|
5509
|
+
logger.logger.debug(`[GeminiSessionFork] Forked ${sessionId} -> ${newSessionId}`);
|
|
7036
5510
|
return { success: true, newSessionId };
|
|
7037
5511
|
} catch (error) {
|
|
7038
5512
|
try {
|
|
@@ -7169,14 +5643,14 @@ function isSystemMessage(text) {
|
|
|
7169
5643
|
async function readCodexSessionUserMessages(codexSessionId, limit = 50) {
|
|
7170
5644
|
const filePath = findCodexSessionFile(codexSessionId);
|
|
7171
5645
|
if (!filePath) {
|
|
7172
|
-
logger.debug(`[CodexSessionReader] Session file not found for: ${codexSessionId}`);
|
|
5646
|
+
logger.logger.debug(`[CodexSessionReader] Session file not found for: ${codexSessionId}`);
|
|
7173
5647
|
return [];
|
|
7174
5648
|
}
|
|
7175
5649
|
let content;
|
|
7176
5650
|
try {
|
|
7177
5651
|
content = await promises.readFile(filePath, "utf-8");
|
|
7178
5652
|
} catch (error) {
|
|
7179
|
-
logger.debug(`[CodexSessionReader] Failed to read file: ${filePath}`, error);
|
|
5653
|
+
logger.logger.debug(`[CodexSessionReader] Failed to read file: ${filePath}`, error);
|
|
7180
5654
|
return [];
|
|
7181
5655
|
}
|
|
7182
5656
|
const lines = content.split("\n");
|
|
@@ -7473,7 +5947,7 @@ async function forkAndTruncateCodexSession(codexSessionId, truncateBeforeUuid) {
|
|
|
7473
5947
|
}
|
|
7474
5948
|
await promises.writeFile(newPath, outputLines.join("\n") + "\n", "utf-8");
|
|
7475
5949
|
}
|
|
7476
|
-
logger.debug(`[CodexSessionFork] Forked ${path.basename(originalPath)} -> ${path.basename(newPath)}`);
|
|
5950
|
+
logger.logger.debug(`[CodexSessionFork] Forked ${path.basename(originalPath)} -> ${path.basename(newPath)}`);
|
|
7477
5951
|
return { success: true, newFilePath: newPath };
|
|
7478
5952
|
} catch (error) {
|
|
7479
5953
|
try {
|
|
@@ -7660,7 +6134,7 @@ function createSessionCacheStatsReporter(saveStats, label) {
|
|
|
7660
6134
|
const stats = pendingStats;
|
|
7661
6135
|
pendingStats = null;
|
|
7662
6136
|
flushPromise = saveStats(stats).catch((error) => {
|
|
7663
|
-
logger.debug(`[API MACHINE] Failed to persist ${label} session cache stats`, error);
|
|
6137
|
+
logger.logger.debug(`[API MACHINE] Failed to persist ${label} session cache stats`, error);
|
|
7664
6138
|
}).then(() => {
|
|
7665
6139
|
flushPromise = null;
|
|
7666
6140
|
});
|
|
@@ -7692,7 +6166,7 @@ class ApiMachineClient {
|
|
|
7692
6166
|
scopePrefix: this.machine.id,
|
|
7693
6167
|
encryptionKey: this.machine.encryptionKey,
|
|
7694
6168
|
encryptionVariant: this.machine.encryptionVariant,
|
|
7695
|
-
logger: (msg, data) => logger.debug(msg, data)
|
|
6169
|
+
logger: (msg, data) => logger.logger.debug(msg, data)
|
|
7696
6170
|
});
|
|
7697
6171
|
registerCommonHandlers(this.rpcHandlerManager, process.env.HAPPY_DAEMON_ROOT || "/", this.machine.id);
|
|
7698
6172
|
registerOpenClawHandlers(this.rpcHandlerManager, {
|
|
@@ -7741,7 +6215,7 @@ class ApiMachineClient {
|
|
|
7741
6215
|
event,
|
|
7742
6216
|
payload
|
|
7743
6217
|
};
|
|
7744
|
-
const encryptedData = encodeBase64(encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, eventData));
|
|
6218
|
+
const encryptedData = logger.encodeBase64(logger.encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, eventData));
|
|
7745
6219
|
const rpcMethod = `${this.machine.id}:openclaw-tunnel-event`;
|
|
7746
6220
|
this.socket.emit("rpc-call", {
|
|
7747
6221
|
method: rpcMethod,
|
|
@@ -7757,12 +6231,12 @@ class ApiMachineClient {
|
|
|
7757
6231
|
orchestratorCancel
|
|
7758
6232
|
}) {
|
|
7759
6233
|
this.rpcHandlerManager.registerHandler("spawn-happy-session", async (params) => {
|
|
7760
|
-
const settings = await readSettings();
|
|
6234
|
+
const settings = await logger.readSettings();
|
|
7761
6235
|
if (settings.deviceMode) {
|
|
7762
6236
|
throw new Error("This machine is enrolled as a device and does not host sessions");
|
|
7763
6237
|
}
|
|
7764
6238
|
const { directory, sessionId, resumeSessionId, intent, sessionTitle, skipForkSession, machineId, approvedNewDirectoryCreation, agent, token, environmentVariables, worktreeBasePath, worktreeBranchName, workspaceRepos, workspacePath, repoScripts, mcpServers } = params || {};
|
|
7765
|
-
logger.debug(`[API MACHINE] Spawning session with params: ${JSON.stringify(params)}`);
|
|
6239
|
+
logger.logger.debug(`[API MACHINE] Spawning session with params: ${JSON.stringify(params)}`);
|
|
7766
6240
|
if (!directory) {
|
|
7767
6241
|
throw new Error("Directory is required");
|
|
7768
6242
|
}
|
|
@@ -7772,10 +6246,10 @@ class ApiMachineClient {
|
|
|
7772
6246
|
this.claudeCache.invalidate();
|
|
7773
6247
|
this.geminiCache.invalidate();
|
|
7774
6248
|
this.codexCache.invalidate();
|
|
7775
|
-
logger.debug(`[API MACHINE] Spawned session ${result.sessionId}`);
|
|
6249
|
+
logger.logger.debug(`[API MACHINE] Spawned session ${result.sessionId}`);
|
|
7776
6250
|
return { type: "success", sessionId: result.sessionId };
|
|
7777
6251
|
case "requestToApproveDirectoryCreation":
|
|
7778
|
-
logger.debug(`[API MACHINE] Requesting directory creation approval for: ${result.directory}`);
|
|
6252
|
+
logger.logger.debug(`[API MACHINE] Requesting directory creation approval for: ${result.directory}`);
|
|
7779
6253
|
return { type: "requestToApproveDirectoryCreation", directory: result.directory };
|
|
7780
6254
|
case "error":
|
|
7781
6255
|
throw new Error(result.errorMessage);
|
|
@@ -7791,9 +6265,9 @@ class ApiMachineClient {
|
|
|
7791
6265
|
const { worktreePath, basePath, branchName, archiveScript, deleteBranch } = repo;
|
|
7792
6266
|
try {
|
|
7793
6267
|
if (archiveScript) {
|
|
7794
|
-
logger.info(`[DAEMON] Running archive script in ${worktreePath}...`);
|
|
6268
|
+
logger.logger.info(`[DAEMON] Running archive script in ${worktreePath}...`);
|
|
7795
6269
|
node_child_process.execSync(archiveScript, { cwd: worktreePath, stdio: "pipe", timeout: 3e5 });
|
|
7796
|
-
logger.info(`[DAEMON] Archive script completed for ${worktreePath}`);
|
|
6270
|
+
logger.logger.info(`[DAEMON] Archive script completed for ${worktreePath}`);
|
|
7797
6271
|
}
|
|
7798
6272
|
if (worktreePath !== basePath) {
|
|
7799
6273
|
try {
|
|
@@ -7803,7 +6277,7 @@ class ApiMachineClient {
|
|
|
7803
6277
|
timeout: 3e4
|
|
7804
6278
|
});
|
|
7805
6279
|
} catch (err) {
|
|
7806
|
-
logger.warn(`[DAEMON] git worktree remove failed: ${err.message}`);
|
|
6280
|
+
logger.logger.warn(`[DAEMON] git worktree remove failed: ${err.message}`);
|
|
7807
6281
|
}
|
|
7808
6282
|
if (deleteBranch && branchName) {
|
|
7809
6283
|
try {
|
|
@@ -7813,13 +6287,13 @@ class ApiMachineClient {
|
|
|
7813
6287
|
timeout: 1e4
|
|
7814
6288
|
});
|
|
7815
6289
|
} catch (err) {
|
|
7816
|
-
logger.warn(`[DAEMON] git branch -D failed: ${err.message}`);
|
|
6290
|
+
logger.logger.warn(`[DAEMON] git branch -D failed: ${err.message}`);
|
|
7817
6291
|
}
|
|
7818
6292
|
}
|
|
7819
6293
|
}
|
|
7820
6294
|
results.push({ repo: worktreePath, success: true });
|
|
7821
6295
|
} catch (err) {
|
|
7822
|
-
logger.warn(`[DAEMON] Archive failed for ${worktreePath}: ${err.message}`);
|
|
6296
|
+
logger.logger.warn(`[DAEMON] Archive failed for ${worktreePath}: ${err.message}`);
|
|
7823
6297
|
results.push({ repo: worktreePath, success: false, error: err.message });
|
|
7824
6298
|
}
|
|
7825
6299
|
}
|
|
@@ -7828,7 +6302,7 @@ class ApiMachineClient {
|
|
|
7828
6302
|
const entries = fs.readdirSync(workspacePath);
|
|
7829
6303
|
if (entries.length === 0) {
|
|
7830
6304
|
fs.rmdirSync(workspacePath);
|
|
7831
|
-
logger.info(`[DAEMON] Removed empty workspace directory: ${workspacePath}`);
|
|
6305
|
+
logger.logger.info(`[DAEMON] Removed empty workspace directory: ${workspacePath}`);
|
|
7832
6306
|
}
|
|
7833
6307
|
} catch {
|
|
7834
6308
|
}
|
|
@@ -7847,13 +6321,13 @@ class ApiMachineClient {
|
|
|
7847
6321
|
this.claudeCache.invalidate();
|
|
7848
6322
|
this.geminiCache.invalidate();
|
|
7849
6323
|
this.codexCache.invalidate();
|
|
7850
|
-
logger.debug(`[API MACHINE] Stopped session ${sessionId}`);
|
|
6324
|
+
logger.logger.debug(`[API MACHINE] Stopped session ${sessionId}`);
|
|
7851
6325
|
return { message: "Session stopped" };
|
|
7852
6326
|
});
|
|
7853
6327
|
this.rpcHandlerManager.registerHandler("stop-daemon", () => {
|
|
7854
|
-
logger.debug("[API MACHINE] Received stop-daemon RPC request");
|
|
6328
|
+
logger.logger.debug("[API MACHINE] Received stop-daemon RPC request");
|
|
7855
6329
|
setTimeout(() => {
|
|
7856
|
-
logger.debug("[API MACHINE] Initiating daemon shutdown from RPC");
|
|
6330
|
+
logger.logger.debug("[API MACHINE] Initiating daemon shutdown from RPC");
|
|
7857
6331
|
requestShutdown();
|
|
7858
6332
|
}, 100);
|
|
7859
6333
|
return { message: "Daemon stop request acknowledged, starting shutdown sequence..." };
|
|
@@ -8091,21 +6565,21 @@ class ApiMachineClient {
|
|
|
8091
6565
|
* for example to set a custom name.
|
|
8092
6566
|
*/
|
|
8093
6567
|
async updateMachineMetadata(handler) {
|
|
8094
|
-
await backoff(async () => {
|
|
6568
|
+
await time.backoff(async () => {
|
|
8095
6569
|
const updated = handler(this.machine.metadata);
|
|
8096
6570
|
const answer = await this.socket.emitWithAck("machine-update-metadata", {
|
|
8097
6571
|
machineId: this.machine.id,
|
|
8098
|
-
metadata: encodeBase64(encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, updated)),
|
|
6572
|
+
metadata: logger.encodeBase64(logger.encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, updated)),
|
|
8099
6573
|
expectedVersion: this.machine.metadataVersion
|
|
8100
6574
|
});
|
|
8101
6575
|
if (answer.result === "success") {
|
|
8102
|
-
this.machine.metadata = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.metadata));
|
|
6576
|
+
this.machine.metadata = logger.decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, logger.decodeBase64(answer.metadata));
|
|
8103
6577
|
this.machine.metadataVersion = answer.version;
|
|
8104
|
-
logger.debug("[API MACHINE] Metadata updated successfully");
|
|
6578
|
+
logger.logger.debug("[API MACHINE] Metadata updated successfully");
|
|
8105
6579
|
} else if (answer.result === "version-mismatch") {
|
|
8106
6580
|
if (answer.version > this.machine.metadataVersion) {
|
|
8107
6581
|
this.machine.metadataVersion = answer.version;
|
|
8108
|
-
this.machine.metadata = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.metadata));
|
|
6582
|
+
this.machine.metadata = logger.decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, logger.decodeBase64(answer.metadata));
|
|
8109
6583
|
}
|
|
8110
6584
|
throw new Error("Metadata version mismatch");
|
|
8111
6585
|
}
|
|
@@ -8116,29 +6590,29 @@ class ApiMachineClient {
|
|
|
8116
6590
|
* Simplified without lock - relies on backoff for retry
|
|
8117
6591
|
*/
|
|
8118
6592
|
async updateDaemonState(handler) {
|
|
8119
|
-
await backoff(async () => {
|
|
6593
|
+
await time.backoff(async () => {
|
|
8120
6594
|
const updated = handler(this.machine.daemonState);
|
|
8121
6595
|
const answer = await this.socket.emitWithAck("machine-update-state", {
|
|
8122
6596
|
machineId: this.machine.id,
|
|
8123
|
-
daemonState: encodeBase64(encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, updated)),
|
|
6597
|
+
daemonState: logger.encodeBase64(logger.encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, updated)),
|
|
8124
6598
|
expectedVersion: this.machine.daemonStateVersion
|
|
8125
6599
|
});
|
|
8126
6600
|
if (answer.result === "success") {
|
|
8127
|
-
this.machine.daemonState = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.daemonState));
|
|
6601
|
+
this.machine.daemonState = logger.decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, logger.decodeBase64(answer.daemonState));
|
|
8128
6602
|
this.machine.daemonStateVersion = answer.version;
|
|
8129
|
-
logger.debug("[API MACHINE] Daemon state updated successfully");
|
|
6603
|
+
logger.logger.debug("[API MACHINE] Daemon state updated successfully");
|
|
8130
6604
|
} else if (answer.result === "version-mismatch") {
|
|
8131
6605
|
if (answer.version > this.machine.daemonStateVersion) {
|
|
8132
6606
|
this.machine.daemonStateVersion = answer.version;
|
|
8133
|
-
this.machine.daemonState = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.daemonState));
|
|
6607
|
+
this.machine.daemonState = logger.decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, logger.decodeBase64(answer.daemonState));
|
|
8134
6608
|
}
|
|
8135
6609
|
throw new Error("Daemon state version mismatch");
|
|
8136
6610
|
}
|
|
8137
6611
|
});
|
|
8138
6612
|
}
|
|
8139
6613
|
connect() {
|
|
8140
|
-
const serverUrl = configuration.serverUrl.replace(/^http/, "ws");
|
|
8141
|
-
logger.debug(`[API MACHINE] Connecting to ${serverUrl}`);
|
|
6614
|
+
const serverUrl = logger.configuration.serverUrl.replace(/^http/, "ws");
|
|
6615
|
+
logger.logger.debug(`[API MACHINE] Connecting to ${serverUrl}`);
|
|
8142
6616
|
this.socket = socket_ioClient.io(serverUrl, {
|
|
8143
6617
|
transports: ["websocket"],
|
|
8144
6618
|
auth: {
|
|
@@ -8152,7 +6626,7 @@ class ApiMachineClient {
|
|
|
8152
6626
|
reconnectionDelayMax: 5e3
|
|
8153
6627
|
});
|
|
8154
6628
|
this.socket.on("connect", () => {
|
|
8155
|
-
logger.debug("[API MACHINE] Connected to server");
|
|
6629
|
+
logger.logger.debug("[API MACHINE] Connected to server");
|
|
8156
6630
|
this.updateDaemonState((state) => buildRunningDaemonState(
|
|
8157
6631
|
state,
|
|
8158
6632
|
this.currentRuntimeDaemonState ?? this.machine.daemonState
|
|
@@ -8161,36 +6635,36 @@ class ApiMachineClient {
|
|
|
8161
6635
|
this.startKeepAlive();
|
|
8162
6636
|
});
|
|
8163
6637
|
this.socket.on("disconnect", () => {
|
|
8164
|
-
logger.debug("[API MACHINE] Disconnected from server");
|
|
6638
|
+
logger.logger.debug("[API MACHINE] Disconnected from server");
|
|
8165
6639
|
this.rpcHandlerManager.onSocketDisconnect();
|
|
8166
6640
|
this.stopKeepAlive();
|
|
8167
6641
|
});
|
|
8168
6642
|
this.socket.on("rpc-request", async (data, callback) => {
|
|
8169
|
-
logger.debugLargeJson(`[API MACHINE] Received RPC request:`, data);
|
|
6643
|
+
logger.logger.debugLargeJson(`[API MACHINE] Received RPC request:`, data);
|
|
8170
6644
|
callback(await this.rpcHandlerManager.handleRequest(data));
|
|
8171
6645
|
});
|
|
8172
6646
|
this.socket.on("update", (data) => {
|
|
8173
6647
|
if (data.body.t === "update-machine" && data.body.machineId === this.machine.id) {
|
|
8174
6648
|
const update = data.body;
|
|
8175
6649
|
if (update.metadata) {
|
|
8176
|
-
logger.debug("[API MACHINE] Received external metadata update");
|
|
8177
|
-
this.machine.metadata = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(update.metadata.value));
|
|
6650
|
+
logger.logger.debug("[API MACHINE] Received external metadata update");
|
|
6651
|
+
this.machine.metadata = logger.decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, logger.decodeBase64(update.metadata.value));
|
|
8178
6652
|
this.machine.metadataVersion = update.metadata.version;
|
|
8179
6653
|
}
|
|
8180
6654
|
if (update.daemonState) {
|
|
8181
|
-
logger.debug("[API MACHINE] Received external daemon state update");
|
|
8182
|
-
this.machine.daemonState = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(update.daemonState.value));
|
|
6655
|
+
logger.logger.debug("[API MACHINE] Received external daemon state update");
|
|
6656
|
+
this.machine.daemonState = logger.decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, logger.decodeBase64(update.daemonState.value));
|
|
8183
6657
|
this.machine.daemonStateVersion = update.daemonState.version;
|
|
8184
6658
|
}
|
|
8185
6659
|
} else {
|
|
8186
|
-
logger.debug(`[API MACHINE] Received unknown update type: ${data.body.t}`);
|
|
6660
|
+
logger.logger.debug(`[API MACHINE] Received unknown update type: ${data.body.t}`);
|
|
8187
6661
|
}
|
|
8188
6662
|
});
|
|
8189
6663
|
this.socket.on("connect_error", (error) => {
|
|
8190
|
-
logger.debug(`[API MACHINE] Connection error: ${error.message}`);
|
|
6664
|
+
logger.logger.debug(`[API MACHINE] Connection error: ${error.message}`);
|
|
8191
6665
|
});
|
|
8192
6666
|
this.socket.io.on("error", (error) => {
|
|
8193
|
-
logger.debug("[API MACHINE] Socket error:", error);
|
|
6667
|
+
logger.logger.debug("[API MACHINE] Socket error:", error);
|
|
8194
6668
|
});
|
|
8195
6669
|
}
|
|
8196
6670
|
startKeepAlive() {
|
|
@@ -8200,27 +6674,27 @@ class ApiMachineClient {
|
|
|
8200
6674
|
machineId: this.machine.id,
|
|
8201
6675
|
time: Date.now()
|
|
8202
6676
|
};
|
|
8203
|
-
if (isDebug()) {
|
|
8204
|
-
logger.debugLargeJson(`[API MACHINE] Emitting machine-alive`, payload);
|
|
6677
|
+
if (logger.isDebug()) {
|
|
6678
|
+
logger.logger.debugLargeJson(`[API MACHINE] Emitting machine-alive`, payload);
|
|
8205
6679
|
}
|
|
8206
6680
|
this.socket.emit("machine-alive", payload);
|
|
8207
6681
|
}, 2e4);
|
|
8208
|
-
logger.debug("[API MACHINE] Keep-alive started (20s interval)");
|
|
6682
|
+
logger.logger.debug("[API MACHINE] Keep-alive started (20s interval)");
|
|
8209
6683
|
}
|
|
8210
6684
|
stopKeepAlive() {
|
|
8211
6685
|
if (this.keepAliveInterval) {
|
|
8212
6686
|
clearInterval(this.keepAliveInterval);
|
|
8213
6687
|
this.keepAliveInterval = null;
|
|
8214
|
-
logger.debug("[API MACHINE] Keep-alive stopped");
|
|
6688
|
+
logger.logger.debug("[API MACHINE] Keep-alive stopped");
|
|
8215
6689
|
}
|
|
8216
6690
|
}
|
|
8217
6691
|
shutdown() {
|
|
8218
|
-
logger.debug("[API MACHINE] Shutting down");
|
|
6692
|
+
logger.logger.debug("[API MACHINE] Shutting down");
|
|
8219
6693
|
openClawTunnelManager.closeAll();
|
|
8220
6694
|
this.stopKeepAlive();
|
|
8221
6695
|
if (this.socket) {
|
|
8222
6696
|
this.socket.close();
|
|
8223
|
-
logger.debug("[API MACHINE] Socket closed");
|
|
6697
|
+
logger.logger.debug("[API MACHINE] Socket closed");
|
|
8224
6698
|
}
|
|
8225
6699
|
}
|
|
8226
6700
|
}
|
|
@@ -8248,13 +6722,13 @@ class PushNotificationClient {
|
|
|
8248
6722
|
}
|
|
8249
6723
|
}
|
|
8250
6724
|
);
|
|
8251
|
-
logger.debug(`Fetched ${response.data.tokens.length} push tokens`);
|
|
6725
|
+
logger.logger.debug(`Fetched ${response.data.tokens.length} push tokens`);
|
|
8252
6726
|
response.data.tokens.forEach((token, index) => {
|
|
8253
|
-
logger.debug(`[PUSH] Token ${index + 1}: id=${token.id}, created=${new Date(token.createdAt).toISOString()}, updated=${new Date(token.updatedAt).toISOString()}`);
|
|
6727
|
+
logger.logger.debug(`[PUSH] Token ${index + 1}: id=${token.id}, created=${new Date(token.createdAt).toISOString()}, updated=${new Date(token.updatedAt).toISOString()}`);
|
|
8254
6728
|
});
|
|
8255
6729
|
return response.data.tokens;
|
|
8256
6730
|
} catch (error) {
|
|
8257
|
-
logger.debug("[PUSH] [ERROR] Failed to fetch push tokens:", error);
|
|
6731
|
+
logger.logger.debug("[PUSH] [ERROR] Failed to fetch push tokens:", error);
|
|
8258
6732
|
throw new Error(`Failed to fetch push tokens: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
8259
6733
|
}
|
|
8260
6734
|
}
|
|
@@ -8263,7 +6737,7 @@ class PushNotificationClient {
|
|
|
8263
6737
|
* @param messages - Array of push messages to send
|
|
8264
6738
|
*/
|
|
8265
6739
|
async sendPushNotifications(messages) {
|
|
8266
|
-
logger.debug(`Sending ${messages.length} push notifications`);
|
|
6740
|
+
logger.logger.debug(`Sending ${messages.length} push notifications`);
|
|
8267
6741
|
const validMessages = messages.filter((message) => {
|
|
8268
6742
|
if (Array.isArray(message.to)) {
|
|
8269
6743
|
return message.to.every((token) => expoServerSdk.Expo.isExpoPushToken(token));
|
|
@@ -8271,7 +6745,7 @@ class PushNotificationClient {
|
|
|
8271
6745
|
return expoServerSdk.Expo.isExpoPushToken(message.to);
|
|
8272
6746
|
});
|
|
8273
6747
|
if (validMessages.length === 0) {
|
|
8274
|
-
logger.debug("No valid Expo push tokens found");
|
|
6748
|
+
logger.logger.debug("No valid Expo push tokens found");
|
|
8275
6749
|
return;
|
|
8276
6750
|
}
|
|
8277
6751
|
const chunks = this.expo.chunkPushNotifications(validMessages);
|
|
@@ -8285,7 +6759,7 @@ class PushNotificationClient {
|
|
|
8285
6759
|
const errors = ticketChunk.filter((ticket) => ticket.status === "error");
|
|
8286
6760
|
if (errors.length > 0) {
|
|
8287
6761
|
const errorDetails = errors.map((e) => ({ message: e.message, details: e.details }));
|
|
8288
|
-
logger.debug("[PUSH] Some notifications failed:", errorDetails);
|
|
6762
|
+
logger.logger.debug("[PUSH] Some notifications failed:", errorDetails);
|
|
8289
6763
|
}
|
|
8290
6764
|
if (errors.length === ticketChunk.length) {
|
|
8291
6765
|
throw new Error("All push notifications in chunk failed");
|
|
@@ -8294,7 +6768,7 @@ class PushNotificationClient {
|
|
|
8294
6768
|
} catch (error) {
|
|
8295
6769
|
const elapsed = Date.now() - startTime;
|
|
8296
6770
|
if (elapsed >= timeout) {
|
|
8297
|
-
logger.debug("[PUSH] Timeout reached after 5 minutes, giving up on chunk");
|
|
6771
|
+
logger.logger.debug("[PUSH] Timeout reached after 5 minutes, giving up on chunk");
|
|
8298
6772
|
break;
|
|
8299
6773
|
}
|
|
8300
6774
|
attempt++;
|
|
@@ -8302,13 +6776,13 @@ class PushNotificationClient {
|
|
|
8302
6776
|
const remainingTime = timeout - elapsed;
|
|
8303
6777
|
const waitTime = Math.min(delay, remainingTime);
|
|
8304
6778
|
if (waitTime > 0) {
|
|
8305
|
-
logger.debug(`[PUSH] Retrying in ${waitTime}ms (attempt ${attempt})`);
|
|
6779
|
+
logger.logger.debug(`[PUSH] Retrying in ${waitTime}ms (attempt ${attempt})`);
|
|
8306
6780
|
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
8307
6781
|
}
|
|
8308
6782
|
}
|
|
8309
6783
|
}
|
|
8310
6784
|
}
|
|
8311
|
-
logger.debug(`Push notifications sent successfully`);
|
|
6785
|
+
logger.logger.debug(`Push notifications sent successfully`);
|
|
8312
6786
|
}
|
|
8313
6787
|
/**
|
|
8314
6788
|
* Increment the badge count on the server and return the new value
|
|
@@ -8327,7 +6801,7 @@ class PushNotificationClient {
|
|
|
8327
6801
|
);
|
|
8328
6802
|
return response.data.badgeCount;
|
|
8329
6803
|
} catch (error) {
|
|
8330
|
-
logger.debug("[PUSH] Failed to increment badge count:", error);
|
|
6804
|
+
logger.logger.debug("[PUSH] Failed to increment badge count:", error);
|
|
8331
6805
|
return 1;
|
|
8332
6806
|
}
|
|
8333
6807
|
}
|
|
@@ -8338,24 +6812,24 @@ class PushNotificationClient {
|
|
|
8338
6812
|
* @param data - Additional data to send with the notification
|
|
8339
6813
|
*/
|
|
8340
6814
|
sendToAllDevices(title, body, data) {
|
|
8341
|
-
logger.debug(`[PUSH] sendToAllDevices called with title: "${title}", body: "${body}"`);
|
|
6815
|
+
logger.logger.debug(`[PUSH] sendToAllDevices called with title: "${title}", body: "${body}"`);
|
|
8342
6816
|
(async () => {
|
|
8343
6817
|
try {
|
|
8344
|
-
logger.debug("[PUSH] Fetching push tokens and incrementing badge...");
|
|
6818
|
+
logger.logger.debug("[PUSH] Fetching push tokens and incrementing badge...");
|
|
8345
6819
|
const [tokens, badgeCount] = await Promise.all([
|
|
8346
6820
|
this.fetchPushTokens(),
|
|
8347
6821
|
this.incrementBadgeCount()
|
|
8348
6822
|
]);
|
|
8349
|
-
logger.debug(`[PUSH] Fetched ${tokens.length} push tokens, badge: ${badgeCount}`);
|
|
6823
|
+
logger.logger.debug(`[PUSH] Fetched ${tokens.length} push tokens, badge: ${badgeCount}`);
|
|
8350
6824
|
tokens.forEach((token, index) => {
|
|
8351
|
-
logger.debug(`[PUSH] Using token ${index + 1}: id=${token.id}`);
|
|
6825
|
+
logger.logger.debug(`[PUSH] Using token ${index + 1}: id=${token.id}`);
|
|
8352
6826
|
});
|
|
8353
6827
|
if (tokens.length === 0) {
|
|
8354
|
-
logger.debug("No push tokens found for user");
|
|
6828
|
+
logger.logger.debug("No push tokens found for user");
|
|
8355
6829
|
return;
|
|
8356
6830
|
}
|
|
8357
6831
|
const messages = tokens.map((token, index) => {
|
|
8358
|
-
logger.debug(`[PUSH] Creating message ${index + 1} for token`);
|
|
6832
|
+
logger.logger.debug(`[PUSH] Creating message ${index + 1} for token`);
|
|
8359
6833
|
return {
|
|
8360
6834
|
to: token.token,
|
|
8361
6835
|
title,
|
|
@@ -8367,43 +6841,16 @@ class PushNotificationClient {
|
|
|
8367
6841
|
badge: badgeCount
|
|
8368
6842
|
};
|
|
8369
6843
|
});
|
|
8370
|
-
logger.debug(`[PUSH] Sending ${messages.length} push notifications...`);
|
|
6844
|
+
logger.logger.debug(`[PUSH] Sending ${messages.length} push notifications...`);
|
|
8371
6845
|
await this.sendPushNotifications(messages);
|
|
8372
|
-
logger.debug("[PUSH] Push notifications sent successfully");
|
|
6846
|
+
logger.logger.debug("[PUSH] Push notifications sent successfully");
|
|
8373
6847
|
} catch (error) {
|
|
8374
|
-
logger.debug("[PUSH] Error sending to all devices:", error);
|
|
6848
|
+
logger.logger.debug("[PUSH] Error sending to all devices:", error);
|
|
8375
6849
|
}
|
|
8376
6850
|
})();
|
|
8377
6851
|
}
|
|
8378
6852
|
}
|
|
8379
6853
|
|
|
8380
|
-
function keyPath(sessionId) {
|
|
8381
|
-
return path.join(configuration.sessionKeysDir, `${sessionId}.key`);
|
|
8382
|
-
}
|
|
8383
|
-
async function cacheSessionKey(sessionId, sessionAESKey, machineKey) {
|
|
8384
|
-
if (!fs.existsSync(configuration.sessionKeysDir)) {
|
|
8385
|
-
fs.mkdirSync(configuration.sessionKeysDir, { recursive: true });
|
|
8386
|
-
}
|
|
8387
|
-
const encrypted = encryptWithDataKey(encodeBase64(sessionAESKey), machineKey);
|
|
8388
|
-
await promises.writeFile(keyPath(sessionId), encrypted);
|
|
8389
|
-
}
|
|
8390
|
-
function readCachedSessionKey(sessionId, machineKey) {
|
|
8391
|
-
const p = keyPath(sessionId);
|
|
8392
|
-
if (!fs.existsSync(p)) {
|
|
8393
|
-
return null;
|
|
8394
|
-
}
|
|
8395
|
-
try {
|
|
8396
|
-
const blob = new Uint8Array(fs.readFileSync(p));
|
|
8397
|
-
const b64 = decryptWithDataKey(blob, machineKey);
|
|
8398
|
-
if (typeof b64 !== "string") {
|
|
8399
|
-
return null;
|
|
8400
|
-
}
|
|
8401
|
-
return decodeBase64(b64);
|
|
8402
|
-
} catch {
|
|
8403
|
-
return null;
|
|
8404
|
-
}
|
|
8405
|
-
}
|
|
8406
|
-
|
|
8407
6854
|
function startOfflineReconnection(config) {
|
|
8408
6855
|
let reconnected = false;
|
|
8409
6856
|
let session = null;
|
|
@@ -8428,16 +6875,16 @@ function startOfflineReconnection(config) {
|
|
|
8428
6875
|
if (cancelled) return;
|
|
8429
6876
|
reconnected = true;
|
|
8430
6877
|
config.onNotify("\u2705 Reconnected! Session syncing in background.");
|
|
8431
|
-
logger.debug("[OfflineReconnection] Successfully reconnected");
|
|
6878
|
+
logger.logger.debug("[OfflineReconnection] Successfully reconnected");
|
|
8432
6879
|
} catch (e) {
|
|
8433
6880
|
if (axios.isAxiosError(e) && e.response?.status === 401) {
|
|
8434
|
-
logger.debug("[OfflineReconnection] Authentication error, stopping retries");
|
|
6881
|
+
logger.logger.debug("[OfflineReconnection] Authentication error, stopping retries");
|
|
8435
6882
|
config.onNotify("\u274C Authentication failed. Please re-authenticate with `happy auth`.");
|
|
8436
6883
|
return;
|
|
8437
6884
|
}
|
|
8438
6885
|
failureCount++;
|
|
8439
|
-
const delay = exponentialBackoffDelay(failureCount, 5e3, 6e4, 10);
|
|
8440
|
-
logger.debug(`[OfflineReconnection] Attempt ${failureCount} failed, retrying in ${delay}ms`);
|
|
6886
|
+
const delay = time.exponentialBackoffDelay(failureCount, 5e3, 6e4, 10);
|
|
6887
|
+
logger.logger.debug(`[OfflineReconnection] Attempt ${failureCount} failed, retrying in ${delay}ms`);
|
|
8441
6888
|
if (!cancelled) {
|
|
8442
6889
|
timeoutId = setTimeout(attemptReconnect, delay);
|
|
8443
6890
|
}
|
|
@@ -8537,7 +6984,7 @@ class ApiClient {
|
|
|
8537
6984
|
pushClient;
|
|
8538
6985
|
constructor(credential) {
|
|
8539
6986
|
this.credential = credential;
|
|
8540
|
-
this.pushClient = new PushNotificationClient(credential.token, configuration.serverUrl);
|
|
6987
|
+
this.pushClient = new PushNotificationClient(credential.token, logger.configuration.serverUrl);
|
|
8541
6988
|
}
|
|
8542
6989
|
/**
|
|
8543
6990
|
* Create a new session or load existing one with the given tag
|
|
@@ -8547,9 +6994,9 @@ class ApiClient {
|
|
|
8547
6994
|
let encryptionKey;
|
|
8548
6995
|
let encryptionVariant;
|
|
8549
6996
|
if (this.credential.encryption.type === "dataKey") {
|
|
8550
|
-
encryptionKey = getRandomBytes(32);
|
|
6997
|
+
encryptionKey = logger.getRandomBytes(32);
|
|
8551
6998
|
encryptionVariant = "dataKey";
|
|
8552
|
-
let encryptedDataKey = libsodiumEncryptForPublicKey(encryptionKey, this.credential.encryption.publicKey);
|
|
6999
|
+
let encryptedDataKey = logger.libsodiumEncryptForPublicKey(encryptionKey, this.credential.encryption.publicKey);
|
|
8553
7000
|
dataEncryptionKey = new Uint8Array(encryptedDataKey.length + 1);
|
|
8554
7001
|
dataEncryptionKey.set([0], 0);
|
|
8555
7002
|
dataEncryptionKey.set(encryptedDataKey, 1);
|
|
@@ -8559,12 +7006,12 @@ class ApiClient {
|
|
|
8559
7006
|
}
|
|
8560
7007
|
try {
|
|
8561
7008
|
const response = await axios.post(
|
|
8562
|
-
`${configuration.serverUrl}/v1/sessions`,
|
|
7009
|
+
`${logger.configuration.serverUrl}/v1/sessions`,
|
|
8563
7010
|
{
|
|
8564
7011
|
tag: opts.tag,
|
|
8565
|
-
metadata: encodeBase64(encrypt(encryptionKey, encryptionVariant, opts.metadata)),
|
|
8566
|
-
agentState: opts.state ? encodeBase64(encrypt(encryptionKey, encryptionVariant, opts.state)) : null,
|
|
8567
|
-
dataEncryptionKey: dataEncryptionKey ? encodeBase64(dataEncryptionKey) : null
|
|
7012
|
+
metadata: logger.encodeBase64(logger.encrypt(encryptionKey, encryptionVariant, opts.metadata)),
|
|
7013
|
+
agentState: opts.state ? logger.encodeBase64(logger.encrypt(encryptionKey, encryptionVariant, opts.state)) : null,
|
|
7014
|
+
dataEncryptionKey: dataEncryptionKey ? logger.encodeBase64(dataEncryptionKey) : null
|
|
8568
7015
|
},
|
|
8569
7016
|
{
|
|
8570
7017
|
headers: {
|
|
@@ -8575,25 +7022,25 @@ class ApiClient {
|
|
|
8575
7022
|
// 1 minute timeout for very bad network connections
|
|
8576
7023
|
}
|
|
8577
7024
|
);
|
|
8578
|
-
logger.debug(`Session created/loaded: ${response.data.session.id} (tag: ${opts.tag})`);
|
|
7025
|
+
logger.logger.debug(`Session created/loaded: ${response.data.session.id} (tag: ${opts.tag})`);
|
|
8579
7026
|
let raw = response.data.session;
|
|
8580
7027
|
let session = {
|
|
8581
7028
|
id: raw.id,
|
|
8582
7029
|
seq: raw.seq,
|
|
8583
|
-
metadata: decrypt(encryptionKey, encryptionVariant, decodeBase64(raw.metadata)),
|
|
7030
|
+
metadata: logger.decrypt(encryptionKey, encryptionVariant, logger.decodeBase64(raw.metadata)),
|
|
8584
7031
|
metadataVersion: raw.metadataVersion,
|
|
8585
|
-
agentState: raw.agentState ? decrypt(encryptionKey, encryptionVariant, decodeBase64(raw.agentState)) : null,
|
|
7032
|
+
agentState: raw.agentState ? logger.decrypt(encryptionKey, encryptionVariant, logger.decodeBase64(raw.agentState)) : null,
|
|
8586
7033
|
agentStateVersion: raw.agentStateVersion,
|
|
8587
7034
|
encryptionKey,
|
|
8588
7035
|
encryptionVariant
|
|
8589
7036
|
};
|
|
8590
7037
|
if (this.credential.encryption.type === "dataKey") {
|
|
8591
|
-
cacheSessionKey(raw.id, encryptionKey, this.credential.encryption.machineKey).catch(() => {
|
|
7038
|
+
sessionKeyCache.cacheSessionKey(raw.id, encryptionKey, this.credential.encryption.machineKey).catch(() => {
|
|
8592
7039
|
});
|
|
8593
7040
|
}
|
|
8594
7041
|
return session;
|
|
8595
7042
|
} catch (error) {
|
|
8596
|
-
logger.debug("[API] [ERROR] Failed to get or create session:", error);
|
|
7043
|
+
logger.logger.debug("[API] [ERROR] Failed to get or create session:", error);
|
|
8597
7044
|
if (error && typeof error === "object" && "code" in error) {
|
|
8598
7045
|
const errorCode = error.code;
|
|
8599
7046
|
if (isNetworkError(errorCode)) {
|
|
@@ -8601,7 +7048,7 @@ class ApiClient {
|
|
|
8601
7048
|
operation: "Session creation",
|
|
8602
7049
|
caller: "api.getOrCreateSession",
|
|
8603
7050
|
errorCode,
|
|
8604
|
-
url: `${configuration.serverUrl}/v1/sessions`
|
|
7051
|
+
url: `${logger.configuration.serverUrl}/v1/sessions`
|
|
8605
7052
|
});
|
|
8606
7053
|
return null;
|
|
8607
7054
|
}
|
|
@@ -8611,7 +7058,7 @@ class ApiClient {
|
|
|
8611
7058
|
connectionState.fail({
|
|
8612
7059
|
operation: "Session creation",
|
|
8613
7060
|
errorCode: "404",
|
|
8614
|
-
url: `${configuration.serverUrl}/v1/sessions`
|
|
7061
|
+
url: `${logger.configuration.serverUrl}/v1/sessions`
|
|
8615
7062
|
});
|
|
8616
7063
|
return null;
|
|
8617
7064
|
}
|
|
@@ -8621,7 +7068,7 @@ class ApiClient {
|
|
|
8621
7068
|
connectionState.fail({
|
|
8622
7069
|
operation: "Session creation",
|
|
8623
7070
|
errorCode: String(status),
|
|
8624
|
-
url: `${configuration.serverUrl}/v1/sessions`,
|
|
7071
|
+
url: `${logger.configuration.serverUrl}/v1/sessions`,
|
|
8625
7072
|
details: ["Server encountered an error, will retry automatically"]
|
|
8626
7073
|
});
|
|
8627
7074
|
return null;
|
|
@@ -8641,7 +7088,7 @@ class ApiClient {
|
|
|
8641
7088
|
if (this.credential.encryption.type === "dataKey") {
|
|
8642
7089
|
encryptionVariant = "dataKey";
|
|
8643
7090
|
encryptionKey = this.credential.encryption.machineKey;
|
|
8644
|
-
let encryptedDataKey = libsodiumEncryptForPublicKey(this.credential.encryption.machineKey, this.credential.encryption.publicKey);
|
|
7091
|
+
let encryptedDataKey = logger.libsodiumEncryptForPublicKey(this.credential.encryption.machineKey, this.credential.encryption.publicKey);
|
|
8645
7092
|
dataEncryptionKey = new Uint8Array(encryptedDataKey.length + 1);
|
|
8646
7093
|
dataEncryptionKey.set([0], 0);
|
|
8647
7094
|
dataEncryptionKey.set(encryptedDataKey, 1);
|
|
@@ -8660,12 +7107,12 @@ class ApiClient {
|
|
|
8660
7107
|
});
|
|
8661
7108
|
try {
|
|
8662
7109
|
const response = await axios.post(
|
|
8663
|
-
`${configuration.serverUrl}/v1/machines`,
|
|
7110
|
+
`${logger.configuration.serverUrl}/v1/machines`,
|
|
8664
7111
|
{
|
|
8665
7112
|
id: opts.machineId,
|
|
8666
|
-
metadata: encodeBase64(encrypt(encryptionKey, encryptionVariant, opts.metadata)),
|
|
8667
|
-
daemonState: opts.daemonState ? encodeBase64(encrypt(encryptionKey, encryptionVariant, opts.daemonState)) : void 0,
|
|
8668
|
-
dataEncryptionKey: dataEncryptionKey ? encodeBase64(dataEncryptionKey) : void 0,
|
|
7113
|
+
metadata: logger.encodeBase64(logger.encrypt(encryptionKey, encryptionVariant, opts.metadata)),
|
|
7114
|
+
daemonState: opts.daemonState ? logger.encodeBase64(logger.encrypt(encryptionKey, encryptionVariant, opts.daemonState)) : void 0,
|
|
7115
|
+
dataEncryptionKey: dataEncryptionKey ? logger.encodeBase64(dataEncryptionKey) : void 0,
|
|
8669
7116
|
// Plaintext label so other clients can render a device list without
|
|
8670
7117
|
// holding this machine's key. Everything else stays encrypted.
|
|
8671
7118
|
displayName: opts.metadata.displayName || opts.metadata.host || void 0,
|
|
@@ -8683,14 +7130,14 @@ class ApiClient {
|
|
|
8683
7130
|
}
|
|
8684
7131
|
);
|
|
8685
7132
|
const raw = response.data.machine;
|
|
8686
|
-
logger.debug(`[API] Machine ${opts.machineId} registered/updated with server`);
|
|
7133
|
+
logger.logger.debug(`[API] Machine ${opts.machineId} registered/updated with server`);
|
|
8687
7134
|
const machine = {
|
|
8688
7135
|
id: raw.id,
|
|
8689
7136
|
encryptionKey,
|
|
8690
7137
|
encryptionVariant,
|
|
8691
|
-
metadata: raw.metadata ? decrypt(encryptionKey, encryptionVariant, decodeBase64(raw.metadata)) : null,
|
|
7138
|
+
metadata: raw.metadata ? logger.decrypt(encryptionKey, encryptionVariant, logger.decodeBase64(raw.metadata)) : null,
|
|
8692
7139
|
metadataVersion: raw.metadataVersion || 0,
|
|
8693
|
-
daemonState: raw.daemonState ? decrypt(encryptionKey, encryptionVariant, decodeBase64(raw.daemonState)) : null,
|
|
7140
|
+
daemonState: raw.daemonState ? logger.decrypt(encryptionKey, encryptionVariant, logger.decodeBase64(raw.daemonState)) : null,
|
|
8694
7141
|
daemonStateVersion: raw.daemonStateVersion || 0
|
|
8695
7142
|
};
|
|
8696
7143
|
return machine;
|
|
@@ -8700,7 +7147,7 @@ class ApiClient {
|
|
|
8700
7147
|
operation: "Machine registration",
|
|
8701
7148
|
caller: "api.getOrCreateMachine",
|
|
8702
7149
|
errorCode: error.code,
|
|
8703
|
-
url: `${configuration.serverUrl}/v1/machines`
|
|
7150
|
+
url: `${logger.configuration.serverUrl}/v1/machines`
|
|
8704
7151
|
});
|
|
8705
7152
|
return createMinimalMachine();
|
|
8706
7153
|
}
|
|
@@ -8728,7 +7175,7 @@ class ApiClient {
|
|
|
8728
7175
|
connectionState.fail({
|
|
8729
7176
|
operation: "Machine registration",
|
|
8730
7177
|
errorCode: String(status),
|
|
8731
|
-
url: `${configuration.serverUrl}/v1/machines`,
|
|
7178
|
+
url: `${logger.configuration.serverUrl}/v1/machines`,
|
|
8732
7179
|
details: ["Server encountered an error, will retry automatically"]
|
|
8733
7180
|
});
|
|
8734
7181
|
return createMinimalMachine();
|
|
@@ -8737,7 +7184,7 @@ class ApiClient {
|
|
|
8737
7184
|
connectionState.fail({
|
|
8738
7185
|
operation: "Machine registration",
|
|
8739
7186
|
errorCode: "404",
|
|
8740
|
-
url: `${configuration.serverUrl}/v1/machines`
|
|
7187
|
+
url: `${logger.configuration.serverUrl}/v1/machines`
|
|
8741
7188
|
});
|
|
8742
7189
|
return createMinimalMachine();
|
|
8743
7190
|
}
|
|
@@ -8759,7 +7206,7 @@ class ApiClient {
|
|
|
8759
7206
|
*/
|
|
8760
7207
|
async reportOrchestratorExecutionStart(opts) {
|
|
8761
7208
|
await axios.post(
|
|
8762
|
-
`${configuration.serverUrl}/v1/orchestrator/executions/${opts.executionId}/start`,
|
|
7209
|
+
`${logger.configuration.serverUrl}/v1/orchestrator/executions/${opts.executionId}/start`,
|
|
8763
7210
|
{
|
|
8764
7211
|
dispatchToken: opts.dispatchToken,
|
|
8765
7212
|
startedAt: opts.startedAt,
|
|
@@ -8779,7 +7226,7 @@ class ApiClient {
|
|
|
8779
7226
|
*/
|
|
8780
7227
|
async reportOrchestratorExecutionFinish(opts) {
|
|
8781
7228
|
await axios.post(
|
|
8782
|
-
`${configuration.serverUrl}/v1/orchestrator/executions/${opts.executionId}/finish`,
|
|
7229
|
+
`${logger.configuration.serverUrl}/v1/orchestrator/executions/${opts.executionId}/finish`,
|
|
8783
7230
|
{
|
|
8784
7231
|
dispatchToken: opts.dispatchToken,
|
|
8785
7232
|
status: opts.status,
|
|
@@ -8808,7 +7255,7 @@ class ApiClient {
|
|
|
8808
7255
|
async registerVendorToken(vendor, apiKey) {
|
|
8809
7256
|
try {
|
|
8810
7257
|
const response = await axios.post(
|
|
8811
|
-
`${configuration.serverUrl}/v1/connect/${vendor}/register`,
|
|
7258
|
+
`${logger.configuration.serverUrl}/v1/connect/${vendor}/register`,
|
|
8812
7259
|
{
|
|
8813
7260
|
token: JSON.stringify(apiKey)
|
|
8814
7261
|
},
|
|
@@ -8823,9 +7270,9 @@ class ApiClient {
|
|
|
8823
7270
|
if (response.status !== 200 && response.status !== 201) {
|
|
8824
7271
|
throw new Error(`Server returned status ${response.status}`);
|
|
8825
7272
|
}
|
|
8826
|
-
logger.debug(`[API] Vendor token for ${vendor} registered successfully`);
|
|
7273
|
+
logger.logger.debug(`[API] Vendor token for ${vendor} registered successfully`);
|
|
8827
7274
|
} catch (error) {
|
|
8828
|
-
logger.debug(`[API] [ERROR] Failed to register vendor token:`, error);
|
|
7275
|
+
logger.logger.debug(`[API] [ERROR] Failed to register vendor token:`, error);
|
|
8829
7276
|
throw new Error(`Failed to register vendor token: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
8830
7277
|
}
|
|
8831
7278
|
}
|
|
@@ -8838,7 +7285,7 @@ class ApiClient {
|
|
|
8838
7285
|
async listMemories() {
|
|
8839
7286
|
try {
|
|
8840
7287
|
const response = await axios.get(
|
|
8841
|
-
`${configuration.serverUrl}/v1/memory`,
|
|
7288
|
+
`${logger.configuration.serverUrl}/v1/memory`,
|
|
8842
7289
|
{
|
|
8843
7290
|
headers: {
|
|
8844
7291
|
"Authorization": `Bearer ${this.credential.token}`,
|
|
@@ -8852,7 +7299,7 @@ class ApiClient {
|
|
|
8852
7299
|
}
|
|
8853
7300
|
return response.data.memories;
|
|
8854
7301
|
} catch (err) {
|
|
8855
|
-
logger.debug("[API] listMemories failed (continuing without memory injection):", err);
|
|
7302
|
+
logger.logger.debug("[API] listMemories failed (continuing without memory injection):", err);
|
|
8856
7303
|
return [];
|
|
8857
7304
|
}
|
|
8858
7305
|
}
|
|
@@ -8863,7 +7310,7 @@ class ApiClient {
|
|
|
8863
7310
|
async getVendorToken(vendor) {
|
|
8864
7311
|
try {
|
|
8865
7312
|
const response = await axios.get(
|
|
8866
|
-
`${configuration.serverUrl}/v1/connect/${vendor}/token`,
|
|
7313
|
+
`${logger.configuration.serverUrl}/v1/connect/${vendor}/token`,
|
|
8867
7314
|
{
|
|
8868
7315
|
headers: {
|
|
8869
7316
|
"Authorization": `Bearer ${this.credential.token}`,
|
|
@@ -8873,13 +7320,13 @@ class ApiClient {
|
|
|
8873
7320
|
}
|
|
8874
7321
|
);
|
|
8875
7322
|
if (response.status === 404) {
|
|
8876
|
-
logger.debug(`[API] No vendor token found for ${vendor}`);
|
|
7323
|
+
logger.logger.debug(`[API] No vendor token found for ${vendor}`);
|
|
8877
7324
|
return null;
|
|
8878
7325
|
}
|
|
8879
7326
|
if (response.status !== 200) {
|
|
8880
7327
|
throw new Error(`Server returned status ${response.status}`);
|
|
8881
7328
|
}
|
|
8882
|
-
logger.debug(`[API] Raw vendor token response:`, {
|
|
7329
|
+
logger.logger.debug(`[API] Raw vendor token response:`, {
|
|
8883
7330
|
status: response.status,
|
|
8884
7331
|
dataKeys: Object.keys(response.data || {}),
|
|
8885
7332
|
hasToken: "token" in (response.data || {}),
|
|
@@ -8891,153 +7338,62 @@ class ApiClient {
|
|
|
8891
7338
|
try {
|
|
8892
7339
|
tokenData = JSON.parse(response.data.token);
|
|
8893
7340
|
} catch (parseError) {
|
|
8894
|
-
logger.debug(`[API] Failed to parse token as JSON, using as string:`, parseError);
|
|
7341
|
+
logger.logger.debug(`[API] Failed to parse token as JSON, using as string:`, parseError);
|
|
8895
7342
|
tokenData = response.data.token;
|
|
8896
7343
|
}
|
|
8897
7344
|
} else if (response.data.token !== null) {
|
|
8898
7345
|
tokenData = response.data.token;
|
|
8899
7346
|
} else {
|
|
8900
|
-
logger.debug(`[API] Token is null for ${vendor}, treating as not found`);
|
|
7347
|
+
logger.logger.debug(`[API] Token is null for ${vendor}, treating as not found`);
|
|
8901
7348
|
return null;
|
|
8902
7349
|
}
|
|
8903
7350
|
} else if (response.data && typeof response.data === "object") {
|
|
8904
7351
|
if (response.data.token === null && Object.keys(response.data).length === 1) {
|
|
8905
|
-
logger.debug(`[API] Response contains only null token for ${vendor}, treating as not found`);
|
|
7352
|
+
logger.logger.debug(`[API] Response contains only null token for ${vendor}, treating as not found`);
|
|
8906
7353
|
return null;
|
|
8907
7354
|
}
|
|
8908
7355
|
tokenData = response.data;
|
|
8909
7356
|
}
|
|
8910
7357
|
if (tokenData === null || tokenData && typeof tokenData === "object" && tokenData.token === null && Object.keys(tokenData).length === 1) {
|
|
8911
|
-
logger.debug(`[API] Token data is null for ${vendor}`);
|
|
7358
|
+
logger.logger.debug(`[API] Token data is null for ${vendor}`);
|
|
8912
7359
|
return null;
|
|
8913
7360
|
}
|
|
8914
|
-
logger.debug(`[API] Vendor token for ${vendor} retrieved successfully`, {
|
|
7361
|
+
logger.logger.debug(`[API] Vendor token for ${vendor} retrieved successfully`, {
|
|
8915
7362
|
tokenDataType: typeof tokenData,
|
|
8916
7363
|
tokenDataKeys: tokenData && typeof tokenData === "object" ? Object.keys(tokenData) : "not an object"
|
|
8917
7364
|
});
|
|
8918
7365
|
return tokenData;
|
|
8919
7366
|
} catch (error) {
|
|
8920
7367
|
if (error.response?.status === 404) {
|
|
8921
|
-
logger.debug(`[API] No vendor token found for ${vendor}`);
|
|
7368
|
+
logger.logger.debug(`[API] No vendor token found for ${vendor}`);
|
|
8922
7369
|
return null;
|
|
8923
7370
|
}
|
|
8924
|
-
logger.debug(`[API] [ERROR] Failed to get vendor token:`, error);
|
|
7371
|
+
logger.logger.debug(`[API] [ERROR] Failed to get vendor token:`, error);
|
|
8925
7372
|
return null;
|
|
8926
7373
|
}
|
|
8927
7374
|
}
|
|
8928
7375
|
}
|
|
8929
7376
|
|
|
8930
7377
|
var api = /*#__PURE__*/Object.freeze({
|
|
8931
|
-
|
|
8932
|
-
|
|
7378
|
+
__proto__: null,
|
|
7379
|
+
ApiClient: ApiClient
|
|
8933
7380
|
});
|
|
8934
7381
|
|
|
8935
|
-
const UsageSchema = z.z.object({
|
|
8936
|
-
input_tokens: z.z.number().int().nonnegative(),
|
|
8937
|
-
cache_creation_input_tokens: z.z.number().int().nonnegative().optional(),
|
|
8938
|
-
cache_read_input_tokens: z.z.number().int().nonnegative().optional(),
|
|
8939
|
-
output_tokens: z.z.number().int().nonnegative(),
|
|
8940
|
-
service_tier: z.z.string().nullish()
|
|
8941
|
-
}).passthrough();
|
|
8942
|
-
const RawJSONLinesSchema = z.z.discriminatedUnion("type", [
|
|
8943
|
-
// User message - validates uuid and message.content
|
|
8944
|
-
z.z.object({
|
|
8945
|
-
type: z.z.literal("user"),
|
|
8946
|
-
isSidechain: z.z.boolean().optional(),
|
|
8947
|
-
isMeta: z.z.boolean().optional(),
|
|
8948
|
-
uuid: z.z.string(),
|
|
8949
|
-
// Used in getMessageKey()
|
|
8950
|
-
message: z.z.object({
|
|
8951
|
-
content: z.z.union([z.z.string(), z.z.any()])
|
|
8952
|
-
// Used in sessionScanner.ts
|
|
8953
|
-
}).passthrough()
|
|
8954
|
-
}).passthrough(),
|
|
8955
|
-
// Assistant message - only validates uuid and type
|
|
8956
|
-
// message object is optional to handle synthetic error messages (isApiErrorMessage: true)
|
|
8957
|
-
// which may have different structure than normal assistant messages
|
|
8958
|
-
z.z.object({
|
|
8959
|
-
uuid: z.z.string(),
|
|
8960
|
-
type: z.z.literal("assistant"),
|
|
8961
|
-
message: z.z.object({
|
|
8962
|
-
usage: UsageSchema.optional(),
|
|
8963
|
-
// Used in apiSession.ts
|
|
8964
|
-
model: z.z.string().optional()
|
|
8965
|
-
// Used for cost calculation
|
|
8966
|
-
}).passthrough().optional()
|
|
8967
|
-
}).passthrough(),
|
|
8968
|
-
// Summary message - validates summary and leafUuid
|
|
8969
|
-
z.z.object({
|
|
8970
|
-
type: z.z.literal("summary"),
|
|
8971
|
-
summary: z.z.string(),
|
|
8972
|
-
// Used in apiSession.ts
|
|
8973
|
-
leafUuid: z.z.string()
|
|
8974
|
-
// Used in getMessageKey()
|
|
8975
|
-
}).passthrough(),
|
|
8976
|
-
// System message - validates uuid
|
|
8977
|
-
z.z.object({
|
|
8978
|
-
type: z.z.literal("system"),
|
|
8979
|
-
uuid: z.z.string()
|
|
8980
|
-
// Used in getMessageKey()
|
|
8981
|
-
}).passthrough(),
|
|
8982
|
-
// Progress message - hook progress events, not counted toward message limits
|
|
8983
|
-
z.z.object({
|
|
8984
|
-
type: z.z.literal("progress"),
|
|
8985
|
-
uuid: z.z.string()
|
|
8986
|
-
}).passthrough()
|
|
8987
|
-
]);
|
|
8988
|
-
|
|
8989
7382
|
exports.ApiClient = ApiClient;
|
|
8990
7383
|
exports.ApiSessionClient = ApiSessionClient;
|
|
8991
7384
|
exports.AsyncLock = AsyncLock;
|
|
8992
|
-
exports.GEMINI_MODEL_MODES = GEMINI_MODEL_MODES;
|
|
8993
7385
|
exports.GeminiSessionWriter = GeminiSessionWriter;
|
|
8994
7386
|
exports.InvalidateSync = InvalidateSync;
|
|
8995
|
-
exports.MODEL_MODE_DEFAULT = MODEL_MODE_DEFAULT;
|
|
8996
|
-
exports.RawJSONLinesSchema = RawJSONLinesSchema;
|
|
8997
|
-
exports.acquireDaemonLock = acquireDaemonLock;
|
|
8998
7387
|
exports.api = api;
|
|
8999
7388
|
exports.buildResumeContextFromSessionLog = buildResumeContextFromSessionLog;
|
|
9000
|
-
exports.clearCredentials = clearCredentials;
|
|
9001
|
-
exports.clearDaemonState = clearDaemonState;
|
|
9002
|
-
exports.clearMachineId = clearMachineId;
|
|
9003
|
-
exports.configuration = configuration;
|
|
9004
7389
|
exports.connectionState = connectionState;
|
|
9005
|
-
exports.decodeBase64 = decodeBase64;
|
|
9006
|
-
exports.decrypt = decrypt;
|
|
9007
|
-
exports.decryptLegacy = decryptLegacy;
|
|
9008
|
-
exports.decryptWithDataKey = decryptWithDataKey;
|
|
9009
|
-
exports.delay = delay;
|
|
9010
|
-
exports.encodeBase64 = encodeBase64;
|
|
9011
|
-
exports.encodeBase64Url = encodeBase64Url;
|
|
9012
|
-
exports.encrypt = encrypt;
|
|
9013
7390
|
exports.extractUserText = extractUserText;
|
|
9014
7391
|
exports.findClaudeProjectId = findClaudeProjectId;
|
|
9015
7392
|
exports.findCodexSessionFile = findCodexSessionFile;
|
|
9016
7393
|
exports.generateStableUuid = generateStableUuid;
|
|
9017
|
-
exports.getLatestDaemonLog = getLatestDaemonLog;
|
|
9018
|
-
exports.getProfileEnvironmentVariables = getProfileEnvironmentVariables;
|
|
9019
|
-
exports.isDebug = isDebug;
|
|
9020
|
-
exports.isModelModeForAgent = isModelModeForAgent;
|
|
9021
7394
|
exports.isSystemMessage = isSystemMessage;
|
|
9022
|
-
exports.libsodiumPublicKeyFromSecretKey = libsodiumPublicKeyFromSecretKey;
|
|
9023
|
-
exports.logger = logger;
|
|
9024
|
-
exports.packageJson = packageJson;
|
|
9025
|
-
exports.parseClaudeModelMode = parseClaudeModelMode;
|
|
9026
|
-
exports.parseCodexModelMode = parseCodexModelMode;
|
|
9027
|
-
exports.persistence = persistence;
|
|
9028
|
-
exports.projectPath = projectPath;
|
|
9029
|
-
exports.readCachedSessionKey = readCachedSessionKey;
|
|
9030
|
-
exports.readCredentials = readCredentials;
|
|
9031
|
-
exports.readDaemonState = readDaemonState;
|
|
9032
7395
|
exports.readGeminiSessionLog = readGeminiSessionLog;
|
|
9033
|
-
exports.readSettings = readSettings;
|
|
9034
|
-
exports.releaseDaemonLock = releaseDaemonLock;
|
|
9035
7396
|
exports.resolveToolsDir = resolveToolsDir;
|
|
9036
7397
|
exports.saveDiffRecords = saveDiffRecords;
|
|
9037
7398
|
exports.saveToolOutputRecord = saveToolOutputRecord;
|
|
9038
7399
|
exports.startOfflineReconnection = startOfflineReconnection;
|
|
9039
|
-
exports.updateSettings = updateSettings;
|
|
9040
|
-
exports.validateProfileForAgent = validateProfileForAgent;
|
|
9041
|
-
exports.writeCredentialsDataKey = writeCredentialsDataKey;
|
|
9042
|
-
exports.writeCredentialsLegacy = writeCredentialsLegacy;
|
|
9043
|
-
exports.writeDaemonState = writeDaemonState;
|