@codexhost/cli-linux-arm64 0.11.0 → 0.12.0

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.
@@ -5,9 +5,491 @@ var __export = (target, all) => {
5
5
  __defProp(target, name, { get: all[name], enumerable: true });
6
6
  };
7
7
 
8
+ // ../../harness-discovery/dist/environment.js
9
+ import fs from "node:fs";
10
+ import path from "node:path";
11
+ function targetPath(platform) {
12
+ return platform === "win32" ? path.win32 : path.posix;
13
+ }
14
+ function environmentValue(environment, name) {
15
+ const lowered = name.toLowerCase();
16
+ for (const [key, value] of Object.entries(environment)) {
17
+ if (key.toLowerCase() === lowered)
18
+ return value;
19
+ }
20
+ return void 0;
21
+ }
22
+ function pathDelimiter(platform) {
23
+ return platform === "win32" ? ";" : ":";
24
+ }
25
+ function pathDirectories(environment, platform) {
26
+ return (environmentValue(environment, "PATH") ?? "").split(pathDelimiter(platform)).map((directory) => directory.trim().replace(/^"|"$/gu, "")).filter(Boolean);
27
+ }
28
+ function executableExtensions(command, platform, environment) {
29
+ if (platform !== "win32")
30
+ return [""];
31
+ if (targetPath(platform).extname(command) !== "")
32
+ return [""];
33
+ return (environmentValue(environment, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter(Boolean);
34
+ }
35
+ function isExecutableFile(filePath, platform) {
36
+ try {
37
+ fs.accessSync(filePath, platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK);
38
+ return fs.statSync(filePath).isFile();
39
+ } catch {
40
+ return false;
41
+ }
42
+ }
43
+ function subdirectoryNames(directory) {
44
+ try {
45
+ return fs.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
46
+ } catch {
47
+ return [];
48
+ }
49
+ }
50
+ function newestFirst(names) {
51
+ return [...names].sort((left, right) => right.localeCompare(left, void 0, { numeric: true }));
52
+ }
53
+
54
+ // ../../harness-discovery/dist/invocation.js
55
+ import path2 from "node:path";
56
+ function commandInvocation(command, arguments_, environment, platform = process.platform) {
57
+ const extension = path2.win32.extname(command).toLowerCase();
58
+ if (platform !== "win32" || ![".cmd", ".bat"].includes(extension)) {
59
+ return { command, arguments: [...arguments_], windowsVerbatimArguments: false };
60
+ }
61
+ const quote = (value) => `"${value.replaceAll("%", "%%").replaceAll('"', '""')}"`;
62
+ const commandLine = [command, ...arguments_].map(quote).join(" ");
63
+ return {
64
+ command: environmentValue(environment, "ComSpec") ?? "cmd.exe",
65
+ arguments: ["/d", "/v:off", "/s", "/c", `"${commandLine}"`],
66
+ windowsVerbatimArguments: true
67
+ };
68
+ }
69
+
70
+ // ../../harness-discovery/dist/node-runtime.js
71
+ import path3 from "node:path";
72
+ function withNodeRuntimeOnPath(environment, runtimeExecutable = process.execPath, platform = process.platform) {
73
+ const pathKey = Object.keys(environment).find((name) => name.toLowerCase() === "path") ?? "PATH";
74
+ const delimiter = platform === "win32" ? ";" : ":";
75
+ const runtimeDirectory = path3.dirname(runtimeExecutable);
76
+ const directories = (environment[pathKey] ?? "").split(delimiter).filter(Boolean);
77
+ const equal = platform === "win32" ? (value) => value.toLowerCase() : (value) => value;
78
+ if (!directories.some((directory) => equal(directory) === equal(runtimeDirectory))) {
79
+ directories.push(runtimeDirectory);
80
+ }
81
+ return { ...environment, [pathKey]: directories.join(delimiter) };
82
+ }
83
+
84
+ // ../../harness-discovery/dist/resolve.js
85
+ import os from "node:os";
86
+
87
+ // ../../harness-discovery/dist/version-managers.js
88
+ function versionManagerBinaryDirectories(context) {
89
+ const { platform, environment, home } = context;
90
+ const list = context.subdirectories ?? subdirectoryNames;
91
+ const pathFlavor = targetPath(platform);
92
+ const value = (name) => environmentValue(environment, name);
93
+ const directories = [];
94
+ const versioned = (root, ...tail) => {
95
+ for (const version2 of newestFirst(list(root))) {
96
+ directories.push(pathFlavor.join(root, version2, ...tail));
97
+ }
98
+ };
99
+ if (platform === "win32") {
100
+ const appData = value("APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming");
101
+ const localAppData = value("LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local");
102
+ versioned(pathFlavor.join(appData, "nvm"));
103
+ versioned(value("FNM_DIR") ?? pathFlavor.join(appData, "fnm", "node-versions"), "installation");
104
+ directories.push(pathFlavor.join(localAppData, "Volta", "bin"));
105
+ directories.push(pathFlavor.join(home, ".bun", "bin"));
106
+ const pnpmHome2 = value("PNPM_HOME");
107
+ if (pnpmHome2)
108
+ directories.push(pnpmHome2);
109
+ directories.push(pathFlavor.join(localAppData, "pnpm"));
110
+ return directories;
111
+ }
112
+ versioned(pathFlavor.join(value("NVM_DIR") ?? pathFlavor.join(home, ".nvm"), "versions", "node"), "bin");
113
+ const fnmRoots = [
114
+ value("FNM_DIR"),
115
+ pathFlavor.join(home, ".local", "share", "fnm"),
116
+ pathFlavor.join(home, "Library", "Application Support", "fnm")
117
+ ].filter((root) => root !== void 0);
118
+ for (const root of fnmRoots) {
119
+ versioned(pathFlavor.join(root, "node-versions"), "installation", "bin");
120
+ }
121
+ const voltaHome = value("VOLTA_HOME") ?? pathFlavor.join(home, ".volta");
122
+ versioned(pathFlavor.join(voltaHome, "tools", "image", "node"), "bin");
123
+ directories.push(pathFlavor.join(voltaHome, "bin"));
124
+ const asdfHome = value("ASDF_DATA_DIR") ?? pathFlavor.join(home, ".asdf");
125
+ versioned(pathFlavor.join(asdfHome, "installs", "nodejs"), "bin");
126
+ directories.push(pathFlavor.join(asdfHome, "shims"));
127
+ const nodenvHome = value("NODENV_ROOT") ?? pathFlavor.join(home, ".nodenv");
128
+ versioned(pathFlavor.join(nodenvHome, "versions"), "bin");
129
+ directories.push(pathFlavor.join(nodenvHome, "shims"));
130
+ versioned(pathFlavor.join(value("N_PREFIX") ?? "/usr/local", "n", "versions", "node"), "bin");
131
+ directories.push(pathFlavor.join(home, ".bun", "bin"));
132
+ const pnpmHome = value("PNPM_HOME");
133
+ if (pnpmHome)
134
+ directories.push(pnpmHome);
135
+ directories.push(pathFlavor.join(home, "Library", "pnpm"));
136
+ directories.push(pathFlavor.join(home, ".local", "share", "pnpm"));
137
+ for (const prefix of ["/opt/homebrew/opt", "/usr/local/opt"]) {
138
+ for (const formula of newestFirst(list(prefix).filter((name) => name.startsWith("node@")))) {
139
+ directories.push(pathFlavor.join(prefix, formula, "bin"));
140
+ }
141
+ }
142
+ return directories;
143
+ }
144
+
145
+ // ../../harness-discovery/dist/resolve.js
146
+ var VERSION_MANAGER_ROOTS = "<version-managers>";
147
+ function installRootExtensions(platform) {
148
+ return platform === "win32" ? [".exe", ".cmd"] : [""];
149
+ }
150
+ function resolveHomeDirectory(input) {
151
+ return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
152
+ }
153
+ function templateVariables(environment, platform, home) {
154
+ const pathFlavor = targetPath(platform);
155
+ return {
156
+ HOME: home,
157
+ USERPROFILE: home,
158
+ APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
159
+ LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
160
+ };
161
+ }
162
+ function joinTemplate(platform, value) {
163
+ const pathFlavor = targetPath(platform);
164
+ const segments = value.split("/");
165
+ const head = segments[0] ?? "";
166
+ const tail = segments.slice(1);
167
+ if (head === "")
168
+ return pathFlavor.join(pathFlavor.sep, ...tail);
169
+ return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
170
+ }
171
+ function expandInstallRoot(template, environment, platform, home) {
172
+ const variables = templateVariables(environment, platform, home);
173
+ let unresolved = false;
174
+ const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
175
+ const value = variables[name] ?? environmentValue(environment, name);
176
+ if (value === void 0 || value === "") {
177
+ unresolved = true;
178
+ return "";
179
+ }
180
+ return value;
181
+ });
182
+ return unresolved ? void 0 : joinTemplate(platform, substituted);
183
+ }
184
+ function installRootDirectories(spec, input, dependencies, platform, home) {
185
+ const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
186
+ const directories = [];
187
+ for (const template of templates) {
188
+ if (template === VERSION_MANAGER_ROOTS) {
189
+ directories.push(...versionManagerBinaryDirectories({
190
+ platform,
191
+ environment: input.environment,
192
+ home,
193
+ ...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
194
+ }));
195
+ continue;
196
+ }
197
+ const directory = expandInstallRoot(template, input.environment, platform, home);
198
+ if (directory !== void 0)
199
+ directories.push(directory);
200
+ }
201
+ return directories;
202
+ }
203
+ function harnessCandidates(spec, input, dependencies = {}) {
204
+ const platform = input.platform ?? process.platform;
205
+ const pathFlavor = targetPath(platform);
206
+ const configured = input.command ?? (spec.commandEnvironmentVariable ? environmentValue(input.environment, spec.commandEnvironmentVariable) : void 0);
207
+ const command = configured ?? spec.command;
208
+ if (pathFlavor.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
209
+ return [{ candidate: command, source: "configured" }];
210
+ }
211
+ const candidates = [];
212
+ const extensions = executableExtensions(command, platform, input.environment);
213
+ for (const directory of pathDirectories(input.environment, platform)) {
214
+ for (const extension of extensions) {
215
+ candidates.push({
216
+ candidate: pathFlavor.join(directory, command + extension),
217
+ source: "path"
218
+ });
219
+ }
220
+ }
221
+ if (configured !== void 0)
222
+ return candidates;
223
+ const home = resolveHomeDirectory(input);
224
+ for (const directory of installRootDirectories(spec, input, dependencies, platform, home)) {
225
+ for (const extension of installRootExtensions(platform)) {
226
+ candidates.push({
227
+ candidate: pathFlavor.join(directory, spec.command + extension),
228
+ source: "install-root"
229
+ });
230
+ }
231
+ }
232
+ return candidates;
233
+ }
234
+ function resolveHarnessExecutable(spec, input, dependencies = {}) {
235
+ const platform = input.platform ?? process.platform;
236
+ const isExecutable = dependencies.isExecutable ?? ((candidate) => isExecutableFile(candidate, platform));
237
+ const runnable = spec.runnableCandidate ?? ((candidate) => candidate);
238
+ const context = { platform, isExecutable };
239
+ for (const { candidate, source } of harnessCandidates(spec, input, dependencies)) {
240
+ const executable = runnable(candidate, context);
241
+ if (executable !== void 0 && isExecutable(executable))
242
+ return { executable, source };
243
+ }
244
+ return void 0;
245
+ }
246
+
247
+ // ../../harness-discovery/dist/installation.js
248
+ import { execFile } from "node:child_process";
249
+ import { homedir } from "node:os";
250
+ function runInstallationCommand(command, args, environment, timeout = 3e4) {
251
+ const env = withNodeRuntimeOnPath(environment);
252
+ const invocation = /\.[cm]?js$/i.test(command) ? commandInvocation(process.execPath, [command, ...args], env) : commandInvocation(command, args, env);
253
+ return new Promise((resolve, reject) => {
254
+ const child = execFile(invocation.command, invocation.arguments, {
255
+ env,
256
+ cwd: env.HOME ?? env.USERPROFILE ?? homedir(),
257
+ encoding: "utf8",
258
+ timeout,
259
+ killSignal: "SIGKILL",
260
+ maxBuffer: 1024 * 1024,
261
+ windowsHide: true,
262
+ windowsVerbatimArguments: invocation.windowsVerbatimArguments
263
+ }, (error51, stdout, stderr) => {
264
+ if (error51)
265
+ reject(new Error(error51.killed ? "Harness command timed out" : "Harness command failed; check the native installation and retry"));
266
+ else
267
+ resolve((stdout || stderr).trim());
268
+ });
269
+ child.stdin?.end();
270
+ });
271
+ }
272
+ function installationVersion(value) {
273
+ if (typeof value !== "string" || !/^v?\d+(?:\.\d+){1,3}(?:-[\w.-]+)?(?:\+[\w.-]+)?$/.test(value.trim()))
274
+ throw new Error("Harness returned an invalid version");
275
+ return value.trim().replace(/^v/, "");
276
+ }
277
+ function versionFromOutput(output) {
278
+ return installationVersion(output.match(/\b\d+(?:\.\d+){1,3}(?:-[\w.-]+)?(?:\+[\w.-]+)?\b/)?.[0]);
279
+ }
280
+ function newerInstallationVersion(current, latest) {
281
+ const a = installationVersion(current).replace(/\+.*/, "");
282
+ const b = installationVersion(latest).replace(/\+.*/, "");
283
+ const coreA = a.replace(/-.*/, "").split(".").map(BigInt);
284
+ const coreB = b.replace(/-.*/, "").split(".").map(BigInt);
285
+ for (let i = 0; i < Math.max(coreA.length, coreB.length); i++) {
286
+ if ((coreA[i] ?? 0n) !== (coreB[i] ?? 0n))
287
+ return (coreB[i] ?? 0n) > (coreA[i] ?? 0n);
288
+ }
289
+ const preA = a.includes("-") ? a.slice(a.indexOf("-") + 1).split(".") : [];
290
+ const preB = b.includes("-") ? b.slice(b.indexOf("-") + 1).split(".") : [];
291
+ if (!preA.length || !preB.length)
292
+ return !!preA.length && !preB.length;
293
+ for (let i = 0; i < Math.max(preA.length, preB.length); i++) {
294
+ const x = preA[i];
295
+ const y = preB[i];
296
+ if (x === y)
297
+ continue;
298
+ if (x === void 0 || y === void 0)
299
+ return x === void 0;
300
+ const numericX = /^\d+$/.test(x);
301
+ const numericY = /^\d+$/.test(y);
302
+ if (numericX && numericY) {
303
+ if (BigInt(x) === BigInt(y))
304
+ continue;
305
+ return BigInt(y) > BigInt(x);
306
+ }
307
+ if (numericX !== numericY)
308
+ return numericX;
309
+ return y > x;
310
+ }
311
+ return false;
312
+ }
313
+ function createInstallationManager(options) {
314
+ let checking;
315
+ let updating;
316
+ const check2 = () => checking ??= options.check().finally(() => {
317
+ checking = void 0;
318
+ });
319
+ return (action) => {
320
+ if (updating)
321
+ return updating;
322
+ if (action === "check")
323
+ return check2();
324
+ updating = (async () => {
325
+ const before = await check2();
326
+ if (!before.updateAvailable)
327
+ return before;
328
+ if (!before.canUpdate)
329
+ throw new Error(before.message ?? "This installation cannot be updated automatically");
330
+ await options.update(before);
331
+ const after = await check2();
332
+ if (after.currentVersion === before.currentVersion)
333
+ throw new Error("The Harness version did not change; check the native updater and retry");
334
+ return after;
335
+ })().finally(() => {
336
+ updating = void 0;
337
+ });
338
+ return updating;
339
+ };
340
+ }
341
+ async function fetchInstallationText(url2) {
342
+ const request = async () => {
343
+ const response = await fetch(url2, { signal: AbortSignal.timeout(15e3) });
344
+ if (!response.ok)
345
+ throw new Error("Could not check the latest Harness version");
346
+ return response.text();
347
+ };
348
+ try {
349
+ return await request();
350
+ } catch (error51) {
351
+ if (error51 instanceof DOMException && (error51.name === "AbortError" || error51.name === "TimeoutError"))
352
+ throw error51;
353
+ return request();
354
+ }
355
+ }
356
+
357
+ // ../../harness-discovery/dist/npm-installation.js
358
+ import { readFile, realpath } from "node:fs/promises";
359
+ import path4 from "node:path";
360
+ function referencesNpmBin(shim, name, bin) {
361
+ if (bin.includes(".."))
362
+ return false;
363
+ const target = `node_modules/${name}/${bin.replace(/^\.\//, "")}`.toLowerCase();
364
+ const text = shim.replaceAll("\\", "/").toLowerCase();
365
+ return text.includes(`%dp0%/${target}"`) || text.includes(`%~dp0/${target}"`);
366
+ }
367
+ async function npmInstallation(command, packages, environment) {
368
+ let selected = await realpath(command);
369
+ if (process.platform === "win32" && /\.(cmd|bat)$/i.test(selected)) {
370
+ const shim = (await readFile(selected, "utf8")).replaceAll("\\", "/");
371
+ const root = path4.dirname(selected);
372
+ for (const name of packages) {
373
+ const directory2 = path4.join(root, "node_modules", ...name.split("/"));
374
+ const metadata = await readFile(path4.join(directory2, "package.json"), "utf8").then((text) => JSON.parse(text)).catch(() => null);
375
+ const bins = typeof metadata?.bin === "string" ? [metadata.bin] : Object.values(metadata?.bin ?? {});
376
+ const bin = bins.find((entry) => referencesNpmBin(shim, name, entry));
377
+ if (bin) {
378
+ selected = await realpath(path4.join(directory2, bin));
379
+ break;
380
+ }
381
+ }
382
+ }
383
+ let directory = path4.dirname(selected);
384
+ for (let depth = 0; depth < 8; depth++) {
385
+ const metadata = await readFile(path4.join(directory, "package.json"), "utf8").then((text) => JSON.parse(text)).catch(() => null);
386
+ if (metadata?.name && packages.includes(metadata.name)) {
387
+ const name = metadata.name;
388
+ const currentVersion = installationVersion(metadata.version);
389
+ const segments = name.split("/");
390
+ let modules = directory;
391
+ for (let index = 0; index < segments.length; index++)
392
+ modules = path4.dirname(modules);
393
+ const prefix = process.platform === "win32" ? path4.dirname(modules) : path4.dirname(path4.dirname(modules));
394
+ const globalRoot = process.platform === "win32" ? path4.join(prefix, "node_modules") : path4.join(prefix, "lib", "node_modules");
395
+ const env = withNodeRuntimeOnPath(environment);
396
+ const npm = resolveHarnessExecutable({ id: "npm", command: "npm", installRoots: { posix: [], windows: [] } }, { environment: env });
397
+ let globalInstall = modules === globalRoot;
398
+ if (process.platform === "win32") {
399
+ const project = (await Promise.all(["package.json", "package-lock.json", "npm-shrinkwrap.json"].map((file2) => readFile(path4.join(prefix, file2), "utf8").then(() => true, (error51) => error51.code !== "ENOENT")))).some(Boolean);
400
+ const bins = typeof metadata.bin === "string" ? { [name.split("/").at(-1) ?? name]: metadata.bin } : metadata.bin ?? {};
401
+ const launchers = await Promise.all(Object.entries(bins).map(async ([bin, entry]) => {
402
+ if (path4.basename(bin) !== bin || entry.includes(".."))
403
+ return false;
404
+ const target = await realpath(path4.join(directory, entry)).catch(() => "");
405
+ if (target.toLowerCase() !== selected.toLowerCase())
406
+ return false;
407
+ const shim = await readFile(path4.join(prefix, `${bin}.cmd`), "utf8").catch(() => "");
408
+ return referencesNpmBin(shim, name, entry);
409
+ }));
410
+ globalInstall = globalInstall && !project && launchers.some(Boolean);
411
+ }
412
+ const canUpdate = globalInstall && !!npm;
413
+ return {
414
+ prefix,
415
+ currentVersion,
416
+ canUpdate,
417
+ latest: async () => {
418
+ const data = JSON.parse(await fetchInstallationText(`https://registry.npmjs.org/${encodeURIComponent(name)}/latest`));
419
+ return installationVersion(data.version);
420
+ },
421
+ update: async (version2) => {
422
+ if (!canUpdate || !npm)
423
+ throw new Error("Use the original package manager to update this installation");
424
+ await runInstallationCommand(npm.executable, ["install", "--global", "--prefix", prefix, `${name}@${installationVersion(version2)}`], env, 3e5);
425
+ }
426
+ };
427
+ }
428
+ const parent = path4.dirname(directory);
429
+ if (parent === directory)
430
+ break;
431
+ directory = parent;
432
+ }
433
+ return null;
434
+ }
435
+
436
+ // ../../harness-discovery/dist/installer.js
437
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
438
+ import { tmpdir } from "node:os";
439
+ import { join } from "node:path";
440
+ function createHarnessInstaller(environment, source) {
441
+ return async () => {
442
+ if (!["darwin", "linux", "win32"].includes(process.platform))
443
+ throw new Error("Unsupported installation platform");
444
+ const env = withNodeRuntimeOnPath(environment);
445
+ if ("npm" in source) {
446
+ const npm = resolveHarnessExecutable({
447
+ id: "npm",
448
+ command: "npm",
449
+ installRoots: {
450
+ posix: [
451
+ "~/.npm-global/bin",
452
+ "~/.local/bin",
453
+ VERSION_MANAGER_ROOTS,
454
+ "/opt/homebrew/bin",
455
+ "/usr/local/bin",
456
+ "/usr/bin"
457
+ ],
458
+ windows: [
459
+ "${APPDATA}/npm",
460
+ VERSION_MANAGER_ROOTS,
461
+ "${ProgramFiles}/nodejs",
462
+ "${LOCALAPPDATA}/Programs/nodejs"
463
+ ]
464
+ }
465
+ }, { environment: env });
466
+ if (!npm)
467
+ throw new Error("Install Node.js and npm first");
468
+ await runInstallationCommand(npm.executable, ["install", "--global", source.npm], {
469
+ ...env,
470
+ ...source.allowScripts ? { npm_config_allow_scripts: source.allowScripts } : {}
471
+ }, 6e5);
472
+ return;
473
+ }
474
+ const windows = process.platform === "win32";
475
+ const url2 = windows ? source.windows : source.posix;
476
+ if (new URL(url2).protocol !== "https:")
477
+ throw new Error("Installer requires HTTPS");
478
+ const script = await fetchInstallationText(url2);
479
+ const directory = await mkdtemp(join(tmpdir(), "codexhost-installer-"));
480
+ try {
481
+ const file2 = join(directory, windows ? "install.ps1" : "install.sh");
482
+ await writeFile(file2, script, { mode: 384 });
483
+ await runInstallationCommand(windows ? "powershell.exe" : source.shell ?? "bash", windows ? ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", file2] : [file2], env, 6e5);
484
+ } finally {
485
+ await rm(directory, { recursive: true, force: true });
486
+ }
487
+ };
488
+ }
489
+
8
490
  // dist/kimi-adapter.js
9
- import { readFile as readFile5 } from "node:fs/promises";
10
- import path8 from "node:path";
491
+ import { readFile as readFile6 } from "node:fs/promises";
492
+ import path9 from "node:path";
11
493
  import { isDeepStrictEqual } from "node:util";
12
494
 
13
495
  // ../../../node_modules/zod/v4/classic/external.js
@@ -776,10 +1258,10 @@ function mergeDefs(...defs) {
776
1258
  function cloneDef(schema) {
777
1259
  return mergeDefs(schema._zod.def);
778
1260
  }
779
- function getElementAtPath(obj, path9) {
780
- if (!path9)
1261
+ function getElementAtPath(obj, path10) {
1262
+ if (!path10)
781
1263
  return obj;
782
- return path9.reduce((acc, key) => acc?.[key], obj);
1264
+ return path10.reduce((acc, key) => acc?.[key], obj);
783
1265
  }
784
1266
  function promiseAllObject(promisesObj) {
785
1267
  const keys = Object.keys(promisesObj);
@@ -1188,11 +1670,11 @@ function explicitlyAborted(x, startIndex = 0) {
1188
1670
  }
1189
1671
  return false;
1190
1672
  }
1191
- function prefixIssues(path9, issues) {
1673
+ function prefixIssues(path10, issues) {
1192
1674
  return issues.map((iss) => {
1193
1675
  var _a3;
1194
1676
  (_a3 = iss).path ?? (_a3.path = []);
1195
- iss.path.unshift(path9);
1677
+ iss.path.unshift(path10);
1196
1678
  return iss;
1197
1679
  });
1198
1680
  }
@@ -1339,16 +1821,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
1339
1821
  }
1340
1822
  function formatError(error51, mapper = (issue2) => issue2.message) {
1341
1823
  const fieldErrors = { _errors: [] };
1342
- const processError = (error52, path9 = []) => {
1824
+ const processError = (error52, path10 = []) => {
1343
1825
  for (const issue2 of error52.issues) {
1344
1826
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1345
- issue2.errors.map((issues) => processError({ issues }, [...path9, ...issue2.path]));
1827
+ issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
1346
1828
  } else if (issue2.code === "invalid_key") {
1347
- processError({ issues: issue2.issues }, [...path9, ...issue2.path]);
1829
+ processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
1348
1830
  } else if (issue2.code === "invalid_element") {
1349
- processError({ issues: issue2.issues }, [...path9, ...issue2.path]);
1831
+ processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
1350
1832
  } else {
1351
- const fullpath = [...path9, ...issue2.path];
1833
+ const fullpath = [...path10, ...issue2.path];
1352
1834
  if (fullpath.length === 0) {
1353
1835
  fieldErrors._errors.push(mapper(issue2));
1354
1836
  } else {
@@ -1375,17 +1857,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
1375
1857
  }
1376
1858
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
1377
1859
  const result = { errors: [] };
1378
- const processError = (error52, path9 = []) => {
1860
+ const processError = (error52, path10 = []) => {
1379
1861
  var _a3, _b;
1380
1862
  for (const issue2 of error52.issues) {
1381
1863
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1382
- issue2.errors.map((issues) => processError({ issues }, [...path9, ...issue2.path]));
1864
+ issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
1383
1865
  } else if (issue2.code === "invalid_key") {
1384
- processError({ issues: issue2.issues }, [...path9, ...issue2.path]);
1866
+ processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
1385
1867
  } else if (issue2.code === "invalid_element") {
1386
- processError({ issues: issue2.issues }, [...path9, ...issue2.path]);
1868
+ processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
1387
1869
  } else {
1388
- const fullpath = [...path9, ...issue2.path];
1870
+ const fullpath = [...path10, ...issue2.path];
1389
1871
  if (fullpath.length === 0) {
1390
1872
  result.errors.push(mapper(issue2));
1391
1873
  continue;
@@ -1417,8 +1899,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
1417
1899
  }
1418
1900
  function toDotPath(_path) {
1419
1901
  const segs = [];
1420
- const path9 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1421
- for (const seg of path9) {
1902
+ const path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1903
+ for (const seg of path10) {
1422
1904
  if (typeof seg === "number")
1423
1905
  segs.push(`[${seg}]`);
1424
1906
  else if (typeof seg === "symbol")
@@ -14110,13 +14592,13 @@ function resolveRef(ref, ctx) {
14110
14592
  if (!ref.startsWith("#")) {
14111
14593
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14112
14594
  }
14113
- const path9 = ref.slice(1).split("/").filter(Boolean);
14114
- if (path9.length === 0) {
14595
+ const path10 = ref.slice(1).split("/").filter(Boolean);
14596
+ if (path10.length === 0) {
14115
14597
  return ctx.rootSchema;
14116
14598
  }
14117
14599
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14118
- if (path9[0] === defsKey) {
14119
- const key = path9[1];
14600
+ if (path10[0] === defsKey) {
14601
+ const key = path10[1];
14120
14602
  if (!key || !ctx.defs[key]) {
14121
14603
  throw new Error(`Reference not found: ${ref}`);
14122
14604
  }
@@ -14610,6 +15092,7 @@ var CONSOLE_HOST_METHODS = Object.freeze([
14610
15092
  "codexhost/harness/display-settings/get",
14611
15093
  "codexhost/harness/display-settings/set",
14612
15094
  "codexhost/harness/inspect",
15095
+ "codexhost/harness/installation",
14613
15096
  "codexhost/harness/launch-settings/get",
14614
15097
  "codexhost/harness/launch-settings/set",
14615
15098
  "codexhost/harness/web-ui/open",
@@ -15256,14 +15739,17 @@ var harnessLaunchSettingsSchema = external_exports.object({
15256
15739
  // ../../shared-contracts/dist/harness-installation.js
15257
15740
  var harnessInstallationParamsSchema = external_exports.object({
15258
15741
  harnessId: harnessIdSchema,
15259
- action: external_exports.enum(["check", "update"])
15742
+ action: external_exports.enum(["check", "update", "install"])
15260
15743
  }).strict();
15261
15744
  var harnessInstallationStateSchema = external_exports.object({
15262
15745
  currentVersion: external_exports.string().min(1).max(128),
15263
15746
  latestVersion: external_exports.string().min(1).max(128),
15264
15747
  updateAvailable: external_exports.boolean(),
15265
15748
  canUpdate: external_exports.boolean(),
15266
- message: external_exports.string().max(2048).optional()
15749
+ // Adapter-owned diagnostic text; UI uses messageCode rather than displaying it verbatim.
15750
+ message: external_exports.string().max(2048).optional(),
15751
+ messageCode: external_exports.string().min(1).max(128).optional(),
15752
+ latestVersionKind: external_exports.enum(["unknown", "tracking-branch"]).optional()
15267
15753
  }).strict();
15268
15754
 
15269
15755
  // ../../shared-contracts/dist/codex-accounts.js
@@ -15565,6 +16051,38 @@ var updateStatusResultSchema = external_exports.strictObject({
15565
16051
  status: updateStatusSchema.nullable()
15566
16052
  });
15567
16053
 
16054
+ // ../../shared-contracts/dist/remote-runtime.js
16055
+ var remoteUpdatePhaseSchema = external_exports.enum([
16056
+ "idle",
16057
+ "installing",
16058
+ "restarting",
16059
+ "succeeded",
16060
+ "failed"
16061
+ ]);
16062
+ var runtimeStatusSchema = external_exports.object({
16063
+ runningVersion: external_exports.string().nullable(),
16064
+ installedVersion: external_exports.string().nullable(),
16065
+ restartRequired: external_exports.boolean(),
16066
+ remote: external_exports.boolean(),
16067
+ updateSupported: external_exports.boolean(),
16068
+ update: external_exports.object({
16069
+ phase: remoteUpdatePhaseSchema,
16070
+ targetVersion: external_exports.string().nullable(),
16071
+ error: external_exports.string().nullable()
16072
+ })
16073
+ });
16074
+ var remoteUpdateParamsSchema = external_exports.object({
16075
+ version: external_exports.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
16076
+ }).strict();
16077
+ var remoteSshSetupParamsSchema = external_exports.object({
16078
+ hostname: external_exports.string().min(1).max(1024).refine((value) => !value.startsWith("-") && !/\s/u.test(value)),
16079
+ port: external_exports.number().int().min(1).max(65535).nullable(),
16080
+ identity: external_exports.string().max(4096).nullable(),
16081
+ action: external_exports.enum(["inspect", "install", "update", "repair"]),
16082
+ version: external_exports.string().regex(/^\d+\.\d+\.\d+$/u).nullable()
16083
+ }).strict();
16084
+ var remoteSshSetupResultSchema = external_exports.object({ state: external_exports.enum(["installed", "not-installed"]) }).strict();
16085
+
15568
16086
  // ../../shared-contracts/dist/index.js
15569
16087
  var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
15570
16088
 
@@ -19679,683 +20197,253 @@ var ClientSideConnection = class {
19679
20197
  *
19680
20198
  * This method is only available if the agent advertises the `providers` capability.
19681
20199
  *
19682
- * @experimental
19683
- */
19684
- unstable_listProviders(params) {
19685
- return this.connection.sendRequest(AGENT_METHODS.providers_list, params);
19686
- }
19687
- /**
19688
- * **UNSTABLE**
19689
- *
19690
- * This capability is not part of the spec yet, and may be removed or changed at any point.
19691
- *
19692
- * Replaces the configuration for a provider.
19693
- *
19694
- * This method is only available if the agent advertises the `providers` capability.
19695
- *
19696
- * @experimental
19697
- */
19698
- unstable_setProvider(params) {
19699
- return this.connection.sendRequest(AGENT_METHODS.providers_set, params, emptyObjectResponse);
19700
- }
19701
- /**
19702
- * **UNSTABLE**
19703
- *
19704
- * This capability is not part of the spec yet, and may be removed or changed at any point.
19705
- *
19706
- * Disables a provider.
19707
- *
19708
- * This method is only available if the agent advertises the `providers` capability.
19709
- *
19710
- * @experimental
19711
- */
19712
- unstable_disableProvider(params) {
19713
- return this.connection.sendRequest(AGENT_METHODS.providers_disable, params, emptyObjectResponse);
19714
- }
19715
- /**
19716
- * Logout of the current authentication method.
19717
- */
19718
- logout(params) {
19719
- return this.connection.sendRequest(AGENT_METHODS.logout, params, emptyObjectResponse);
19720
- }
19721
- /**
19722
- * Processes a user prompt within a session.
19723
- *
19724
- * This method handles the whole lifecycle of a prompt:
19725
- * - Receives user messages with optional context (files, images, etc.)
19726
- * - Processes the prompt using language models
19727
- * - Reports language model content and tool calls to the Clients
19728
- * - Requests permission to run tools
19729
- * - Executes any requested tool calls
19730
- * - Returns when the turn is complete with a stop reason
19731
- *
19732
- * See protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)
19733
- */
19734
- prompt(params) {
19735
- return this.connection.sendRequest(AGENT_METHODS.session_prompt, params);
19736
- }
19737
- /**
19738
- * Cancels ongoing operations for a session.
19739
- *
19740
- * This is a notification sent by the client to cancel an ongoing prompt turn.
19741
- *
19742
- * Upon receiving this notification, the Agent SHOULD:
19743
- * - Stop all language model requests as soon as possible
19744
- * - Abort all tool call invocations in progress
19745
- * - Send any pending `session/update` notifications
19746
- * - Respond to the original `session/prompt` request with `StopReason::Cancelled`
19747
- *
19748
- * See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
19749
- */
19750
- cancel(params) {
19751
- return this.connection.sendNotification(AGENT_METHODS.session_cancel, params);
19752
- }
19753
- /**
19754
- * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
19755
- *
19756
- * Starts a NES (Next Edit Suggestions) session.
19757
- *
19758
- * @experimental
19759
- */
19760
- unstable_startNes(params) {
19761
- return this.connection.sendRequest(AGENT_METHODS.nes_start, params);
19762
- }
19763
- /**
19764
- * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
19765
- *
19766
- * Sends a NES suggestion request.
19767
- *
19768
- * @experimental
19769
- */
19770
- unstable_suggestNes(params) {
19771
- return this.connection.sendRequest(AGENT_METHODS.nes_suggest, params);
19772
- }
19773
- /**
19774
- * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
19775
- *
19776
- * Closes a NES session.
19777
- *
19778
- * @experimental
19779
- */
19780
- unstable_closeNes(params) {
19781
- return this.connection.sendRequest(AGENT_METHODS.nes_close, params, emptyObjectResponse);
19782
- }
19783
- /**
19784
- * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
19785
- *
19786
- * Notifies the agent that a document was opened.
19787
- *
19788
- * @experimental
19789
- */
19790
- unstable_didOpenDocument(params) {
19791
- return this.connection.sendNotification(AGENT_METHODS.document_did_open, params);
19792
- }
19793
- /**
19794
- * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
19795
- *
19796
- * Notifies the agent that a document was changed.
19797
- *
19798
- * @experimental
19799
- */
19800
- unstable_didChangeDocument(params) {
19801
- return this.connection.sendNotification(AGENT_METHODS.document_did_change, params);
19802
- }
19803
- /**
19804
- * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
19805
- *
19806
- * Notifies the agent that a document was closed.
19807
- *
19808
- * @experimental
19809
- */
19810
- unstable_didCloseDocument(params) {
19811
- return this.connection.sendNotification(AGENT_METHODS.document_did_close, params);
19812
- }
19813
- /**
19814
- * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
19815
- *
19816
- * Notifies the agent that a document was saved.
19817
- *
19818
- * @experimental
19819
- */
19820
- unstable_didSaveDocument(params) {
19821
- return this.connection.sendNotification(AGENT_METHODS.document_did_save, params);
19822
- }
19823
- /**
19824
- * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
19825
- *
19826
- * Notifies the agent that a document received focus.
19827
- *
19828
- * @experimental
19829
- */
19830
- unstable_didFocusDocument(params) {
19831
- return this.connection.sendNotification(AGENT_METHODS.document_did_focus, params);
19832
- }
19833
- /**
19834
- * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
19835
- *
19836
- * Notifies the agent that a NES suggestion was accepted.
19837
- *
19838
- * @experimental
19839
- */
19840
- unstable_acceptNes(params) {
19841
- return this.connection.sendNotification(AGENT_METHODS.nes_accept, params);
19842
- }
19843
- /**
19844
- * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
19845
- *
19846
- * Notifies the agent that a NES suggestion was rejected.
19847
- *
19848
- * @experimental
19849
- */
19850
- unstable_rejectNes(params) {
19851
- return this.connection.sendNotification(AGENT_METHODS.nes_reject, params);
19852
- }
19853
- request(method, params, options) {
19854
- const spec = agentRequestSpecsByMethod[method];
19855
- return this.connection.sendRequest(method, params, spec?.mapResponse, options);
19856
- }
19857
- notify(method, params) {
19858
- return this.connection.sendNotification(method, params);
19859
- }
19860
- /**
19861
- * Extension method.
19862
- *
19863
- * @deprecated Use {@link request}.
19864
- */
19865
- extMethod(method, params) {
19866
- return this.request(method, params);
19867
- }
19868
- /**
19869
- * Extension notification.
19870
- *
19871
- * @deprecated Use {@link notify}.
19872
- */
19873
- extNotification(method, params) {
19874
- return this.notify(method, params);
19875
- }
19876
- /**
19877
- * AbortSignal that aborts when the connection closes.
19878
- *
19879
- * This signal can be used to:
19880
- * - Listen for connection closure: `connection.signal.addEventListener('abort', () => {...})`
19881
- * - Check connection status synchronously: `if (connection.signal.aborted) {...}`
19882
- * - Pass to other APIs (fetch, setTimeout) for automatic cancellation
19883
- *
19884
- * The connection closes when the underlying stream ends, either normally or due to an error.
20200
+ * @experimental
20201
+ */
20202
+ unstable_listProviders(params) {
20203
+ return this.connection.sendRequest(AGENT_METHODS.providers_list, params);
20204
+ }
20205
+ /**
20206
+ * **UNSTABLE**
19885
20207
  *
19886
- * @example
19887
- * ```typescript
19888
- * const connection = new ClientSideConnection(client, stream);
20208
+ * This capability is not part of the spec yet, and may be removed or changed at any point.
19889
20209
  *
19890
- * // Listen for closure
19891
- * connection.signal.addEventListener('abort', () => {
19892
- * console.log('Connection closed - performing cleanup');
19893
- * });
20210
+ * Replaces the configuration for a provider.
19894
20211
  *
19895
- * // Check status
19896
- * if (connection.signal.aborted) {
19897
- * console.log('Connection is already closed');
19898
- * }
20212
+ * This method is only available if the agent advertises the `providers` capability.
19899
20213
  *
19900
- * // Pass to other APIs
19901
- * fetch(url, { signal: connection.signal });
19902
- * ```
20214
+ * @experimental
19903
20215
  */
19904
- get signal() {
19905
- return this.connection.signal;
20216
+ unstable_setProvider(params) {
20217
+ return this.connection.sendRequest(AGENT_METHODS.providers_set, params, emptyObjectResponse);
19906
20218
  }
19907
20219
  /**
19908
- * Promise that resolves when the connection closes.
20220
+ * **UNSTABLE**
19909
20221
  *
19910
- * The connection closes when the underlying stream ends, either normally or due to an error.
19911
- * Once closed, the connection cannot send or receive any more messages.
20222
+ * This capability is not part of the spec yet, and may be removed or changed at any point.
19912
20223
  *
19913
- * This is useful for async/await style cleanup:
20224
+ * Disables a provider.
19914
20225
  *
19915
- * @example
19916
- * ```typescript
19917
- * const connection = new ClientSideConnection(client, stream);
19918
- * await connection.closed;
19919
- * console.log('Connection closed - performing cleanup');
19920
- * ```
20226
+ * This method is only available if the agent advertises the `providers` capability.
20227
+ *
20228
+ * @experimental
19921
20229
  */
19922
- get closed() {
19923
- return this.connection.closed;
19924
- }
19925
- };
19926
-
19927
- // dist/command.js
19928
- import path5 from "node:path";
19929
-
19930
- // ../../harness-discovery/dist/environment.js
19931
- import fs from "node:fs";
19932
- import path from "node:path";
19933
- function targetPath(platform) {
19934
- return platform === "win32" ? path.win32 : path.posix;
19935
- }
19936
- function environmentValue(environment, name) {
19937
- const lowered = name.toLowerCase();
19938
- for (const [key, value] of Object.entries(environment)) {
19939
- if (key.toLowerCase() === lowered)
19940
- return value;
19941
- }
19942
- return void 0;
19943
- }
19944
- function pathDelimiter(platform) {
19945
- return platform === "win32" ? ";" : ":";
19946
- }
19947
- function pathDirectories(environment, platform) {
19948
- return (environmentValue(environment, "PATH") ?? "").split(pathDelimiter(platform)).map((directory) => directory.trim().replace(/^"|"$/gu, "")).filter(Boolean);
19949
- }
19950
- function executableExtensions(command, platform, environment) {
19951
- if (platform !== "win32")
19952
- return [""];
19953
- if (targetPath(platform).extname(command) !== "")
19954
- return [""];
19955
- return (environmentValue(environment, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter(Boolean);
19956
- }
19957
- function isExecutableFile(filePath, platform) {
19958
- try {
19959
- fs.accessSync(filePath, platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK);
19960
- return fs.statSync(filePath).isFile();
19961
- } catch {
19962
- return false;
19963
- }
19964
- }
19965
- function subdirectoryNames(directory) {
19966
- try {
19967
- return fs.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
19968
- } catch {
19969
- return [];
19970
- }
19971
- }
19972
- function newestFirst(names) {
19973
- return [...names].sort((left, right) => right.localeCompare(left, void 0, { numeric: true }));
19974
- }
19975
-
19976
- // ../../harness-discovery/dist/invocation.js
19977
- import path2 from "node:path";
19978
- function commandInvocation(command, arguments_, environment, platform = process.platform) {
19979
- const extension = path2.win32.extname(command).toLowerCase();
19980
- if (platform !== "win32" || ![".cmd", ".bat"].includes(extension)) {
19981
- return { command, arguments: [...arguments_], windowsVerbatimArguments: false };
19982
- }
19983
- const quote = (value) => `"${value.replaceAll("%", "%%").replaceAll('"', '""')}"`;
19984
- const commandLine = [command, ...arguments_].map(quote).join(" ");
19985
- return {
19986
- command: environmentValue(environment, "ComSpec") ?? "cmd.exe",
19987
- arguments: ["/d", "/v:off", "/s", "/c", `"${commandLine}"`],
19988
- windowsVerbatimArguments: true
19989
- };
19990
- }
19991
-
19992
- // ../../harness-discovery/dist/node-runtime.js
19993
- import path3 from "node:path";
19994
- function withNodeRuntimeOnPath(environment, runtimeExecutable = process.execPath, platform = process.platform) {
19995
- const pathKey = Object.keys(environment).find((name) => name.toLowerCase() === "path") ?? "PATH";
19996
- const delimiter = platform === "win32" ? ";" : ":";
19997
- const runtimeDirectory = path3.dirname(runtimeExecutable);
19998
- const directories = (environment[pathKey] ?? "").split(delimiter).filter(Boolean);
19999
- const equal = platform === "win32" ? (value) => value.toLowerCase() : (value) => value;
20000
- if (!directories.some((directory) => equal(directory) === equal(runtimeDirectory))) {
20001
- directories.push(runtimeDirectory);
20002
- }
20003
- return { ...environment, [pathKey]: directories.join(delimiter) };
20004
- }
20005
-
20006
- // ../../harness-discovery/dist/resolve.js
20007
- import os from "node:os";
20008
-
20009
- // ../../harness-discovery/dist/version-managers.js
20010
- function versionManagerBinaryDirectories(context) {
20011
- const { platform, environment, home } = context;
20012
- const list = context.subdirectories ?? subdirectoryNames;
20013
- const pathFlavor = targetPath(platform);
20014
- const value = (name) => environmentValue(environment, name);
20015
- const directories = [];
20016
- const versioned = (root, ...tail) => {
20017
- for (const version2 of newestFirst(list(root))) {
20018
- directories.push(pathFlavor.join(root, version2, ...tail));
20019
- }
20020
- };
20021
- if (platform === "win32") {
20022
- const appData = value("APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming");
20023
- const localAppData = value("LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local");
20024
- versioned(pathFlavor.join(appData, "nvm"));
20025
- versioned(value("FNM_DIR") ?? pathFlavor.join(appData, "fnm", "node-versions"), "installation");
20026
- directories.push(pathFlavor.join(localAppData, "Volta", "bin"));
20027
- directories.push(pathFlavor.join(home, ".bun", "bin"));
20028
- const pnpmHome2 = value("PNPM_HOME");
20029
- if (pnpmHome2)
20030
- directories.push(pnpmHome2);
20031
- directories.push(pathFlavor.join(localAppData, "pnpm"));
20032
- return directories;
20033
- }
20034
- versioned(pathFlavor.join(value("NVM_DIR") ?? pathFlavor.join(home, ".nvm"), "versions", "node"), "bin");
20035
- const fnmRoots = [
20036
- value("FNM_DIR"),
20037
- pathFlavor.join(home, ".local", "share", "fnm"),
20038
- pathFlavor.join(home, "Library", "Application Support", "fnm")
20039
- ].filter((root) => root !== void 0);
20040
- for (const root of fnmRoots) {
20041
- versioned(pathFlavor.join(root, "node-versions"), "installation", "bin");
20230
+ unstable_disableProvider(params) {
20231
+ return this.connection.sendRequest(AGENT_METHODS.providers_disable, params, emptyObjectResponse);
20042
20232
  }
20043
- const voltaHome = value("VOLTA_HOME") ?? pathFlavor.join(home, ".volta");
20044
- versioned(pathFlavor.join(voltaHome, "tools", "image", "node"), "bin");
20045
- directories.push(pathFlavor.join(voltaHome, "bin"));
20046
- const asdfHome = value("ASDF_DATA_DIR") ?? pathFlavor.join(home, ".asdf");
20047
- versioned(pathFlavor.join(asdfHome, "installs", "nodejs"), "bin");
20048
- directories.push(pathFlavor.join(asdfHome, "shims"));
20049
- const nodenvHome = value("NODENV_ROOT") ?? pathFlavor.join(home, ".nodenv");
20050
- versioned(pathFlavor.join(nodenvHome, "versions"), "bin");
20051
- directories.push(pathFlavor.join(nodenvHome, "shims"));
20052
- versioned(pathFlavor.join(value("N_PREFIX") ?? "/usr/local", "n", "versions", "node"), "bin");
20053
- directories.push(pathFlavor.join(home, ".bun", "bin"));
20054
- const pnpmHome = value("PNPM_HOME");
20055
- if (pnpmHome)
20056
- directories.push(pnpmHome);
20057
- directories.push(pathFlavor.join(home, "Library", "pnpm"));
20058
- directories.push(pathFlavor.join(home, ".local", "share", "pnpm"));
20059
- for (const prefix of ["/opt/homebrew/opt", "/usr/local/opt"]) {
20060
- for (const formula of newestFirst(list(prefix).filter((name) => name.startsWith("node@")))) {
20061
- directories.push(pathFlavor.join(prefix, formula, "bin"));
20062
- }
20233
+ /**
20234
+ * Logout of the current authentication method.
20235
+ */
20236
+ logout(params) {
20237
+ return this.connection.sendRequest(AGENT_METHODS.logout, params, emptyObjectResponse);
20063
20238
  }
20064
- return directories;
20065
- }
20066
-
20067
- // ../../harness-discovery/dist/resolve.js
20068
- var VERSION_MANAGER_ROOTS = "<version-managers>";
20069
- function installRootExtensions(platform) {
20070
- return platform === "win32" ? [".exe", ".cmd"] : [""];
20071
- }
20072
- function resolveHomeDirectory(input) {
20073
- return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
20074
- }
20075
- function templateVariables(environment, platform, home) {
20076
- const pathFlavor = targetPath(platform);
20077
- return {
20078
- HOME: home,
20079
- USERPROFILE: home,
20080
- APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
20081
- LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
20082
- };
20083
- }
20084
- function joinTemplate(platform, value) {
20085
- const pathFlavor = targetPath(platform);
20086
- const segments = value.split("/");
20087
- const head = segments[0] ?? "";
20088
- const tail = segments.slice(1);
20089
- if (head === "")
20090
- return pathFlavor.join(pathFlavor.sep, ...tail);
20091
- return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
20092
- }
20093
- function expandInstallRoot(template, environment, platform, home) {
20094
- const variables = templateVariables(environment, platform, home);
20095
- let unresolved = false;
20096
- const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
20097
- const value = variables[name] ?? environmentValue(environment, name);
20098
- if (value === void 0 || value === "") {
20099
- unresolved = true;
20100
- return "";
20101
- }
20102
- return value;
20103
- });
20104
- return unresolved ? void 0 : joinTemplate(platform, substituted);
20105
- }
20106
- function installRootDirectories(spec, input, dependencies, platform, home) {
20107
- const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
20108
- const directories = [];
20109
- for (const template of templates) {
20110
- if (template === VERSION_MANAGER_ROOTS) {
20111
- directories.push(...versionManagerBinaryDirectories({
20112
- platform,
20113
- environment: input.environment,
20114
- home,
20115
- ...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
20116
- }));
20117
- continue;
20118
- }
20119
- const directory = expandInstallRoot(template, input.environment, platform, home);
20120
- if (directory !== void 0)
20121
- directories.push(directory);
20239
+ /**
20240
+ * Processes a user prompt within a session.
20241
+ *
20242
+ * This method handles the whole lifecycle of a prompt:
20243
+ * - Receives user messages with optional context (files, images, etc.)
20244
+ * - Processes the prompt using language models
20245
+ * - Reports language model content and tool calls to the Clients
20246
+ * - Requests permission to run tools
20247
+ * - Executes any requested tool calls
20248
+ * - Returns when the turn is complete with a stop reason
20249
+ *
20250
+ * See protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)
20251
+ */
20252
+ prompt(params) {
20253
+ return this.connection.sendRequest(AGENT_METHODS.session_prompt, params);
20122
20254
  }
20123
- return directories;
20124
- }
20125
- function harnessCandidates(spec, input, dependencies = {}) {
20126
- const platform = input.platform ?? process.platform;
20127
- const pathFlavor = targetPath(platform);
20128
- const configured = input.command ?? (spec.commandEnvironmentVariable ? environmentValue(input.environment, spec.commandEnvironmentVariable) : void 0);
20129
- const command = configured ?? spec.command;
20130
- if (pathFlavor.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
20131
- return [{ candidate: command, source: "configured" }];
20255
+ /**
20256
+ * Cancels ongoing operations for a session.
20257
+ *
20258
+ * This is a notification sent by the client to cancel an ongoing prompt turn.
20259
+ *
20260
+ * Upon receiving this notification, the Agent SHOULD:
20261
+ * - Stop all language model requests as soon as possible
20262
+ * - Abort all tool call invocations in progress
20263
+ * - Send any pending `session/update` notifications
20264
+ * - Respond to the original `session/prompt` request with `StopReason::Cancelled`
20265
+ *
20266
+ * See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
20267
+ */
20268
+ cancel(params) {
20269
+ return this.connection.sendNotification(AGENT_METHODS.session_cancel, params);
20132
20270
  }
20133
- const candidates = [];
20134
- const extensions = executableExtensions(command, platform, input.environment);
20135
- for (const directory of pathDirectories(input.environment, platform)) {
20136
- for (const extension of extensions) {
20137
- candidates.push({
20138
- candidate: pathFlavor.join(directory, command + extension),
20139
- source: "path"
20140
- });
20141
- }
20271
+ /**
20272
+ * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
20273
+ *
20274
+ * Starts a NES (Next Edit Suggestions) session.
20275
+ *
20276
+ * @experimental
20277
+ */
20278
+ unstable_startNes(params) {
20279
+ return this.connection.sendRequest(AGENT_METHODS.nes_start, params);
20142
20280
  }
20143
- if (configured !== void 0)
20144
- return candidates;
20145
- const home = resolveHomeDirectory(input);
20146
- for (const directory of installRootDirectories(spec, input, dependencies, platform, home)) {
20147
- for (const extension of installRootExtensions(platform)) {
20148
- candidates.push({
20149
- candidate: pathFlavor.join(directory, spec.command + extension),
20150
- source: "install-root"
20151
- });
20152
- }
20281
+ /**
20282
+ * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
20283
+ *
20284
+ * Sends a NES suggestion request.
20285
+ *
20286
+ * @experimental
20287
+ */
20288
+ unstable_suggestNes(params) {
20289
+ return this.connection.sendRequest(AGENT_METHODS.nes_suggest, params);
20153
20290
  }
20154
- return candidates;
20155
- }
20156
- function resolveHarnessExecutable(spec, input, dependencies = {}) {
20157
- const platform = input.platform ?? process.platform;
20158
- const isExecutable = dependencies.isExecutable ?? ((candidate) => isExecutableFile(candidate, platform));
20159
- const runnable = spec.runnableCandidate ?? ((candidate) => candidate);
20160
- const context = { platform, isExecutable };
20161
- for (const { candidate, source } of harnessCandidates(spec, input, dependencies)) {
20162
- const executable = runnable(candidate, context);
20163
- if (executable !== void 0 && isExecutable(executable))
20164
- return { executable, source };
20291
+ /**
20292
+ * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
20293
+ *
20294
+ * Closes a NES session.
20295
+ *
20296
+ * @experimental
20297
+ */
20298
+ unstable_closeNes(params) {
20299
+ return this.connection.sendRequest(AGENT_METHODS.nes_close, params, emptyObjectResponse);
20165
20300
  }
20166
- return void 0;
20167
- }
20168
-
20169
- // ../../harness-discovery/dist/installation.js
20170
- import { execFile } from "node:child_process";
20171
- import { homedir } from "node:os";
20172
- function runInstallationCommand(command, args, environment, timeout = 3e4) {
20173
- const env = withNodeRuntimeOnPath(environment);
20174
- const invocation = /\.[cm]?js$/i.test(command) ? commandInvocation(process.execPath, [command, ...args], env) : commandInvocation(command, args, env);
20175
- return new Promise((resolve, reject) => {
20176
- const child = execFile(invocation.command, invocation.arguments, {
20177
- env,
20178
- cwd: env.HOME ?? env.USERPROFILE ?? homedir(),
20179
- encoding: "utf8",
20180
- timeout,
20181
- killSignal: "SIGKILL",
20182
- maxBuffer: 1024 * 1024,
20183
- windowsHide: true,
20184
- windowsVerbatimArguments: invocation.windowsVerbatimArguments
20185
- }, (error51, stdout, stderr) => {
20186
- if (error51)
20187
- reject(new Error(error51.killed ? "Harness command timed out" : "Harness command failed; check the native installation and retry"));
20188
- else
20189
- resolve((stdout || stderr).trim());
20190
- });
20191
- child.stdin?.end();
20192
- });
20193
- }
20194
- function installationVersion(value) {
20195
- if (typeof value !== "string" || !/^v?\d+(?:\.\d+){1,3}(?:-[\w.-]+)?(?:\+[\w.-]+)?$/.test(value.trim()))
20196
- throw new Error("Harness returned an invalid version");
20197
- return value.trim().replace(/^v/, "");
20198
- }
20199
- function versionFromOutput(output) {
20200
- return installationVersion(output.match(/\b\d+(?:\.\d+){1,3}(?:-[\w.-]+)?(?:\+[\w.-]+)?\b/)?.[0]);
20201
- }
20202
- function newerInstallationVersion(current, latest) {
20203
- const a = installationVersion(current).replace(/\+.*/, "");
20204
- const b = installationVersion(latest).replace(/\+.*/, "");
20205
- const coreA = a.replace(/-.*/, "").split(".").map(BigInt);
20206
- const coreB = b.replace(/-.*/, "").split(".").map(BigInt);
20207
- for (let i = 0; i < Math.max(coreA.length, coreB.length); i++) {
20208
- if ((coreA[i] ?? 0n) !== (coreB[i] ?? 0n))
20209
- return (coreB[i] ?? 0n) > (coreA[i] ?? 0n);
20301
+ /**
20302
+ * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
20303
+ *
20304
+ * Notifies the agent that a document was opened.
20305
+ *
20306
+ * @experimental
20307
+ */
20308
+ unstable_didOpenDocument(params) {
20309
+ return this.connection.sendNotification(AGENT_METHODS.document_did_open, params);
20210
20310
  }
20211
- const preA = a.includes("-") ? a.slice(a.indexOf("-") + 1).split(".") : [];
20212
- const preB = b.includes("-") ? b.slice(b.indexOf("-") + 1).split(".") : [];
20213
- if (!preA.length || !preB.length)
20214
- return !!preA.length && !preB.length;
20215
- for (let i = 0; i < Math.max(preA.length, preB.length); i++) {
20216
- const x = preA[i];
20217
- const y = preB[i];
20218
- if (x === y)
20219
- continue;
20220
- if (x === void 0 || y === void 0)
20221
- return x === void 0;
20222
- const numericX = /^\d+$/.test(x);
20223
- const numericY = /^\d+$/.test(y);
20224
- if (numericX && numericY) {
20225
- if (BigInt(x) === BigInt(y))
20226
- continue;
20227
- return BigInt(y) > BigInt(x);
20228
- }
20229
- if (numericX !== numericY)
20230
- return numericX;
20231
- return y > x;
20311
+ /**
20312
+ * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
20313
+ *
20314
+ * Notifies the agent that a document was changed.
20315
+ *
20316
+ * @experimental
20317
+ */
20318
+ unstable_didChangeDocument(params) {
20319
+ return this.connection.sendNotification(AGENT_METHODS.document_did_change, params);
20232
20320
  }
20233
- return false;
20234
- }
20235
- function createInstallationManager(options) {
20236
- let checking;
20237
- let updating;
20238
- const check2 = () => checking ??= options.check().finally(() => {
20239
- checking = void 0;
20240
- });
20241
- return (action) => {
20242
- if (updating)
20243
- return updating;
20244
- if (action === "check")
20245
- return check2();
20246
- updating = (async () => {
20247
- const before = await check2();
20248
- if (!before.updateAvailable)
20249
- return before;
20250
- if (!before.canUpdate)
20251
- throw new Error(before.message ?? "This installation cannot be updated automatically");
20252
- await options.update(before);
20253
- const after = await check2();
20254
- if (after.currentVersion === before.currentVersion)
20255
- throw new Error("The Harness version did not change; check the native updater and retry");
20256
- return after;
20257
- })().finally(() => {
20258
- updating = void 0;
20259
- });
20260
- return updating;
20261
- };
20262
- }
20263
- async function fetchInstallationText(url2) {
20264
- const request = async () => {
20265
- const response = await fetch(url2, { signal: AbortSignal.timeout(15e3) });
20266
- if (!response.ok)
20267
- throw new Error("Could not check the latest Harness version");
20268
- return response.text();
20269
- };
20270
- try {
20271
- return await request();
20272
- } catch (error51) {
20273
- if (error51 instanceof DOMException && (error51.name === "AbortError" || error51.name === "TimeoutError"))
20274
- throw error51;
20275
- return request();
20321
+ /**
20322
+ * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
20323
+ *
20324
+ * Notifies the agent that a document was closed.
20325
+ *
20326
+ * @experimental
20327
+ */
20328
+ unstable_didCloseDocument(params) {
20329
+ return this.connection.sendNotification(AGENT_METHODS.document_did_close, params);
20330
+ }
20331
+ /**
20332
+ * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
20333
+ *
20334
+ * Notifies the agent that a document was saved.
20335
+ *
20336
+ * @experimental
20337
+ */
20338
+ unstable_didSaveDocument(params) {
20339
+ return this.connection.sendNotification(AGENT_METHODS.document_did_save, params);
20340
+ }
20341
+ /**
20342
+ * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
20343
+ *
20344
+ * Notifies the agent that a document received focus.
20345
+ *
20346
+ * @experimental
20347
+ */
20348
+ unstable_didFocusDocument(params) {
20349
+ return this.connection.sendNotification(AGENT_METHODS.document_did_focus, params);
20350
+ }
20351
+ /**
20352
+ * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
20353
+ *
20354
+ * Notifies the agent that a NES suggestion was accepted.
20355
+ *
20356
+ * @experimental
20357
+ */
20358
+ unstable_acceptNes(params) {
20359
+ return this.connection.sendNotification(AGENT_METHODS.nes_accept, params);
20276
20360
  }
20277
- }
20278
-
20279
- // ../../harness-discovery/dist/npm-installation.js
20280
- import { readFile, realpath } from "node:fs/promises";
20281
- import path4 from "node:path";
20282
- function referencesNpmBin(shim, name, bin) {
20283
- if (bin.includes(".."))
20284
- return false;
20285
- const target = `node_modules/${name}/${bin.replace(/^\.\//, "")}`.toLowerCase();
20286
- const text = shim.replaceAll("\\", "/").toLowerCase();
20287
- return text.includes(`%dp0%/${target}"`) || text.includes(`%~dp0/${target}"`);
20288
- }
20289
- async function npmInstallation(command, packages, environment) {
20290
- let selected = await realpath(command);
20291
- if (process.platform === "win32" && /\.(cmd|bat)$/i.test(selected)) {
20292
- const shim = (await readFile(selected, "utf8")).replaceAll("\\", "/");
20293
- const root = path4.dirname(selected);
20294
- for (const name of packages) {
20295
- const directory2 = path4.join(root, "node_modules", ...name.split("/"));
20296
- const metadata = await readFile(path4.join(directory2, "package.json"), "utf8").then((text) => JSON.parse(text)).catch(() => null);
20297
- const bins = typeof metadata?.bin === "string" ? [metadata.bin] : Object.values(metadata?.bin ?? {});
20298
- const bin = bins.find((entry) => referencesNpmBin(shim, name, entry));
20299
- if (bin) {
20300
- selected = await realpath(path4.join(directory2, bin));
20301
- break;
20302
- }
20303
- }
20361
+ /**
20362
+ * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
20363
+ *
20364
+ * Notifies the agent that a NES suggestion was rejected.
20365
+ *
20366
+ * @experimental
20367
+ */
20368
+ unstable_rejectNes(params) {
20369
+ return this.connection.sendNotification(AGENT_METHODS.nes_reject, params);
20304
20370
  }
20305
- let directory = path4.dirname(selected);
20306
- for (let depth = 0; depth < 8; depth++) {
20307
- const metadata = await readFile(path4.join(directory, "package.json"), "utf8").then((text) => JSON.parse(text)).catch(() => null);
20308
- if (metadata?.name && packages.includes(metadata.name)) {
20309
- const name = metadata.name;
20310
- const currentVersion = installationVersion(metadata.version);
20311
- const segments = name.split("/");
20312
- let modules = directory;
20313
- for (let index = 0; index < segments.length; index++)
20314
- modules = path4.dirname(modules);
20315
- const prefix = process.platform === "win32" ? path4.dirname(modules) : path4.dirname(path4.dirname(modules));
20316
- const globalRoot = process.platform === "win32" ? path4.join(prefix, "node_modules") : path4.join(prefix, "lib", "node_modules");
20317
- const env = withNodeRuntimeOnPath(environment);
20318
- const npm = resolveHarnessExecutable({ id: "npm", command: "npm", installRoots: { posix: [], windows: [] } }, { environment: env });
20319
- let globalInstall = modules === globalRoot;
20320
- if (process.platform === "win32") {
20321
- const project = (await Promise.all(["package.json", "package-lock.json", "npm-shrinkwrap.json"].map((file2) => readFile(path4.join(prefix, file2), "utf8").then(() => true, (error51) => error51.code !== "ENOENT")))).some(Boolean);
20322
- const bins = typeof metadata.bin === "string" ? { [name.split("/").at(-1) ?? name]: metadata.bin } : metadata.bin ?? {};
20323
- const launchers = await Promise.all(Object.entries(bins).map(async ([bin, entry]) => {
20324
- if (path4.basename(bin) !== bin || entry.includes(".."))
20325
- return false;
20326
- const target = await realpath(path4.join(directory, entry)).catch(() => "");
20327
- if (target.toLowerCase() !== selected.toLowerCase())
20328
- return false;
20329
- const shim = await readFile(path4.join(prefix, `${bin}.cmd`), "utf8").catch(() => "");
20330
- return referencesNpmBin(shim, name, entry);
20331
- }));
20332
- globalInstall = globalInstall && !project && launchers.some(Boolean);
20333
- }
20334
- const canUpdate = globalInstall && !!npm;
20335
- return {
20336
- prefix,
20337
- currentVersion,
20338
- canUpdate,
20339
- latest: async () => {
20340
- const data = JSON.parse(await fetchInstallationText(`https://registry.npmjs.org/${encodeURIComponent(name)}/latest`));
20341
- return installationVersion(data.version);
20342
- },
20343
- update: async (version2) => {
20344
- if (!canUpdate || !npm)
20345
- throw new Error("Use the original package manager to update this installation");
20346
- await runInstallationCommand(npm.executable, ["install", "--global", "--prefix", prefix, `${name}@${installationVersion(version2)}`], env, 3e5);
20347
- }
20348
- };
20349
- }
20350
- const parent = path4.dirname(directory);
20351
- if (parent === directory)
20352
- break;
20353
- directory = parent;
20371
+ request(method, params, options) {
20372
+ const spec = agentRequestSpecsByMethod[method];
20373
+ return this.connection.sendRequest(method, params, spec?.mapResponse, options);
20354
20374
  }
20355
- return null;
20356
- }
20375
+ notify(method, params) {
20376
+ return this.connection.sendNotification(method, params);
20377
+ }
20378
+ /**
20379
+ * Extension method.
20380
+ *
20381
+ * @deprecated Use {@link request}.
20382
+ */
20383
+ extMethod(method, params) {
20384
+ return this.request(method, params);
20385
+ }
20386
+ /**
20387
+ * Extension notification.
20388
+ *
20389
+ * @deprecated Use {@link notify}.
20390
+ */
20391
+ extNotification(method, params) {
20392
+ return this.notify(method, params);
20393
+ }
20394
+ /**
20395
+ * AbortSignal that aborts when the connection closes.
20396
+ *
20397
+ * This signal can be used to:
20398
+ * - Listen for connection closure: `connection.signal.addEventListener('abort', () => {...})`
20399
+ * - Check connection status synchronously: `if (connection.signal.aborted) {...}`
20400
+ * - Pass to other APIs (fetch, setTimeout) for automatic cancellation
20401
+ *
20402
+ * The connection closes when the underlying stream ends, either normally or due to an error.
20403
+ *
20404
+ * @example
20405
+ * ```typescript
20406
+ * const connection = new ClientSideConnection(client, stream);
20407
+ *
20408
+ * // Listen for closure
20409
+ * connection.signal.addEventListener('abort', () => {
20410
+ * console.log('Connection closed - performing cleanup');
20411
+ * });
20412
+ *
20413
+ * // Check status
20414
+ * if (connection.signal.aborted) {
20415
+ * console.log('Connection is already closed');
20416
+ * }
20417
+ *
20418
+ * // Pass to other APIs
20419
+ * fetch(url, { signal: connection.signal });
20420
+ * ```
20421
+ */
20422
+ get signal() {
20423
+ return this.connection.signal;
20424
+ }
20425
+ /**
20426
+ * Promise that resolves when the connection closes.
20427
+ *
20428
+ * The connection closes when the underlying stream ends, either normally or due to an error.
20429
+ * Once closed, the connection cannot send or receive any more messages.
20430
+ *
20431
+ * This is useful for async/await style cleanup:
20432
+ *
20433
+ * @example
20434
+ * ```typescript
20435
+ * const connection = new ClientSideConnection(client, stream);
20436
+ * await connection.closed;
20437
+ * console.log('Connection closed - performing cleanup');
20438
+ * ```
20439
+ */
20440
+ get closed() {
20441
+ return this.connection.closed;
20442
+ }
20443
+ };
20357
20444
 
20358
20445
  // dist/command.js
20446
+ import path5 from "node:path";
20359
20447
  var KimiExecutableError = class extends Error {
20360
20448
  code = "KIMI_NOT_FOUND";
20361
20449
  };
@@ -20825,9 +20913,9 @@ var KimiAcpTransport = class {
20825
20913
 
20826
20914
  // dist/account-identity.js
20827
20915
  import { randomUUID } from "node:crypto";
20828
- import { readFile as readFile2, rename, unlink, writeFile } from "node:fs/promises";
20916
+ import { readFile as readFile2, rename, unlink, writeFile as writeFile2 } from "node:fs/promises";
20829
20917
  import { homedir as homedir2 } from "node:os";
20830
- import { join } from "node:path";
20918
+ import { join as join2 } from "node:path";
20831
20919
  var KIMI_USAGES_ENDPOINT = "https://api.kimi.com/coding/v1/usages";
20832
20920
  var KIMI_OAUTH_TOKEN_ENDPOINT = "https://auth.kimi.com/api/oauth/token";
20833
20921
  var KIMI_CODE_CLIENT_ID = "17e5f671-d194-4dfb-9706-5516cb48c098";
@@ -20849,10 +20937,10 @@ var refreshResponseSchema = external_exports.object({
20849
20937
  token_type: external_exports.string().optional()
20850
20938
  });
20851
20939
  function kimiHome(environment) {
20852
- return environment.KIMI_CODE_HOME ?? join(environment.HOME ?? homedir2(), ".kimi-code");
20940
+ return environment.KIMI_CODE_HOME ?? join2(environment.HOME ?? homedir2(), ".kimi-code");
20853
20941
  }
20854
20942
  function credentialPath(environment) {
20855
- return join(kimiHome(environment), "credentials", "kimi-code.json");
20943
+ return join2(kimiHome(environment), "credentials", "kimi-code.json");
20856
20944
  }
20857
20945
  function oauthTokenUrl(environment) {
20858
20946
  const host = environment.KIMI_CODE_OAUTH_HOST ?? environment.KIMI_OAUTH_HOST;
@@ -20957,7 +21045,7 @@ async function readNativeCredentials(filePath, readAuthFile) {
20957
21045
  async function defaultWriteAuthFile(filePath, contents) {
20958
21046
  const temporary = `${filePath}.${randomUUID()}.tmp`;
20959
21047
  try {
20960
- await writeFile(temporary, contents, { encoding: "utf8", mode: 384, flag: "wx" });
21048
+ await writeFile2(temporary, contents, { encoding: "utf8", mode: 384, flag: "wx" });
20961
21049
  await rename(temporary, filePath);
20962
21050
  } finally {
20963
21051
  await unlink(temporary).catch(() => void 0);
@@ -21147,16 +21235,16 @@ var Diff = class {
21147
21235
  }
21148
21236
  }
21149
21237
  }
21150
- addToPath(path9, added, removed, oldPosInc, options) {
21151
- const last = path9.lastComponent;
21238
+ addToPath(path10, added, removed, oldPosInc, options) {
21239
+ const last = path10.lastComponent;
21152
21240
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
21153
21241
  return {
21154
- oldPos: path9.oldPos + oldPosInc,
21242
+ oldPos: path10.oldPos + oldPosInc,
21155
21243
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
21156
21244
  };
21157
21245
  } else {
21158
21246
  return {
21159
- oldPos: path9.oldPos + oldPosInc,
21247
+ oldPos: path10.oldPos + oldPosInc,
21160
21248
  lastComponent: { count: 1, added, removed, previousComponent: last }
21161
21249
  };
21162
21250
  }
@@ -23110,19 +23198,259 @@ async function readKimiSessionUsage(sessionId, options = {}) {
23110
23198
  }
23111
23199
  }
23112
23200
 
23201
+ // dist/session-import.js
23202
+ import { readFile as readFile4, stat } from "node:fs/promises";
23203
+ import path7 from "node:path";
23204
+
23205
+ // ../../harness-adapter/dist/session-import.js
23206
+ import { lstat } from "node:fs/promises";
23207
+ var SessionImportChangedError = class extends Error {
23208
+ constructor(message = "Native Session changed during discovery; refresh and retry") {
23209
+ super(message);
23210
+ this.name = "SessionImportChangedError";
23211
+ }
23212
+ };
23213
+ function isMissingFileError(error51) {
23214
+ return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "ENOENT";
23215
+ }
23216
+ function sameFileFingerprint(left, right) {
23217
+ return left === null || right === null ? left === right : left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs;
23218
+ }
23219
+ var STORAGE_ACCESS_ERRORS = /* @__PURE__ */ new Set(["EACCES", "EPERM", "EIO", "EMFILE", "ENFILE"]);
23220
+ function isStorageAccessError(error51) {
23221
+ return typeof error51 === "object" && error51 !== null && "code" in error51 && typeof error51.code === "string" && STORAGE_ACCESS_ERRORS.has(error51.code);
23222
+ }
23223
+ async function optionalLstat(file2) {
23224
+ try {
23225
+ return await lstat(file2);
23226
+ } catch (error51) {
23227
+ if (isMissingFileError(error51))
23228
+ return null;
23229
+ throw error51;
23230
+ }
23231
+ }
23232
+ async function readStableFiles(files, read) {
23233
+ const before = await Promise.all(files.map(optionalLstat));
23234
+ const value = await read(before);
23235
+ const after = await Promise.all(files.map(optionalLstat));
23236
+ if (before.some((info, index) => !sameFileFingerprint(info, after[index] ?? null)))
23237
+ throw new SessionImportChangedError();
23238
+ return value;
23239
+ }
23240
+ function sessionImportTitle(value, maxLength = HARNESS_SESSION_IMPORT_TITLE_MAX_LENGTH) {
23241
+ if (typeof value !== "string")
23242
+ return null;
23243
+ const normalized = value.replaceAll("\0", "").replaceAll(/\s+/gu, " ").trim();
23244
+ if (!normalized)
23245
+ return null;
23246
+ if (normalized.length <= maxLength)
23247
+ return normalized;
23248
+ const characters = [...normalized];
23249
+ if (characters.length <= maxLength)
23250
+ return normalized;
23251
+ return `${characters.slice(0, maxLength - 1).join("").trimEnd()}…`;
23252
+ }
23253
+ function sessionImportCandidate(input) {
23254
+ const time3 = typeof input.updatedAt === "number" ? input.updatedAt : typeof input.updatedAt === "string" ? Date.parse(input.updatedAt) : Number.NaN;
23255
+ const parsed = harnessSessionImportCandidateSchema.safeParse({
23256
+ nativeSessionId: input.nativeSessionId,
23257
+ cwd: input.cwd,
23258
+ title: typeof input.title === "string" && input.title.trim().length > 0 ? input.title : null,
23259
+ updatedAt: Math.floor(time3),
23260
+ // Unknown must stay unknown; only an explicit boolean is a native statement.
23261
+ running: typeof input.running === "boolean" ? input.running : null
23262
+ });
23263
+ return parsed.success ? parsed.data : null;
23264
+ }
23265
+ var SessionImportScope = class {
23266
+ #abort = new AbortController();
23267
+ #options;
23268
+ #pending = /* @__PURE__ */ new Set();
23269
+ constructor(options) {
23270
+ this.#options = options;
23271
+ }
23272
+ #closed() {
23273
+ return {
23274
+ ok: false,
23275
+ error: { code: "invalidState", message: this.#options.closedMessage, retryable: false }
23276
+ };
23277
+ }
23278
+ read(operation) {
23279
+ const signal = this.#abort.signal;
23280
+ if (signal.aborted)
23281
+ return Promise.resolve(this.#closed());
23282
+ let started;
23283
+ try {
23284
+ started = operation(signal);
23285
+ } catch (error51) {
23286
+ started = Promise.reject(error51 instanceof Error ? error51 : new Error("Session read failed"));
23287
+ }
23288
+ const request = started.then((value) => signal.aborted ? this.#closed() : { ok: true, value }).catch(() => signal.aborted ? this.#closed() : {
23289
+ ok: false,
23290
+ error: {
23291
+ code: "unavailable",
23292
+ message: this.#options.unavailableMessage,
23293
+ retryable: true
23294
+ }
23295
+ }).finally(() => this.#pending.delete(request));
23296
+ this.#pending.add(request);
23297
+ return request;
23298
+ }
23299
+ /** `read` for `resolveCandidate`: a null source is the selected Session having disappeared. */
23300
+ async resolve(operation) {
23301
+ const result = await this.read(operation);
23302
+ if (!result.ok)
23303
+ return result;
23304
+ return result.value ? { ok: true, value: result.value } : {
23305
+ ok: false,
23306
+ error: {
23307
+ code: "sessionNotFound",
23308
+ message: this.#options.notFoundMessage,
23309
+ retryable: false
23310
+ }
23311
+ };
23312
+ }
23313
+ /** Idempotent. Resolves after every started read has settled. */
23314
+ async close() {
23315
+ this.#abort.abort();
23316
+ await Promise.allSettled(this.#pending);
23317
+ }
23318
+ };
23319
+
23320
+ // dist/session-import.js
23321
+ function isRecord5(value) {
23322
+ return typeof value === "object" && value !== null && !Array.isArray(value);
23323
+ }
23324
+ var KimiSessionImport = class {
23325
+ #home;
23326
+ #scope = new SessionImportScope({
23327
+ closedMessage: "Kimi Session import is closed",
23328
+ unavailableMessage: "Kimi sessions could not be read; close native clients, check storage access and retry",
23329
+ notFoundMessage: "Kimi Session is no longer importable"
23330
+ });
23331
+ constructor(options) {
23332
+ this.#home = getKimiCodeHome(options.homeDirectory, options.environment);
23333
+ }
23334
+ listCandidates() {
23335
+ return this.#scope.read(async (signal) => {
23336
+ const candidates = [];
23337
+ for (const nativeSessionId of await this.#indexedSessions(signal)) {
23338
+ try {
23339
+ const source = await this.#source(nativeSessionId, signal);
23340
+ if (source)
23341
+ candidates.push(source.candidate);
23342
+ } catch (error51) {
23343
+ if (!(error51 instanceof SessionImportChangedError))
23344
+ throw error51;
23345
+ }
23346
+ }
23347
+ return candidates;
23348
+ });
23349
+ }
23350
+ resolveCandidate(nativeSessionId) {
23351
+ return this.#scope.resolve(async (signal) => (await this.#indexedSessions(signal)).has(nativeSessionId) ? this.#source(nativeSessionId, signal) : null);
23352
+ }
23353
+ close() {
23354
+ return this.#scope.close();
23355
+ }
23356
+ /** Live identities in Kimi's index. The last record of an identity decides, as in resume. */
23357
+ async #indexedSessions(signal) {
23358
+ const live = /* @__PURE__ */ new Set();
23359
+ let content;
23360
+ try {
23361
+ content = await readFile4(path7.join(this.#home, "session_index.jsonl"), {
23362
+ encoding: "utf8",
23363
+ signal
23364
+ });
23365
+ } catch (error51) {
23366
+ signal.throwIfAborted();
23367
+ if (isMissingFileError(error51))
23368
+ return live;
23369
+ throw error51;
23370
+ }
23371
+ for (const line of content.split("\n")) {
23372
+ if (!line.trim())
23373
+ continue;
23374
+ let entry;
23375
+ try {
23376
+ entry = JSON.parse(line);
23377
+ } catch {
23378
+ continue;
23379
+ }
23380
+ if (!isRecord5(entry) || typeof entry.sessionId !== "string" || !entry.sessionId)
23381
+ continue;
23382
+ if (entry.deleted || typeof entry.sessionDir !== "string")
23383
+ live.delete(entry.sessionId);
23384
+ else
23385
+ live.add(entry.sessionId);
23386
+ }
23387
+ return live;
23388
+ }
23389
+ async #source(nativeSessionId, signal) {
23390
+ signal.throwIfAborted();
23391
+ const options = { kimiCodeHome: this.#home };
23392
+ let located;
23393
+ try {
23394
+ located = await locateKimiSession(nativeSessionId, options);
23395
+ } catch (error51) {
23396
+ if (isStorageAccessError(error51))
23397
+ throw error51;
23398
+ return null;
23399
+ }
23400
+ if (!located)
23401
+ return null;
23402
+ const { state } = located;
23403
+ const files = [
23404
+ path7.join(located.sessionDir, "state.json"),
23405
+ path7.join(located.mainHomeDir, "wire.jsonl")
23406
+ ];
23407
+ return readStableFiles(files, async ([stateInfo, wire]) => {
23408
+ if (!stateInfo?.isFile() || !wire?.isFile())
23409
+ return null;
23410
+ try {
23411
+ if (typeof state.cwd !== "string" || !path7.isAbsolute(state.cwd))
23412
+ return null;
23413
+ const cwd = path7.resolve(state.cwd);
23414
+ if (!(await stat(cwd)).isDirectory())
23415
+ return null;
23416
+ signal.throwIfAborted();
23417
+ const { turns } = await readKimiSessionSnapshot(nativeSessionId, options);
23418
+ const prompt = turns.flatMap((turn) => turn.input).find((input) => input.type === "text" && input.text.trim().length > 0);
23419
+ if (!prompt)
23420
+ return null;
23421
+ const activity = turns.flatMap((turn) => [turn.completedAtMs, turn.startedAtMs]).filter((time3) => typeof time3 === "number" && Number.isFinite(time3));
23422
+ const candidate = sessionImportCandidate({
23423
+ nativeSessionId,
23424
+ cwd,
23425
+ title: sessionImportTitle(state.title) ?? sessionImportTitle(prompt.text),
23426
+ // Wire record times are milliseconds; the state file's unit is not documented.
23427
+ updatedAt: activity.length > 0 ? Math.max(...activity) : wire.mtimeMs
23428
+ // Kimi has no cross-process activity marker: idleness cannot be established.
23429
+ });
23430
+ return candidate ? { candidate, nativeRef: createKimiNativeSessionRef(nativeSessionId, cwd) } : null;
23431
+ } catch (error51) {
23432
+ signal.throwIfAborted();
23433
+ if (isStorageAccessError(error51))
23434
+ throw error51;
23435
+ return null;
23436
+ }
23437
+ });
23438
+ }
23439
+ };
23440
+
23113
23441
  // dist/kimi-session.js
23114
23442
  import { setTimeout as delay } from "node:timers/promises";
23115
23443
 
23116
23444
  // dist/command-history.js
23117
- import { appendFile, readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
23118
- import path7 from "node:path";
23445
+ import { appendFile, readFile as readFile5, writeFile as writeFile3 } from "node:fs/promises";
23446
+ import path8 from "node:path";
23119
23447
  async function readKimiCommandHistory(sessionId, options) {
23120
23448
  const located = await locateKimiSession(sessionId, options);
23121
23449
  if (!located)
23122
23450
  return [];
23123
23451
  let content;
23124
23452
  try {
23125
- content = await readFile4(path7.join(located.sessionDir, "codexhost-commands.jsonl"), "utf8");
23453
+ content = await readFile5(path8.join(located.sessionDir, "codexhost-commands.jsonl"), "utf8");
23126
23454
  } catch (error51) {
23127
23455
  if (error51.code === "ENOENT")
23128
23456
  return [];
@@ -23152,7 +23480,7 @@ async function appendKimiCommandHistory(turn, options) {
23152
23480
  const located = await locateKimiSession(turn.nativeTurnRef.nativeSessionId, options);
23153
23481
  if (!located)
23154
23482
  throw new Error("Cannot persist Kimi command: native session is missing");
23155
- await appendFile(path7.join(located.sessionDir, "codexhost-commands.jsonl"), `${JSON.stringify(turn)}
23483
+ await appendFile(path8.join(located.sessionDir, "codexhost-commands.jsonl"), `${JSON.stringify(turn)}
23156
23484
  `, "utf8");
23157
23485
  }
23158
23486
  async function copyKimiCommandHistory(turns, sessionId, options) {
@@ -23166,7 +23494,7 @@ async function copyKimiCommandHistory(turns, sessionId, options) {
23166
23494
  nativeTurnRef: { ...turn.nativeTurnRef, nativeSessionId: sessionId },
23167
23495
  ...turn.checkpoint ? { checkpoint: { ...turn.checkpoint, nativeSessionId: sessionId } } : {}
23168
23496
  }));
23169
- await writeFile2(path7.join(located.sessionDir, "codexhost-commands.jsonl"), copied.map((turn) => `${JSON.stringify(turn)}
23497
+ await writeFile3(path8.join(located.sessionDir, "codexhost-commands.jsonl"), copied.map((turn) => `${JSON.stringify(turn)}
23170
23498
  `).join(""), "utf8");
23171
23499
  }
23172
23500
 
@@ -24335,6 +24663,7 @@ function stateFromConfig(sessionId, cwd, configOptions) {
24335
24663
  }
24336
24664
  var KimiAdapter = class {
24337
24665
  harnessId = kimiHarnessId3;
24666
+ sessionImport;
24338
24667
  #options;
24339
24668
  #deps;
24340
24669
  #sessions = /* @__PURE__ */ new Set();
@@ -24347,6 +24676,10 @@ var KimiAdapter = class {
24347
24676
  constructor(options = {}, dependencies = {}) {
24348
24677
  this.#options = options;
24349
24678
  this.#deps = dependencies;
24679
+ this.sessionImport = new KimiSessionImport({
24680
+ environment: { ...process.env, ...options.environment },
24681
+ homeDirectory: options.homeDirectory
24682
+ });
24350
24683
  }
24351
24684
  async inspectAccount() {
24352
24685
  if (this.#closed)
@@ -24385,10 +24718,10 @@ var KimiAdapter = class {
24385
24718
  return result;
24386
24719
  }
24387
24720
  const kimiHome2 = getKimiCodeHome(this.#options.homeDirectory, environment);
24388
- const configPath = path8.join(kimiHome2, "config.toml");
24721
+ const configPath = path9.join(kimiHome2, "config.toml");
24389
24722
  let nativeConfig = null;
24390
24723
  try {
24391
- const configContent = await readFile5(configPath, "utf8");
24724
+ const configContent = await readFile6(configPath, "utf8");
24392
24725
  nativeConfig = parseKimiConfigToml(configContent);
24393
24726
  } catch {
24394
24727
  nativeConfig = null;
@@ -24499,10 +24832,10 @@ var KimiAdapter = class {
24499
24832
  onFault: (error51) => session?.handleTransportFault(error51)
24500
24833
  });
24501
24834
  const kimiHome2 = getKimiCodeHome(this.#options.homeDirectory, environment);
24502
- const configPath = path8.join(kimiHome2, "config.toml");
24835
+ const configPath = path9.join(kimiHome2, "config.toml");
24503
24836
  let nativeConfig = null;
24504
24837
  try {
24505
- const configContent = await readFile5(configPath, "utf8");
24838
+ const configContent = await readFile6(configPath, "utf8");
24506
24839
  nativeConfig = parseKimiConfigToml(configContent);
24507
24840
  } catch {
24508
24841
  nativeConfig = null;
@@ -24559,7 +24892,7 @@ var KimiAdapter = class {
24559
24892
  await transport.close().catch(() => void 0);
24560
24893
  return err2("checkpointNotFound", "Kimi Checkpoint does not belong to the source Native Session");
24561
24894
  }
24562
- if (path8.resolve(cwd) !== path8.resolve(located.state.cwd)) {
24895
+ if (path9.resolve(cwd) !== path9.resolve(located.state.cwd)) {
24563
24896
  await transport.close().catch(() => void 0);
24564
24897
  return err2("unsupported", "Kimi Code cannot fork across different working directories");
24565
24898
  }
@@ -24682,7 +25015,7 @@ var KimiAdapter = class {
24682
25015
  const located = await locateKimiSession(sourceId, historyOptions);
24683
25016
  if (!located)
24684
25017
  return err2("sessionNotFound", "Kimi source session was not found");
24685
- if (path8.resolve(input.cwd) !== path8.resolve(located.state.cwd))
25018
+ if (path9.resolve(input.cwd) !== path9.resolve(located.state.cwd))
24686
25019
  return err2("unsupported", "Kimi cannot roll back into another working directory");
24687
25020
  const source = [...this.#sessions].find((candidate) => candidate.initialState.nativeRef?.nativeSessionId === sourceId);
24688
25021
  if (source) {
@@ -24740,6 +25073,7 @@ var KimiAdapter = class {
24740
25073
  return;
24741
25074
  this.#closed = true;
24742
25075
  this.#commandCatalog = KIMI_DEFAULT_COMMAND_CATALOG;
25076
+ await this.sessionImport.close();
24743
25077
  for (const session of this.#sessions) {
24744
25078
  await session.close().catch(() => void 0);
24745
25079
  }
@@ -24748,9 +25082,9 @@ var KimiAdapter = class {
24748
25082
  };
24749
25083
 
24750
25084
  // dist/installation.js
24751
- import { open, readFile as readFile6 } from "node:fs/promises";
25085
+ import { open, readFile as readFile7 } from "node:fs/promises";
24752
25086
  import { homedir as homedir3 } from "node:os";
24753
- import { join as join2 } from "node:path";
25087
+ import { join as join3 } from "node:path";
24754
25088
  function createKimiInstallation(environment) {
24755
25089
  const executable = () => resolveKimiExecutable({ environment });
24756
25090
  const run = (args, timeout) => runInstallationCommand(executable(), args, { ...environment, KIMI_CODE_NO_AUTO_UPDATE: "1" }, timeout);
@@ -24770,8 +25104,8 @@ function createKimiInstallation(environment) {
24770
25104
  return createInstallationManager({
24771
25105
  async check() {
24772
25106
  const currentVersion = versionFromOutput(await run(["--version"]));
24773
- const home = environment.KIMI_CODE_HOME ?? join2(environment.HOME ?? homedir3(), ".kimi-code");
24774
- const region = await readFile6(join2(home, "region"), "utf8").catch(() => "");
25107
+ const home = environment.KIMI_CODE_HOME ?? join3(environment.HOME ?? homedir3(), ".kimi-code");
25108
+ const region = await readFile7(join3(home, "region"), "utf8").catch(() => "");
24775
25109
  const base = region.trim() === "global" ? "https://code.kimi.ai/kimi-code" : "https://code.kimi.com/kimi-code";
24776
25110
  const latestVersion = installationVersion(await fetchInstallationText(`${base}/latest`));
24777
25111
  const npm = await npmInstallation(executable(), ["@moonshot-ai/kimi-code"], environment);
@@ -24781,7 +25115,10 @@ function createKimiInstallation(environment) {
24781
25115
  latestVersion,
24782
25116
  updateAvailable: newerInstallationVersion(currentVersion, latestVersion),
24783
25117
  canUpdate,
24784
- ...!canUpdate ? { message: "Use the original installer to update this Kimi installation" } : {}
25118
+ ...!canUpdate ? {
25119
+ messageCode: "original-installer",
25120
+ message: "Use the original installer to update this Kimi installation"
25121
+ } : {}
24785
25122
  };
24786
25123
  },
24787
25124
  async update(state) {
@@ -24804,7 +25141,13 @@ function createHarnessAdapter(context) {
24804
25141
  return Object.assign(new KimiAdapter({
24805
25142
  ...environment[KIMI_COMMAND_ENV] ? { command: environment[KIMI_COMMAND_ENV] } : {},
24806
25143
  environment
24807
- }), { installation: createKimiInstallation(environment) });
25144
+ }), {
25145
+ installation: createKimiInstallation(environment),
25146
+ install: createHarnessInstaller(environment, {
25147
+ posix: "https://code.kimi.com/kimi-code/install.sh",
25148
+ windows: "https://code.kimi.com/kimi-code/install.ps1"
25149
+ })
25150
+ });
24808
25151
  }
24809
25152
  export {
24810
25153
  createHarnessAdapter