@codexhost/cli-darwin-x64 0.11.0 → 0.12.1

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,351 @@ 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
+ async function fetchInstallationText(url2) {
281
+ const request = async () => {
282
+ const response = await fetch(url2, { signal: AbortSignal.timeout(15e3) });
283
+ if (!response.ok)
284
+ throw new Error("Could not check the latest Harness version");
285
+ return response.text();
286
+ };
287
+ try {
288
+ return await request();
289
+ } catch (error51) {
290
+ if (error51 instanceof DOMException && (error51.name === "AbortError" || error51.name === "TimeoutError"))
291
+ throw error51;
292
+ return request();
293
+ }
294
+ }
295
+
296
+ // ../../harness-discovery/dist/installer.js
297
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
298
+ import { tmpdir } from "node:os";
299
+ import { join } from "node:path";
300
+ function createHarnessInstaller(environment, source) {
301
+ return async () => {
302
+ if (!["darwin", "linux", "win32"].includes(process.platform))
303
+ throw new Error("Unsupported installation platform");
304
+ const env = withNodeRuntimeOnPath(environment);
305
+ if ("npm" in source) {
306
+ const npm = resolveHarnessExecutable({
307
+ id: "npm",
308
+ command: "npm",
309
+ installRoots: {
310
+ posix: [
311
+ "~/.npm-global/bin",
312
+ "~/.local/bin",
313
+ VERSION_MANAGER_ROOTS,
314
+ "/opt/homebrew/bin",
315
+ "/usr/local/bin",
316
+ "/usr/bin"
317
+ ],
318
+ windows: [
319
+ "${APPDATA}/npm",
320
+ VERSION_MANAGER_ROOTS,
321
+ "${ProgramFiles}/nodejs",
322
+ "${LOCALAPPDATA}/Programs/nodejs"
323
+ ]
324
+ }
325
+ }, { environment: env });
326
+ if (!npm)
327
+ throw new Error("Install Node.js and npm first");
328
+ await runInstallationCommand(npm.executable, ["install", "--global", source.npm], {
329
+ ...env,
330
+ ...source.allowScripts ? { npm_config_allow_scripts: source.allowScripts } : {}
331
+ }, 6e5);
332
+ return;
333
+ }
334
+ const windows = process.platform === "win32";
335
+ const url2 = windows ? source.windows : source.posix;
336
+ if (new URL(url2).protocol !== "https:")
337
+ throw new Error("Installer requires HTTPS");
338
+ const script = await fetchInstallationText(url2);
339
+ const directory = await mkdtemp(join(tmpdir(), "codexhost-installer-"));
340
+ try {
341
+ const file2 = join(directory, windows ? "install.ps1" : "install.sh");
342
+ await writeFile(file2, script, { mode: 384 });
343
+ await runInstallationCommand(windows ? "powershell.exe" : source.shell ?? "bash", windows ? ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", file2] : [file2], env, 6e5);
344
+ } finally {
345
+ await rm(directory, { recursive: true, force: true });
346
+ }
347
+ };
348
+ }
349
+
8
350
  // dist/kiro-adapter.js
9
351
  import { randomUUID } from "node:crypto";
10
- import path7 from "node:path";
352
+ import path8 from "node:path";
11
353
 
12
354
  // ../../../node_modules/zod/v4/classic/external.js
13
355
  var external_exports = {};
@@ -775,10 +1117,10 @@ function mergeDefs(...defs) {
775
1117
  function cloneDef(schema) {
776
1118
  return mergeDefs(schema._zod.def);
777
1119
  }
778
- function getElementAtPath(obj, path8) {
779
- if (!path8)
1120
+ function getElementAtPath(obj, path9) {
1121
+ if (!path9)
780
1122
  return obj;
781
- return path8.reduce((acc, key) => acc?.[key], obj);
1123
+ return path9.reduce((acc, key) => acc?.[key], obj);
782
1124
  }
783
1125
  function promiseAllObject(promisesObj) {
784
1126
  const keys = Object.keys(promisesObj);
@@ -1187,11 +1529,11 @@ function explicitlyAborted(x, startIndex = 0) {
1187
1529
  }
1188
1530
  return false;
1189
1531
  }
1190
- function prefixIssues(path8, issues) {
1532
+ function prefixIssues(path9, issues) {
1191
1533
  return issues.map((iss) => {
1192
1534
  var _a3;
1193
1535
  (_a3 = iss).path ?? (_a3.path = []);
1194
- iss.path.unshift(path8);
1536
+ iss.path.unshift(path9);
1195
1537
  return iss;
1196
1538
  });
1197
1539
  }
@@ -1338,16 +1680,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
1338
1680
  }
1339
1681
  function formatError(error51, mapper = (issue2) => issue2.message) {
1340
1682
  const fieldErrors = { _errors: [] };
1341
- const processError = (error52, path8 = []) => {
1683
+ const processError = (error52, path9 = []) => {
1342
1684
  for (const issue2 of error52.issues) {
1343
1685
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1344
- issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
1686
+ issue2.errors.map((issues) => processError({ issues }, [...path9, ...issue2.path]));
1345
1687
  } else if (issue2.code === "invalid_key") {
1346
- processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1688
+ processError({ issues: issue2.issues }, [...path9, ...issue2.path]);
1347
1689
  } else if (issue2.code === "invalid_element") {
1348
- processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1690
+ processError({ issues: issue2.issues }, [...path9, ...issue2.path]);
1349
1691
  } else {
1350
- const fullpath = [...path8, ...issue2.path];
1692
+ const fullpath = [...path9, ...issue2.path];
1351
1693
  if (fullpath.length === 0) {
1352
1694
  fieldErrors._errors.push(mapper(issue2));
1353
1695
  } else {
@@ -1374,17 +1716,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
1374
1716
  }
1375
1717
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
1376
1718
  const result = { errors: [] };
1377
- const processError = (error52, path8 = []) => {
1719
+ const processError = (error52, path9 = []) => {
1378
1720
  var _a3, _b;
1379
1721
  for (const issue2 of error52.issues) {
1380
1722
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1381
- issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
1723
+ issue2.errors.map((issues) => processError({ issues }, [...path9, ...issue2.path]));
1382
1724
  } else if (issue2.code === "invalid_key") {
1383
- processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1725
+ processError({ issues: issue2.issues }, [...path9, ...issue2.path]);
1384
1726
  } else if (issue2.code === "invalid_element") {
1385
- processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1727
+ processError({ issues: issue2.issues }, [...path9, ...issue2.path]);
1386
1728
  } else {
1387
- const fullpath = [...path8, ...issue2.path];
1729
+ const fullpath = [...path9, ...issue2.path];
1388
1730
  if (fullpath.length === 0) {
1389
1731
  result.errors.push(mapper(issue2));
1390
1732
  continue;
@@ -1416,8 +1758,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
1416
1758
  }
1417
1759
  function toDotPath(_path) {
1418
1760
  const segs = [];
1419
- const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1420
- for (const seg of path8) {
1761
+ const path9 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1762
+ for (const seg of path9) {
1421
1763
  if (typeof seg === "number")
1422
1764
  segs.push(`[${seg}]`);
1423
1765
  else if (typeof seg === "symbol")
@@ -14109,13 +14451,13 @@ function resolveRef(ref, ctx) {
14109
14451
  if (!ref.startsWith("#")) {
14110
14452
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14111
14453
  }
14112
- const path8 = ref.slice(1).split("/").filter(Boolean);
14113
- if (path8.length === 0) {
14454
+ const path9 = ref.slice(1).split("/").filter(Boolean);
14455
+ if (path9.length === 0) {
14114
14456
  return ctx.rootSchema;
14115
14457
  }
14116
14458
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14117
- if (path8[0] === defsKey) {
14118
- const key = path8[1];
14459
+ if (path9[0] === defsKey) {
14460
+ const key = path9[1];
14119
14461
  if (!key || !ctx.defs[key]) {
14120
14462
  throw new Error(`Reference not found: ${ref}`);
14121
14463
  }
@@ -14593,6 +14935,20 @@ var harnessDisplaySetSchema = external_exports.strictObject({
14593
14935
  initializeOnly: external_exports.boolean().optional()
14594
14936
  });
14595
14937
 
14938
+ // ../../shared-contracts/dist/ids.js
14939
+ var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
14940
+ message: "Identifier must not be empty or whitespace"
14941
+ });
14942
+ var harnessIdSchema = opaqueIdSchema.brand();
14943
+ var hostThreadIdSchema = opaqueIdSchema.brand();
14944
+ var hostTurnIdSchema = opaqueIdSchema.brand();
14945
+ var hostItemIdSchema = opaqueIdSchema.brand();
14946
+ var hostInteractionIdSchema = opaqueIdSchema.brand();
14947
+
14948
+ // ../../shared-contracts/dist/thread-prewarm.js
14949
+ var threadPrewarmDiscardParamsSchema = external_exports.object({ threadId: hostThreadIdSchema });
14950
+ var threadPrewarmDiscardResultSchema = external_exports.object({ discarded: external_exports.boolean() });
14951
+
14596
14952
  // ../../shared-contracts/dist/console.js
14597
14953
  var consoleAnnouncementSchema = external_exports.strictObject({
14598
14954
  title: external_exports.string().trim().min(1).max(200),
@@ -14605,10 +14961,14 @@ var consoleOpenResultSchema = external_exports.strictObject({
14605
14961
  url: external_exports.string().max(2048).regex(/^http:\/\/(?:127\.0\.0\.1|localhost):\d{1,5}\/(?:\?.*)?$/u)
14606
14962
  });
14607
14963
  var CONSOLE_HOST_METHODS = Object.freeze([
14964
+ "codexhost/console/remote-connections",
14965
+ "codexhost/runtime/status",
14966
+ "codexhost/remote/ssh-setup",
14608
14967
  "codexhost/harness/plugins/list",
14609
14968
  "codexhost/harness/display-settings/get",
14610
14969
  "codexhost/harness/display-settings/set",
14611
14970
  "codexhost/harness/inspect",
14971
+ "codexhost/harness/installation",
14612
14972
  "codexhost/harness/launch-settings/get",
14613
14973
  "codexhost/harness/launch-settings/set",
14614
14974
  "codexhost/harness/web-ui/open",
@@ -14670,16 +15030,6 @@ var loadedSessionsSchema = external_exports.array(external_exports.strictObject(
14670
15030
  inactiveMs: external_exports.number().nonnegative()
14671
15031
  }));
14672
15032
 
14673
- // ../../shared-contracts/dist/ids.js
14674
- var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
14675
- message: "Identifier must not be empty or whitespace"
14676
- });
14677
- var harnessIdSchema = opaqueIdSchema.brand();
14678
- var hostThreadIdSchema = opaqueIdSchema.brand();
14679
- var hostTurnIdSchema = opaqueIdSchema.brand();
14680
- var hostItemIdSchema = opaqueIdSchema.brand();
14681
- var hostInteractionIdSchema = opaqueIdSchema.brand();
14682
-
14683
15033
  // ../../shared-contracts/dist/manual-compaction.js
14684
15034
  var threadManualCompactionStartedSchema = external_exports.strictObject({
14685
15035
  threadId: hostThreadIdSchema,
@@ -15255,14 +15605,17 @@ var harnessLaunchSettingsSchema = external_exports.object({
15255
15605
  // ../../shared-contracts/dist/harness-installation.js
15256
15606
  var harnessInstallationParamsSchema = external_exports.object({
15257
15607
  harnessId: harnessIdSchema,
15258
- action: external_exports.enum(["check", "update"])
15608
+ action: external_exports.enum(["check", "update", "install"])
15259
15609
  }).strict();
15260
15610
  var harnessInstallationStateSchema = external_exports.object({
15261
15611
  currentVersion: external_exports.string().min(1).max(128),
15262
15612
  latestVersion: external_exports.string().min(1).max(128),
15263
15613
  updateAvailable: external_exports.boolean(),
15264
15614
  canUpdate: external_exports.boolean(),
15265
- message: external_exports.string().max(2048).optional()
15615
+ // Adapter-owned diagnostic text; UI uses messageCode rather than displaying it verbatim.
15616
+ message: external_exports.string().max(2048).optional(),
15617
+ messageCode: external_exports.string().min(1).max(128).optional(),
15618
+ latestVersionKind: external_exports.enum(["unknown", "tracking-branch"]).optional()
15266
15619
  }).strict();
15267
15620
 
15268
15621
  // ../../shared-contracts/dist/codex-accounts.js
@@ -15564,6 +15917,80 @@ var updateStatusResultSchema = external_exports.strictObject({
15564
15917
  status: updateStatusSchema.nullable()
15565
15918
  });
15566
15919
 
15920
+ // ../../shared-contracts/dist/remote-runtime.js
15921
+ var remoteUpdatePhaseSchema = external_exports.enum([
15922
+ "idle",
15923
+ "installing",
15924
+ "restarting",
15925
+ "succeeded",
15926
+ "failed"
15927
+ ]);
15928
+ var runtimeStatusSchema = external_exports.object({
15929
+ runningVersion: external_exports.string().nullable(),
15930
+ installedVersion: external_exports.string().nullable(),
15931
+ restartRequired: external_exports.boolean(),
15932
+ remote: external_exports.boolean(),
15933
+ updateSupported: external_exports.boolean(),
15934
+ update: external_exports.object({
15935
+ phase: remoteUpdatePhaseSchema,
15936
+ targetVersion: external_exports.string().nullable(),
15937
+ error: external_exports.string().nullable()
15938
+ })
15939
+ });
15940
+ var remoteUpdateParamsSchema = external_exports.object({
15941
+ version: external_exports.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
15942
+ }).strict();
15943
+ var remoteSshSetupParamsSchema = external_exports.object({
15944
+ hostname: external_exports.string().min(1).max(1024).refine((value) => !value.startsWith("-") && !/\s/u.test(value)),
15945
+ port: external_exports.number().int().min(1).max(65535).nullable(),
15946
+ identity: external_exports.string().max(4096).nullable(),
15947
+ action: external_exports.enum(["inspect", "install", "update", "repair", "uninstall"]),
15948
+ uninstallPackage: external_exports.boolean().optional(),
15949
+ version: external_exports.string().regex(/^\d+\.\d+\.\d+$/u).nullable()
15950
+ }).strict();
15951
+ var remoteSshSetupResultSchema = external_exports.object({ state: external_exports.enum(["installed", "not-installed"]) }).strict();
15952
+
15953
+ // ../../shared-contracts/dist/remote-connections.js
15954
+ var hostId = external_exports.string().min(1).max(1024);
15955
+ var codexSshConnectionSchema = external_exports.object({
15956
+ hostId,
15957
+ displayName: external_exports.string().min(1).max(1024),
15958
+ source: external_exports.enum(["codex-managed", "discovered"]),
15959
+ sshAlias: external_exports.string().max(1024).nullable(),
15960
+ sshHost: external_exports.string().min(1).max(1024),
15961
+ sshPort: external_exports.number().int().min(1).max(65535).nullable(),
15962
+ identity: external_exports.string().max(4096).nullable(),
15963
+ autoConnect: external_exports.boolean(),
15964
+ connectionAnalyticsId: external_exports.string().max(1024).optional()
15965
+ });
15966
+ var codexSshDraftSchema = external_exports.strictObject({
15967
+ displayName: external_exports.string().min(1).max(1024),
15968
+ hostname: external_exports.string().min(1).max(1024),
15969
+ sshPort: external_exports.number().int().min(1).max(65535).nullable(),
15970
+ identity: external_exports.string().max(4096).nullable()
15971
+ });
15972
+ var remoteConnectionsRequestSchema = external_exports.discriminatedUnion("action", [
15973
+ external_exports.strictObject({ action: external_exports.literal("list") }),
15974
+ external_exports.strictObject({
15975
+ action: external_exports.literal("save"),
15976
+ draft: codexSshDraftSchema,
15977
+ previous: codexSshConnectionSchema.nullable()
15978
+ }),
15979
+ external_exports.strictObject({ action: external_exports.literal("remove"), previous: codexSshConnectionSchema }),
15980
+ external_exports.strictObject({ action: external_exports.literal("connect"), hostId, enabled: external_exports.boolean() }),
15981
+ external_exports.strictObject({ action: external_exports.literal("state"), hostId }),
15982
+ external_exports.strictObject({ action: external_exports.literal("runtime"), hostId }),
15983
+ external_exports.strictObject({
15984
+ action: external_exports.literal("update"),
15985
+ hostId: hostId.refine((id) => id !== "local"),
15986
+ version: remoteUpdateParamsSchema.shape.version
15987
+ })
15988
+ ]);
15989
+ var remoteConnectionsReplySchema = external_exports.union([
15990
+ external_exports.strictObject({ result: jsonValueSchema }),
15991
+ external_exports.strictObject({ error: external_exports.strictObject({ code: external_exports.number().int(), message: external_exports.string() }) })
15992
+ ]);
15993
+
15567
15994
  // ../../shared-contracts/dist/index.js
15568
15995
  var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
15569
15996
 
@@ -15582,581 +16009,308 @@ function invalidRequest2(message) {
15582
16009
  function validateHostQuestionResponse(interaction, response) {
15583
16010
  const questionIds = new Set(interaction.questions.map(({ id }) => id));
15584
16011
  if (response.cancelled) {
15585
- return Object.keys(response.answers).length === 0 ? null : invalidRequest2("Cancelled Question Response must not contain answers");
15586
- }
15587
- for (const answerId of Object.keys(response.answers)) {
15588
- if (!questionIds.has(answerId)) {
15589
- return invalidRequest2("Question Response contains an unknown Question ID");
15590
- }
15591
- }
15592
- for (const question of interaction.questions) {
15593
- const answers = response.answers[question.id] ?? [];
15594
- if (!question.optional && answers.length === 0) {
15595
- return invalidRequest2("Question Response omits a required answer");
15596
- }
15597
- if (question.type === "text") {
15598
- if (answers.length > 1) {
15599
- return invalidRequest2("Text Question accepts at most one answer");
15600
- }
15601
- continue;
15602
- }
15603
- if (!question.multiple && answers.length > 1) {
15604
- return invalidRequest2("Single-choice Question accepts at most one answer");
15605
- }
15606
- const declared = new Set(question.options.map(({ value }) => value));
15607
- if (!question.allowOther && answers.some((answer) => !declared.has(answer))) {
15608
- return invalidRequest2("Question Response contains an undeclared choice");
15609
- }
15610
- }
15611
- return null;
15612
- }
15613
-
15614
- // ../../harness-adapter/dist/output-channel.js
15615
- var HarnessOutputChannel = class {
15616
- outputs;
15617
- #consumerCreated = false;
15618
- #ended = false;
15619
- #pending = [];
15620
- #values = [];
15621
- constructor() {
15622
- this.outputs = {
15623
- [Symbol.asyncIterator]: () => {
15624
- if (this.#consumerCreated) {
15625
- throw new Error("Harness outputs allow only one consumer");
15626
- }
15627
- this.#consumerCreated = true;
15628
- return {
15629
- next: () => this.#next()
15630
- };
15631
- }
15632
- };
15633
- }
15634
- emit(value) {
15635
- if (this.#ended)
15636
- return false;
15637
- const resolve = this.#pending.shift();
15638
- if (resolve)
15639
- resolve({ done: false, value });
15640
- else
15641
- this.#values.push(value);
15642
- return true;
15643
- }
15644
- end() {
15645
- if (this.#ended)
15646
- return;
15647
- this.#ended = true;
15648
- if (this.#values.length !== 0)
15649
- return;
15650
- for (const resolve of this.#pending.splice(0))
15651
- resolve({ done: true, value: void 0 });
15652
- }
15653
- #next() {
15654
- const value = this.#values.shift();
15655
- if (value !== void 0)
15656
- return Promise.resolve({ done: false, value });
15657
- if (this.#ended)
15658
- return Promise.resolve({ done: true, value: void 0 });
15659
- return new Promise((resolve) => this.#pending.push(resolve));
15660
- }
15661
- };
15662
-
15663
- // ../../harness-adapter/dist/diagnostics.js
15664
- var DIAGNOSTIC_TAIL_MAX_LENGTH = 8e3;
15665
- var SENSITIVE_VALUE_PATTERN = /(api[_-]?key|access[_-]?token|auth(?:orization)?|password|secret)(\s*[:=]\s*)([^\s,;]+)/giu;
15666
- var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/giu;
15667
- function sanitizeDiagnosticTail(value) {
15668
- const redacted = value.replace(BEARER_PATTERN, "Bearer [redacted]").replace(SENSITIVE_VALUE_PATTERN, "$1$2[redacted]");
15669
- return redacted.length <= DIAGNOSTIC_TAIL_MAX_LENGTH ? redacted : redacted.slice(-DIAGNOSTIC_TAIL_MAX_LENGTH);
15670
- }
15671
-
15672
- // ../../harness-adapter/dist/usage.js
15673
- var tokenFields = [
15674
- "inputTokens",
15675
- "cachedInputTokens",
15676
- "cacheWriteInputTokens",
15677
- "outputTokens",
15678
- "outputTokensPerSecond",
15679
- "reasoningOutputTokens",
15680
- "totalTokens",
15681
- "contextWindowTokens",
15682
- "contextUsedTokens"
15683
- ];
15684
- var safeIntegerFields = [
15685
- "planFiveHourResetsAtUnix",
15686
- "planSevenDayResetsAtUnix"
15687
- ];
15688
- var percentFields = [
15689
- "cacheHitRatePercent",
15690
- "planFiveHourUsedPercent",
15691
- "planSevenDayUsedPercent"
15692
- ];
15693
- var usageFields = /* @__PURE__ */ new Set([
15694
- ...tokenFields,
15695
- ...safeIntegerFields,
15696
- ...percentFields,
15697
- "totalCostUsd",
15698
- "totalCredits",
15699
- "contextUsagePercent"
15700
- ]);
15701
- function isRecord(value) {
15702
- return typeof value === "object" && value !== null && !Array.isArray(value);
15703
- }
15704
- function parseHostUsage(value) {
15705
- if (!isRecord(value))
15706
- throw new Error("Harness Usage must be an object");
15707
- const keys = Object.keys(value);
15708
- if (keys.length === 0)
15709
- throw new Error("Harness Usage must contain a reliable field");
15710
- for (const key of keys) {
15711
- if (!usageFields.has(key)) {
15712
- throw new Error(`Harness Usage contains unknown field '${key}'`);
15713
- }
16012
+ return Object.keys(response.answers).length === 0 ? null : invalidRequest2("Cancelled Question Response must not contain answers");
15714
16013
  }
15715
- for (const field of ["totalCredits", "contextUsagePercent"]) {
15716
- const candidate = value[field];
15717
- if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)) {
15718
- throw new Error(`Harness Usage '${field}' must be a finite non-negative number`);
16014
+ for (const answerId of Object.keys(response.answers)) {
16015
+ if (!questionIds.has(answerId)) {
16016
+ return invalidRequest2("Question Response contains an unknown Question ID");
15719
16017
  }
15720
16018
  }
15721
- for (const field of tokenFields) {
15722
- const candidate = value[field];
15723
- if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
15724
- throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
16019
+ for (const question of interaction.questions) {
16020
+ const answers = response.answers[question.id] ?? [];
16021
+ if (!question.optional && answers.length === 0) {
16022
+ return invalidRequest2("Question Response omits a required answer");
15725
16023
  }
15726
- }
15727
- for (const field of safeIntegerFields) {
15728
- const candidate = value[field];
15729
- if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
15730
- throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
16024
+ if (question.type === "text") {
16025
+ if (answers.length > 1) {
16026
+ return invalidRequest2("Text Question accepts at most one answer");
16027
+ }
16028
+ continue;
15731
16029
  }
15732
- }
15733
- if (value.outputTokensPerSecond !== void 0 && (typeof value.outputTokensPerSecond !== "number" || !Number.isFinite(value.outputTokensPerSecond) || value.outputTokensPerSecond < 0)) {
15734
- throw new Error("Harness Usage 'outputTokensPerSecond' must be a finite non-negative number");
15735
- }
15736
- if (value.totalCostUsd !== void 0 && (typeof value.totalCostUsd !== "number" || !Number.isFinite(value.totalCostUsd) || value.totalCostUsd < 0)) {
15737
- throw new Error("Harness Usage 'totalCostUsd' must be a finite non-negative number");
15738
- }
15739
- for (const field of percentFields) {
15740
- const candidate = value[field];
15741
- if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0 || candidate > 100)) {
15742
- throw new Error(`Harness Usage '${field}' must be between 0 and 100`);
16030
+ if (!question.multiple && answers.length > 1) {
16031
+ return invalidRequest2("Single-choice Question accepts at most one answer");
16032
+ }
16033
+ const declared = new Set(question.options.map(({ value }) => value));
16034
+ if (!question.allowOther && answers.some((answer) => !declared.has(answer))) {
16035
+ return invalidRequest2("Question Response contains an undeclared choice");
15743
16036
  }
15744
16037
  }
15745
- const hasContextUsed = value.contextUsedTokens !== void 0;
15746
- const hasContextWindow = value.contextWindowTokens !== void 0;
15747
- if (hasContextUsed !== hasContextWindow) {
15748
- throw new Error("Harness Usage context fields must be provided together");
15749
- }
15750
- if (hasContextWindow && value.contextWindowTokens === 0) {
15751
- throw new Error("Harness Usage 'contextWindowTokens' must be greater than zero");
15752
- }
15753
- if (value.planFiveHourResetsAtUnix !== void 0 && value.planFiveHourUsedPercent === void 0) {
15754
- throw new Error("Harness Usage 'planFiveHourResetsAtUnix' must be provided with 'planFiveHourUsedPercent'");
15755
- }
15756
- if (value.planSevenDayResetsAtUnix !== void 0 && value.planSevenDayUsedPercent === void 0) {
15757
- throw new Error("Harness Usage 'planSevenDayResetsAtUnix' must be provided with 'planSevenDayUsedPercent'");
15758
- }
15759
- return { ...value };
15760
- }
15761
-
15762
- // ../../harness-adapter/dist/live-command-catalog.js
15763
- var COMMON_EXCLUDED_LIVE_COMMANDS = /* @__PURE__ */ new Set([
15764
- // Session lifecycle
15765
- "branch",
15766
- "clear",
15767
- "exit",
15768
- "fork",
15769
- "fresh",
15770
- "new",
15771
- "quit",
15772
- "rename",
15773
- "rename-chat",
15774
- "reset",
15775
- "resume",
15776
- "rewind",
15777
- "session",
15778
- "sessions",
15779
- // Desktop-owned configuration
15780
- "autocompact",
15781
- "color",
15782
- "config",
15783
- "effort",
15784
- "fast",
15785
- "keybindings",
15786
- "model",
15787
- "models",
15788
- "output-style",
15789
- "permissions",
15790
- "settings",
15791
- "statusline",
15792
- "terminal-setup",
15793
- "theme",
15794
- "vim",
15795
- // Trust and approval policy
15796
- "always-approve",
15797
- "auto-mode-setup",
15798
- // Native login
15799
- "login",
15800
- "logout",
15801
- // Work outliving the Turn
15802
- "autopilot",
15803
- "background",
15804
- "bg",
15805
- "goal",
15806
- "jobs",
15807
- "loop",
15808
- "multitask",
15809
- "queue",
15810
- "remote-control",
15811
- "schedule",
15812
- "steer",
15813
- // Native terminal UI
15814
- "copy",
15815
- "debug",
15816
- "feedback",
15817
- "heapdump",
15818
- "share",
15819
- "shell",
15820
- // Plugin and MCP management
15821
- "marketplace",
15822
- "mcp",
15823
- "plugins",
15824
- "reload-plugins"
15825
- ]);
15826
- var COMMON_EXCLUDED_LIVE_COMMAND_PREFIXES = ["__", "hooks-"];
15827
- function isExcludedLiveCommand(name, kind, extra = {}) {
15828
- const normalized = name.trim().replace(/^\//u, "");
15829
- if (new Set(extra.names ?? []).has(normalized))
15830
- return true;
15831
- if (extra.prefixes?.some((prefix) => normalized.startsWith(prefix)))
15832
- return true;
15833
- if (kind === "skill")
15834
- return false;
15835
- return COMMON_EXCLUDED_LIVE_COMMANDS.has(normalized) || COMMON_EXCLUDED_LIVE_COMMAND_PREFIXES.some((prefix) => normalized.startsWith(prefix));
15836
- }
15837
- function liveHarnessCommandPrompt(catalog, idPrefix, commandId, argumentText) {
15838
- if (!commandId.startsWith(idPrefix))
15839
- return null;
15840
- const descriptor = catalog.commands.find(({ id }) => id === commandId);
15841
- if (!descriptor)
15842
- return null;
15843
- const text = typeof argumentText === "string" ? argumentText.trim() : "";
15844
- return text ? `${descriptor.invocation} ${text}` : descriptor.invocation;
15845
- }
15846
- function mergeLiveHarnessCommands(builtIns, idPrefix, live, exclusions = {}) {
15847
- if (!live)
15848
- return builtIns;
15849
- const invocations = new Set(builtIns.commands.map(({ invocation }) => invocation));
15850
- const ids = new Set(builtIns.commands.map(({ id }) => id));
15851
- const dynamic = [];
15852
- for (const command of live) {
15853
- const name = command.name.trim().replace(/^\//u, "");
15854
- if (!name || /\s/u.test(name))
15855
- continue;
15856
- if (isExcludedLiveCommand(name, command.kind, exclusions))
15857
- continue;
15858
- const invocation = `/${name}`;
15859
- const id = `${idPrefix}${name.replace(/[^A-Za-z0-9._:-]/gu, "-")}`.slice(0, 128);
15860
- if (invocations.has(invocation) || ids.has(id))
15861
- continue;
15862
- const description = command.description?.trim().slice(0, 512);
15863
- const parsed = harnessCommandDescriptorSchema.safeParse({
15864
- id,
15865
- invocation,
15866
- label: name.slice(0, 128),
15867
- ...description ? { description } : {},
15868
- argumentMode: "text",
15869
- kind: command.kind
15870
- });
15871
- if (!parsed.success)
15872
- continue;
15873
- invocations.add(invocation);
15874
- ids.add(id);
15875
- dynamic.push(parsed.data);
15876
- }
15877
- return harnessCommandCatalogSchema.parse({ commands: [...builtIns.commands, ...dynamic] });
16038
+ return null;
15878
16039
  }
15879
16040
 
15880
- // dist/acp-transport.js
15881
- import { spawn, spawnSync } from "node:child_process";
15882
- import { Readable, Writable } from "node:stream";
15883
- import { execFile as execFile2 } from "node:child_process";
15884
- import { promisify } from "node:util";
15885
- import { setTimeout as delay } from "node:timers/promises";
15886
-
15887
- // ../../harness-discovery/dist/environment.js
15888
- import fs from "node:fs";
15889
- import path from "node:path";
15890
- function targetPath(platform) {
15891
- return platform === "win32" ? path.win32 : path.posix;
15892
- }
15893
- function environmentValue(environment, name) {
15894
- const lowered = name.toLowerCase();
15895
- for (const [key, value] of Object.entries(environment)) {
15896
- if (key.toLowerCase() === lowered)
15897
- return value;
16041
+ // ../../harness-adapter/dist/output-channel.js
16042
+ var HarnessOutputChannel = class {
16043
+ outputs;
16044
+ #consumerCreated = false;
16045
+ #ended = false;
16046
+ #pending = [];
16047
+ #values = [];
16048
+ constructor() {
16049
+ this.outputs = {
16050
+ [Symbol.asyncIterator]: () => {
16051
+ if (this.#consumerCreated) {
16052
+ throw new Error("Harness outputs allow only one consumer");
16053
+ }
16054
+ this.#consumerCreated = true;
16055
+ return {
16056
+ next: () => this.#next()
16057
+ };
16058
+ }
16059
+ };
15898
16060
  }
15899
- return void 0;
15900
- }
15901
- function pathDelimiter(platform) {
15902
- return platform === "win32" ? ";" : ":";
15903
- }
15904
- function pathDirectories(environment, platform) {
15905
- return (environmentValue(environment, "PATH") ?? "").split(pathDelimiter(platform)).map((directory) => directory.trim().replace(/^"|"$/gu, "")).filter(Boolean);
15906
- }
15907
- function executableExtensions(command, platform, environment) {
15908
- if (platform !== "win32")
15909
- return [""];
15910
- if (targetPath(platform).extname(command) !== "")
15911
- return [""];
15912
- return (environmentValue(environment, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter(Boolean);
15913
- }
15914
- function isExecutableFile(filePath, platform) {
15915
- try {
15916
- fs.accessSync(filePath, platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK);
15917
- return fs.statSync(filePath).isFile();
15918
- } catch {
15919
- return false;
16061
+ emit(value) {
16062
+ if (this.#ended)
16063
+ return false;
16064
+ const resolve = this.#pending.shift();
16065
+ if (resolve)
16066
+ resolve({ done: false, value });
16067
+ else
16068
+ this.#values.push(value);
16069
+ return true;
15920
16070
  }
15921
- }
15922
- function subdirectoryNames(directory) {
15923
- try {
15924
- return fs.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
15925
- } catch {
15926
- return [];
16071
+ end() {
16072
+ if (this.#ended)
16073
+ return;
16074
+ this.#ended = true;
16075
+ if (this.#values.length !== 0)
16076
+ return;
16077
+ for (const resolve of this.#pending.splice(0))
16078
+ resolve({ done: true, value: void 0 });
15927
16079
  }
15928
- }
15929
- function newestFirst(names) {
15930
- return [...names].sort((left, right) => right.localeCompare(left, void 0, { numeric: true }));
15931
- }
15932
-
15933
- // ../../harness-discovery/dist/invocation.js
15934
- import path2 from "node:path";
15935
- function commandInvocation(command, arguments_, environment, platform = process.platform) {
15936
- const extension = path2.win32.extname(command).toLowerCase();
15937
- if (platform !== "win32" || ![".cmd", ".bat"].includes(extension)) {
15938
- return { command, arguments: [...arguments_], windowsVerbatimArguments: false };
16080
+ #next() {
16081
+ const value = this.#values.shift();
16082
+ if (value !== void 0)
16083
+ return Promise.resolve({ done: false, value });
16084
+ if (this.#ended)
16085
+ return Promise.resolve({ done: true, value: void 0 });
16086
+ return new Promise((resolve) => this.#pending.push(resolve));
15939
16087
  }
15940
- const quote = (value) => `"${value.replaceAll("%", "%%").replaceAll('"', '""')}"`;
15941
- const commandLine = [command, ...arguments_].map(quote).join(" ");
15942
- return {
15943
- command: environmentValue(environment, "ComSpec") ?? "cmd.exe",
15944
- arguments: ["/d", "/v:off", "/s", "/c", `"${commandLine}"`],
15945
- windowsVerbatimArguments: true
15946
- };
15947
- }
16088
+ };
15948
16089
 
15949
- // ../../harness-discovery/dist/node-runtime.js
15950
- import path3 from "node:path";
15951
- function withNodeRuntimeOnPath(environment, runtimeExecutable = process.execPath, platform = process.platform) {
15952
- const pathKey = Object.keys(environment).find((name) => name.toLowerCase() === "path") ?? "PATH";
15953
- const delimiter = platform === "win32" ? ";" : ":";
15954
- const runtimeDirectory = path3.dirname(runtimeExecutable);
15955
- const directories = (environment[pathKey] ?? "").split(delimiter).filter(Boolean);
15956
- const equal = platform === "win32" ? (value) => value.toLowerCase() : (value) => value;
15957
- if (!directories.some((directory) => equal(directory) === equal(runtimeDirectory))) {
15958
- directories.push(runtimeDirectory);
15959
- }
15960
- return { ...environment, [pathKey]: directories.join(delimiter) };
16090
+ // ../../harness-adapter/dist/diagnostics.js
16091
+ var DIAGNOSTIC_TAIL_MAX_LENGTH = 8e3;
16092
+ var SENSITIVE_VALUE_PATTERN = /(api[_-]?key|access[_-]?token|auth(?:orization)?|password|secret)(\s*[:=]\s*)([^\s,;]+)/giu;
16093
+ var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/giu;
16094
+ function sanitizeDiagnosticTail(value) {
16095
+ const redacted = value.replace(BEARER_PATTERN, "Bearer [redacted]").replace(SENSITIVE_VALUE_PATTERN, "$1$2[redacted]");
16096
+ return redacted.length <= DIAGNOSTIC_TAIL_MAX_LENGTH ? redacted : redacted.slice(-DIAGNOSTIC_TAIL_MAX_LENGTH);
15961
16097
  }
15962
16098
 
15963
- // ../../harness-discovery/dist/resolve.js
15964
- import os from "node:os";
15965
-
15966
- // ../../harness-discovery/dist/version-managers.js
15967
- function versionManagerBinaryDirectories(context) {
15968
- const { platform, environment, home } = context;
15969
- const list = context.subdirectories ?? subdirectoryNames;
15970
- const pathFlavor = targetPath(platform);
15971
- const value = (name) => environmentValue(environment, name);
15972
- const directories = [];
15973
- const versioned = (root, ...tail) => {
15974
- for (const version2 of newestFirst(list(root))) {
15975
- directories.push(pathFlavor.join(root, version2, ...tail));
16099
+ // ../../harness-adapter/dist/usage.js
16100
+ var tokenFields = [
16101
+ "inputTokens",
16102
+ "cachedInputTokens",
16103
+ "cacheWriteInputTokens",
16104
+ "outputTokens",
16105
+ "outputTokensPerSecond",
16106
+ "reasoningOutputTokens",
16107
+ "totalTokens",
16108
+ "contextWindowTokens",
16109
+ "contextUsedTokens"
16110
+ ];
16111
+ var safeIntegerFields = [
16112
+ "planFiveHourResetsAtUnix",
16113
+ "planSevenDayResetsAtUnix"
16114
+ ];
16115
+ var percentFields = [
16116
+ "cacheHitRatePercent",
16117
+ "planFiveHourUsedPercent",
16118
+ "planSevenDayUsedPercent"
16119
+ ];
16120
+ var usageFields = /* @__PURE__ */ new Set([
16121
+ ...tokenFields,
16122
+ ...safeIntegerFields,
16123
+ ...percentFields,
16124
+ "totalCostUsd",
16125
+ "totalCredits",
16126
+ "contextUsagePercent"
16127
+ ]);
16128
+ function isRecord(value) {
16129
+ return typeof value === "object" && value !== null && !Array.isArray(value);
16130
+ }
16131
+ function parseHostUsage(value) {
16132
+ if (!isRecord(value))
16133
+ throw new Error("Harness Usage must be an object");
16134
+ const keys = Object.keys(value);
16135
+ if (keys.length === 0)
16136
+ throw new Error("Harness Usage must contain a reliable field");
16137
+ for (const key of keys) {
16138
+ if (!usageFields.has(key)) {
16139
+ throw new Error(`Harness Usage contains unknown field '${key}'`);
15976
16140
  }
15977
- };
15978
- if (platform === "win32") {
15979
- const appData = value("APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming");
15980
- const localAppData = value("LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local");
15981
- versioned(pathFlavor.join(appData, "nvm"));
15982
- versioned(value("FNM_DIR") ?? pathFlavor.join(appData, "fnm", "node-versions"), "installation");
15983
- directories.push(pathFlavor.join(localAppData, "Volta", "bin"));
15984
- directories.push(pathFlavor.join(home, ".bun", "bin"));
15985
- const pnpmHome2 = value("PNPM_HOME");
15986
- if (pnpmHome2)
15987
- directories.push(pnpmHome2);
15988
- directories.push(pathFlavor.join(localAppData, "pnpm"));
15989
- return directories;
15990
- }
15991
- versioned(pathFlavor.join(value("NVM_DIR") ?? pathFlavor.join(home, ".nvm"), "versions", "node"), "bin");
15992
- const fnmRoots = [
15993
- value("FNM_DIR"),
15994
- pathFlavor.join(home, ".local", "share", "fnm"),
15995
- pathFlavor.join(home, "Library", "Application Support", "fnm")
15996
- ].filter((root) => root !== void 0);
15997
- for (const root of fnmRoots) {
15998
- versioned(pathFlavor.join(root, "node-versions"), "installation", "bin");
15999
16141
  }
16000
- const voltaHome = value("VOLTA_HOME") ?? pathFlavor.join(home, ".volta");
16001
- versioned(pathFlavor.join(voltaHome, "tools", "image", "node"), "bin");
16002
- directories.push(pathFlavor.join(voltaHome, "bin"));
16003
- const asdfHome = value("ASDF_DATA_DIR") ?? pathFlavor.join(home, ".asdf");
16004
- versioned(pathFlavor.join(asdfHome, "installs", "nodejs"), "bin");
16005
- directories.push(pathFlavor.join(asdfHome, "shims"));
16006
- const nodenvHome = value("NODENV_ROOT") ?? pathFlavor.join(home, ".nodenv");
16007
- versioned(pathFlavor.join(nodenvHome, "versions"), "bin");
16008
- directories.push(pathFlavor.join(nodenvHome, "shims"));
16009
- versioned(pathFlavor.join(value("N_PREFIX") ?? "/usr/local", "n", "versions", "node"), "bin");
16010
- directories.push(pathFlavor.join(home, ".bun", "bin"));
16011
- const pnpmHome = value("PNPM_HOME");
16012
- if (pnpmHome)
16013
- directories.push(pnpmHome);
16014
- directories.push(pathFlavor.join(home, "Library", "pnpm"));
16015
- directories.push(pathFlavor.join(home, ".local", "share", "pnpm"));
16016
- for (const prefix of ["/opt/homebrew/opt", "/usr/local/opt"]) {
16017
- for (const formula of newestFirst(list(prefix).filter((name) => name.startsWith("node@")))) {
16018
- directories.push(pathFlavor.join(prefix, formula, "bin"));
16142
+ for (const field of ["totalCredits", "contextUsagePercent"]) {
16143
+ const candidate = value[field];
16144
+ if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)) {
16145
+ throw new Error(`Harness Usage '${field}' must be a finite non-negative number`);
16019
16146
  }
16020
16147
  }
16021
- return directories;
16022
- }
16023
-
16024
- // ../../harness-discovery/dist/resolve.js
16025
- var VERSION_MANAGER_ROOTS = "<version-managers>";
16026
- function installRootExtensions(platform) {
16027
- return platform === "win32" ? [".exe", ".cmd"] : [""];
16028
- }
16029
- function resolveHomeDirectory(input) {
16030
- return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
16031
- }
16032
- function templateVariables(environment, platform, home) {
16033
- const pathFlavor = targetPath(platform);
16034
- return {
16035
- HOME: home,
16036
- USERPROFILE: home,
16037
- APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
16038
- LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
16039
- };
16040
- }
16041
- function joinTemplate(platform, value) {
16042
- const pathFlavor = targetPath(platform);
16043
- const segments = value.split("/");
16044
- const head = segments[0] ?? "";
16045
- const tail = segments.slice(1);
16046
- if (head === "")
16047
- return pathFlavor.join(pathFlavor.sep, ...tail);
16048
- return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
16049
- }
16050
- function expandInstallRoot(template, environment, platform, home) {
16051
- const variables = templateVariables(environment, platform, home);
16052
- let unresolved = false;
16053
- const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
16054
- const value = variables[name] ?? environmentValue(environment, name);
16055
- if (value === void 0 || value === "") {
16056
- unresolved = true;
16057
- return "";
16148
+ for (const field of tokenFields) {
16149
+ const candidate = value[field];
16150
+ if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
16151
+ throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
16058
16152
  }
16059
- return value;
16060
- });
16061
- return unresolved ? void 0 : joinTemplate(platform, substituted);
16062
- }
16063
- function installRootDirectories(spec, input, dependencies, platform, home) {
16064
- const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
16065
- const directories = [];
16066
- for (const template of templates) {
16067
- if (template === VERSION_MANAGER_ROOTS) {
16068
- directories.push(...versionManagerBinaryDirectories({
16069
- platform,
16070
- environment: input.environment,
16071
- home,
16072
- ...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
16073
- }));
16074
- continue;
16153
+ }
16154
+ for (const field of safeIntegerFields) {
16155
+ const candidate = value[field];
16156
+ if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
16157
+ throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
16075
16158
  }
16076
- const directory = expandInstallRoot(template, input.environment, platform, home);
16077
- if (directory !== void 0)
16078
- directories.push(directory);
16079
16159
  }
16080
- return directories;
16081
- }
16082
- function harnessCandidates(spec, input, dependencies = {}) {
16083
- const platform = input.platform ?? process.platform;
16084
- const pathFlavor = targetPath(platform);
16085
- const configured = input.command ?? (spec.commandEnvironmentVariable ? environmentValue(input.environment, spec.commandEnvironmentVariable) : void 0);
16086
- const command = configured ?? spec.command;
16087
- if (pathFlavor.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
16088
- return [{ candidate: command, source: "configured" }];
16160
+ if (value.outputTokensPerSecond !== void 0 && (typeof value.outputTokensPerSecond !== "number" || !Number.isFinite(value.outputTokensPerSecond) || value.outputTokensPerSecond < 0)) {
16161
+ throw new Error("Harness Usage 'outputTokensPerSecond' must be a finite non-negative number");
16089
16162
  }
16090
- const candidates = [];
16091
- const extensions = executableExtensions(command, platform, input.environment);
16092
- for (const directory of pathDirectories(input.environment, platform)) {
16093
- for (const extension of extensions) {
16094
- candidates.push({
16095
- candidate: pathFlavor.join(directory, command + extension),
16096
- source: "path"
16097
- });
16098
- }
16163
+ if (value.totalCostUsd !== void 0 && (typeof value.totalCostUsd !== "number" || !Number.isFinite(value.totalCostUsd) || value.totalCostUsd < 0)) {
16164
+ throw new Error("Harness Usage 'totalCostUsd' must be a finite non-negative number");
16099
16165
  }
16100
- if (configured !== void 0)
16101
- return candidates;
16102
- const home = resolveHomeDirectory(input);
16103
- for (const directory of installRootDirectories(spec, input, dependencies, platform, home)) {
16104
- for (const extension of installRootExtensions(platform)) {
16105
- candidates.push({
16106
- candidate: pathFlavor.join(directory, spec.command + extension),
16107
- source: "install-root"
16108
- });
16166
+ for (const field of percentFields) {
16167
+ const candidate = value[field];
16168
+ if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0 || candidate > 100)) {
16169
+ throw new Error(`Harness Usage '${field}' must be between 0 and 100`);
16109
16170
  }
16110
16171
  }
16111
- return candidates;
16112
- }
16113
- function resolveHarnessExecutable(spec, input, dependencies = {}) {
16114
- const platform = input.platform ?? process.platform;
16115
- const isExecutable = dependencies.isExecutable ?? ((candidate) => isExecutableFile(candidate, platform));
16116
- const runnable = spec.runnableCandidate ?? ((candidate) => candidate);
16117
- const context = { platform, isExecutable };
16118
- for (const { candidate, source } of harnessCandidates(spec, input, dependencies)) {
16119
- const executable = runnable(candidate, context);
16120
- if (executable !== void 0 && isExecutable(executable))
16121
- return { executable, source };
16172
+ const hasContextUsed = value.contextUsedTokens !== void 0;
16173
+ const hasContextWindow = value.contextWindowTokens !== void 0;
16174
+ if (hasContextUsed !== hasContextWindow) {
16175
+ throw new Error("Harness Usage context fields must be provided together");
16176
+ }
16177
+ if (hasContextWindow && value.contextWindowTokens === 0) {
16178
+ throw new Error("Harness Usage 'contextWindowTokens' must be greater than zero");
16179
+ }
16180
+ if (value.planFiveHourResetsAtUnix !== void 0 && value.planFiveHourUsedPercent === void 0) {
16181
+ throw new Error("Harness Usage 'planFiveHourResetsAtUnix' must be provided with 'planFiveHourUsedPercent'");
16182
+ }
16183
+ if (value.planSevenDayResetsAtUnix !== void 0 && value.planSevenDayUsedPercent === void 0) {
16184
+ throw new Error("Harness Usage 'planSevenDayResetsAtUnix' must be provided with 'planSevenDayUsedPercent'");
16122
16185
  }
16123
- return void 0;
16186
+ return { ...value };
16124
16187
  }
16125
16188
 
16126
- // ../../harness-discovery/dist/installation.js
16127
- import { execFile } from "node:child_process";
16128
- import { homedir } from "node:os";
16129
- function runInstallationCommand(command, args, environment, timeout = 3e4) {
16130
- const env = withNodeRuntimeOnPath(environment);
16131
- const invocation = /\.[cm]?js$/i.test(command) ? commandInvocation(process.execPath, [command, ...args], env) : commandInvocation(command, args, env);
16132
- return new Promise((resolve, reject) => {
16133
- const child = execFile(invocation.command, invocation.arguments, {
16134
- env,
16135
- cwd: env.HOME ?? env.USERPROFILE ?? homedir(),
16136
- encoding: "utf8",
16137
- timeout,
16138
- killSignal: "SIGKILL",
16139
- maxBuffer: 1024 * 1024,
16140
- windowsHide: true,
16141
- windowsVerbatimArguments: invocation.windowsVerbatimArguments
16142
- }, (error51, stdout, stderr) => {
16143
- if (error51)
16144
- reject(new Error(error51.killed ? "Harness command timed out" : "Harness command failed; check the native installation and retry"));
16145
- else
16146
- resolve((stdout || stderr).trim());
16147
- });
16148
- child.stdin?.end();
16149
- });
16189
+ // ../../harness-adapter/dist/live-command-catalog.js
16190
+ var COMMON_EXCLUDED_LIVE_COMMANDS = /* @__PURE__ */ new Set([
16191
+ // Session lifecycle
16192
+ "branch",
16193
+ "clear",
16194
+ "exit",
16195
+ "fork",
16196
+ "fresh",
16197
+ "new",
16198
+ "quit",
16199
+ "rename",
16200
+ "rename-chat",
16201
+ "reset",
16202
+ "resume",
16203
+ "rewind",
16204
+ "session",
16205
+ "sessions",
16206
+ // Desktop-owned configuration
16207
+ "autocompact",
16208
+ "color",
16209
+ "config",
16210
+ "effort",
16211
+ "fast",
16212
+ "keybindings",
16213
+ "model",
16214
+ "models",
16215
+ "output-style",
16216
+ "permissions",
16217
+ "settings",
16218
+ "statusline",
16219
+ "terminal-setup",
16220
+ "theme",
16221
+ "vim",
16222
+ // Trust and approval policy
16223
+ "always-approve",
16224
+ "auto-mode-setup",
16225
+ // Native login
16226
+ "login",
16227
+ "logout",
16228
+ // Work outliving the Turn
16229
+ "autopilot",
16230
+ "background",
16231
+ "bg",
16232
+ "goal",
16233
+ "jobs",
16234
+ "loop",
16235
+ "multitask",
16236
+ "queue",
16237
+ "remote-control",
16238
+ "schedule",
16239
+ "steer",
16240
+ // Native terminal UI
16241
+ "copy",
16242
+ "debug",
16243
+ "feedback",
16244
+ "heapdump",
16245
+ "share",
16246
+ "shell",
16247
+ // Plugin and MCP management
16248
+ "marketplace",
16249
+ "mcp",
16250
+ "plugins",
16251
+ "reload-plugins"
16252
+ ]);
16253
+ var COMMON_EXCLUDED_LIVE_COMMAND_PREFIXES = ["__", "hooks-"];
16254
+ function isExcludedLiveCommand(name, kind, extra = {}) {
16255
+ const normalized = name.trim().replace(/^\//u, "");
16256
+ if (new Set(extra.names ?? []).has(normalized))
16257
+ return true;
16258
+ if (extra.prefixes?.some((prefix) => normalized.startsWith(prefix)))
16259
+ return true;
16260
+ if (kind === "skill")
16261
+ return false;
16262
+ return COMMON_EXCLUDED_LIVE_COMMANDS.has(normalized) || COMMON_EXCLUDED_LIVE_COMMAND_PREFIXES.some((prefix) => normalized.startsWith(prefix));
16150
16263
  }
16151
- function installationVersion(value) {
16152
- if (typeof value !== "string" || !/^v?\d+(?:\.\d+){1,3}(?:-[\w.-]+)?(?:\+[\w.-]+)?$/.test(value.trim()))
16153
- throw new Error("Harness returned an invalid version");
16154
- return value.trim().replace(/^v/, "");
16264
+ function liveHarnessCommandPrompt(catalog, idPrefix, commandId, argumentText) {
16265
+ if (!commandId.startsWith(idPrefix))
16266
+ return null;
16267
+ const descriptor = catalog.commands.find(({ id }) => id === commandId);
16268
+ if (!descriptor)
16269
+ return null;
16270
+ const text = typeof argumentText === "string" ? argumentText.trim() : "";
16271
+ return text ? `${descriptor.invocation} ${text}` : descriptor.invocation;
16155
16272
  }
16156
- function versionFromOutput(output) {
16157
- return installationVersion(output.match(/\b\d+(?:\.\d+){1,3}(?:-[\w.-]+)?(?:\+[\w.-]+)?\b/)?.[0]);
16273
+ function mergeLiveHarnessCommands(builtIns, idPrefix, live, exclusions = {}) {
16274
+ if (!live)
16275
+ return builtIns;
16276
+ const invocations = new Set(builtIns.commands.map(({ invocation }) => invocation));
16277
+ const ids = new Set(builtIns.commands.map(({ id }) => id));
16278
+ const dynamic = [];
16279
+ for (const command of live) {
16280
+ const name = command.name.trim().replace(/^\//u, "");
16281
+ if (!name || /\s/u.test(name))
16282
+ continue;
16283
+ if (isExcludedLiveCommand(name, command.kind, exclusions))
16284
+ continue;
16285
+ const invocation = `/${name}`;
16286
+ const id = `${idPrefix}${name.replace(/[^A-Za-z0-9._:-]/gu, "-")}`.slice(0, 128);
16287
+ if (invocations.has(invocation) || ids.has(id))
16288
+ continue;
16289
+ const description = command.description?.trim().slice(0, 512);
16290
+ const parsed = harnessCommandDescriptorSchema.safeParse({
16291
+ id,
16292
+ invocation,
16293
+ label: name.slice(0, 128),
16294
+ ...description ? { description } : {},
16295
+ argumentMode: "text",
16296
+ kind: command.kind
16297
+ });
16298
+ if (!parsed.success)
16299
+ continue;
16300
+ invocations.add(invocation);
16301
+ ids.add(id);
16302
+ dynamic.push(parsed.data);
16303
+ }
16304
+ return harnessCommandCatalogSchema.parse({ commands: [...builtIns.commands, ...dynamic] });
16158
16305
  }
16159
16306
 
16307
+ // dist/acp-transport.js
16308
+ import { spawn, spawnSync } from "node:child_process";
16309
+ import { Readable, Writable } from "node:stream";
16310
+ import { execFile as execFile2 } from "node:child_process";
16311
+ import { promisify } from "node:util";
16312
+ import { setTimeout as delay } from "node:timers/promises";
16313
+
16160
16314
  // ../../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
16161
16315
  var AGENT_METHODS = {
16162
16316
  initialize: "initialize",
@@ -20527,18 +20681,19 @@ function isRecord5(value) {
20527
20681
  function errorText(error51) {
20528
20682
  return error51 instanceof Error ? error51.message : String(error51);
20529
20683
  }
20530
- function classifyStartupError(error51) {
20531
- if (error51 instanceof KiroTransportError)
20532
- return error51;
20684
+ function classifyStartupError(error51, stderr = "") {
20533
20685
  if (error51 instanceof KiroExecutableError) {
20534
20686
  return new KiroTransportError("notInstalled", error51.message, { cause: error51 });
20535
20687
  }
20536
- const text = errorText(error51).toLowerCase();
20537
- if (text.includes("auth_required") || text.includes("authentication") || text.includes("not logged in") || text.includes("sign in") || text.includes("unauthorized")) {
20538
- return new KiroTransportError("authenticationRequired", "Kiro CLI authentication is required", {
20688
+ const text = `${errorText(error51)}
20689
+ ${stderr}`.toLowerCase();
20690
+ if (text.includes("auth_required") || text.includes("authentication") || text.includes("not logged in") || text.includes("not log in") || text.includes("sign in") || text.includes("unauthorized")) {
20691
+ return new KiroTransportError("authenticationRequired", "Kiro CLI authentication is required (run `kiro-cli login`)", {
20539
20692
  cause: error51
20540
20693
  });
20541
20694
  }
20695
+ if (error51 instanceof KiroTransportError)
20696
+ return error51;
20542
20697
  return new KiroTransportError("unavailable", "Kiro CLI could not start", { cause: error51 });
20543
20698
  }
20544
20699
  var KiroRequestTimeoutError = class extends KiroTransportError {
@@ -20648,9 +20803,8 @@ var KiroAcpTransport = class {
20648
20803
  });
20649
20804
  return { ...initialize, catalog: parseKiroCliModels(JSON.parse(stdout)) };
20650
20805
  } catch (error51) {
20651
- const classified = classifyStartupError(error51);
20652
20806
  await this.close().catch(() => void 0);
20653
- throw classified;
20807
+ throw classifyStartupError(error51, this.#stderrTail);
20654
20808
  }
20655
20809
  }
20656
20810
  async open(input) {
@@ -20738,9 +20892,8 @@ var KiroAcpTransport = class {
20738
20892
  replay
20739
20893
  };
20740
20894
  } catch (error51) {
20741
- const classified = classifyStartupError(error51);
20742
20895
  await this.close().catch(() => void 0);
20743
- throw classified;
20896
+ throw classifyStartupError(error51, this.#stderrTail);
20744
20897
  }
20745
20898
  }
20746
20899
  async setConfigOption(configId, value) {
@@ -21329,16 +21482,16 @@ var Diff = class {
21329
21482
  }
21330
21483
  }
21331
21484
  }
21332
- addToPath(path8, added, removed, oldPosInc, options) {
21333
- const last = path8.lastComponent;
21485
+ addToPath(path9, added, removed, oldPosInc, options) {
21486
+ const last = path9.lastComponent;
21334
21487
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
21335
21488
  return {
21336
- oldPos: path8.oldPos + oldPosInc,
21489
+ oldPos: path9.oldPos + oldPosInc,
21337
21490
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
21338
21491
  };
21339
21492
  } else {
21340
21493
  return {
21341
- oldPos: path8.oldPos + oldPosInc,
21494
+ oldPos: path9.oldPos + oldPosInc,
21342
21495
  lastComponent: { count: 1, added, removed, previousComponent: last }
21343
21496
  };
21344
21497
  }
@@ -22618,10 +22771,265 @@ async function readKiroSnapshot(location) {
22618
22771
  };
22619
22772
  }
22620
22773
 
22621
- // dist/kiro-adapter.js
22774
+ // dist/session-import.js
22775
+ import { opendir, readFile as readFile2, stat } from "node:fs/promises";
22776
+ import path7 from "node:path";
22777
+
22778
+ // ../../harness-adapter/dist/session-import.js
22779
+ import { lstat } from "node:fs/promises";
22780
+ var SessionImportChangedError = class extends Error {
22781
+ constructor(message = "Native Session changed during discovery; refresh and retry") {
22782
+ super(message);
22783
+ this.name = "SessionImportChangedError";
22784
+ }
22785
+ };
22786
+ function isMissingFileError(error51) {
22787
+ return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "ENOENT";
22788
+ }
22789
+ function sameFileFingerprint(left, right) {
22790
+ 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;
22791
+ }
22792
+ var STORAGE_ACCESS_ERRORS = /* @__PURE__ */ new Set(["EACCES", "EPERM", "EIO", "EMFILE", "ENFILE"]);
22793
+ function isStorageAccessError(error51) {
22794
+ return typeof error51 === "object" && error51 !== null && "code" in error51 && typeof error51.code === "string" && STORAGE_ACCESS_ERRORS.has(error51.code);
22795
+ }
22796
+ async function optionalLstat(file2) {
22797
+ try {
22798
+ return await lstat(file2);
22799
+ } catch (error51) {
22800
+ if (isMissingFileError(error51))
22801
+ return null;
22802
+ throw error51;
22803
+ }
22804
+ }
22805
+ async function readStableFiles(files, read) {
22806
+ const before = await Promise.all(files.map(optionalLstat));
22807
+ const value = await read(before);
22808
+ const after = await Promise.all(files.map(optionalLstat));
22809
+ if (before.some((info, index) => !sameFileFingerprint(info, after[index] ?? null)))
22810
+ throw new SessionImportChangedError();
22811
+ return value;
22812
+ }
22813
+ function sessionImportTitle(value, maxLength = HARNESS_SESSION_IMPORT_TITLE_MAX_LENGTH) {
22814
+ if (typeof value !== "string")
22815
+ return null;
22816
+ const normalized = value.replaceAll("\0", "").replaceAll(/\s+/gu, " ").trim();
22817
+ if (!normalized)
22818
+ return null;
22819
+ if (normalized.length <= maxLength)
22820
+ return normalized;
22821
+ const characters = [...normalized];
22822
+ if (characters.length <= maxLength)
22823
+ return normalized;
22824
+ return `${characters.slice(0, maxLength - 1).join("").trimEnd()}…`;
22825
+ }
22826
+ function sessionImportCandidate(input) {
22827
+ const time3 = typeof input.updatedAt === "number" ? input.updatedAt : typeof input.updatedAt === "string" ? Date.parse(input.updatedAt) : Number.NaN;
22828
+ const parsed = harnessSessionImportCandidateSchema.safeParse({
22829
+ nativeSessionId: input.nativeSessionId,
22830
+ cwd: input.cwd,
22831
+ title: typeof input.title === "string" && input.title.trim().length > 0 ? input.title : null,
22832
+ updatedAt: Math.floor(time3),
22833
+ // Unknown must stay unknown; only an explicit boolean is a native statement.
22834
+ running: typeof input.running === "boolean" ? input.running : null
22835
+ });
22836
+ return parsed.success ? parsed.data : null;
22837
+ }
22838
+ var SessionImportScope = class {
22839
+ #abort = new AbortController();
22840
+ #options;
22841
+ #pending = /* @__PURE__ */ new Set();
22842
+ constructor(options) {
22843
+ this.#options = options;
22844
+ }
22845
+ #closed() {
22846
+ return {
22847
+ ok: false,
22848
+ error: { code: "invalidState", message: this.#options.closedMessage, retryable: false }
22849
+ };
22850
+ }
22851
+ read(operation) {
22852
+ const signal = this.#abort.signal;
22853
+ if (signal.aborted)
22854
+ return Promise.resolve(this.#closed());
22855
+ let started;
22856
+ try {
22857
+ started = operation(signal);
22858
+ } catch (error51) {
22859
+ started = Promise.reject(error51 instanceof Error ? error51 : new Error("Session read failed"));
22860
+ }
22861
+ const request = started.then((value) => signal.aborted ? this.#closed() : { ok: true, value }).catch(() => signal.aborted ? this.#closed() : {
22862
+ ok: false,
22863
+ error: {
22864
+ code: "unavailable",
22865
+ message: this.#options.unavailableMessage,
22866
+ retryable: true
22867
+ }
22868
+ }).finally(() => this.#pending.delete(request));
22869
+ this.#pending.add(request);
22870
+ return request;
22871
+ }
22872
+ /** `read` for `resolveCandidate`: a null source is the selected Session having disappeared. */
22873
+ async resolve(operation) {
22874
+ const result = await this.read(operation);
22875
+ if (!result.ok)
22876
+ return result;
22877
+ return result.value ? { ok: true, value: result.value } : {
22878
+ ok: false,
22879
+ error: {
22880
+ code: "sessionNotFound",
22881
+ message: this.#options.notFoundMessage,
22882
+ retryable: false
22883
+ }
22884
+ };
22885
+ }
22886
+ /** Idempotent. Resolves after every started read has settled. */
22887
+ async close() {
22888
+ this.#abort.abort();
22889
+ await Promise.allSettled(this.#pending);
22890
+ }
22891
+ };
22892
+
22893
+ // dist/session-import.js
22894
+ var MAX_METADATA_BYTES = 1024 * 1024;
22895
+ var NON_WORKSPACE_DIRECTORIES = /* @__PURE__ */ new Set(["cli"]);
22622
22896
  function isRecord11(value) {
22623
22897
  return typeof value === "object" && value !== null && !Array.isArray(value);
22624
22898
  }
22899
+ function userText(row) {
22900
+ const { content, text } = row.payload;
22901
+ return kiroVisibleText(typeof content === "string" ? content : text ?? "");
22902
+ }
22903
+ var KiroSessionImport = class {
22904
+ #environment;
22905
+ #scope = new SessionImportScope({
22906
+ closedMessage: "Kiro Session import is closed",
22907
+ unavailableMessage: "Kiro sessions could not be read; close native clients, check storage access and retry",
22908
+ notFoundMessage: "Kiro Session is no longer importable"
22909
+ });
22910
+ constructor(environment) {
22911
+ this.#environment = { ...environment };
22912
+ }
22913
+ listCandidates() {
22914
+ return this.#scope.read(async (signal) => {
22915
+ const candidates = [];
22916
+ for (const [, directories] of await this.#sessionDirectories(signal)) {
22917
+ if (directories.length !== 1 || !directories[0])
22918
+ continue;
22919
+ try {
22920
+ const candidate = await this.#candidate(directories[0], signal);
22921
+ if (candidate)
22922
+ candidates.push(candidate);
22923
+ } catch (error51) {
22924
+ if (!(error51 instanceof SessionImportChangedError))
22925
+ throw error51;
22926
+ }
22927
+ }
22928
+ return candidates;
22929
+ });
22930
+ }
22931
+ resolveCandidate(nativeSessionId) {
22932
+ return this.#scope.resolve(async (signal) => {
22933
+ const directories = (await this.#sessionDirectories(signal)).get(nativeSessionId);
22934
+ if (directories?.length !== 1 || !directories[0])
22935
+ return null;
22936
+ const candidate = await this.#candidate(directories[0], signal);
22937
+ if (!candidate)
22938
+ return null;
22939
+ return {
22940
+ candidate,
22941
+ nativeRef: nativeSessionRefSchema.parse({
22942
+ harnessId: "kiro-cli",
22943
+ nativeSessionId,
22944
+ formatVersion: 1
22945
+ })
22946
+ };
22947
+ });
22948
+ }
22949
+ close() {
22950
+ return this.#scope.close();
22951
+ }
22952
+ /** Session ID to every directory claiming it. Enumerated links are not followed. */
22953
+ async #sessionDirectories(signal) {
22954
+ const root = path7.join(kiroHomeDir(this.#environment), "sessions");
22955
+ const found = /* @__PURE__ */ new Map();
22956
+ const info = await optionalLstat(root);
22957
+ if (!info)
22958
+ return found;
22959
+ if (!info.isDirectory())
22960
+ throw new Error("Kiro Session store is not a directory");
22961
+ for await (const workspace of await opendir(root)) {
22962
+ signal.throwIfAborted();
22963
+ if (!workspace.isDirectory() || NON_WORKSPACE_DIRECTORIES.has(workspace.name))
22964
+ continue;
22965
+ const workspaceDirectory = path7.join(root, workspace.name);
22966
+ const sessions = await opendir(workspaceDirectory).catch((error51) => {
22967
+ if (isMissingFileError(error51))
22968
+ return null;
22969
+ throw error51;
22970
+ });
22971
+ if (!sessions)
22972
+ continue;
22973
+ for await (const session of sessions) {
22974
+ signal.throwIfAborted();
22975
+ if (!session.isDirectory())
22976
+ continue;
22977
+ const directories = found.get(session.name) ?? [];
22978
+ directories.push(path7.join(workspaceDirectory, session.name));
22979
+ found.set(session.name, directories);
22980
+ }
22981
+ }
22982
+ return found;
22983
+ }
22984
+ async #candidate(sessionDirectory, signal) {
22985
+ signal.throwIfAborted();
22986
+ const files = [
22987
+ path7.join(sessionDirectory, "session.json"),
22988
+ path7.join(sessionDirectory, "messages.jsonl")
22989
+ ];
22990
+ return readStableFiles(files, async ([metadata, messages]) => {
22991
+ if (!metadata?.isFile() || !messages?.isFile() || metadata.size > MAX_METADATA_BYTES)
22992
+ return null;
22993
+ try {
22994
+ const meta3 = JSON.parse(await readFile2(files[0], { encoding: "utf8", signal }));
22995
+ if (!isRecord11(meta3) || meta3.id !== path7.basename(sessionDirectory))
22996
+ return null;
22997
+ const workspacePath = Array.isArray(meta3.workspacePaths) ? meta3.workspacePaths[0] : void 0;
22998
+ if (typeof workspacePath !== "string" || !path7.isAbsolute(workspacePath) || workspacePath.includes("\0"))
22999
+ return null;
23000
+ const cwd = path7.resolve(workspacePath);
23001
+ if (!(await stat(cwd)).isDirectory())
23002
+ return null;
23003
+ signal.throwIfAborted();
23004
+ const rows = await readKiroSessionMessages({
23005
+ sessionDirectory,
23006
+ sessionMeta: meta3,
23007
+ cwd
23008
+ });
23009
+ const firstUser = rows.find((row) => row.payload.type === "user");
23010
+ if (!firstUser)
23011
+ return null;
23012
+ const modified = typeof meta3.lastModifiedAt === "string" ? Date.parse(meta3.lastModifiedAt) : Number.NaN;
23013
+ return sessionImportCandidate({
23014
+ nativeSessionId: meta3.id,
23015
+ cwd,
23016
+ title: sessionImportTitle(meta3.title) ?? sessionImportTitle(userText(firstUser)),
23017
+ updatedAt: Number.isFinite(modified) && modified >= 0 ? modified : messages.mtimeMs
23018
+ });
23019
+ } catch (error51) {
23020
+ signal.throwIfAborted();
23021
+ if (isStorageAccessError(error51))
23022
+ throw error51;
23023
+ return null;
23024
+ }
23025
+ });
23026
+ }
23027
+ };
23028
+
23029
+ // dist/kiro-adapter.js
23030
+ function isRecord12(value) {
23031
+ return typeof value === "object" && value !== null && !Array.isArray(value);
23032
+ }
22625
23033
  var KIRO_SESSION_CAPABILITIES = {
22626
23034
  configuration: {
22627
23035
  selectModel: true,
@@ -22646,6 +23054,7 @@ var KiroAdapter = class {
22646
23054
  harnessId = harnessIdSchema.parse("kiro-cli");
22647
23055
  commandCatalog = KIRO_COMMAND_CATALOG;
22648
23056
  liveCommandCatalog = true;
23057
+ sessionImport;
22649
23058
  #options;
22650
23059
  #deps;
22651
23060
  #sessions = /* @__PURE__ */ new Set();
@@ -22654,9 +23063,10 @@ var KiroAdapter = class {
22654
23063
  constructor(options = {}, deps = {}) {
22655
23064
  this.#options = options;
22656
23065
  this.#deps = deps;
23066
+ this.sessionImport = new KiroSessionImport({ ...process.env, ...options.environment });
22657
23067
  }
22658
23068
  async inspect(input = {}) {
22659
- const cwd = path7.resolve(input.cwd ?? process.cwd());
23069
+ const cwd = path8.resolve(input.cwd ?? process.cwd());
22660
23070
  const cached2 = this.#inspectionCache.get(cwd);
22661
23071
  if (!input.refresh && cached2) {
22662
23072
  if (cached2.refreshAfter <= Date.now()) {
@@ -22717,7 +23127,7 @@ var KiroAdapter = class {
22717
23127
  const transport = this.#createTransport(cwd);
22718
23128
  try {
22719
23129
  const initialize = await transport.inspect();
22720
- const modelCatalog = isRecord11(initialize) && isRecord11(initialize.catalog) ? initialize.catalog : parseKiroModelCatalog(isRecord11(initialize) ? initialize.configOptions : void 0);
23130
+ const modelCatalog = isRecord12(initialize) && isRecord12(initialize.catalog) ? initialize.catalog : parseKiroModelCatalog(isRecord12(initialize) ? initialize.configOptions : void 0);
22721
23131
  if (modelCatalog.models.length === 0)
22722
23132
  throw new Error("Kiro returned no native model catalog");
22723
23133
  return {
@@ -22733,7 +23143,7 @@ var KiroAdapter = class {
22733
23143
  status: "error",
22734
23144
  error: {
22735
23145
  code: "authenticationRequired",
22736
- message: "Kiro CLI authentication is required",
23146
+ message: "Kiro CLI authentication is required (run `kiro-cli login`)",
22737
23147
  retryable: false
22738
23148
  }
22739
23149
  };
@@ -22971,6 +23381,7 @@ var KiroAdapter = class {
22971
23381
  async close() {
22972
23382
  try {
22973
23383
  await Promise.all([
23384
+ this.sessionImport.close(),
22974
23385
  ...this.#inspectionInFlight.values(),
22975
23386
  ...[...this.#sessions].map((session) => session.close())
22976
23387
  ]);
@@ -23138,7 +23549,7 @@ var KiroSession = class {
23138
23549
  }
23139
23550
  };
23140
23551
  } catch (error51) {
23141
- if (this.#newSessionWithoutTurn && isRecord11(error51) && error51.code === "ENOENT") {
23552
+ if (this.#newSessionWithoutTurn && isRecord12(error51) && error51.code === "ENOENT") {
23142
23553
  return { ok: true, value: { turns: [], state: this.#state() } };
23143
23554
  }
23144
23555
  return {
@@ -23199,7 +23610,7 @@ var KiroSession = class {
23199
23610
  kind: "event",
23200
23611
  event: { type: "turn.started", turnId }
23201
23612
  });
23202
- const userText = command.input.map((i) => i.text).join("\n");
23613
+ const userText2 = command.input.map((i) => i.text).join("\n");
23203
23614
  const output = new KiroTurnOutput(turnId, this.#cwd, (event) => this.#channel.emit(event));
23204
23615
  let assignedUserMessageId;
23205
23616
  const stopped = new Promise((_resolve, reject) => {
@@ -23210,14 +23621,14 @@ var KiroSession = class {
23210
23621
  try {
23211
23622
  const promptResult = await Promise.race([
23212
23623
  stopped,
23213
- this.#transport.runTurn(userText, (event) => {
23624
+ this.#transport.runTurn(userText2, (event) => {
23214
23625
  if (this.#closed || this.#activeTurnId !== turnId)
23215
23626
  return;
23216
23627
  output.accept(event);
23217
23628
  if (event.type === "usage") {
23218
23629
  this.observeUsage(event);
23219
23630
  const meta3 = event.metadata?.kiro;
23220
- if (isRecord11(meta3) && meta3.kind === "user_message_id_assigned" && typeof meta3.userMessageId === "string") {
23631
+ if (isRecord12(meta3) && meta3.kind === "user_message_id_assigned" && typeof meta3.userMessageId === "string") {
23221
23632
  assignedUserMessageId = meta3.userMessageId;
23222
23633
  }
23223
23634
  } else if (event.type === "compaction.completed") {
@@ -23299,7 +23710,7 @@ var KiroSession = class {
23299
23710
  });
23300
23711
  })
23301
23712
  ]);
23302
- if (isRecord11(promptResult) && promptResult.stopReason === "cancelled") {
23713
+ if (isRecord12(promptResult) && promptResult.stopReason === "cancelled") {
23303
23714
  turnOutcome = { status: "cancelled", reason: "User cancelled" };
23304
23715
  } else {
23305
23716
  turnOutcome = { status: "succeeded" };
@@ -23628,7 +24039,7 @@ var KiroSession = class {
23628
24039
  }
23629
24040
  });
23630
24041
  const result2 = await Promise.race([stopped, this.#transport.compact()]);
23631
- if (isRecord11(result2) && result2.success === false) {
24042
+ if (isRecord12(result2) && result2.success === false) {
23632
24043
  throw new Error("Kiro context compaction did not complete");
23633
24044
  }
23634
24045
  this.#channel.emit({
@@ -23780,6 +24191,7 @@ function createKiroInstallation(environment, command) {
23780
24191
  latestVersion: "Unknown",
23781
24192
  updateAvailable: false,
23782
24193
  canUpdate: false,
24194
+ messageCode: "kiro-native-updater",
23783
24195
  message: "Use Kiro CLI's original installer or native updater to check for and install updates."
23784
24196
  };
23785
24197
  };
@@ -23792,7 +24204,13 @@ function createHarnessAdapter(context) {
23792
24204
  return Object.assign(new KiroAdapter({
23793
24205
  ...environment[CODEXHOST_KIRO_COMMAND] ? { command: environment[CODEXHOST_KIRO_COMMAND] } : {},
23794
24206
  environment
23795
- }), { installation: createKiroInstallation(environment, environment[CODEXHOST_KIRO_COMMAND]) });
24207
+ }), {
24208
+ installation: createKiroInstallation(environment, environment[CODEXHOST_KIRO_COMMAND]),
24209
+ install: createHarnessInstaller(environment, {
24210
+ posix: "https://cli.kiro.dev/install",
24211
+ windows: "https://cli.kiro.dev/install.ps1"
24212
+ })
24213
+ });
23796
24214
  }
23797
24215
  export {
23798
24216
  CODEXHOST_KIRO_COMMAND,