@zonease/happy 0.6.38 → 0.6.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/bin/happy.mjs +10 -0
  2. package/dist/{types-DvTsFaqR.cjs → api-C7FyJfZ1.cjs} +400 -1964
  3. package/dist/{types-BWpRU1VN.mjs → api-D6WL40-U.mjs} +220 -1729
  4. package/dist/auth-C7ZScWEw.cjs +274 -0
  5. package/dist/auth-DCsIoZLT.cjs +183 -0
  6. package/dist/auth-DO9GexAR.mjs +181 -0
  7. package/dist/auth-DxJ3VvrX.mjs +270 -0
  8. package/dist/browser-AoVGRX7y.mjs +20 -0
  9. package/dist/browser-DzgO4oaD.cjs +22 -0
  10. package/dist/claudeLocal-C6BdzhDx.cjs +352 -0
  11. package/dist/claudeLocal-CWNGpJ0-.mjs +344 -0
  12. package/dist/codex/happyMcpStdioBridge.cjs +4 -1
  13. package/dist/codex/happyMcpStdioBridge.mjs +4 -1
  14. package/dist/common-BdNgghUJ.mjs +75 -0
  15. package/dist/common-CZvSRU4p.cjs +83 -0
  16. package/dist/{config-0Xnc8ARM.cjs → config-CclB3QW9.cjs} +21 -34
  17. package/dist/{config-_GW4YBCP.mjs → config-DZk-mJ0K.mjs} +7 -20
  18. package/dist/connect-BXLUKJ5P.mjs +679 -0
  19. package/dist/connect-k9CqDJ-T.cjs +681 -0
  20. package/dist/{constants-B4x1K7by.cjs → constants-E_UWYTo3.cjs} +2 -2
  21. package/dist/{constants-BO9OAFOT.mjs → constants-pmXZGibX.mjs} +1 -1
  22. package/dist/controlClient-B23M-WPp.cjs +177 -0
  23. package/dist/controlClient-DB5tDU7V.mjs +167 -0
  24. package/dist/deviceKeys-BTdo34Uz.mjs +175 -0
  25. package/dist/deviceKeys-C540DcXl.cjs +182 -0
  26. package/dist/diagnose-B3D1a_v0.cjs +60 -0
  27. package/dist/diagnose-CuRKXxt1.mjs +58 -0
  28. package/dist/doctor-BQGLhrcI.cjs +214 -0
  29. package/dist/doctor-C08m5Z9f.cjs +78 -0
  30. package/dist/doctor-CU4JLGQ1.mjs +211 -0
  31. package/dist/doctor-ON7pN5G5.mjs +74 -0
  32. package/dist/downloadImage-DZXI3mXL.mjs +887 -0
  33. package/dist/downloadImage-cQ1Z7hkC.cjs +897 -0
  34. package/dist/enroll-B55BQR56.mjs +113 -0
  35. package/dist/enroll-Bo-CNio1.cjs +115 -0
  36. package/dist/evidence-DQp8QWcv.cjs +129 -0
  37. package/dist/evidence-DTYRAaOZ.mjs +127 -0
  38. package/dist/formatImageMessage-CixDYY6G.cjs +46 -0
  39. package/dist/formatImageMessage-DbKSSjMx.mjs +43 -0
  40. package/dist/github-DKcyF1zp.mjs +57 -0
  41. package/dist/github-h9GhJJ_C.cjs +59 -0
  42. package/dist/index-CDTNgfUf.cjs +578 -0
  43. package/dist/index-CPKdvi7J.mjs +554 -0
  44. package/dist/index.cjs +812 -40
  45. package/dist/index.mjs +813 -40
  46. package/dist/install-B1e6rdy7.mjs +94 -0
  47. package/dist/install-CgUPGIoF.mjs +95 -0
  48. package/dist/install-D7Ir7ciZ.cjs +96 -0
  49. package/dist/install-DSDufaPd.cjs +98 -0
  50. package/dist/lib.cjs +18 -12
  51. package/dist/lib.d.cts +77 -0
  52. package/dist/lib.d.mts +77 -0
  53. package/dist/lib.mjs +13 -7
  54. package/dist/{loadableToolOutput-va3RLplh.mjs → loadableToolOutput-Bfei9wPq.mjs} +4 -2
  55. package/dist/{loadableToolOutput-5vdQB98M.cjs → loadableToolOutput-CbLGtvST.cjs} +63 -61
  56. package/dist/mcpToolSchemas-CjeTfrAs.mjs +62 -0
  57. package/dist/mcpToolSchemas-DK42yoZ_.cjs +64 -0
  58. package/dist/persistence-CBTtC_dm.cjs +996 -0
  59. package/dist/persistence-DKfF81pd.mjs +944 -0
  60. package/dist/projectPath-BTBIMB57.mjs +10 -0
  61. package/dist/projectPath-ChLhdOyt.cjs +13 -0
  62. package/dist/prompt-BTWDZZO0.cjs +25 -0
  63. package/dist/prompt-BsAZsPbo.mjs +22 -0
  64. package/dist/release-BMEzNONE.mjs +168 -0
  65. package/dist/release-EhOJeAZe.cjs +171 -0
  66. package/dist/run-BVZsMNwN.mjs +2164 -0
  67. package/dist/run-CURx7LhK.cjs +2188 -0
  68. package/dist/runClaude-6Gi0sYQy.mjs +3763 -0
  69. package/dist/runClaude-CL3Kt5ex.cjs +3766 -0
  70. package/dist/{runCodex-DiKzBf9q.mjs → runCodex-ClwEgJ7M.mjs} +36 -20
  71. package/dist/{runCodex-skq0j05d.cjs → runCodex-YKyVBkJ3.cjs} +169 -153
  72. package/dist/{runGemini-BeqrVq8R.mjs → runGemini-BPWxVr60.mjs} +34 -17
  73. package/dist/{runGemini-CVp-CEIh.cjs → runGemini-Xz2W1spn.cjs} +212 -195
  74. package/dist/{runOneShot-ltCpHbBB.mjs → runOneShot-CdCWiiLr.mjs} +14 -38
  75. package/dist/{runOneShot-BQNkNW61.cjs → runOneShot-DjZyCvDI.cjs} +31 -55
  76. package/dist/{serve-BNdoEDVx.mjs → serve-B48JttQ3.mjs} +12 -35
  77. package/dist/{serve-BECdtivY.cjs → serve-B8vaWQA0.cjs} +35 -58
  78. package/dist/session-BXboDn2V.mjs +108 -0
  79. package/dist/session-BZO25zxp.cjs +110 -0
  80. package/dist/sessionKeyCache-B6cGadYL.mjs +33 -0
  81. package/dist/sessionKeyCache-CDmexJ9p.cjs +36 -0
  82. package/dist/sessionList-CgAYZpNj.mjs +51 -0
  83. package/dist/sessionList-lQ-nqEhc.cjs +54 -0
  84. package/dist/sessionSummary-CcORiQSq.cjs +393 -0
  85. package/dist/sessionSummary-DCWQoaDP.mjs +387 -0
  86. package/dist/spawnHappyCLI-KiazE3kL.cjs +70 -0
  87. package/dist/spawnHappyCLI-yBIP_Oqi.mjs +66 -0
  88. package/dist/ssh-q5uZhqBf.mjs +359 -0
  89. package/dist/ssh-yMllSHu5.cjs +365 -0
  90. package/dist/systemdScope-BeOtAkhk.mjs +25 -0
  91. package/dist/systemdScope-DW3-UoKB.cjs +29 -0
  92. package/dist/task-_nr7J19j.cjs +167 -0
  93. package/dist/task-wNX1N2i4.mjs +165 -0
  94. package/dist/time-Bj2HRkKH.cjs +33 -0
  95. package/dist/time-DgsBLJA_.mjs +29 -0
  96. package/dist/trimIdent-4gvk9Wk6.cjs +22 -0
  97. package/dist/trimIdent-BAjmv_TG.mjs +20 -0
  98. package/dist/types-BoJh4Qfv.mjs +57 -0
  99. package/dist/types-DWeB7aqh.cjs +59 -0
  100. package/dist/uninstall-Buaz7d-X.cjs +77 -0
  101. package/dist/uninstall-Dxf6_4mQ.mjs +75 -0
  102. package/dist/update-CGlIfa8e.cjs +111 -0
  103. package/dist/update-CnnoX2cV.mjs +109 -0
  104. package/dist/workflowCommon-B0d01Y_a.mjs +56 -0
  105. package/dist/workflowCommon-Bl568-rt.cjs +62 -0
  106. package/dist/workflowReports-BEWuQesA.cjs +113 -0
  107. package/dist/workflowReports-Dd8-4-8f.mjs +108 -0
  108. package/package.json +1 -1
  109. package/dist/index-BbCDDvoB.cjs +0 -11376
  110. package/dist/index-vvZXdswy.mjs +0 -11336
  111. package/dist/mcpToolSchemas-CdPXJQmb.mjs +0 -175
  112. 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 chalk = require('chalk');
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-CBTtC_dm.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
- var cuid2 = require('@paralleldrive/cuid2');
8
+ require('./index-CDTNgfUf.cjs');
9
+ var time = require('./time-Bj2HRkKH.cjs');
13
10
  var node_crypto = require('node:crypto');
14
- var tweetnacl = require('tweetnacl');
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$2 = require('fs/promises');
19
+ var fs$1 = require('fs/promises');
21
20
  var path$1 = require('path');
22
- var url = require('url');
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-CDmexJ9p.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.38";
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-DvTsFaqR.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('types-DvTsFaqR.cjs', document.baseURI).href))).resolve(`${toolsPackageName()}/package.json`);
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-C7FyJfZ1.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,13 +1545,13 @@ 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
  }
2708
1552
  const shell = process.env.SHELL || (process.platform === "win32" ? "powershell.exe" : "bash");
2709
1553
  const cwd = opts.cwd ?? process.cwd();
2710
- const shellArgs = process.platform !== "win32" && isBashShell(shell) ? ["--rcfile", createHappyBashRc(), "-i"] : [];
1554
+ const shellArgs = process.platform === "win32" ? [] : isBashShell(shell) ? ["--rcfile", createHappyBashRc(), "-i"] : ["-l", "-i"];
2711
1555
  const shellEnv = { ...process.env };
2712
1556
  delete shellEnv.NO_COLOR;
2713
1557
  delete shellEnv.NODE_DISABLE_COLORS;
@@ -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) {
@@ -2883,21 +1727,25 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
2883
1727
  cwd: data.cwd === "/" ? void 0 : data.cwd,
2884
1728
  timeout: data.timeout || 3e4,
2885
1729
  // Default 30 seconds timeout
1730
+ // node's 1MB default kills the child and reports failure once
1731
+ // output crosses it — the command has already succeeded by
1732
+ // then, and the caller sees a truncated result with an error.
1733
+ maxBuffer: 64 * 1024 * 1024,
2886
1734
  // launchd and systemd hand the daemon a bare PATH, so without
2887
1735
  // this a command that works when typed into the device terminal
2888
1736
  // fails here with "command not found".
2889
1737
  env: await resolveLoginShellEnv()
2890
1738
  };
2891
- logger.debug("Shell command executing...", { cwd: options.cwd, timeout: options.timeout });
1739
+ logger.logger.debug("Shell command executing...", { cwd: options.cwd, timeout: options.timeout });
2892
1740
  const { stdout, stderr } = await execAsync(data.command, options);
2893
- logger.debug("Shell command executed, processing result...");
1741
+ logger.logger.debug("Shell command executed, processing result...");
2894
1742
  const result = {
2895
1743
  success: true,
2896
1744
  stdout: stdout ? stdout.toString() : "",
2897
1745
  stderr: stderr ? stderr.toString() : "",
2898
1746
  exitCode: 0
2899
1747
  };
2900
- logger.debug("Shell command result:", {
1748
+ logger.logger.debug("Shell command result:", {
2901
1749
  success: true,
2902
1750
  exitCode: 0,
2903
1751
  stdoutLen: result.stdout.length,
@@ -2914,7 +1762,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
2914
1762
  exitCode: typeof execError.code === "number" ? execError.code : -1,
2915
1763
  error: "Command timed out"
2916
1764
  };
2917
- logger.debug("Shell command timed out:", {
1765
+ logger.logger.debug("Shell command timed out:", {
2918
1766
  success: false,
2919
1767
  exitCode: result2.exitCode,
2920
1768
  error: "Command timed out"
@@ -2928,7 +1776,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
2928
1776
  exitCode: typeof execError.code === "number" ? execError.code : 1,
2929
1777
  error: execError.message || "Command failed"
2930
1778
  };
2931
- logger.debug("Shell command failed:", {
1779
+ logger.logger.debug("Shell command failed:", {
2932
1780
  success: false,
2933
1781
  exitCode: result.exitCode,
2934
1782
  error: result.error,
@@ -2939,40 +1787,40 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
2939
1787
  }
2940
1788
  });
2941
1789
  rpcHandlerManager.registerHandler("readFile", async (data) => {
2942
- logger.debug("Read file request:", data.path);
1790
+ logger.logger.debug("Read file request:", data.path);
2943
1791
  const validation = validatePath(data.path, workingDirectory);
2944
1792
  if (!validation.valid) {
2945
1793
  return { success: false, error: validation.error };
2946
1794
  }
2947
1795
  try {
2948
- const buffer = await fs$2.readFile(data.path);
1796
+ const buffer = await fs$1.readFile(data.path);
2949
1797
  const content = buffer.toString("base64");
2950
1798
  return { success: true, content };
2951
1799
  } catch (error) {
2952
- logger.debug("Failed to read file:", error);
1800
+ logger.logger.debug("Failed to read file:", error);
2953
1801
  return { success: false, error: error instanceof Error ? error.message : "Failed to read file" };
2954
1802
  }
2955
1803
  });
2956
1804
  rpcHandlerManager.registerHandler("writeFile", async (data) => {
2957
- logger.debug("Write file request:", data.path);
1805
+ logger.logger.debug("Write file request:", data.path);
2958
1806
  const absPath = path$1.resolve(workingDirectory, data.path);
2959
1807
  const validation = validatePath(data.path, workingDirectory);
2960
1808
  if (!validation.valid) {
2961
- logger.debug("[writeFile] path=%s ok=%s reason=%s", absPath, false, validation.error);
1809
+ logger.logger.debug("[writeFile] path=%s ok=%s reason=%s", absPath, false, validation.error);
2962
1810
  return { success: false, error: validation.error };
2963
1811
  }
2964
1812
  if (!isWritableForSession(absPath)) {
2965
- logger.debug("[writeFile] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
1813
+ logger.logger.debug("[writeFile] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
2966
1814
  return { success: false, error: `Path '${absPath}' is on the system write deny-list` };
2967
1815
  }
2968
1816
  try {
2969
1817
  const buf = Buffer.from(data.content, "base64");
2970
- await fs$2.writeFile(absPath, buf);
2971
- logger.debug("[writeFile] path=%s bytes=%d ok=%s", absPath, buf.length, true);
1818
+ await fs$1.writeFile(absPath, buf);
1819
+ logger.logger.debug("[writeFile] path=%s bytes=%d ok=%s", absPath, buf.length, true);
2972
1820
  return { success: true, bytesWritten: buf.length };
2973
1821
  } catch (error) {
2974
1822
  const message = error instanceof Error ? error.message : "Failed to write file";
2975
- logger.debug("[writeFile] path=%s ok=%s reason=%s", absPath, false, message);
1823
+ logger.logger.debug("[writeFile] path=%s ok=%s reason=%s", absPath, false, message);
2976
1824
  return { success: false, error: message };
2977
1825
  }
2978
1826
  });
@@ -3001,10 +1849,10 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3001
1849
  return { success: false, error: `Path '${paths.absolutePath}' is on the system write deny-list` };
3002
1850
  }
3003
1851
  try {
3004
- await fs$2.mkdir(paths.directory, { recursive: true });
3005
- await fs$2.rm(paths.tempAbsolutePath, { force: true });
3006
- await fs$2.rm(paths.absolutePath, { force: true });
3007
- await fs$2.writeFile(paths.tempAbsolutePath, Buffer.alloc(0));
1852
+ await fs$1.mkdir(paths.directory, { recursive: true });
1853
+ await fs$1.rm(paths.tempAbsolutePath, { force: true });
1854
+ await fs$1.rm(paths.absolutePath, { force: true });
1855
+ await fs$1.writeFile(paths.tempAbsolutePath, Buffer.alloc(0));
3008
1856
  return {
3009
1857
  success: true,
3010
1858
  relativePath: paths.relativePath,
@@ -3033,12 +1881,12 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3033
1881
  }
3034
1882
  try {
3035
1883
  const chunk = Buffer.from(data.chunkBase64, "base64");
3036
- const current = await fs$2.stat(paths.tempAbsolutePath).catch(() => null);
1884
+ const current = await fs$1.stat(paths.tempAbsolutePath).catch(() => null);
3037
1885
  const currentSize = current?.size ?? 0;
3038
1886
  if (currentSize + chunk.length > MAX_SESSION_UPLOAD_FILE_BYTES) {
3039
1887
  return { success: false, error: "File exceeds 100MB limit" };
3040
1888
  }
3041
- await fs$2.appendFile(paths.tempAbsolutePath, chunk);
1889
+ await fs$1.appendFile(paths.tempAbsolutePath, chunk);
3042
1890
  return {
3043
1891
  success: true,
3044
1892
  relativePath: paths.relativePath,
@@ -3074,11 +1922,11 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3074
1922
  return { success: false, error: `Path '${paths.absolutePath}' is on the system write deny-list` };
3075
1923
  }
3076
1924
  try {
3077
- const info = await fs$2.stat(paths.tempAbsolutePath);
1925
+ const info = await fs$1.stat(paths.tempAbsolutePath);
3078
1926
  if (info.size !== data.fileSize) {
3079
1927
  return { success: false, error: `Upload size mismatch: expected ${data.fileSize}, got ${info.size}` };
3080
1928
  }
3081
- await fs$2.rename(paths.tempAbsolutePath, paths.absolutePath);
1929
+ await fs$1.rename(paths.tempAbsolutePath, paths.absolutePath);
3082
1930
  return {
3083
1931
  success: true,
3084
1932
  relativePath: paths.relativePath,
@@ -3096,14 +1944,14 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3096
1944
  uploadId: data.uploadId,
3097
1945
  fileName: data.fileName
3098
1946
  });
3099
- await fs$2.rm(paths.tempAbsolutePath, { force: true });
1947
+ await fs$1.rm(paths.tempAbsolutePath, { force: true });
3100
1948
  return { success: true };
3101
1949
  } catch (error) {
3102
1950
  return { success: false, error: error instanceof Error ? error.message : "Failed to abort upload" };
3103
1951
  }
3104
1952
  });
3105
1953
  rpcHandlerManager.registerHandler("rename", async (data) => {
3106
- logger.debug("Rename request:", data.from, "->", data.to);
1954
+ logger.logger.debug("Rename request:", data.from, "->", data.to);
3107
1955
  const absFrom = path$1.resolve(workingDirectory, data.from);
3108
1956
  const absTo = path$1.resolve(workingDirectory, data.to);
3109
1957
  const fromValidation = validatePath(data.from, workingDirectory);
@@ -3115,68 +1963,68 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3115
1963
  return { success: false, error: toValidation.error };
3116
1964
  }
3117
1965
  if (!isWritableForSession(absFrom)) {
3118
- logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, false);
1966
+ logger.logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, false);
3119
1967
  return { success: false, error: `Path '${absFrom}' is on the system write deny-list` };
3120
1968
  }
3121
1969
  if (!isWritableForSession(absTo)) {
3122
- logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, false);
1970
+ logger.logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, false);
3123
1971
  return { success: false, error: `Path '${absTo}' is on the system write deny-list` };
3124
1972
  }
3125
1973
  try {
3126
- await fs$2.rename(absFrom, absTo);
3127
- logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, true);
1974
+ await fs$1.rename(absFrom, absTo);
1975
+ logger.logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, true);
3128
1976
  return { success: true };
3129
1977
  } catch (error) {
3130
1978
  const message = error instanceof Error ? error.message : "Failed to rename";
3131
- logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, false);
1979
+ logger.logger.info("[rename] %s -> %s ok=%s", absFrom, absTo, false);
3132
1980
  return { success: false, error: message };
3133
1981
  }
3134
1982
  });
3135
1983
  rpcHandlerManager.registerHandler("deleteFile", async (data) => {
3136
- logger.debug("Delete file request:", data.path);
1984
+ logger.logger.debug("Delete file request:", data.path);
3137
1985
  const absPath = path$1.resolve(workingDirectory, data.path);
3138
1986
  const validation = validatePath(data.path, workingDirectory);
3139
1987
  if (!validation.valid) {
3140
1988
  return { success: false, error: validation.error };
3141
1989
  }
3142
1990
  if (!isWritableForSession(absPath)) {
3143
- logger.info("[deleteFile] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
1991
+ logger.logger.info("[deleteFile] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
3144
1992
  return { success: false, error: `Path '${absPath}' is on the system write deny-list` };
3145
1993
  }
3146
1994
  try {
3147
- const st = await fs$2.lstat(absPath);
1995
+ const st = await fs$1.lstat(absPath);
3148
1996
  if (st.isDirectory()) {
3149
- logger.info("[deleteFile] path=%s ok=%s reason=%s", absPath, false, "is directory");
1997
+ logger.logger.info("[deleteFile] path=%s ok=%s reason=%s", absPath, false, "is directory");
3150
1998
  return { success: false, error: "Not a file, use deleteDirectory" };
3151
1999
  }
3152
- await fs$2.unlink(absPath);
3153
- logger.info("[deleteFile] path=%s ok=%s", absPath, true);
2000
+ await fs$1.unlink(absPath);
2001
+ logger.logger.info("[deleteFile] path=%s ok=%s", absPath, true);
3154
2002
  return { success: true };
3155
2003
  } catch (error) {
3156
2004
  const message = error instanceof Error ? error.message : "Failed to delete file";
3157
- logger.info("[deleteFile] path=%s ok=%s reason=%s", absPath, false, message);
2005
+ logger.logger.info("[deleteFile] path=%s ok=%s reason=%s", absPath, false, message);
3158
2006
  return { success: false, error: message };
3159
2007
  }
3160
2008
  });
3161
2009
  rpcHandlerManager.registerHandler("deleteDirectory", async (data) => {
3162
- logger.debug("Delete directory request:", data.path);
2010
+ logger.logger.debug("Delete directory request:", data.path);
3163
2011
  const absPath = path$1.resolve(workingDirectory, data.path);
3164
2012
  const validation = validatePath(data.path, workingDirectory);
3165
2013
  if (!validation.valid) {
3166
2014
  return { success: false, error: validation.error };
3167
2015
  }
3168
2016
  if (!isWritableForSession(absPath)) {
3169
- logger.info("[deleteDirectory] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
2017
+ logger.logger.info("[deleteDirectory] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
3170
2018
  return { success: false, error: `Path '${absPath}' is on the system write deny-list` };
3171
2019
  }
3172
2020
  try {
3173
- const top = await fs$2.lstat(absPath);
2021
+ const top = await fs$1.lstat(absPath);
3174
2022
  if (!top.isDirectory()) {
3175
- logger.info("[deleteDirectory] path=%s ok=%s reason=%s", absPath, false, "not a directory");
2023
+ logger.logger.info("[deleteDirectory] path=%s ok=%s reason=%s", absPath, false, "not a directory");
3176
2024
  return { success: false, error: "Not a directory" };
3177
2025
  }
3178
2026
  async function countEntries(dir) {
3179
- const entries = await fs$2.readdir(dir, { withFileTypes: true });
2027
+ const entries = await fs$1.readdir(dir, { withFileTypes: true });
3180
2028
  let n = 0;
3181
2029
  for (const entry of entries) {
3182
2030
  n += 1;
@@ -3187,70 +2035,70 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3187
2035
  return n;
3188
2036
  }
3189
2037
  const deletedCount = await countEntries(absPath);
3190
- await fs$2.rm(absPath, { recursive: true, force: false });
3191
- logger.info("[deleteDirectory] path=%s deletedCount=%d ok=%s", absPath, deletedCount, true);
2038
+ await fs$1.rm(absPath, { recursive: true, force: false });
2039
+ logger.logger.info("[deleteDirectory] path=%s deletedCount=%d ok=%s", absPath, deletedCount, true);
3192
2040
  return { success: true, deletedCount };
3193
2041
  } catch (error) {
3194
2042
  const message = error instanceof Error ? error.message : "Failed to delete directory";
3195
- logger.info("[deleteDirectory] path=%s ok=%s reason=%s", absPath, false, message);
2043
+ logger.logger.info("[deleteDirectory] path=%s ok=%s reason=%s", absPath, false, message);
3196
2044
  return { success: false, error: message };
3197
2045
  }
3198
2046
  });
3199
2047
  rpcHandlerManager.registerHandler("createFile", async (data) => {
3200
- logger.debug("Create file request:", data.path);
2048
+ logger.logger.debug("Create file request:", data.path);
3201
2049
  const absPath = path$1.resolve(workingDirectory, data.path);
3202
2050
  const validation = validatePath(data.path, workingDirectory);
3203
2051
  if (!validation.valid) {
3204
2052
  return { success: false, error: validation.error };
3205
2053
  }
3206
2054
  if (!isWritableForSession(absPath)) {
3207
- logger.info("[createFile] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
2055
+ logger.logger.info("[createFile] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
3208
2056
  return { success: false, error: `Path '${absPath}' is on the system write deny-list` };
3209
2057
  }
3210
2058
  try {
3211
2059
  const buf = data.content ? Buffer.from(data.content, "base64") : Buffer.alloc(0);
3212
- await fs$2.writeFile(absPath, buf, { flag: "wx" });
3213
- logger.info("[createFile] path=%s bytes=%d ok=%s", absPath, buf.length, true);
2060
+ await fs$1.writeFile(absPath, buf, { flag: "wx" });
2061
+ logger.logger.info("[createFile] path=%s bytes=%d ok=%s", absPath, buf.length, true);
3214
2062
  return { success: true };
3215
2063
  } catch (error) {
3216
2064
  const errno = error.code;
3217
2065
  if (errno === "EEXIST") {
3218
- logger.info("[createFile] path=%s ok=%s reason=%s", absPath, false, "file exists");
2066
+ logger.logger.info("[createFile] path=%s ok=%s reason=%s", absPath, false, "file exists");
3219
2067
  return { success: false, error: "File exists" };
3220
2068
  }
3221
2069
  const message = error instanceof Error ? error.message : "Failed to create file";
3222
- logger.info("[createFile] path=%s ok=%s reason=%s", absPath, false, message);
2070
+ logger.logger.info("[createFile] path=%s ok=%s reason=%s", absPath, false, message);
3223
2071
  return { success: false, error: message };
3224
2072
  }
3225
2073
  });
3226
2074
  rpcHandlerManager.registerHandler("createDirectory", async (data) => {
3227
- logger.debug("Create directory request:", data.path);
2075
+ logger.logger.debug("Create directory request:", data.path);
3228
2076
  const absPath = path$1.resolve(workingDirectory, data.path);
3229
2077
  const validation = validatePath(data.path, workingDirectory);
3230
2078
  if (!validation.valid) {
3231
2079
  return { success: false, error: validation.error };
3232
2080
  }
3233
2081
  if (!isWritableForSession(absPath)) {
3234
- logger.info("[createDirectory] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
2082
+ logger.logger.info("[createDirectory] path=%s ok=%s reason=%s", absPath, false, "system path is read-only");
3235
2083
  return { success: false, error: `Path '${absPath}' is on the system write deny-list` };
3236
2084
  }
3237
2085
  try {
3238
- await fs$2.mkdir(absPath);
3239
- logger.info("[createDirectory] path=%s ok=%s", absPath, true);
2086
+ await fs$1.mkdir(absPath);
2087
+ logger.logger.info("[createDirectory] path=%s ok=%s", absPath, true);
3240
2088
  return { success: true };
3241
2089
  } catch (error) {
3242
2090
  const errno = error.code;
3243
2091
  if (errno === "EEXIST") {
3244
- logger.info("[createDirectory] path=%s ok=%s reason=%s", absPath, false, "directory exists");
2092
+ logger.logger.info("[createDirectory] path=%s ok=%s reason=%s", absPath, false, "directory exists");
3245
2093
  return { success: false, error: "Directory exists" };
3246
2094
  }
3247
2095
  const message = error instanceof Error ? error.message : "Failed to create directory";
3248
- logger.info("[createDirectory] path=%s ok=%s reason=%s", absPath, false, message);
2096
+ logger.logger.info("[createDirectory] path=%s ok=%s reason=%s", absPath, false, message);
3249
2097
  return { success: false, error: message };
3250
2098
  }
3251
2099
  });
3252
2100
  rpcHandlerManager.registerHandler("listDirectory", async (data) => {
3253
- logger.debug("List directory request:", data.path);
2101
+ logger.logger.debug("List directory request:", data.path);
3254
2102
  const absPath = path$1.resolve(workingDirectory, data.path);
3255
2103
  const validation = validatePath(data.path, workingDirectory);
3256
2104
  if (!validation.valid) {
@@ -3258,7 +2106,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3258
2106
  }
3259
2107
  const hideSystem = data.hideSystem !== false;
3260
2108
  try {
3261
- const rawEntries = await fs$2.readdir(absPath, { withFileTypes: true });
2109
+ const rawEntries = await fs$1.readdir(absPath, { withFileTypes: true });
3262
2110
  const noSymlinks = rawEntries.filter((e) => !e.isSymbolicLink());
3263
2111
  const visible = hideSystem ? noSymlinks.filter((e) => !isSystemNoise(e.name)) : noSymlinks;
3264
2112
  const entries = await Promise.all(
@@ -3268,11 +2116,11 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3268
2116
  let size;
3269
2117
  let mtime;
3270
2118
  try {
3271
- const stats = await fs$2.stat(fullPath);
2119
+ const stats = await fs$1.stat(fullPath);
3272
2120
  size = stats.size;
3273
2121
  mtime = stats.mtime.getTime();
3274
2122
  } catch (error) {
3275
- logger.debug(`Failed to stat ${fullPath}:`, error);
2123
+ logger.logger.debug(`Failed to stat ${fullPath}:`, error);
3276
2124
  }
3277
2125
  return { name: entry.name, path: fullPath, type, size, mtime };
3278
2126
  })
@@ -3284,19 +2132,19 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3284
2132
  });
3285
2133
  return { success: true, entries };
3286
2134
  } catch (error) {
3287
- logger.debug("Failed to list directory:", error);
2135
+ logger.logger.debug("Failed to list directory:", error);
3288
2136
  return { success: false, error: error instanceof Error ? error.message : "Failed to list directory" };
3289
2137
  }
3290
2138
  });
3291
2139
  rpcHandlerManager.registerHandler("getDirectoryTree", async (data) => {
3292
- logger.debug("Get directory tree request:", data.path, "maxDepth:", data.maxDepth);
2140
+ logger.logger.debug("Get directory tree request:", data.path, "maxDepth:", data.maxDepth);
3293
2141
  const validation = validatePath(data.path, workingDirectory);
3294
2142
  if (!validation.valid) {
3295
2143
  return { success: false, error: validation.error };
3296
2144
  }
3297
2145
  async function buildTree(path, name, currentDepth) {
3298
2146
  try {
3299
- const stats = await fs$2.stat(path);
2147
+ const stats = await fs$1.stat(path);
3300
2148
  const node = {
3301
2149
  name,
3302
2150
  path,
@@ -3305,12 +2153,12 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3305
2153
  modified: stats.mtime.getTime()
3306
2154
  };
3307
2155
  if (stats.isDirectory() && currentDepth < data.maxDepth) {
3308
- const entries = await fs$2.readdir(path, { withFileTypes: true });
2156
+ const entries = await fs$1.readdir(path, { withFileTypes: true });
3309
2157
  const children = [];
3310
2158
  await Promise.all(
3311
2159
  entries.map(async (entry) => {
3312
2160
  if (entry.isSymbolicLink()) {
3313
- logger.debug(`Skipping symlink: ${path$1.join(path, entry.name)}`);
2161
+ logger.logger.debug(`Skipping symlink: ${path$1.join(path, entry.name)}`);
3314
2162
  return;
3315
2163
  }
3316
2164
  const childPath = path$1.join(path, entry.name);
@@ -3329,7 +2177,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3329
2177
  }
3330
2178
  return node;
3331
2179
  } catch (error) {
3332
- logger.debug(`Failed to process ${path}:`, error instanceof Error ? error.message : String(error));
2180
+ logger.logger.debug(`Failed to process ${path}:`, error instanceof Error ? error.message : String(error));
3333
2181
  return null;
3334
2182
  }
3335
2183
  }
@@ -3344,12 +2192,12 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3344
2192
  }
3345
2193
  return { success: true, tree };
3346
2194
  } catch (error) {
3347
- logger.debug("Failed to get directory tree:", error);
2195
+ logger.logger.debug("Failed to get directory tree:", error);
3348
2196
  return { success: false, error: error instanceof Error ? error.message : "Failed to get directory tree" };
3349
2197
  }
3350
2198
  });
3351
2199
  rpcHandlerManager.registerHandler("ripgrep", async (data) => {
3352
- logger.debug("Ripgrep request with args:", data.args, "cwd:", data.cwd);
2200
+ logger.logger.debug("Ripgrep request with args:", data.args, "cwd:", data.cwd);
3353
2201
  if (data.cwd) {
3354
2202
  const validation = validatePath(data.cwd, workingDirectory);
3355
2203
  if (!validation.valid) {
@@ -3365,7 +2213,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3365
2213
  stderr: result.stderr.toString()
3366
2214
  };
3367
2215
  } catch (error) {
3368
- logger.debug("Failed to run ripgrep:", error);
2216
+ logger.logger.debug("Failed to run ripgrep:", error);
3369
2217
  return {
3370
2218
  success: false,
3371
2219
  error: error instanceof Error ? error.message : "Failed to run ripgrep"
@@ -3373,7 +2221,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3373
2221
  }
3374
2222
  });
3375
2223
  rpcHandlerManager.registerHandler("difftastic", async (data) => {
3376
- logger.debug("Difftastic request with args:", data.args, "cwd:", data.cwd);
2224
+ logger.logger.debug("Difftastic request with args:", data.args, "cwd:", data.cwd);
3377
2225
  if (data.cwd) {
3378
2226
  const validation = validatePath(data.cwd, workingDirectory);
3379
2227
  if (!validation.valid) {
@@ -3389,7 +2237,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3389
2237
  stderr: result.stderr.toString()
3390
2238
  };
3391
2239
  } catch (error) {
3392
- logger.debug("Failed to run difftastic:", error);
2240
+ logger.logger.debug("Failed to run difftastic:", error);
3393
2241
  return {
3394
2242
  success: false,
3395
2243
  error: error instanceof Error ? error.message : "Failed to run difftastic"
@@ -3398,7 +2246,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3398
2246
  });
3399
2247
  if (sessionId) {
3400
2248
  rpcHandlerManager.registerHandler("getDiffDetail", async (data) => {
3401
- logger.debug("getDiffDetail request:", data.callId, data.filePath);
2249
+ logger.logger.debug("getDiffDetail request:", data.callId, data.filePath);
3402
2250
  const result = getDiffDetail(sessionId, data.callId, data.filePath);
3403
2251
  if (!result) {
3404
2252
  return { success: false, error: "not_found" };
@@ -3411,7 +2259,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3411
2259
  };
3412
2260
  });
3413
2261
  rpcHandlerManager.registerHandler("getToolOutput", async (data) => {
3414
- logger.debug("getToolOutput request:", data.callId);
2262
+ logger.logger.debug("getToolOutput request:", data.callId);
3415
2263
  const record = getToolOutputRecord(sessionId, data.callId);
3416
2264
  if (!record) {
3417
2265
  return { success: false, error: "not_found" };
@@ -3424,19 +2272,24 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3424
2272
  };
3425
2273
  });
3426
2274
  const outboundStates = /* @__PURE__ */ new Map();
3427
- const emitEncrypted = (event, payload) => {
2275
+ const emitEncrypted = (event, payload, reliable = false) => {
3428
2276
  const socket = rpcHandlerManager.getSocket();
3429
2277
  if (!socket || !socket.connected) {
3430
2278
  return;
3431
2279
  }
3432
2280
  const envelope = { sessionId: payload.sessionId, ptyId: payload.ptyId };
3433
- if (event === "pty-output" && typeof payload.data === "string") {
2281
+ if (reliable) envelope.reliable = true;
2282
+ if (event === "pty-output" && payload.data !== void 0) {
3434
2283
  const key = rpcHandlerManager.getEncryptionKey();
3435
2284
  const variant = rpcHandlerManager.getEncryptionVariant();
3436
- envelope.data = encodeBase64(encrypt(key, variant, payload.data));
2285
+ envelope.data = logger.encodeBase64(logger.encrypt(key, variant, payload.data));
3437
2286
  } else if (event === "pty-exit" && typeof payload.exitCode === "number") {
3438
2287
  envelope.exitCode = payload.exitCode;
3439
2288
  }
2289
+ if (reliable) {
2290
+ socket.emit(event, envelope);
2291
+ return;
2292
+ }
3440
2293
  socket.volatile.emit(event, envelope);
3441
2294
  };
3442
2295
  const splitOnUtf8Boundary = (merged) => {
@@ -3493,7 +2346,73 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3493
2346
  outboundStates.delete(ptyId);
3494
2347
  };
3495
2348
  rpcHandlerManager.registerHandler("pty-start", async (data) => {
3496
- logger.debug("[pty-start] request", { cols: data.cols, rows: data.rows, cwd: data.cwd });
2349
+ logger.logger.debug("[pty-start] request", { cols: data.cols, rows: data.rows, cwd: data.cwd, exec: !!data.exec });
2350
+ if (data.exec) {
2351
+ const execId = node_crypto.randomUUID();
2352
+ const child = child_process.spawn(process.env.SHELL || "/bin/sh", ["-c", data.exec.command], {
2353
+ cwd: data.cwd,
2354
+ env: await resolveLoginShellEnv(),
2355
+ stdio: ["ignore", "pipe", "pipe"]
2356
+ });
2357
+ const killTimer = setTimeout(() => child.kill("SIGTERM"), data.exec.timeoutMs ?? 3e5);
2358
+ child.stdout?.pause();
2359
+ child.stderr?.pause();
2360
+ setImmediate(() => {
2361
+ child.stdout?.resume();
2362
+ child.stderr?.resume();
2363
+ });
2364
+ const pending = { stdout: [], stderr: [] };
2365
+ let pendingBytes = 0;
2366
+ let frameCount = 0;
2367
+ let flushTimer = null;
2368
+ const flushExec = () => {
2369
+ if (flushTimer) {
2370
+ clearTimeout(flushTimer);
2371
+ flushTimer = null;
2372
+ }
2373
+ pendingBytes = 0;
2374
+ frameCount++;
2375
+ for (const stream of ["stdout", "stderr"]) {
2376
+ if (pending[stream].length === 0) continue;
2377
+ const chunk = Buffer.concat(pending[stream]);
2378
+ pending[stream] = [];
2379
+ emitEncrypted("pty-output", {
2380
+ sessionId,
2381
+ ptyId: execId,
2382
+ data: { stream, chunk: chunk.toString("base64") }
2383
+ }, true);
2384
+ }
2385
+ };
2386
+ for (const [stream, source] of [["stdout", child.stdout], ["stderr", child.stderr]]) {
2387
+ source?.on("data", (chunk) => {
2388
+ pending[stream].push(chunk);
2389
+ pendingBytes += chunk.length;
2390
+ if (pendingBytes >= PTY_OUTPUT_FLUSH_BYTES) {
2391
+ flushExec();
2392
+ return;
2393
+ }
2394
+ if (!flushTimer) flushTimer = setTimeout(flushExec, PTY_OUTPUT_FLUSH_MS);
2395
+ });
2396
+ }
2397
+ child.on("close", (code, signal) => {
2398
+ clearTimeout(killTimer);
2399
+ logger.logger.debug(`[exec] close code=${code} signal=${signal} pending=${pendingBytes}`);
2400
+ flushExec();
2401
+ logger.logger.debug(`[exec] flushed ${frameCount} frames, emitting exit`);
2402
+ emitEncrypted("pty-exit", { sessionId, ptyId: execId, exitCode: code ?? (signal ? 143 : 1) }, true);
2403
+ });
2404
+ child.on("error", (error) => {
2405
+ clearTimeout(killTimer);
2406
+ emitEncrypted("pty-output", {
2407
+ sessionId,
2408
+ ptyId: execId,
2409
+ data: { stream: "stderr", chunk: Buffer.from(`${error.message}
2410
+ `).toString("base64") }
2411
+ }, true);
2412
+ emitEncrypted("pty-exit", { sessionId, ptyId: execId, exitCode: 1 }, true);
2413
+ });
2414
+ return { ok: true, ptyId: execId };
2415
+ }
3497
2416
  try {
3498
2417
  const { ptyId, term } = spawnShell({
3499
2418
  cols: data.cols,
@@ -3515,7 +2434,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3515
2434
  }
3516
2435
  });
3517
2436
  const exitDispose = term.onExit(({ exitCode }) => {
3518
- logger.debug(`[pty-exit] ${ptyId} exitCode=${exitCode}`);
2437
+ logger.logger.debug(`[pty-exit] ${ptyId} exitCode=${exitCode}`);
3519
2438
  flushPtyOutput(ptyId);
3520
2439
  emitEncrypted("pty-exit", { sessionId, ptyId, exitCode });
3521
2440
  cleanupPtyState(ptyId);
@@ -3532,27 +2451,27 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3532
2451
  } catch (err) {
3533
2452
  const message = err instanceof Error ? err.message : String(err);
3534
2453
  if (message === PTY_UNAVAILABLE) {
3535
- logger.debug("[pty-start] node-pty unavailable on this host");
2454
+ logger.logger.debug("[pty-start] node-pty unavailable on this host");
3536
2455
  return { ok: false, error: PTY_UNAVAILABLE };
3537
2456
  }
3538
- logger.debug("[pty-start] spawn failed:", message);
2457
+ logger.logger.debug("[pty-start] spawn failed:", message);
3539
2458
  return { ok: false, error: message };
3540
2459
  }
3541
2460
  });
3542
2461
  rpcHandlerManager.registerHandler("pty-resize", async (data) => {
3543
- logger.debug(`[pty-resize] ${data.ptyId} ${data.cols}x${data.rows}`);
2462
+ logger.logger.debug(`[pty-resize] ${data.ptyId} ${data.cols}x${data.rows}`);
3544
2463
  const ok = resizePty(data.ptyId, data.cols, data.rows);
3545
2464
  return { ok };
3546
2465
  });
3547
2466
  rpcHandlerManager.registerHandler("pty-close", async (data) => {
3548
- logger.debug(`[pty-close] ${data.ptyId}`);
2467
+ logger.logger.debug(`[pty-close] ${data.ptyId}`);
3549
2468
  cleanupPtyState(data.ptyId);
3550
2469
  const ok = closePty(data.ptyId);
3551
2470
  return { ok };
3552
2471
  });
3553
2472
  rpcHandlerManager.registerSocketEvent("pty-input", (envelope) => {
3554
2473
  if (!envelope || typeof envelope !== "object") {
3555
- logger.debug("[pty-input] unexpected envelope shape, dropping");
2474
+ logger.logger.debug("[pty-input] unexpected envelope shape, dropping");
3556
2475
  return;
3557
2476
  }
3558
2477
  if (envelope.sessionId !== sessionId) return;
@@ -3561,14 +2480,14 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
3561
2480
  try {
3562
2481
  const key = rpcHandlerManager.getEncryptionKey();
3563
2482
  const variant = rpcHandlerManager.getEncryptionVariant();
3564
- const decoded = decrypt(key, variant, decodeBase64(envelope.data));
2483
+ const decoded = logger.decrypt(key, variant, logger.decodeBase64(envelope.data));
3565
2484
  if (typeof decoded !== "string") {
3566
- logger.debug("[pty-input] decrypted payload not a string, dropping");
2485
+ logger.logger.debug("[pty-input] decrypted payload not a string, dropping");
3567
2486
  return;
3568
2487
  }
3569
2488
  writeToPty(envelope.ptyId, decoded);
3570
2489
  } catch (err) {
3571
- logger.debug("[pty-input] decrypt/dispatch failed:", err);
2490
+ logger.logger.debug("[pty-input] decrypt/dispatch failed:", err);
3572
2491
  }
3573
2492
  });
3574
2493
  }
@@ -3836,7 +2755,7 @@ class ApiSessionClient extends node_events.EventEmitter {
3836
2755
  initialTitleSet = false;
3837
2756
  queueOrDeliverUserMessage(message, source) {
3838
2757
  if (isHumanOnlyMessageRecord(message)) {
3839
- logger.debug(`[API] Ignoring human-only collaboration message from ${source}`);
2758
+ logger.logger.debug(`[API] Ignoring human-only collaboration message from ${source}`);
3840
2759
  return false;
3841
2760
  }
3842
2761
  if (this.pendingMessageCallback) {
@@ -3861,7 +2780,7 @@ class ApiSessionClient extends node_events.EventEmitter {
3861
2780
  scopePrefix: this.sessionId,
3862
2781
  encryptionKey: this.encryptionKey,
3863
2782
  encryptionVariant: this.encryptionVariant,
3864
- logger: (msg, data) => logger.debug(msg, data)
2783
+ logger: (msg, data) => logger.logger.debug(msg, data)
3865
2784
  });
3866
2785
  registerCommonHandlers(this.rpcHandlerManager, this.metadata.path, this.sessionId);
3867
2786
  this.autoReviewGuard = this.createAutoReviewGuard();
@@ -3878,7 +2797,7 @@ class ApiSessionClient extends node_events.EventEmitter {
3878
2797
  }
3879
2798
  });
3880
2799
  this.sendSync = new InvalidateSync(() => this.flushOutbox());
3881
- this.socket = socket_ioClient.io(configuration.serverUrl, {
2800
+ this.socket = socket_ioClient.io(logger.configuration.serverUrl, {
3882
2801
  auth: {
3883
2802
  token: this.token,
3884
2803
  clientType: "session-scoped",
@@ -3895,18 +2814,18 @@ class ApiSessionClient extends node_events.EventEmitter {
3895
2814
  autoConnect: false
3896
2815
  });
3897
2816
  this.socket.on("connect", () => {
3898
- logger.debug("Socket connected successfully");
2817
+ logger.logger.debug("Socket connected successfully");
3899
2818
  this.rpcHandlerManager.onSocketConnect(this.socket);
3900
2819
  });
3901
2820
  this.socket.on("rpc-request", async (data, callback) => {
3902
2821
  callback(await this.rpcHandlerManager.handleRequest(data));
3903
2822
  });
3904
2823
  this.socket.on("disconnect", (reason) => {
3905
- logger.debug("[API] Socket disconnected:", reason);
2824
+ logger.logger.debug("[API] Socket disconnected:", reason);
3906
2825
  this.rpcHandlerManager.onSocketDisconnect();
3907
2826
  });
3908
2827
  this.socket.on("connect_error", (error) => {
3909
- logger.debug("[API] Socket connection error:", error);
2828
+ logger.logger.debug("[API] Socket connection error:", error);
3910
2829
  this.rpcHandlerManager.onSocketDisconnect();
3911
2830
  });
3912
2831
  this.socket.on("ephemeral", (payload) => {
@@ -3939,20 +2858,20 @@ class ApiSessionClient extends node_events.EventEmitter {
3939
2858
  });
3940
2859
  };
3941
2860
  try {
3942
- logger.debugLargeJson("[SOCKET] [UPDATE] Received update:", data);
2861
+ logger.logger.debugLargeJson("[SOCKET] [UPDATE] Received update:", data);
3943
2862
  if (!data.body) {
3944
- logger.debug("[SOCKET] [UPDATE] [ERROR] No body in update!");
2863
+ logger.logger.debug("[SOCKET] [UPDATE] [ERROR] No body in update!");
3945
2864
  return;
3946
2865
  }
3947
2866
  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);
2867
+ const body = logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(data.body.message.content.c));
2868
+ logger.logger.debugLargeJson("[SOCKET] [UPDATE] Received update:", body);
3950
2869
  const userResult = UserMessageSchema.safeParse(body);
3951
2870
  if (userResult.success) {
3952
2871
  if (isHumanOnlyMessageRecord(body)) {
3953
- logger.debug("[SOCKET] [UPDATE] Ignoring human-only collaboration message");
2872
+ logger.logger.debug("[SOCKET] [UPDATE] Ignoring human-only collaboration message");
3954
2873
  } else if (userResult.data.meta?.sentFrom === "cli") {
3955
- logger.debug("[SOCKET] [UPDATE] Ignoring echo of CLI-originated user message");
2874
+ logger.logger.debug("[SOCKET] [UPDATE] Ignoring echo of CLI-originated user message");
3956
2875
  } else {
3957
2876
  this.maybeSetInitialTitleFromUserText(userResult.data.content.text);
3958
2877
  if (this.queueOrDeliverUserMessage(userResult.data, "socket-update")) {
@@ -3971,22 +2890,22 @@ class ApiSessionClient extends node_events.EventEmitter {
3971
2890
  if (data.body.metadata && data.body.metadata.version > this.metadataVersion) {
3972
2891
  this.metadata = adoptServerSessionMetadata(
3973
2892
  this.metadata,
3974
- decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(data.body.metadata.value))
2893
+ logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(data.body.metadata.value))
3975
2894
  );
3976
2895
  this.metadataVersion = data.body.metadata.version;
3977
2896
  this.syncedModel = this.metadata?.model?.trim() || null;
3978
2897
  }
3979
2898
  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;
2899
+ this.agentState = data.body.agentState.value ? logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(data.body.agentState.value)) : null;
3981
2900
  this.agentStateVersion = data.body.agentState.version;
3982
2901
  }
3983
2902
  } else if (data.body.t === "update-machine") {
3984
- logger.debug(`[SOCKET] WARNING: Session client received unexpected machine update - ignoring`);
2903
+ logger.logger.debug(`[SOCKET] WARNING: Session client received unexpected machine update - ignoring`);
3985
2904
  } else {
3986
2905
  this.emit("message", data.body);
3987
2906
  }
3988
2907
  } catch (error) {
3989
- logger.debug("[SOCKET] [UPDATE] [ERROR] Error handling update", { error });
2908
+ logger.logger.debug("[SOCKET] [UPDATE] [ERROR] Error handling update", { error });
3990
2909
  if (data?.body?.t === "new-message") {
3991
2910
  const errorMessage = error instanceof Error ? error.message : String(error);
3992
2911
  emitMessageReceipt({
@@ -4000,7 +2919,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4000
2919
  }
4001
2920
  });
4002
2921
  this.socket.on("error", (error) => {
4003
- logger.debug("[API] Socket error:", error);
2922
+ logger.logger.debug("[API] Socket error:", error);
4004
2923
  });
4005
2924
  this.socket.connect();
4006
2925
  }
@@ -4015,7 +2934,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4015
2934
  }
4016
2935
  async orchestratorSubmit(body) {
4017
2936
  const response = await axios.post(
4018
- `${configuration.serverUrl}/v1/orchestrator/submit`,
2937
+ `${logger.configuration.serverUrl}/v1/orchestrator/submit`,
4019
2938
  body,
4020
2939
  {
4021
2940
  headers: this.orchestratorHeaders(),
@@ -4026,7 +2945,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4026
2945
  }
4027
2946
  async orchestratorGetContext() {
4028
2947
  const response = await axios.get(
4029
- `${configuration.serverUrl}/v1/orchestrator/context`,
2948
+ `${logger.configuration.serverUrl}/v1/orchestrator/context`,
4030
2949
  {
4031
2950
  headers: this.orchestratorHeaders(),
4032
2951
  timeout: 3e4
@@ -4036,7 +2955,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4036
2955
  }
4037
2956
  async orchestratorGetRun(runId, includeTasks = true) {
4038
2957
  const response = await axios.get(
4039
- `${configuration.serverUrl}/v1/orchestrator/runs/${encodeURIComponent(runId)}`,
2958
+ `${logger.configuration.serverUrl}/v1/orchestrator/runs/${encodeURIComponent(runId)}`,
4040
2959
  {
4041
2960
  headers: this.orchestratorHeaders(),
4042
2961
  params: { includeTasks },
@@ -4047,7 +2966,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4047
2966
  }
4048
2967
  async orchestratorListRuns(query = {}) {
4049
2968
  const response = await axios.get(
4050
- `${configuration.serverUrl}/v1/orchestrator/runs`,
2969
+ `${logger.configuration.serverUrl}/v1/orchestrator/runs`,
4051
2970
  {
4052
2971
  headers: this.orchestratorHeaders(),
4053
2972
  params: query,
@@ -4058,7 +2977,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4058
2977
  }
4059
2978
  async orchestratorPend(runId, query = {}) {
4060
2979
  const response = await axios.get(
4061
- `${configuration.serverUrl}/v1/orchestrator/runs/${encodeURIComponent(runId)}/pend`,
2980
+ `${logger.configuration.serverUrl}/v1/orchestrator/runs/${encodeURIComponent(runId)}/pend`,
4062
2981
  {
4063
2982
  headers: this.orchestratorHeaders(),
4064
2983
  params: query,
@@ -4069,7 +2988,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4069
2988
  }
4070
2989
  async orchestratorSendMessage(body) {
4071
2990
  const response = await axios.post(
4072
- `${configuration.serverUrl}/v1/orchestrator/tasks/${encodeURIComponent(body.taskId)}/send-message`,
2991
+ `${logger.configuration.serverUrl}/v1/orchestrator/tasks/${encodeURIComponent(body.taskId)}/send-message`,
4073
2992
  {
4074
2993
  message: body.message
4075
2994
  },
@@ -4082,7 +3001,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4082
3001
  }
4083
3002
  async orchestratorCancel(runId, body) {
4084
3003
  const response = await axios.post(
4085
- `${configuration.serverUrl}/v1/orchestrator/runs/${encodeURIComponent(runId)}/cancel`,
3004
+ `${logger.configuration.serverUrl}/v1/orchestrator/runs/${encodeURIComponent(runId)}/cancel`,
4086
3005
  body ?? {},
4087
3006
  {
4088
3007
  headers: this.orchestratorHeaders(),
@@ -4321,7 +3240,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4321
3240
  for (let offset = 0; offset < batch.length; offset += OUTBOX_FLUSH_BATCH_SIZE) {
4322
3241
  const chunk = batch.slice(offset, offset + OUTBOX_FLUSH_BATCH_SIZE);
4323
3242
  await axios.post(
4324
- `${configuration.serverUrl}/v3/sessions/${encodeURIComponent(this.sessionId)}/messages`,
3243
+ `${logger.configuration.serverUrl}/v3/sessions/${encodeURIComponent(this.sessionId)}/messages`,
4325
3244
  {
4326
3245
  messages: chunk
4327
3246
  },
@@ -4341,7 +3260,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4341
3260
  * This is the parallel reliable path alongside the fast-path socket emit.
4342
3261
  */
4343
3262
  enqueueMessage(content) {
4344
- const encrypted = encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, content));
3263
+ const encrypted = logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, content));
4345
3264
  this.pendingOutbox.push({
4346
3265
  content: encrypted,
4347
3266
  localId: node_crypto.randomUUID()
@@ -4358,7 +3277,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4358
3277
  const messages = await this.fetchRecentReviewMessages(80);
4359
3278
  return messages.some((message) => message.role === "user" && normalizeAutoReviewTextForDedupe(message.text) === normalized);
4360
3279
  } catch (error) {
4361
- logger.debug("[AUTO_REVIEW] Failed to check duplicate follow-up messages:", error);
3280
+ logger.logger.debug("[AUTO_REVIEW] Failed to check duplicate follow-up messages:", error);
4362
3281
  return false;
4363
3282
  }
4364
3283
  }
@@ -4380,9 +3299,9 @@ class ApiSessionClient extends node_events.EventEmitter {
4380
3299
  displayText: trimmed
4381
3300
  }
4382
3301
  };
4383
- const encrypted = encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, content));
3302
+ const encrypted = logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, content));
4384
3303
  await axios.post(
4385
- `${configuration.serverUrl}/v3/sessions/${encodeURIComponent(this.sessionId)}/send`,
3304
+ `${logger.configuration.serverUrl}/v3/sessions/${encodeURIComponent(this.sessionId)}/send`,
4386
3305
  {
4387
3306
  content: encrypted,
4388
3307
  localId,
@@ -4399,7 +3318,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4399
3318
  }
4400
3319
  async fetchRecentReviewMessages(limit = 200) {
4401
3320
  const response = await axios.get(
4402
- `${configuration.serverUrl}/v3/sessions/${encodeURIComponent(this.sessionId)}/messages`,
3321
+ `${logger.configuration.serverUrl}/v3/sessions/${encodeURIComponent(this.sessionId)}/messages`,
4403
3322
  {
4404
3323
  params: { limit },
4405
3324
  headers: { "Authorization": `Bearer ${this.token}` },
@@ -4412,7 +3331,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4412
3331
  const encrypted = row?.content?.t === "encrypted" ? row.content.c : null;
4413
3332
  if (!encrypted) continue;
4414
3333
  try {
4415
- const decrypted = decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(encrypted));
3334
+ const decrypted = logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(encrypted));
4416
3335
  if (isHumanOnlyMessageRecord(decrypted)) {
4417
3336
  continue;
4418
3337
  }
@@ -4420,7 +3339,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4420
3339
  const text = extractPlainTextForAutoReview(decrypted);
4421
3340
  if (text) result.push({ role, text });
4422
3341
  } catch (error) {
4423
- logger.debug("[AUTO_REVIEW] Failed to decrypt review history message:", error);
3342
+ logger.logger.debug("[AUTO_REVIEW] Failed to decrypt review history message:", error);
4424
3343
  }
4425
3344
  }
4426
3345
  return result;
@@ -4431,13 +3350,13 @@ class ApiSessionClient extends node_events.EventEmitter {
4431
3350
  const isSidechain = body.isSidechain === true;
4432
3351
  this.sendUsageData(body.message.usage, isSidechain ? void 0 : body.message.model);
4433
3352
  } catch (error) {
4434
- logger.debug("[SOCKET] Failed to send usage data:", error);
3353
+ logger.logger.debug("[SOCKET] Failed to send usage data:", error);
4435
3354
  }
4436
3355
  }
4437
3356
  if (body.type === "summary" && "summary" in body && "leafUuid" in body) {
4438
3357
  this.updateMetadata((metadata) => {
4439
3358
  if (metadata.summaryPinned) {
4440
- logger.debug("[SOCKET] Skipping summary update: title is pinned by user");
3359
+ logger.logger.debug("[SOCKET] Skipping summary update: title is pinned by user");
4441
3360
  return metadata;
4442
3361
  }
4443
3362
  const newSummary = body.summary;
@@ -4445,7 +3364,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4445
3364
  const dirName = metadata.path?.split(/[\\/]/).filter(Boolean).pop();
4446
3365
  const isNewSummaryDirName = dirName && newSummary === dirName;
4447
3366
  if (isNewSummaryDirName && currentSummary && currentSummary !== dirName) {
4448
- logger.debug("[SOCKET] Skipping summary update: new summary is directory name but current title is better", {
3367
+ logger.logger.debug("[SOCKET] Skipping summary update: new summary is directory name but current title is better", {
4449
3368
  newSummary,
4450
3369
  currentSummary,
4451
3370
  dirName
@@ -4471,18 +3390,18 @@ class ApiSessionClient extends node_events.EventEmitter {
4471
3390
  if (content.role === "agent") {
4472
3391
  this.autoReviewGuard.onAgentText(extractPlainTextForAutoReview(content), String(body.uuid || node_crypto.randomUUID()));
4473
3392
  }
4474
- logger.debugLargeJson("[SOCKET] Sending message through socket:", content);
3393
+ logger.logger.debugLargeJson("[SOCKET] Sending message through socket:", content);
4475
3394
  this.enqueueMessage(content);
4476
3395
  this.postSendProcessing(body);
4477
3396
  }
4478
3397
  async sendClaudeSessionMessageBatch(messages, mode = "append") {
4479
3398
  if (!this.socket.connected) {
4480
- logger.debug("[API] Socket not connected, cannot send Claude session message batch. Messages will be lost:", { count: messages.length });
3399
+ logger.logger.debug("[API] Socket not connected, cannot send Claude session message batch. Messages will be lost:", { count: messages.length });
4481
3400
  return { result: "error" };
4482
3401
  }
4483
3402
  const payload = messages.map((item) => {
4484
3403
  const content = this.buildMessageContent(item.message);
4485
- const encrypted = encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, content));
3404
+ const encrypted = logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, content));
4486
3405
  return {
4487
3406
  message: encrypted,
4488
3407
  localId: item.localId ?? null
@@ -4537,7 +3456,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4537
3456
  sentFrom: "cli"
4538
3457
  }
4539
3458
  };
4540
- logger.debug(`[SOCKET] Sending ACP message from ${provider}:`, { type: body.type, hasMessage: "message" in body });
3459
+ logger.logger.debug(`[SOCKET] Sending ACP message from ${provider}:`, { type: body.type, hasMessage: "message" in body });
4541
3460
  this.autoReviewGuard.onAgentText(normalizeReviewableAgentText(body), `${provider}-${Date.now()}`);
4542
3461
  this.enqueueMessage(content);
4543
3462
  }
@@ -4548,17 +3467,17 @@ class ApiSessionClient extends node_events.EventEmitter {
4548
3467
  */
4549
3468
  async sendBackfillBatch(messages, mode = "append") {
4550
3469
  if (!this.socket.connected) {
4551
- logger.debug(`[API] Socket not connected, cannot send backfill batch (${messages.length} messages)`);
3470
+ logger.logger.debug(`[API] Socket not connected, cannot send backfill batch (${messages.length} messages)`);
4552
3471
  return { result: "error" };
4553
3472
  }
4554
3473
  const payload = messages.map((item) => {
4555
- const encrypted = encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, item.content));
3474
+ const encrypted = logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, item.content));
4556
3475
  return {
4557
3476
  message: encrypted,
4558
3477
  localId: item.localId
4559
3478
  };
4560
3479
  });
4561
- logger.debug(`[SOCKET] Sending backfill batch: ${messages.length} messages, mode=${mode}`);
3480
+ logger.logger.debug(`[SOCKET] Sending backfill batch: ${messages.length} messages, mode=${mode}`);
4562
3481
  const response = await this.socket.emitWithAck("message-batch", {
4563
3482
  sid: this.sessionId,
4564
3483
  messages: payload,
@@ -4575,7 +3494,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4575
3494
  data: event
4576
3495
  }
4577
3496
  };
4578
- const encrypted = encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, content));
3497
+ const encrypted = logger.encodeBase64(logger.encrypt(this.encryptionKey, this.encryptionVariant, content));
4579
3498
  this.socket.emit("message", {
4580
3499
  sid: this.sessionId,
4581
3500
  message: encrypted
@@ -4585,8 +3504,8 @@ class ApiSessionClient extends node_events.EventEmitter {
4585
3504
  * Send a ping message to keep the connection alive
4586
3505
  */
4587
3506
  keepAlive(thinking, mode) {
4588
- if (isDebug()) {
4589
- logger.debug(`[API] Sending keep alive message: ${thinking}`);
3507
+ if (logger.isDebug()) {
3508
+ logger.logger.debug(`[API] Sending keep alive message: ${thinking}`);
4590
3509
  }
4591
3510
  this.socket.volatile.emit("session-alive", {
4592
3511
  sid: this.sessionId,
@@ -4605,7 +3524,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4605
3524
  * Send a generic usage report to the server for any provider
4606
3525
  */
4607
3526
  sendUsageReport(report) {
4608
- logger.debugLargeJson("[SOCKET] Sending usage report:", report);
3527
+ logger.logger.debugLargeJson("[SOCKET] Sending usage report:", report);
4609
3528
  this.socket.emit("usage-report", {
4610
3529
  key: report.key,
4611
3530
  sessionId: this.sessionId,
@@ -4613,7 +3532,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4613
3532
  cost: report.cost
4614
3533
  }, (response) => {
4615
3534
  if (!response?.success) {
4616
- logger.debug("[SOCKET] Usage report rejected by server", {
3535
+ logger.logger.debug("[SOCKET] Usage report rejected by server", {
4617
3536
  key: report.key,
4618
3537
  sessionId: this.sessionId,
4619
3538
  error: response?.error || "unknown error"
@@ -4700,22 +3619,22 @@ class ApiSessionClient extends node_events.EventEmitter {
4700
3619
  }
4701
3620
  async updateMetadataAsync(handler) {
4702
3621
  await this.metadataLock.inLock(async () => {
4703
- await backoff(async () => {
3622
+ await time.backoff(async () => {
4704
3623
  const base = this.metadata;
4705
3624
  if (!base) {
4706
- logger.debug("[API] skipping metadata update: no local metadata to build on");
3625
+ logger.logger.debug("[API] skipping metadata update: no local metadata to build on");
4707
3626
  return;
4708
3627
  }
4709
3628
  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)) });
3629
+ 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
3630
  if (answer.result === "success") {
4712
- this.metadata = adoptServerSessionMetadata(this.metadata, decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.metadata)));
3631
+ this.metadata = adoptServerSessionMetadata(this.metadata, logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(answer.metadata)));
4713
3632
  this.metadataVersion = answer.version;
4714
3633
  this.syncedModel = this.metadata?.model?.trim() || null;
4715
3634
  } else if (answer.result === "version-mismatch") {
4716
3635
  if (answer.version > this.metadataVersion) {
4717
3636
  this.metadataVersion = answer.version;
4718
- this.metadata = adoptServerSessionMetadata(this.metadata, decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.metadata)));
3637
+ this.metadata = adoptServerSessionMetadata(this.metadata, logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(answer.metadata)));
4719
3638
  this.syncedModel = this.metadata?.model?.trim() || null;
4720
3639
  }
4721
3640
  throw new Error("Metadata version mismatch");
@@ -4728,19 +3647,19 @@ class ApiSessionClient extends node_events.EventEmitter {
4728
3647
  * @param handler - Handler function that returns the updated agent state
4729
3648
  */
4730
3649
  updateAgentState(handler) {
4731
- logger.debugLargeJson("Updating agent state", this.agentState);
3650
+ logger.logger.debugLargeJson("Updating agent state", this.agentState);
4732
3651
  this.agentStateLock.inLock(async () => {
4733
- await backoff(async () => {
3652
+ await time.backoff(async () => {
4734
3653
  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 });
3654
+ 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
3655
  if (answer.result === "success") {
4737
- this.agentState = answer.agentState ? decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.agentState)) : null;
3656
+ this.agentState = answer.agentState ? logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(answer.agentState)) : null;
4738
3657
  this.agentStateVersion = answer.version;
4739
- logger.debug("Agent state updated", this.agentState);
3658
+ logger.logger.debug("Agent state updated", this.agentState);
4740
3659
  } else if (answer.result === "version-mismatch") {
4741
3660
  if (answer.version > this.agentStateVersion) {
4742
3661
  this.agentStateVersion = answer.version;
4743
- this.agentState = answer.agentState ? decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.agentState)) : null;
3662
+ this.agentState = answer.agentState ? logger.decrypt(this.encryptionKey, this.encryptionVariant, logger.decodeBase64(answer.agentState)) : null;
4744
3663
  }
4745
3664
  throw new Error("Agent state version mismatch");
4746
3665
  } else if (answer.result === "error") ;
@@ -4755,7 +3674,7 @@ class ApiSessionClient extends node_events.EventEmitter {
4755
3674
  try {
4756
3675
  await this.sendSync.invalidateAndAwait();
4757
3676
  } catch (error) {
4758
- logger.debug("[API] flush: outbox flush failed, some messages may be lost:", error);
3677
+ logger.logger.debug("[API] flush: outbox flush failed, some messages may be lost:", error);
4759
3678
  }
4760
3679
  if (!this.socket.connected) {
4761
3680
  return;
@@ -4770,387 +3689,17 @@ class ApiSessionClient extends node_events.EventEmitter {
4770
3689
  });
4771
3690
  }
4772
3691
  async close() {
4773
- logger.debug("[API] socket.close() called");
3692
+ logger.logger.debug("[API] socket.close() called");
4774
3693
  try {
4775
3694
  await this.sendSync.invalidateAndAwait();
4776
3695
  } catch (error) {
4777
- logger.debug("[API] close: final outbox flush failed:", error);
3696
+ logger.logger.debug("[API] close: final outbox flush failed:", error);
4778
3697
  }
4779
3698
  this.sendSync.stop();
4780
3699
  this.socket.close();
4781
3700
  }
4782
3701
  }
4783
3702
 
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
3703
  function buildRunningDaemonState(previousState, currentRuntimeState, opts = {}) {
5155
3704
  const currentHttpPort = currentRuntimeState?.httpPort;
5156
3705
  const currentStartedAt = currentRuntimeState?.startedAt;
@@ -5216,11 +3765,11 @@ class OpenClawTunnelManager {
5216
3765
  this.tunnels.set(tunnelId, tunnel);
5217
3766
  return new Promise((resolve) => {
5218
3767
  try {
5219
- logger.debug(`[OpenClawTunnel] Connecting to ${config.url}`);
3768
+ logger.logger.debug(`[OpenClawTunnel] Connecting to ${config.url}`);
5220
3769
  const ws = new WebSocket(config.url);
5221
3770
  tunnel.ws = ws;
5222
3771
  ws.on("open", () => {
5223
- logger.debug(`[OpenClawTunnel] WebSocket opened for tunnel ${tunnelId}`);
3772
+ logger.logger.debug(`[OpenClawTunnel] WebSocket opened for tunnel ${tunnelId}`);
5224
3773
  });
5225
3774
  ws.on("message", async (data) => {
5226
3775
  const result = await this.handleMessage(tunnelId, tunnel, data.toString());
@@ -5229,7 +3778,7 @@ class OpenClawTunnelManager {
5229
3778
  }
5230
3779
  });
5231
3780
  ws.on("error", (error) => {
5232
- logger.debug(`[OpenClawTunnel] WebSocket error for tunnel ${tunnelId}:`, error);
3781
+ logger.logger.debug(`[OpenClawTunnel] WebSocket error for tunnel ${tunnelId}:`, error);
5233
3782
  tunnel.status = "error";
5234
3783
  this.failAllPending(tunnel, new Error("WebSocket error"));
5235
3784
  resolve({
@@ -5240,7 +3789,7 @@ class OpenClawTunnelManager {
5240
3789
  });
5241
3790
  ws.on("close", (code, reason) => {
5242
3791
  const reasonStr = reason?.toString() || "";
5243
- logger.debug(`[OpenClawTunnel] WebSocket closed for tunnel ${tunnelId}: ${code} ${reasonStr}`);
3792
+ logger.logger.debug(`[OpenClawTunnel] WebSocket closed for tunnel ${tunnelId}: ${code} ${reasonStr}`);
5244
3793
  const isPairingRequired = reasonStr.includes("unauthorized") || reasonStr.includes("NOT_PAIRED");
5245
3794
  this.failAllPending(tunnel, new Error(reasonStr || "Connection closed"));
5246
3795
  if (tunnel.status === "connecting") {
@@ -5372,7 +3921,7 @@ class OpenClawTunnelManager {
5372
3921
  tunnel.ws = null;
5373
3922
  }
5374
3923
  this.tunnels.delete(tunnelId);
5375
- logger.debug(`[OpenClawTunnel] Closed tunnel ${tunnelId}`);
3924
+ logger.logger.debug(`[OpenClawTunnel] Closed tunnel ${tunnelId}`);
5376
3925
  return true;
5377
3926
  }
5378
3927
  async handleMessage(tunnelId, tunnel, data) {
@@ -5380,7 +3929,7 @@ class OpenClawTunnelManager {
5380
3929
  try {
5381
3930
  frame = JSON.parse(data);
5382
3931
  } catch {
5383
- logger.debug(`[OpenClawTunnel] Invalid JSON: ${data.slice(0, 100)}`);
3932
+ logger.logger.debug(`[OpenClawTunnel] Invalid JSON: ${data.slice(0, 100)}`);
5384
3933
  return null;
5385
3934
  }
5386
3935
  if (frame.type === "res") {
@@ -5405,7 +3954,7 @@ class OpenClawTunnelManager {
5405
3954
  if (frame.event === "connect.challenge" && !tunnel.connectSent) {
5406
3955
  const nonce = payload?.nonce;
5407
3956
  if (nonce) {
5408
- logger.debug(`[OpenClawTunnel] Received challenge nonce for tunnel ${tunnelId}`);
3957
+ logger.logger.debug(`[OpenClawTunnel] Received challenge nonce for tunnel ${tunnelId}`);
5409
3958
  tunnel.connectNonce = nonce;
5410
3959
  }
5411
3960
  return this.sendConnect(tunnelId, tunnel);
@@ -5485,7 +4034,7 @@ class OpenClawTunnelManager {
5485
4034
  tunnel.mainSessionKey = result.snapshot?.sessionDefaults?.mainSessionKey ?? null;
5486
4035
  tunnel.serverHost = result.server?.host ?? null;
5487
4036
  tunnel.deviceToken = result.auth?.deviceToken ?? null;
5488
- logger.debug(`[OpenClawTunnel] Connected tunnel ${tunnelId}, server: ${tunnel.serverHost}`);
4037
+ logger.logger.debug(`[OpenClawTunnel] Connected tunnel ${tunnelId}, server: ${tunnel.serverHost}`);
5489
4038
  resolve({
5490
4039
  ok: true,
5491
4040
  status: "connected",
@@ -5603,7 +4152,7 @@ function registerOpenClawHandlers(rpcManager, encryptionContext) {
5603
4152
  if (Array.isArray(payload.messages) && payload.messages.length > 0) {
5604
4153
  return {
5605
4154
  __preEncrypted: true,
5606
- data: encodeBase64(encryptLegacy(result, encryptionContext.key))
4155
+ data: logger.encodeBase64(logger.encryptLegacy(result, encryptionContext.key))
5607
4156
  };
5608
4157
  }
5609
4158
  }
@@ -5655,7 +4204,7 @@ const SESSION_CACHE_REFRESH_MODES = /* @__PURE__ */ new Set([
5655
4204
  "background"
5656
4205
  ]);
5657
4206
  function getSessionMetadataCachePath(cacheFileName) {
5658
- return path.join(configuration.happyHomeDir, cacheFileName);
4207
+ return path.join(logger.configuration.happyHomeDir, cacheFileName);
5659
4208
  }
5660
4209
  function getCacheLockPath(cachePath) {
5661
4210
  return `${cachePath}.lock`;
@@ -6702,7 +5251,7 @@ const GeminiSessionLineSchema = z.z.discriminatedUnion("type", [
6702
5251
 
6703
5252
  const SESSIONS_DIR_NAME = "gemini_sessions";
6704
5253
  function getGeminiSessionsDir() {
6705
- return path.join(configuration.happyHomeDir, SESSIONS_DIR_NAME);
5254
+ return path.join(logger.configuration.happyHomeDir, SESSIONS_DIR_NAME);
6706
5255
  }
6707
5256
  function getGeminiSessionFilePath(sessionId) {
6708
5257
  return path.join(getGeminiSessionsDir(), `${sessionId}.jsonl`);
@@ -6722,9 +5271,9 @@ class GeminiSessionWriter {
6722
5271
  value: meta ?? {},
6723
5272
  timestamp: Date.now()
6724
5273
  });
6725
- logger.debug(`[GeminiSessionWriter] Initialized: ${this.filePath}`);
5274
+ logger.logger.debug(`[GeminiSessionWriter] Initialized: ${this.filePath}`);
6726
5275
  } catch (error) {
6727
- logger.debug(`[GeminiSessionWriter] Failed to init:`, error);
5276
+ logger.logger.debug(`[GeminiSessionWriter] Failed to init:`, error);
6728
5277
  }
6729
5278
  }
6730
5279
  getFilePath() {
@@ -6783,7 +5332,7 @@ class GeminiSessionWriter {
6783
5332
  */
6784
5333
  appendLine(line) {
6785
5334
  this.writePromise = this.writePromise.then(() => promises.appendFile(this.filePath, JSON.stringify(line) + "\n", "utf-8")).catch((error) => {
6786
- logger.debug(`[GeminiSessionWriter] Write failed:`, error);
5335
+ logger.logger.debug(`[GeminiSessionWriter] Write failed:`, error);
6787
5336
  });
6788
5337
  }
6789
5338
  }
@@ -6794,7 +5343,7 @@ async function readGeminiSessionLog(sessionId) {
6794
5343
  try {
6795
5344
  content = await promises.readFile(filePath, "utf-8");
6796
5345
  } catch (error) {
6797
- logger.debug(`[GeminiSessionReader] Session file not found: ${filePath}`);
5346
+ logger.logger.debug(`[GeminiSessionReader] Session file not found: ${filePath}`);
6798
5347
  return [];
6799
5348
  }
6800
5349
  const lines = content.split("\n");
@@ -6807,10 +5356,10 @@ async function readGeminiSessionLog(sessionId) {
6807
5356
  if (result.success) {
6808
5357
  entries.push(result.data);
6809
5358
  } else {
6810
- logger.debug(`[GeminiSessionReader] Skipping invalid line: ${line.substring(0, 100)}`);
5359
+ logger.logger.debug(`[GeminiSessionReader] Skipping invalid line: ${line.substring(0, 100)}`);
6811
5360
  }
6812
5361
  } catch {
6813
- logger.debug(`[GeminiSessionReader] Skipping non-JSON line: ${line.substring(0, 100)}`);
5362
+ logger.logger.debug(`[GeminiSessionReader] Skipping non-JSON line: ${line.substring(0, 100)}`);
6814
5363
  }
6815
5364
  }
6816
5365
  return entries;
@@ -7032,7 +5581,7 @@ async function forkAndTruncateGeminiSession(sessionId, truncateBeforeUuid) {
7032
5581
  return { success: false, errorMessage: truncateResult.errorMessage };
7033
5582
  }
7034
5583
  }
7035
- logger.debug(`[GeminiSessionFork] Forked ${sessionId} -> ${newSessionId}`);
5584
+ logger.logger.debug(`[GeminiSessionFork] Forked ${sessionId} -> ${newSessionId}`);
7036
5585
  return { success: true, newSessionId };
7037
5586
  } catch (error) {
7038
5587
  try {
@@ -7169,14 +5718,14 @@ function isSystemMessage(text) {
7169
5718
  async function readCodexSessionUserMessages(codexSessionId, limit = 50) {
7170
5719
  const filePath = findCodexSessionFile(codexSessionId);
7171
5720
  if (!filePath) {
7172
- logger.debug(`[CodexSessionReader] Session file not found for: ${codexSessionId}`);
5721
+ logger.logger.debug(`[CodexSessionReader] Session file not found for: ${codexSessionId}`);
7173
5722
  return [];
7174
5723
  }
7175
5724
  let content;
7176
5725
  try {
7177
5726
  content = await promises.readFile(filePath, "utf-8");
7178
5727
  } catch (error) {
7179
- logger.debug(`[CodexSessionReader] Failed to read file: ${filePath}`, error);
5728
+ logger.logger.debug(`[CodexSessionReader] Failed to read file: ${filePath}`, error);
7180
5729
  return [];
7181
5730
  }
7182
5731
  const lines = content.split("\n");
@@ -7473,7 +6022,7 @@ async function forkAndTruncateCodexSession(codexSessionId, truncateBeforeUuid) {
7473
6022
  }
7474
6023
  await promises.writeFile(newPath, outputLines.join("\n") + "\n", "utf-8");
7475
6024
  }
7476
- logger.debug(`[CodexSessionFork] Forked ${path.basename(originalPath)} -> ${path.basename(newPath)}`);
6025
+ logger.logger.debug(`[CodexSessionFork] Forked ${path.basename(originalPath)} -> ${path.basename(newPath)}`);
7477
6026
  return { success: true, newFilePath: newPath };
7478
6027
  } catch (error) {
7479
6028
  try {
@@ -7660,7 +6209,7 @@ function createSessionCacheStatsReporter(saveStats, label) {
7660
6209
  const stats = pendingStats;
7661
6210
  pendingStats = null;
7662
6211
  flushPromise = saveStats(stats).catch((error) => {
7663
- logger.debug(`[API MACHINE] Failed to persist ${label} session cache stats`, error);
6212
+ logger.logger.debug(`[API MACHINE] Failed to persist ${label} session cache stats`, error);
7664
6213
  }).then(() => {
7665
6214
  flushPromise = null;
7666
6215
  });
@@ -7692,7 +6241,7 @@ class ApiMachineClient {
7692
6241
  scopePrefix: this.machine.id,
7693
6242
  encryptionKey: this.machine.encryptionKey,
7694
6243
  encryptionVariant: this.machine.encryptionVariant,
7695
- logger: (msg, data) => logger.debug(msg, data)
6244
+ logger: (msg, data) => logger.logger.debug(msg, data)
7696
6245
  });
7697
6246
  registerCommonHandlers(this.rpcHandlerManager, process.env.HAPPY_DAEMON_ROOT || "/", this.machine.id);
7698
6247
  registerOpenClawHandlers(this.rpcHandlerManager, {
@@ -7708,6 +6257,11 @@ class ApiMachineClient {
7708
6257
  });
7709
6258
  }
7710
6259
  socket;
6260
+ /** The daemon's live connection. Reused for device RPC so a CLI command does
6261
+ * not spend ~500ms building its own TLS + WebSocket handshake. */
6262
+ get rpcSocket() {
6263
+ return this.socket;
6264
+ }
7711
6265
  keepAliveInterval = null;
7712
6266
  rpcHandlerManager;
7713
6267
  claudeCache = new SessionCache({
@@ -7741,7 +6295,7 @@ class ApiMachineClient {
7741
6295
  event,
7742
6296
  payload
7743
6297
  };
7744
- const encryptedData = encodeBase64(encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, eventData));
6298
+ const encryptedData = logger.encodeBase64(logger.encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, eventData));
7745
6299
  const rpcMethod = `${this.machine.id}:openclaw-tunnel-event`;
7746
6300
  this.socket.emit("rpc-call", {
7747
6301
  method: rpcMethod,
@@ -7757,12 +6311,12 @@ class ApiMachineClient {
7757
6311
  orchestratorCancel
7758
6312
  }) {
7759
6313
  this.rpcHandlerManager.registerHandler("spawn-happy-session", async (params) => {
7760
- const settings = await readSettings();
6314
+ const settings = await logger.readSettings();
7761
6315
  if (settings.deviceMode) {
7762
6316
  throw new Error("This machine is enrolled as a device and does not host sessions");
7763
6317
  }
7764
6318
  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)}`);
6319
+ logger.logger.debug(`[API MACHINE] Spawning session with params: ${JSON.stringify(params)}`);
7766
6320
  if (!directory) {
7767
6321
  throw new Error("Directory is required");
7768
6322
  }
@@ -7772,10 +6326,10 @@ class ApiMachineClient {
7772
6326
  this.claudeCache.invalidate();
7773
6327
  this.geminiCache.invalidate();
7774
6328
  this.codexCache.invalidate();
7775
- logger.debug(`[API MACHINE] Spawned session ${result.sessionId}`);
6329
+ logger.logger.debug(`[API MACHINE] Spawned session ${result.sessionId}`);
7776
6330
  return { type: "success", sessionId: result.sessionId };
7777
6331
  case "requestToApproveDirectoryCreation":
7778
- logger.debug(`[API MACHINE] Requesting directory creation approval for: ${result.directory}`);
6332
+ logger.logger.debug(`[API MACHINE] Requesting directory creation approval for: ${result.directory}`);
7779
6333
  return { type: "requestToApproveDirectoryCreation", directory: result.directory };
7780
6334
  case "error":
7781
6335
  throw new Error(result.errorMessage);
@@ -7791,9 +6345,9 @@ class ApiMachineClient {
7791
6345
  const { worktreePath, basePath, branchName, archiveScript, deleteBranch } = repo;
7792
6346
  try {
7793
6347
  if (archiveScript) {
7794
- logger.info(`[DAEMON] Running archive script in ${worktreePath}...`);
6348
+ logger.logger.info(`[DAEMON] Running archive script in ${worktreePath}...`);
7795
6349
  node_child_process.execSync(archiveScript, { cwd: worktreePath, stdio: "pipe", timeout: 3e5 });
7796
- logger.info(`[DAEMON] Archive script completed for ${worktreePath}`);
6350
+ logger.logger.info(`[DAEMON] Archive script completed for ${worktreePath}`);
7797
6351
  }
7798
6352
  if (worktreePath !== basePath) {
7799
6353
  try {
@@ -7803,7 +6357,7 @@ class ApiMachineClient {
7803
6357
  timeout: 3e4
7804
6358
  });
7805
6359
  } catch (err) {
7806
- logger.warn(`[DAEMON] git worktree remove failed: ${err.message}`);
6360
+ logger.logger.warn(`[DAEMON] git worktree remove failed: ${err.message}`);
7807
6361
  }
7808
6362
  if (deleteBranch && branchName) {
7809
6363
  try {
@@ -7813,13 +6367,13 @@ class ApiMachineClient {
7813
6367
  timeout: 1e4
7814
6368
  });
7815
6369
  } catch (err) {
7816
- logger.warn(`[DAEMON] git branch -D failed: ${err.message}`);
6370
+ logger.logger.warn(`[DAEMON] git branch -D failed: ${err.message}`);
7817
6371
  }
7818
6372
  }
7819
6373
  }
7820
6374
  results.push({ repo: worktreePath, success: true });
7821
6375
  } catch (err) {
7822
- logger.warn(`[DAEMON] Archive failed for ${worktreePath}: ${err.message}`);
6376
+ logger.logger.warn(`[DAEMON] Archive failed for ${worktreePath}: ${err.message}`);
7823
6377
  results.push({ repo: worktreePath, success: false, error: err.message });
7824
6378
  }
7825
6379
  }
@@ -7828,7 +6382,7 @@ class ApiMachineClient {
7828
6382
  const entries = fs.readdirSync(workspacePath);
7829
6383
  if (entries.length === 0) {
7830
6384
  fs.rmdirSync(workspacePath);
7831
- logger.info(`[DAEMON] Removed empty workspace directory: ${workspacePath}`);
6385
+ logger.logger.info(`[DAEMON] Removed empty workspace directory: ${workspacePath}`);
7832
6386
  }
7833
6387
  } catch {
7834
6388
  }
@@ -7847,13 +6401,13 @@ class ApiMachineClient {
7847
6401
  this.claudeCache.invalidate();
7848
6402
  this.geminiCache.invalidate();
7849
6403
  this.codexCache.invalidate();
7850
- logger.debug(`[API MACHINE] Stopped session ${sessionId}`);
6404
+ logger.logger.debug(`[API MACHINE] Stopped session ${sessionId}`);
7851
6405
  return { message: "Session stopped" };
7852
6406
  });
7853
6407
  this.rpcHandlerManager.registerHandler("stop-daemon", () => {
7854
- logger.debug("[API MACHINE] Received stop-daemon RPC request");
6408
+ logger.logger.debug("[API MACHINE] Received stop-daemon RPC request");
7855
6409
  setTimeout(() => {
7856
- logger.debug("[API MACHINE] Initiating daemon shutdown from RPC");
6410
+ logger.logger.debug("[API MACHINE] Initiating daemon shutdown from RPC");
7857
6411
  requestShutdown();
7858
6412
  }, 100);
7859
6413
  return { message: "Daemon stop request acknowledged, starting shutdown sequence..." };
@@ -8091,21 +6645,21 @@ class ApiMachineClient {
8091
6645
  * for example to set a custom name.
8092
6646
  */
8093
6647
  async updateMachineMetadata(handler) {
8094
- await backoff(async () => {
6648
+ await time.backoff(async () => {
8095
6649
  const updated = handler(this.machine.metadata);
8096
6650
  const answer = await this.socket.emitWithAck("machine-update-metadata", {
8097
6651
  machineId: this.machine.id,
8098
- metadata: encodeBase64(encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, updated)),
6652
+ metadata: logger.encodeBase64(logger.encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, updated)),
8099
6653
  expectedVersion: this.machine.metadataVersion
8100
6654
  });
8101
6655
  if (answer.result === "success") {
8102
- this.machine.metadata = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.metadata));
6656
+ this.machine.metadata = logger.decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, logger.decodeBase64(answer.metadata));
8103
6657
  this.machine.metadataVersion = answer.version;
8104
- logger.debug("[API MACHINE] Metadata updated successfully");
6658
+ logger.logger.debug("[API MACHINE] Metadata updated successfully");
8105
6659
  } else if (answer.result === "version-mismatch") {
8106
6660
  if (answer.version > this.machine.metadataVersion) {
8107
6661
  this.machine.metadataVersion = answer.version;
8108
- this.machine.metadata = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.metadata));
6662
+ this.machine.metadata = logger.decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, logger.decodeBase64(answer.metadata));
8109
6663
  }
8110
6664
  throw new Error("Metadata version mismatch");
8111
6665
  }
@@ -8116,29 +6670,29 @@ class ApiMachineClient {
8116
6670
  * Simplified without lock - relies on backoff for retry
8117
6671
  */
8118
6672
  async updateDaemonState(handler) {
8119
- await backoff(async () => {
6673
+ await time.backoff(async () => {
8120
6674
  const updated = handler(this.machine.daemonState);
8121
6675
  const answer = await this.socket.emitWithAck("machine-update-state", {
8122
6676
  machineId: this.machine.id,
8123
- daemonState: encodeBase64(encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, updated)),
6677
+ daemonState: logger.encodeBase64(logger.encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, updated)),
8124
6678
  expectedVersion: this.machine.daemonStateVersion
8125
6679
  });
8126
6680
  if (answer.result === "success") {
8127
- this.machine.daemonState = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.daemonState));
6681
+ this.machine.daemonState = logger.decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, logger.decodeBase64(answer.daemonState));
8128
6682
  this.machine.daemonStateVersion = answer.version;
8129
- logger.debug("[API MACHINE] Daemon state updated successfully");
6683
+ logger.logger.debug("[API MACHINE] Daemon state updated successfully");
8130
6684
  } else if (answer.result === "version-mismatch") {
8131
6685
  if (answer.version > this.machine.daemonStateVersion) {
8132
6686
  this.machine.daemonStateVersion = answer.version;
8133
- this.machine.daemonState = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.daemonState));
6687
+ this.machine.daemonState = logger.decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, logger.decodeBase64(answer.daemonState));
8134
6688
  }
8135
6689
  throw new Error("Daemon state version mismatch");
8136
6690
  }
8137
6691
  });
8138
6692
  }
8139
6693
  connect() {
8140
- const serverUrl = configuration.serverUrl.replace(/^http/, "ws");
8141
- logger.debug(`[API MACHINE] Connecting to ${serverUrl}`);
6694
+ const serverUrl = logger.configuration.serverUrl.replace(/^http/, "ws");
6695
+ logger.logger.debug(`[API MACHINE] Connecting to ${serverUrl}`);
8142
6696
  this.socket = socket_ioClient.io(serverUrl, {
8143
6697
  transports: ["websocket"],
8144
6698
  auth: {
@@ -8152,7 +6706,7 @@ class ApiMachineClient {
8152
6706
  reconnectionDelayMax: 5e3
8153
6707
  });
8154
6708
  this.socket.on("connect", () => {
8155
- logger.debug("[API MACHINE] Connected to server");
6709
+ logger.logger.debug("[API MACHINE] Connected to server");
8156
6710
  this.updateDaemonState((state) => buildRunningDaemonState(
8157
6711
  state,
8158
6712
  this.currentRuntimeDaemonState ?? this.machine.daemonState
@@ -8161,36 +6715,36 @@ class ApiMachineClient {
8161
6715
  this.startKeepAlive();
8162
6716
  });
8163
6717
  this.socket.on("disconnect", () => {
8164
- logger.debug("[API MACHINE] Disconnected from server");
6718
+ logger.logger.debug("[API MACHINE] Disconnected from server");
8165
6719
  this.rpcHandlerManager.onSocketDisconnect();
8166
6720
  this.stopKeepAlive();
8167
6721
  });
8168
6722
  this.socket.on("rpc-request", async (data, callback) => {
8169
- logger.debugLargeJson(`[API MACHINE] Received RPC request:`, data);
6723
+ logger.logger.debugLargeJson(`[API MACHINE] Received RPC request:`, data);
8170
6724
  callback(await this.rpcHandlerManager.handleRequest(data));
8171
6725
  });
8172
6726
  this.socket.on("update", (data) => {
8173
6727
  if (data.body.t === "update-machine" && data.body.machineId === this.machine.id) {
8174
6728
  const update = data.body;
8175
6729
  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));
6730
+ logger.logger.debug("[API MACHINE] Received external metadata update");
6731
+ this.machine.metadata = logger.decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, logger.decodeBase64(update.metadata.value));
8178
6732
  this.machine.metadataVersion = update.metadata.version;
8179
6733
  }
8180
6734
  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));
6735
+ logger.logger.debug("[API MACHINE] Received external daemon state update");
6736
+ this.machine.daemonState = logger.decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, logger.decodeBase64(update.daemonState.value));
8183
6737
  this.machine.daemonStateVersion = update.daemonState.version;
8184
6738
  }
8185
6739
  } else {
8186
- logger.debug(`[API MACHINE] Received unknown update type: ${data.body.t}`);
6740
+ logger.logger.debug(`[API MACHINE] Received unknown update type: ${data.body.t}`);
8187
6741
  }
8188
6742
  });
8189
6743
  this.socket.on("connect_error", (error) => {
8190
- logger.debug(`[API MACHINE] Connection error: ${error.message}`);
6744
+ logger.logger.debug(`[API MACHINE] Connection error: ${error.message}`);
8191
6745
  });
8192
6746
  this.socket.io.on("error", (error) => {
8193
- logger.debug("[API MACHINE] Socket error:", error);
6747
+ logger.logger.debug("[API MACHINE] Socket error:", error);
8194
6748
  });
8195
6749
  }
8196
6750
  startKeepAlive() {
@@ -8200,27 +6754,27 @@ class ApiMachineClient {
8200
6754
  machineId: this.machine.id,
8201
6755
  time: Date.now()
8202
6756
  };
8203
- if (isDebug()) {
8204
- logger.debugLargeJson(`[API MACHINE] Emitting machine-alive`, payload);
6757
+ if (logger.isDebug()) {
6758
+ logger.logger.debugLargeJson(`[API MACHINE] Emitting machine-alive`, payload);
8205
6759
  }
8206
6760
  this.socket.emit("machine-alive", payload);
8207
6761
  }, 2e4);
8208
- logger.debug("[API MACHINE] Keep-alive started (20s interval)");
6762
+ logger.logger.debug("[API MACHINE] Keep-alive started (20s interval)");
8209
6763
  }
8210
6764
  stopKeepAlive() {
8211
6765
  if (this.keepAliveInterval) {
8212
6766
  clearInterval(this.keepAliveInterval);
8213
6767
  this.keepAliveInterval = null;
8214
- logger.debug("[API MACHINE] Keep-alive stopped");
6768
+ logger.logger.debug("[API MACHINE] Keep-alive stopped");
8215
6769
  }
8216
6770
  }
8217
6771
  shutdown() {
8218
- logger.debug("[API MACHINE] Shutting down");
6772
+ logger.logger.debug("[API MACHINE] Shutting down");
8219
6773
  openClawTunnelManager.closeAll();
8220
6774
  this.stopKeepAlive();
8221
6775
  if (this.socket) {
8222
6776
  this.socket.close();
8223
- logger.debug("[API MACHINE] Socket closed");
6777
+ logger.logger.debug("[API MACHINE] Socket closed");
8224
6778
  }
8225
6779
  }
8226
6780
  }
@@ -8248,13 +6802,13 @@ class PushNotificationClient {
8248
6802
  }
8249
6803
  }
8250
6804
  );
8251
- logger.debug(`Fetched ${response.data.tokens.length} push tokens`);
6805
+ logger.logger.debug(`Fetched ${response.data.tokens.length} push tokens`);
8252
6806
  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()}`);
6807
+ logger.logger.debug(`[PUSH] Token ${index + 1}: id=${token.id}, created=${new Date(token.createdAt).toISOString()}, updated=${new Date(token.updatedAt).toISOString()}`);
8254
6808
  });
8255
6809
  return response.data.tokens;
8256
6810
  } catch (error) {
8257
- logger.debug("[PUSH] [ERROR] Failed to fetch push tokens:", error);
6811
+ logger.logger.debug("[PUSH] [ERROR] Failed to fetch push tokens:", error);
8258
6812
  throw new Error(`Failed to fetch push tokens: ${error instanceof Error ? error.message : "Unknown error"}`);
8259
6813
  }
8260
6814
  }
@@ -8263,7 +6817,7 @@ class PushNotificationClient {
8263
6817
  * @param messages - Array of push messages to send
8264
6818
  */
8265
6819
  async sendPushNotifications(messages) {
8266
- logger.debug(`Sending ${messages.length} push notifications`);
6820
+ logger.logger.debug(`Sending ${messages.length} push notifications`);
8267
6821
  const validMessages = messages.filter((message) => {
8268
6822
  if (Array.isArray(message.to)) {
8269
6823
  return message.to.every((token) => expoServerSdk.Expo.isExpoPushToken(token));
@@ -8271,7 +6825,7 @@ class PushNotificationClient {
8271
6825
  return expoServerSdk.Expo.isExpoPushToken(message.to);
8272
6826
  });
8273
6827
  if (validMessages.length === 0) {
8274
- logger.debug("No valid Expo push tokens found");
6828
+ logger.logger.debug("No valid Expo push tokens found");
8275
6829
  return;
8276
6830
  }
8277
6831
  const chunks = this.expo.chunkPushNotifications(validMessages);
@@ -8285,7 +6839,7 @@ class PushNotificationClient {
8285
6839
  const errors = ticketChunk.filter((ticket) => ticket.status === "error");
8286
6840
  if (errors.length > 0) {
8287
6841
  const errorDetails = errors.map((e) => ({ message: e.message, details: e.details }));
8288
- logger.debug("[PUSH] Some notifications failed:", errorDetails);
6842
+ logger.logger.debug("[PUSH] Some notifications failed:", errorDetails);
8289
6843
  }
8290
6844
  if (errors.length === ticketChunk.length) {
8291
6845
  throw new Error("All push notifications in chunk failed");
@@ -8294,7 +6848,7 @@ class PushNotificationClient {
8294
6848
  } catch (error) {
8295
6849
  const elapsed = Date.now() - startTime;
8296
6850
  if (elapsed >= timeout) {
8297
- logger.debug("[PUSH] Timeout reached after 5 minutes, giving up on chunk");
6851
+ logger.logger.debug("[PUSH] Timeout reached after 5 minutes, giving up on chunk");
8298
6852
  break;
8299
6853
  }
8300
6854
  attempt++;
@@ -8302,13 +6856,13 @@ class PushNotificationClient {
8302
6856
  const remainingTime = timeout - elapsed;
8303
6857
  const waitTime = Math.min(delay, remainingTime);
8304
6858
  if (waitTime > 0) {
8305
- logger.debug(`[PUSH] Retrying in ${waitTime}ms (attempt ${attempt})`);
6859
+ logger.logger.debug(`[PUSH] Retrying in ${waitTime}ms (attempt ${attempt})`);
8306
6860
  await new Promise((resolve) => setTimeout(resolve, waitTime));
8307
6861
  }
8308
6862
  }
8309
6863
  }
8310
6864
  }
8311
- logger.debug(`Push notifications sent successfully`);
6865
+ logger.logger.debug(`Push notifications sent successfully`);
8312
6866
  }
8313
6867
  /**
8314
6868
  * Increment the badge count on the server and return the new value
@@ -8327,7 +6881,7 @@ class PushNotificationClient {
8327
6881
  );
8328
6882
  return response.data.badgeCount;
8329
6883
  } catch (error) {
8330
- logger.debug("[PUSH] Failed to increment badge count:", error);
6884
+ logger.logger.debug("[PUSH] Failed to increment badge count:", error);
8331
6885
  return 1;
8332
6886
  }
8333
6887
  }
@@ -8338,24 +6892,24 @@ class PushNotificationClient {
8338
6892
  * @param data - Additional data to send with the notification
8339
6893
  */
8340
6894
  sendToAllDevices(title, body, data) {
8341
- logger.debug(`[PUSH] sendToAllDevices called with title: "${title}", body: "${body}"`);
6895
+ logger.logger.debug(`[PUSH] sendToAllDevices called with title: "${title}", body: "${body}"`);
8342
6896
  (async () => {
8343
6897
  try {
8344
- logger.debug("[PUSH] Fetching push tokens and incrementing badge...");
6898
+ logger.logger.debug("[PUSH] Fetching push tokens and incrementing badge...");
8345
6899
  const [tokens, badgeCount] = await Promise.all([
8346
6900
  this.fetchPushTokens(),
8347
6901
  this.incrementBadgeCount()
8348
6902
  ]);
8349
- logger.debug(`[PUSH] Fetched ${tokens.length} push tokens, badge: ${badgeCount}`);
6903
+ logger.logger.debug(`[PUSH] Fetched ${tokens.length} push tokens, badge: ${badgeCount}`);
8350
6904
  tokens.forEach((token, index) => {
8351
- logger.debug(`[PUSH] Using token ${index + 1}: id=${token.id}`);
6905
+ logger.logger.debug(`[PUSH] Using token ${index + 1}: id=${token.id}`);
8352
6906
  });
8353
6907
  if (tokens.length === 0) {
8354
- logger.debug("No push tokens found for user");
6908
+ logger.logger.debug("No push tokens found for user");
8355
6909
  return;
8356
6910
  }
8357
6911
  const messages = tokens.map((token, index) => {
8358
- logger.debug(`[PUSH] Creating message ${index + 1} for token`);
6912
+ logger.logger.debug(`[PUSH] Creating message ${index + 1} for token`);
8359
6913
  return {
8360
6914
  to: token.token,
8361
6915
  title,
@@ -8367,43 +6921,16 @@ class PushNotificationClient {
8367
6921
  badge: badgeCount
8368
6922
  };
8369
6923
  });
8370
- logger.debug(`[PUSH] Sending ${messages.length} push notifications...`);
6924
+ logger.logger.debug(`[PUSH] Sending ${messages.length} push notifications...`);
8371
6925
  await this.sendPushNotifications(messages);
8372
- logger.debug("[PUSH] Push notifications sent successfully");
6926
+ logger.logger.debug("[PUSH] Push notifications sent successfully");
8373
6927
  } catch (error) {
8374
- logger.debug("[PUSH] Error sending to all devices:", error);
6928
+ logger.logger.debug("[PUSH] Error sending to all devices:", error);
8375
6929
  }
8376
6930
  })();
8377
6931
  }
8378
6932
  }
8379
6933
 
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
6934
  function startOfflineReconnection(config) {
8408
6935
  let reconnected = false;
8409
6936
  let session = null;
@@ -8428,16 +6955,16 @@ function startOfflineReconnection(config) {
8428
6955
  if (cancelled) return;
8429
6956
  reconnected = true;
8430
6957
  config.onNotify("\u2705 Reconnected! Session syncing in background.");
8431
- logger.debug("[OfflineReconnection] Successfully reconnected");
6958
+ logger.logger.debug("[OfflineReconnection] Successfully reconnected");
8432
6959
  } catch (e) {
8433
6960
  if (axios.isAxiosError(e) && e.response?.status === 401) {
8434
- logger.debug("[OfflineReconnection] Authentication error, stopping retries");
6961
+ logger.logger.debug("[OfflineReconnection] Authentication error, stopping retries");
8435
6962
  config.onNotify("\u274C Authentication failed. Please re-authenticate with `happy auth`.");
8436
6963
  return;
8437
6964
  }
8438
6965
  failureCount++;
8439
- const delay = exponentialBackoffDelay(failureCount, 5e3, 6e4, 10);
8440
- logger.debug(`[OfflineReconnection] Attempt ${failureCount} failed, retrying in ${delay}ms`);
6966
+ const delay = time.exponentialBackoffDelay(failureCount, 5e3, 6e4, 10);
6967
+ logger.logger.debug(`[OfflineReconnection] Attempt ${failureCount} failed, retrying in ${delay}ms`);
8441
6968
  if (!cancelled) {
8442
6969
  timeoutId = setTimeout(attemptReconnect, delay);
8443
6970
  }
@@ -8537,7 +7064,7 @@ class ApiClient {
8537
7064
  pushClient;
8538
7065
  constructor(credential) {
8539
7066
  this.credential = credential;
8540
- this.pushClient = new PushNotificationClient(credential.token, configuration.serverUrl);
7067
+ this.pushClient = new PushNotificationClient(credential.token, logger.configuration.serverUrl);
8541
7068
  }
8542
7069
  /**
8543
7070
  * Create a new session or load existing one with the given tag
@@ -8547,9 +7074,9 @@ class ApiClient {
8547
7074
  let encryptionKey;
8548
7075
  let encryptionVariant;
8549
7076
  if (this.credential.encryption.type === "dataKey") {
8550
- encryptionKey = getRandomBytes(32);
7077
+ encryptionKey = logger.getRandomBytes(32);
8551
7078
  encryptionVariant = "dataKey";
8552
- let encryptedDataKey = libsodiumEncryptForPublicKey(encryptionKey, this.credential.encryption.publicKey);
7079
+ let encryptedDataKey = logger.libsodiumEncryptForPublicKey(encryptionKey, this.credential.encryption.publicKey);
8553
7080
  dataEncryptionKey = new Uint8Array(encryptedDataKey.length + 1);
8554
7081
  dataEncryptionKey.set([0], 0);
8555
7082
  dataEncryptionKey.set(encryptedDataKey, 1);
@@ -8559,12 +7086,12 @@ class ApiClient {
8559
7086
  }
8560
7087
  try {
8561
7088
  const response = await axios.post(
8562
- `${configuration.serverUrl}/v1/sessions`,
7089
+ `${logger.configuration.serverUrl}/v1/sessions`,
8563
7090
  {
8564
7091
  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
7092
+ metadata: logger.encodeBase64(logger.encrypt(encryptionKey, encryptionVariant, opts.metadata)),
7093
+ agentState: opts.state ? logger.encodeBase64(logger.encrypt(encryptionKey, encryptionVariant, opts.state)) : null,
7094
+ dataEncryptionKey: dataEncryptionKey ? logger.encodeBase64(dataEncryptionKey) : null
8568
7095
  },
8569
7096
  {
8570
7097
  headers: {
@@ -8575,25 +7102,25 @@ class ApiClient {
8575
7102
  // 1 minute timeout for very bad network connections
8576
7103
  }
8577
7104
  );
8578
- logger.debug(`Session created/loaded: ${response.data.session.id} (tag: ${opts.tag})`);
7105
+ logger.logger.debug(`Session created/loaded: ${response.data.session.id} (tag: ${opts.tag})`);
8579
7106
  let raw = response.data.session;
8580
7107
  let session = {
8581
7108
  id: raw.id,
8582
7109
  seq: raw.seq,
8583
- metadata: decrypt(encryptionKey, encryptionVariant, decodeBase64(raw.metadata)),
7110
+ metadata: logger.decrypt(encryptionKey, encryptionVariant, logger.decodeBase64(raw.metadata)),
8584
7111
  metadataVersion: raw.metadataVersion,
8585
- agentState: raw.agentState ? decrypt(encryptionKey, encryptionVariant, decodeBase64(raw.agentState)) : null,
7112
+ agentState: raw.agentState ? logger.decrypt(encryptionKey, encryptionVariant, logger.decodeBase64(raw.agentState)) : null,
8586
7113
  agentStateVersion: raw.agentStateVersion,
8587
7114
  encryptionKey,
8588
7115
  encryptionVariant
8589
7116
  };
8590
7117
  if (this.credential.encryption.type === "dataKey") {
8591
- cacheSessionKey(raw.id, encryptionKey, this.credential.encryption.machineKey).catch(() => {
7118
+ sessionKeyCache.cacheSessionKey(raw.id, encryptionKey, this.credential.encryption.machineKey).catch(() => {
8592
7119
  });
8593
7120
  }
8594
7121
  return session;
8595
7122
  } catch (error) {
8596
- logger.debug("[API] [ERROR] Failed to get or create session:", error);
7123
+ logger.logger.debug("[API] [ERROR] Failed to get or create session:", error);
8597
7124
  if (error && typeof error === "object" && "code" in error) {
8598
7125
  const errorCode = error.code;
8599
7126
  if (isNetworkError(errorCode)) {
@@ -8601,7 +7128,7 @@ class ApiClient {
8601
7128
  operation: "Session creation",
8602
7129
  caller: "api.getOrCreateSession",
8603
7130
  errorCode,
8604
- url: `${configuration.serverUrl}/v1/sessions`
7131
+ url: `${logger.configuration.serverUrl}/v1/sessions`
8605
7132
  });
8606
7133
  return null;
8607
7134
  }
@@ -8611,7 +7138,7 @@ class ApiClient {
8611
7138
  connectionState.fail({
8612
7139
  operation: "Session creation",
8613
7140
  errorCode: "404",
8614
- url: `${configuration.serverUrl}/v1/sessions`
7141
+ url: `${logger.configuration.serverUrl}/v1/sessions`
8615
7142
  });
8616
7143
  return null;
8617
7144
  }
@@ -8621,7 +7148,7 @@ class ApiClient {
8621
7148
  connectionState.fail({
8622
7149
  operation: "Session creation",
8623
7150
  errorCode: String(status),
8624
- url: `${configuration.serverUrl}/v1/sessions`,
7151
+ url: `${logger.configuration.serverUrl}/v1/sessions`,
8625
7152
  details: ["Server encountered an error, will retry automatically"]
8626
7153
  });
8627
7154
  return null;
@@ -8641,7 +7168,7 @@ class ApiClient {
8641
7168
  if (this.credential.encryption.type === "dataKey") {
8642
7169
  encryptionVariant = "dataKey";
8643
7170
  encryptionKey = this.credential.encryption.machineKey;
8644
- let encryptedDataKey = libsodiumEncryptForPublicKey(this.credential.encryption.machineKey, this.credential.encryption.publicKey);
7171
+ let encryptedDataKey = logger.libsodiumEncryptForPublicKey(this.credential.encryption.machineKey, this.credential.encryption.publicKey);
8645
7172
  dataEncryptionKey = new Uint8Array(encryptedDataKey.length + 1);
8646
7173
  dataEncryptionKey.set([0], 0);
8647
7174
  dataEncryptionKey.set(encryptedDataKey, 1);
@@ -8660,12 +7187,12 @@ class ApiClient {
8660
7187
  });
8661
7188
  try {
8662
7189
  const response = await axios.post(
8663
- `${configuration.serverUrl}/v1/machines`,
7190
+ `${logger.configuration.serverUrl}/v1/machines`,
8664
7191
  {
8665
7192
  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,
7193
+ metadata: logger.encodeBase64(logger.encrypt(encryptionKey, encryptionVariant, opts.metadata)),
7194
+ daemonState: opts.daemonState ? logger.encodeBase64(logger.encrypt(encryptionKey, encryptionVariant, opts.daemonState)) : void 0,
7195
+ dataEncryptionKey: dataEncryptionKey ? logger.encodeBase64(dataEncryptionKey) : void 0,
8669
7196
  // Plaintext label so other clients can render a device list without
8670
7197
  // holding this machine's key. Everything else stays encrypted.
8671
7198
  displayName: opts.metadata.displayName || opts.metadata.host || void 0,
@@ -8683,14 +7210,14 @@ class ApiClient {
8683
7210
  }
8684
7211
  );
8685
7212
  const raw = response.data.machine;
8686
- logger.debug(`[API] Machine ${opts.machineId} registered/updated with server`);
7213
+ logger.logger.debug(`[API] Machine ${opts.machineId} registered/updated with server`);
8687
7214
  const machine = {
8688
7215
  id: raw.id,
8689
7216
  encryptionKey,
8690
7217
  encryptionVariant,
8691
- metadata: raw.metadata ? decrypt(encryptionKey, encryptionVariant, decodeBase64(raw.metadata)) : null,
7218
+ metadata: raw.metadata ? logger.decrypt(encryptionKey, encryptionVariant, logger.decodeBase64(raw.metadata)) : null,
8692
7219
  metadataVersion: raw.metadataVersion || 0,
8693
- daemonState: raw.daemonState ? decrypt(encryptionKey, encryptionVariant, decodeBase64(raw.daemonState)) : null,
7220
+ daemonState: raw.daemonState ? logger.decrypt(encryptionKey, encryptionVariant, logger.decodeBase64(raw.daemonState)) : null,
8694
7221
  daemonStateVersion: raw.daemonStateVersion || 0
8695
7222
  };
8696
7223
  return machine;
@@ -8700,7 +7227,7 @@ class ApiClient {
8700
7227
  operation: "Machine registration",
8701
7228
  caller: "api.getOrCreateMachine",
8702
7229
  errorCode: error.code,
8703
- url: `${configuration.serverUrl}/v1/machines`
7230
+ url: `${logger.configuration.serverUrl}/v1/machines`
8704
7231
  });
8705
7232
  return createMinimalMachine();
8706
7233
  }
@@ -8728,7 +7255,7 @@ class ApiClient {
8728
7255
  connectionState.fail({
8729
7256
  operation: "Machine registration",
8730
7257
  errorCode: String(status),
8731
- url: `${configuration.serverUrl}/v1/machines`,
7258
+ url: `${logger.configuration.serverUrl}/v1/machines`,
8732
7259
  details: ["Server encountered an error, will retry automatically"]
8733
7260
  });
8734
7261
  return createMinimalMachine();
@@ -8737,7 +7264,7 @@ class ApiClient {
8737
7264
  connectionState.fail({
8738
7265
  operation: "Machine registration",
8739
7266
  errorCode: "404",
8740
- url: `${configuration.serverUrl}/v1/machines`
7267
+ url: `${logger.configuration.serverUrl}/v1/machines`
8741
7268
  });
8742
7269
  return createMinimalMachine();
8743
7270
  }
@@ -8759,7 +7286,7 @@ class ApiClient {
8759
7286
  */
8760
7287
  async reportOrchestratorExecutionStart(opts) {
8761
7288
  await axios.post(
8762
- `${configuration.serverUrl}/v1/orchestrator/executions/${opts.executionId}/start`,
7289
+ `${logger.configuration.serverUrl}/v1/orchestrator/executions/${opts.executionId}/start`,
8763
7290
  {
8764
7291
  dispatchToken: opts.dispatchToken,
8765
7292
  startedAt: opts.startedAt,
@@ -8779,7 +7306,7 @@ class ApiClient {
8779
7306
  */
8780
7307
  async reportOrchestratorExecutionFinish(opts) {
8781
7308
  await axios.post(
8782
- `${configuration.serverUrl}/v1/orchestrator/executions/${opts.executionId}/finish`,
7309
+ `${logger.configuration.serverUrl}/v1/orchestrator/executions/${opts.executionId}/finish`,
8783
7310
  {
8784
7311
  dispatchToken: opts.dispatchToken,
8785
7312
  status: opts.status,
@@ -8808,7 +7335,7 @@ class ApiClient {
8808
7335
  async registerVendorToken(vendor, apiKey) {
8809
7336
  try {
8810
7337
  const response = await axios.post(
8811
- `${configuration.serverUrl}/v1/connect/${vendor}/register`,
7338
+ `${logger.configuration.serverUrl}/v1/connect/${vendor}/register`,
8812
7339
  {
8813
7340
  token: JSON.stringify(apiKey)
8814
7341
  },
@@ -8823,9 +7350,9 @@ class ApiClient {
8823
7350
  if (response.status !== 200 && response.status !== 201) {
8824
7351
  throw new Error(`Server returned status ${response.status}`);
8825
7352
  }
8826
- logger.debug(`[API] Vendor token for ${vendor} registered successfully`);
7353
+ logger.logger.debug(`[API] Vendor token for ${vendor} registered successfully`);
8827
7354
  } catch (error) {
8828
- logger.debug(`[API] [ERROR] Failed to register vendor token:`, error);
7355
+ logger.logger.debug(`[API] [ERROR] Failed to register vendor token:`, error);
8829
7356
  throw new Error(`Failed to register vendor token: ${error instanceof Error ? error.message : "Unknown error"}`);
8830
7357
  }
8831
7358
  }
@@ -8838,7 +7365,7 @@ class ApiClient {
8838
7365
  async listMemories() {
8839
7366
  try {
8840
7367
  const response = await axios.get(
8841
- `${configuration.serverUrl}/v1/memory`,
7368
+ `${logger.configuration.serverUrl}/v1/memory`,
8842
7369
  {
8843
7370
  headers: {
8844
7371
  "Authorization": `Bearer ${this.credential.token}`,
@@ -8852,7 +7379,7 @@ class ApiClient {
8852
7379
  }
8853
7380
  return response.data.memories;
8854
7381
  } catch (err) {
8855
- logger.debug("[API] listMemories failed (continuing without memory injection):", err);
7382
+ logger.logger.debug("[API] listMemories failed (continuing without memory injection):", err);
8856
7383
  return [];
8857
7384
  }
8858
7385
  }
@@ -8863,7 +7390,7 @@ class ApiClient {
8863
7390
  async getVendorToken(vendor) {
8864
7391
  try {
8865
7392
  const response = await axios.get(
8866
- `${configuration.serverUrl}/v1/connect/${vendor}/token`,
7393
+ `${logger.configuration.serverUrl}/v1/connect/${vendor}/token`,
8867
7394
  {
8868
7395
  headers: {
8869
7396
  "Authorization": `Bearer ${this.credential.token}`,
@@ -8873,13 +7400,13 @@ class ApiClient {
8873
7400
  }
8874
7401
  );
8875
7402
  if (response.status === 404) {
8876
- logger.debug(`[API] No vendor token found for ${vendor}`);
7403
+ logger.logger.debug(`[API] No vendor token found for ${vendor}`);
8877
7404
  return null;
8878
7405
  }
8879
7406
  if (response.status !== 200) {
8880
7407
  throw new Error(`Server returned status ${response.status}`);
8881
7408
  }
8882
- logger.debug(`[API] Raw vendor token response:`, {
7409
+ logger.logger.debug(`[API] Raw vendor token response:`, {
8883
7410
  status: response.status,
8884
7411
  dataKeys: Object.keys(response.data || {}),
8885
7412
  hasToken: "token" in (response.data || {}),
@@ -8891,153 +7418,62 @@ class ApiClient {
8891
7418
  try {
8892
7419
  tokenData = JSON.parse(response.data.token);
8893
7420
  } catch (parseError) {
8894
- logger.debug(`[API] Failed to parse token as JSON, using as string:`, parseError);
7421
+ logger.logger.debug(`[API] Failed to parse token as JSON, using as string:`, parseError);
8895
7422
  tokenData = response.data.token;
8896
7423
  }
8897
7424
  } else if (response.data.token !== null) {
8898
7425
  tokenData = response.data.token;
8899
7426
  } else {
8900
- logger.debug(`[API] Token is null for ${vendor}, treating as not found`);
7427
+ logger.logger.debug(`[API] Token is null for ${vendor}, treating as not found`);
8901
7428
  return null;
8902
7429
  }
8903
7430
  } else if (response.data && typeof response.data === "object") {
8904
7431
  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`);
7432
+ logger.logger.debug(`[API] Response contains only null token for ${vendor}, treating as not found`);
8906
7433
  return null;
8907
7434
  }
8908
7435
  tokenData = response.data;
8909
7436
  }
8910
7437
  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}`);
7438
+ logger.logger.debug(`[API] Token data is null for ${vendor}`);
8912
7439
  return null;
8913
7440
  }
8914
- logger.debug(`[API] Vendor token for ${vendor} retrieved successfully`, {
7441
+ logger.logger.debug(`[API] Vendor token for ${vendor} retrieved successfully`, {
8915
7442
  tokenDataType: typeof tokenData,
8916
7443
  tokenDataKeys: tokenData && typeof tokenData === "object" ? Object.keys(tokenData) : "not an object"
8917
7444
  });
8918
7445
  return tokenData;
8919
7446
  } catch (error) {
8920
7447
  if (error.response?.status === 404) {
8921
- logger.debug(`[API] No vendor token found for ${vendor}`);
7448
+ logger.logger.debug(`[API] No vendor token found for ${vendor}`);
8922
7449
  return null;
8923
7450
  }
8924
- logger.debug(`[API] [ERROR] Failed to get vendor token:`, error);
7451
+ logger.logger.debug(`[API] [ERROR] Failed to get vendor token:`, error);
8925
7452
  return null;
8926
7453
  }
8927
7454
  }
8928
7455
  }
8929
7456
 
8930
7457
  var api = /*#__PURE__*/Object.freeze({
8931
- __proto__: null,
8932
- ApiClient: ApiClient
7458
+ __proto__: null,
7459
+ ApiClient: ApiClient
8933
7460
  });
8934
7461
 
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
7462
  exports.ApiClient = ApiClient;
8990
7463
  exports.ApiSessionClient = ApiSessionClient;
8991
7464
  exports.AsyncLock = AsyncLock;
8992
- exports.GEMINI_MODEL_MODES = GEMINI_MODEL_MODES;
8993
7465
  exports.GeminiSessionWriter = GeminiSessionWriter;
8994
7466
  exports.InvalidateSync = InvalidateSync;
8995
- exports.MODEL_MODE_DEFAULT = MODEL_MODE_DEFAULT;
8996
- exports.RawJSONLinesSchema = RawJSONLinesSchema;
8997
- exports.acquireDaemonLock = acquireDaemonLock;
8998
7467
  exports.api = api;
8999
7468
  exports.buildResumeContextFromSessionLog = buildResumeContextFromSessionLog;
9000
- exports.clearCredentials = clearCredentials;
9001
- exports.clearDaemonState = clearDaemonState;
9002
- exports.clearMachineId = clearMachineId;
9003
- exports.configuration = configuration;
9004
7469
  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
7470
  exports.extractUserText = extractUserText;
9014
7471
  exports.findClaudeProjectId = findClaudeProjectId;
9015
7472
  exports.findCodexSessionFile = findCodexSessionFile;
9016
7473
  exports.generateStableUuid = generateStableUuid;
9017
- exports.getLatestDaemonLog = getLatestDaemonLog;
9018
- exports.getProfileEnvironmentVariables = getProfileEnvironmentVariables;
9019
- exports.isDebug = isDebug;
9020
- exports.isModelModeForAgent = isModelModeForAgent;
9021
7474
  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
7475
  exports.readGeminiSessionLog = readGeminiSessionLog;
9033
- exports.readSettings = readSettings;
9034
- exports.releaseDaemonLock = releaseDaemonLock;
9035
7476
  exports.resolveToolsDir = resolveToolsDir;
9036
7477
  exports.saveDiffRecords = saveDiffRecords;
9037
7478
  exports.saveToolOutputRecord = saveToolOutputRecord;
9038
7479
  exports.startOfflineReconnection = startOfflineReconnection;
9039
- exports.updateSettings = updateSettings;
9040
- exports.validateProfileForAgent = validateProfileForAgent;
9041
- exports.writeCredentialsDataKey = writeCredentialsDataKey;
9042
- exports.writeCredentialsLegacy = writeCredentialsLegacy;
9043
- exports.writeDaemonState = writeDaemonState;