@codexhost/cli-darwin-x64 0.10.2 → 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.
Files changed (33) hide show
  1. package/README.md +1 -1
  2. package/THIRD_PARTY_NOTICES.txt +4 -0
  3. package/app/codexhost-distribution.json +1 -1
  4. package/app/console-server.mjs +18001 -0
  5. package/app/console-web.js +27674 -0
  6. package/app/desktop-controller.mjs +452 -110
  7. package/app/host-runtime.mjs +6670 -1272
  8. package/app/plugins/antigravity/plugin.mjs +686 -305
  9. package/app/plugins/claude-code/plugin.mjs +2283 -1450
  10. package/app/plugins/codebuddy/plugin.mjs +1272 -506
  11. package/app/plugins/cursor-cli/manifest.json +1 -1
  12. package/app/plugins/cursor-cli/plugin.mjs +1295 -497
  13. package/app/plugins/deepseek-harness/plugin.mjs +4718 -4925
  14. package/app/plugins/enabled.json +2 -1
  15. package/app/plugins/grok/plugin.mjs +1012 -369
  16. package/app/plugins/hermes/plugin.mjs +18587 -22714
  17. package/app/plugins/kimi-code/plugin.mjs +1283 -355
  18. package/app/plugins/kiro-cli/plugin.mjs +840 -299
  19. package/app/plugins/omp/plugin.mjs +1045 -328
  20. package/app/plugins/opencode/plugin.mjs +5341 -1686
  21. package/app/plugins/pi/plugin.mjs +1343 -534
  22. package/app/plugins/qoder/plugin.mjs +913 -258
  23. package/app/plugins/qoder-cn/plugin.mjs +712 -49
  24. package/app/plugins/workbuddy/plugin.mjs +531 -44
  25. package/app/plugins/zcode/assets/icon.svg +8 -0
  26. package/app/plugins/zcode/manifest.json +14 -0
  27. package/app/plugins/zcode/plugin.mjs +19202 -0
  28. package/app/renderer-extension.js +5011 -1899
  29. package/bin/codexhost +0 -0
  30. package/libexec/codexhost-shim +0 -0
  31. package/libexec/codexhost-updater +0 -0
  32. package/licenses/OpenCode-v2-Client-LICENSE.txt +21 -0
  33. package/package.json +1 -1
@@ -5,6 +5,409 @@ 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/installer.js
358
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
359
+ import { tmpdir } from "node:os";
360
+ import { join } from "node:path";
361
+ function createHarnessInstaller(environment, source) {
362
+ return async () => {
363
+ if (!["darwin", "linux", "win32"].includes(process.platform))
364
+ throw new Error("Unsupported installation platform");
365
+ const env = withNodeRuntimeOnPath(environment);
366
+ if ("npm" in source) {
367
+ const npm = resolveHarnessExecutable({
368
+ id: "npm",
369
+ command: "npm",
370
+ installRoots: {
371
+ posix: [
372
+ "~/.npm-global/bin",
373
+ "~/.local/bin",
374
+ VERSION_MANAGER_ROOTS,
375
+ "/opt/homebrew/bin",
376
+ "/usr/local/bin",
377
+ "/usr/bin"
378
+ ],
379
+ windows: [
380
+ "${APPDATA}/npm",
381
+ VERSION_MANAGER_ROOTS,
382
+ "${ProgramFiles}/nodejs",
383
+ "${LOCALAPPDATA}/Programs/nodejs"
384
+ ]
385
+ }
386
+ }, { environment: env });
387
+ if (!npm)
388
+ throw new Error("Install Node.js and npm first");
389
+ await runInstallationCommand(npm.executable, ["install", "--global", source.npm], {
390
+ ...env,
391
+ ...source.allowScripts ? { npm_config_allow_scripts: source.allowScripts } : {}
392
+ }, 6e5);
393
+ return;
394
+ }
395
+ const windows = process.platform === "win32";
396
+ const url2 = windows ? source.windows : source.posix;
397
+ if (new URL(url2).protocol !== "https:")
398
+ throw new Error("Installer requires HTTPS");
399
+ const script = await fetchInstallationText(url2);
400
+ const directory = await mkdtemp(join(tmpdir(), "codexhost-installer-"));
401
+ try {
402
+ const file2 = join(directory, windows ? "install.ps1" : "install.sh");
403
+ await writeFile(file2, script, { mode: 384 });
404
+ await runInstallationCommand(windows ? "powershell.exe" : source.shell ?? "bash", windows ? ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", file2] : [file2], env, 6e5);
405
+ } finally {
406
+ await rm(directory, { recursive: true, force: true });
407
+ }
408
+ };
409
+ }
410
+
8
411
  // ../../../node_modules/diff/libesm/diff/base.js
9
412
  var Diff = class {
10
413
  diff(oldStr, newStr, options = {}) {
@@ -105,16 +508,16 @@ var Diff = class {
105
508
  }
106
509
  }
107
510
  }
108
- addToPath(path5, added, removed, oldPosInc, options) {
109
- const last = path5.lastComponent;
511
+ addToPath(path8, added, removed, oldPosInc, options) {
512
+ const last = path8.lastComponent;
110
513
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
111
514
  return {
112
- oldPos: path5.oldPos + oldPosInc,
515
+ oldPos: path8.oldPos + oldPosInc,
113
516
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
114
517
  };
115
518
  } else {
116
519
  return {
117
- oldPos: path5.oldPos + oldPosInc,
520
+ oldPos: path8.oldPos + oldPosInc,
118
521
  lastComponent: { count: 1, added, removed, previousComponent: last }
119
522
  };
120
523
  }
@@ -527,8 +930,8 @@ function splitLines(text) {
527
930
 
528
931
  // dist/omp-adapter.js
529
932
  import { randomUUID as randomUUID2 } from "node:crypto";
530
- import { realpath as realpath2, stat } from "node:fs/promises";
531
- import path4 from "node:path";
933
+ import { realpath as realpath3, stat as stat2 } from "node:fs/promises";
934
+ import path6 from "node:path";
532
935
 
533
936
  // ../../../node_modules/zod/v4/classic/external.js
534
937
  var external_exports = {};
@@ -1296,10 +1699,10 @@ function mergeDefs(...defs) {
1296
1699
  function cloneDef(schema) {
1297
1700
  return mergeDefs(schema._zod.def);
1298
1701
  }
1299
- function getElementAtPath(obj, path5) {
1300
- if (!path5)
1702
+ function getElementAtPath(obj, path8) {
1703
+ if (!path8)
1301
1704
  return obj;
1302
- return path5.reduce((acc, key) => acc?.[key], obj);
1705
+ return path8.reduce((acc, key) => acc?.[key], obj);
1303
1706
  }
1304
1707
  function promiseAllObject(promisesObj) {
1305
1708
  const keys = Object.keys(promisesObj);
@@ -1708,11 +2111,11 @@ function explicitlyAborted(x, startIndex = 0) {
1708
2111
  }
1709
2112
  return false;
1710
2113
  }
1711
- function prefixIssues(path5, issues) {
2114
+ function prefixIssues(path8, issues) {
1712
2115
  return issues.map((iss) => {
1713
2116
  var _a3;
1714
2117
  (_a3 = iss).path ?? (_a3.path = []);
1715
- iss.path.unshift(path5);
2118
+ iss.path.unshift(path8);
1716
2119
  return iss;
1717
2120
  });
1718
2121
  }
@@ -1859,16 +2262,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
1859
2262
  }
1860
2263
  function formatError(error51, mapper = (issue2) => issue2.message) {
1861
2264
  const fieldErrors = { _errors: [] };
1862
- const processError = (error52, path5 = []) => {
2265
+ const processError = (error52, path8 = []) => {
1863
2266
  for (const issue2 of error52.issues) {
1864
2267
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1865
- issue2.errors.map((issues) => processError({ issues }, [...path5, ...issue2.path]));
2268
+ issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
1866
2269
  } else if (issue2.code === "invalid_key") {
1867
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
2270
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1868
2271
  } else if (issue2.code === "invalid_element") {
1869
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
2272
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1870
2273
  } else {
1871
- const fullpath = [...path5, ...issue2.path];
2274
+ const fullpath = [...path8, ...issue2.path];
1872
2275
  if (fullpath.length === 0) {
1873
2276
  fieldErrors._errors.push(mapper(issue2));
1874
2277
  } else {
@@ -1895,17 +2298,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
1895
2298
  }
1896
2299
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
1897
2300
  const result = { errors: [] };
1898
- const processError = (error52, path5 = []) => {
2301
+ const processError = (error52, path8 = []) => {
1899
2302
  var _a3, _b;
1900
2303
  for (const issue2 of error52.issues) {
1901
2304
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1902
- issue2.errors.map((issues) => processError({ issues }, [...path5, ...issue2.path]));
2305
+ issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
1903
2306
  } else if (issue2.code === "invalid_key") {
1904
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
2307
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1905
2308
  } else if (issue2.code === "invalid_element") {
1906
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
2309
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1907
2310
  } else {
1908
- const fullpath = [...path5, ...issue2.path];
2311
+ const fullpath = [...path8, ...issue2.path];
1909
2312
  if (fullpath.length === 0) {
1910
2313
  result.errors.push(mapper(issue2));
1911
2314
  continue;
@@ -1937,8 +2340,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
1937
2340
  }
1938
2341
  function toDotPath(_path) {
1939
2342
  const segs = [];
1940
- const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1941
- for (const seg of path5) {
2343
+ const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
2344
+ for (const seg of path8) {
1942
2345
  if (typeof seg === "number")
1943
2346
  segs.push(`[${seg}]`);
1944
2347
  else if (typeof seg === "symbol")
@@ -14630,13 +15033,13 @@ function resolveRef(ref, ctx) {
14630
15033
  if (!ref.startsWith("#")) {
14631
15034
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14632
15035
  }
14633
- const path5 = ref.slice(1).split("/").filter(Boolean);
14634
- if (path5.length === 0) {
15036
+ const path8 = ref.slice(1).split("/").filter(Boolean);
15037
+ if (path8.length === 0) {
14635
15038
  return ctx.rootSchema;
14636
15039
  }
14637
15040
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14638
- if (path5[0] === defsKey) {
14639
- const key = path5[1];
15041
+ if (path8[0] === defsKey) {
15042
+ const key = path8[1];
14640
15043
  if (!key || !ctx.defs[key]) {
14641
15044
  throw new Error(`Reference not found: ${ref}`);
14642
15045
  }
@@ -15099,6 +15502,56 @@ var credentialImportsParamsSchema = external_exports.object({
15099
15502
  request: credentialImportsRequestSchema
15100
15503
  }).strict();
15101
15504
 
15505
+ // ../../shared-contracts/dist/harness-display-settings.js
15506
+ var harnessDisplayEntriesSchema = external_exports.array(external_exports.strictObject({
15507
+ agent: external_exports.string().min(1).max(128),
15508
+ section: external_exports.enum(["main", "more", "auto"])
15509
+ })).max(256).refine((entries) => new Set(entries.map((entry) => entry.agent)).size === entries.length, "Duplicate Harness IDs");
15510
+ var harnessDisplaySettingsSchema = external_exports.strictObject({
15511
+ entries: harnessDisplayEntriesSchema.nullable()
15512
+ });
15513
+ var harnessDisplayGetSchema = external_exports.strictObject({});
15514
+ var harnessDisplaySetSchema = external_exports.strictObject({
15515
+ entries: harnessDisplayEntriesSchema,
15516
+ /** Import legacy Desktop preferences only if no shared settings exist yet. */
15517
+ initializeOnly: external_exports.boolean().optional()
15518
+ });
15519
+
15520
+ // ../../shared-contracts/dist/console.js
15521
+ var consoleAnnouncementSchema = external_exports.strictObject({
15522
+ title: external_exports.string().trim().min(1).max(200),
15523
+ type: external_exports.enum(["info", "warning", "danger"]),
15524
+ body: external_exports.string().trim().min(1).max(16 * 1024)
15525
+ });
15526
+ var consoleOpenParamsSchema = external_exports.strictObject({});
15527
+ var consoleOpenResultSchema = external_exports.strictObject({
15528
+ /** The console address. */
15529
+ url: external_exports.string().max(2048).regex(/^http:\/\/(?:127\.0\.0\.1|localhost):\d{1,5}\/(?:\?.*)?$/u)
15530
+ });
15531
+ var CONSOLE_HOST_METHODS = Object.freeze([
15532
+ "codexhost/harness/plugins/list",
15533
+ "codexhost/harness/display-settings/get",
15534
+ "codexhost/harness/display-settings/set",
15535
+ "codexhost/harness/inspect",
15536
+ "codexhost/harness/installation",
15537
+ "codexhost/harness/launch-settings/get",
15538
+ "codexhost/harness/launch-settings/set",
15539
+ "codexhost/harness/web-ui/open",
15540
+ "codexhost/harness/accounts/sources",
15541
+ "codexhost/harness/accounts/list",
15542
+ "codexhost/harness/accounts/inspect",
15543
+ "codexhost/harness/credential-imports",
15544
+ "codexhost/harness/session-import/sources",
15545
+ "codexhost/harness/session-import/list",
15546
+ "codexhost/harness/session-import/import",
15547
+ "codexhost/account/list",
15548
+ "codexhost/account/refresh",
15549
+ "codexhost/account/usage/inspect",
15550
+ "codexhost/update/check",
15551
+ "codexhost/update/start",
15552
+ "codexhost/update/status"
15553
+ ]);
15554
+
15102
15555
  // ../../shared-contracts/dist/version.js
15103
15556
  var WORKSPACE_CONTRACT_VERSION = 1;
15104
15557
 
@@ -15152,6 +15605,12 @@ var hostTurnIdSchema = opaqueIdSchema.brand();
15152
15605
  var hostItemIdSchema = opaqueIdSchema.brand();
15153
15606
  var hostInteractionIdSchema = opaqueIdSchema.brand();
15154
15607
 
15608
+ // ../../shared-contracts/dist/manual-compaction.js
15609
+ var threadManualCompactionStartedSchema = external_exports.strictObject({
15610
+ threadId: hostThreadIdSchema,
15611
+ turnId: hostTurnIdSchema
15612
+ });
15613
+
15155
15614
  // ../../shared-contracts/dist/thread-usage.js
15156
15615
  var nonNegativeSafeIntegerSchema = external_exports.number().int().safe().nonnegative();
15157
15616
  var finiteNonNegativeNumberSchema = external_exports.number().finite().nonnegative();
@@ -15212,6 +15671,10 @@ var threadUsageSnapshotSchema = external_exports.object({
15212
15671
  var usagePercentSchema = external_exports.number().finite().min(0).max(100);
15213
15672
  var accountCreditsProductUsageSchema = external_exports.object({
15214
15673
  product: external_exports.string().min(1),
15674
+ used: external_exports.number().finite().nonnegative().optional(),
15675
+ // Zero is a real empty cap, not an absent field.
15676
+ limit: external_exports.number().finite().nonnegative().optional(),
15677
+ unit: external_exports.string().min(1).max(32).optional(),
15215
15678
  usagePercent: usagePercentSchema,
15216
15679
  resetsAt: external_exports.string().min(1).optional()
15217
15680
  }).strict();
@@ -15221,6 +15684,10 @@ var accountResetCreditsSchema = external_exports.object({
15221
15684
  expiresAt: external_exports.array(external_exports.string().min(1)).min(1).max(32).optional()
15222
15685
  }).strict();
15223
15686
  var accountCreditsSnapshotSchema = external_exports.object({
15687
+ used: external_exports.number().finite().nonnegative().optional(),
15688
+ // Zero is a real empty cap, not an absent field.
15689
+ limit: external_exports.number().finite().nonnegative().optional(),
15690
+ unit: external_exports.string().min(1).max(32).optional(),
15224
15691
  /** Native label when the primary limit is scoped to a model or product group. */
15225
15692
  label: external_exports.string().min(1).optional(),
15226
15693
  usedPercent: usagePercentSchema,
@@ -15240,12 +15707,27 @@ var threadUsageInspectionSchema = external_exports.object({
15240
15707
  }).strict();
15241
15708
 
15242
15709
  // ../../shared-contracts/dist/harness-accounts.js
15243
- var harnessAccountSnapshotSchema = external_exports.object({
15710
+ var accountBalanceSnapshotSchema = external_exports.object({
15711
+ amount: external_exports.number().finite().nonnegative(),
15712
+ /** ISO 4217 code as reported by the Provider, for example `CNY`. */
15713
+ currency: external_exports.string().trim().min(1).max(8),
15714
+ /** Native label when the Harness exposes several Billing Sources. */
15715
+ label: external_exports.string().trim().min(1).max(128).optional()
15716
+ }).strict();
15717
+ var harnessAccountSnapshotObject = external_exports.object({
15244
15718
  email: external_exports.string().trim().min(1).max(320).optional(),
15245
15719
  label: external_exports.string().trim().min(1).max(256).optional(),
15246
15720
  plan: external_exports.string().trim().min(1).max(128).optional(),
15247
- credits: accountCreditsSnapshotSchema
15721
+ credits: accountCreditsSnapshotSchema.optional(),
15722
+ balance: accountBalanceSnapshotSchema.optional()
15248
15723
  }).strict();
15724
+ function requireReportedQuota(schema) {
15725
+ return schema.refine((value) => {
15726
+ const reported = value;
15727
+ return reported.credits !== void 0 || reported.balance !== void 0;
15728
+ }, { message: "Account must report either credits or a balance" });
15729
+ }
15730
+ var harnessAccountSnapshotSchema = requireReportedQuota(harnessAccountSnapshotObject);
15249
15731
  var harnessAccountIdentityShape = {
15250
15732
  harnessId: harnessIdSchema,
15251
15733
  harnessName: external_exports.string().trim().min(1).max(128)
@@ -15256,11 +15738,13 @@ var harnessAccountSourceListResultSchema = external_exports.object({ sources: ex
15256
15738
  var harnessAccountInspectParamsSchema = external_exports.object({ harnessId: harnessIdSchema, refresh: external_exports.boolean().optional() }).strict();
15257
15739
  var harnessAccountInspectResultSchema = external_exports.object({
15258
15740
  ...harnessAccountIdentityShape,
15259
- account: harnessAccountSnapshotSchema.nullable()
15741
+ account: harnessAccountSnapshotSchema.nullable(),
15742
+ /** Every Billing Source from one Harness; `account` remains the first for older clients. */
15743
+ accounts: external_exports.array(harnessAccountSnapshotSchema).max(8).optional()
15260
15744
  }).strict();
15261
15745
  var harnessAccountListParamsSchema = external_exports.object({ refresh: external_exports.boolean().optional() }).strict();
15262
15746
  var harnessAccountListResultSchema = external_exports.object({
15263
- accounts: external_exports.array(harnessAccountSnapshotSchema.extend(harnessAccountIdentityShape)).max(128)
15747
+ accounts: external_exports.array(requireReportedQuota(harnessAccountSnapshotObject.extend(harnessAccountIdentityShape))).max(128)
15264
15748
  }).strict();
15265
15749
 
15266
15750
  // ../../shared-contracts/dist/json-value.js
@@ -15398,6 +15882,8 @@ var harnessModelSchema = external_exports.object({
15398
15882
  ref: harnessModelRefSchema,
15399
15883
  label: nonBlankTextSchema2.max(HARNESS_MODEL_LABEL_MAX_LENGTH),
15400
15884
  resolvedModelLabel: harnessResolvedModelLabelSchema.optional(),
15885
+ /** Optional opaque selection for this same Model with priority processing enabled. */
15886
+ fastModel: harnessModelRefSchema.optional(),
15401
15887
  supportedThinkingOptionIds: external_exports.array(harnessThinkingOptionIdSchema).optional()
15402
15888
  }).strict();
15403
15889
  var harnessThinkingOptionsSchema = external_exports.array(harnessThinkingOptionSchema).superRefine((options, context) => {
@@ -15430,6 +15916,16 @@ var harnessModelCatalogSchema = external_exports.object({
15430
15916
  });
15431
15917
  }
15432
15918
  refs.add(model.ref.id);
15919
+ if (model.fastModel) {
15920
+ if (refs.has(model.fastModel.id) || catalog.models.some((entry) => entry.ref.id === model.fastModel?.id)) {
15921
+ context.addIssue({
15922
+ code: "custom",
15923
+ message: "Fast Model refs must be distinct and unique",
15924
+ path: ["models", index, "fastModel"]
15925
+ });
15926
+ }
15927
+ refs.add(model.fastModel.id);
15928
+ }
15433
15929
  const supportedThinkingIds = /* @__PURE__ */ new Set();
15434
15930
  for (const [optionIndex, optionId] of (model.supportedThinkingOptionIds ?? []).entries()) {
15435
15931
  if (supportedThinkingIds.has(optionId)) {
@@ -15549,11 +16045,13 @@ var threadThinkingSelectParamsSchema = external_exports.object({
15549
16045
  thinkingOptionId: harnessThinkingOptionIdSchema
15550
16046
  }).strict();
15551
16047
  var threadInspectionParamsSchema = external_exports.object({
15552
- threadId: hostThreadIdSchema
16048
+ threadId: hostThreadIdSchema,
16049
+ includeReferenceCapability: external_exports.boolean().optional()
15553
16050
  }).strict();
15554
16051
  var codexThreadInspectionSchema = external_exports.object({
15555
16052
  owner: external_exports.literal("codex"),
15556
- locked: external_exports.literal(true)
16053
+ locked: external_exports.literal(true),
16054
+ supportsThreadReferences: external_exports.literal(true).optional()
15557
16055
  }).strict();
15558
16056
  var externalThreadInspectionSchema = external_exports.object({
15559
16057
  owner: external_exports.literal("external"),
@@ -15679,6 +16177,22 @@ var harnessLaunchSettingsSchema = external_exports.object({
15679
16177
  restartRequired: external_exports.boolean()
15680
16178
  }).strict();
15681
16179
 
16180
+ // ../../shared-contracts/dist/harness-installation.js
16181
+ var harnessInstallationParamsSchema = external_exports.object({
16182
+ harnessId: harnessIdSchema,
16183
+ action: external_exports.enum(["check", "update", "install"])
16184
+ }).strict();
16185
+ var harnessInstallationStateSchema = external_exports.object({
16186
+ currentVersion: external_exports.string().min(1).max(128),
16187
+ latestVersion: external_exports.string().min(1).max(128),
16188
+ updateAvailable: external_exports.boolean(),
16189
+ canUpdate: external_exports.boolean(),
16190
+ // Adapter-owned diagnostic text; UI uses messageCode rather than displaying it verbatim.
16191
+ message: external_exports.string().max(2048).optional(),
16192
+ messageCode: external_exports.string().min(1).max(128).optional(),
16193
+ latestVersionKind: external_exports.enum(["unknown", "tracking-branch"]).optional()
16194
+ }).strict();
16195
+
15682
16196
  // ../../shared-contracts/dist/codex-accounts.js
15683
16197
  var accountIdSchema = external_exports.string().min(1).max(256).regex(/^[A-Za-z0-9._~-]+$/u);
15684
16198
  var nonBlankTextSchema3 = external_exports.string().trim().min(1);
@@ -15978,6 +16492,38 @@ var updateStatusResultSchema = external_exports.strictObject({
15978
16492
  status: updateStatusSchema.nullable()
15979
16493
  });
15980
16494
 
16495
+ // ../../shared-contracts/dist/remote-runtime.js
16496
+ var remoteUpdatePhaseSchema = external_exports.enum([
16497
+ "idle",
16498
+ "installing",
16499
+ "restarting",
16500
+ "succeeded",
16501
+ "failed"
16502
+ ]);
16503
+ var runtimeStatusSchema = external_exports.object({
16504
+ runningVersion: external_exports.string().nullable(),
16505
+ installedVersion: external_exports.string().nullable(),
16506
+ restartRequired: external_exports.boolean(),
16507
+ remote: external_exports.boolean(),
16508
+ updateSupported: external_exports.boolean(),
16509
+ update: external_exports.object({
16510
+ phase: remoteUpdatePhaseSchema,
16511
+ targetVersion: external_exports.string().nullable(),
16512
+ error: external_exports.string().nullable()
16513
+ })
16514
+ });
16515
+ var remoteUpdateParamsSchema = external_exports.object({
16516
+ version: external_exports.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
16517
+ }).strict();
16518
+ var remoteSshSetupParamsSchema = external_exports.object({
16519
+ hostname: external_exports.string().min(1).max(1024).refine((value) => !value.startsWith("-") && !/\s/u.test(value)),
16520
+ port: external_exports.number().int().min(1).max(65535).nullable(),
16521
+ identity: external_exports.string().max(4096).nullable(),
16522
+ action: external_exports.enum(["inspect", "install", "update", "repair"]),
16523
+ version: external_exports.string().regex(/^\d+\.\d+\.\d+$/u).nullable()
16524
+ }).strict();
16525
+ var remoteSshSetupResultSchema = external_exports.object({ state: external_exports.enum(["installed", "not-installed"]) }).strict();
16526
+
15981
16527
  // ../../shared-contracts/dist/index.js
15982
16528
  var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
15983
16529
 
@@ -16799,7 +17345,331 @@ async function verifyOmpSessionCwd(input) {
16799
17345
  if (actualCwd !== expectedCwd) {
16800
17346
  throw new Error("Omp Fork Session did not bind the requested cwd");
16801
17347
  }
16802
- }
17348
+ }
17349
+
17350
+ // dist/session-import.js
17351
+ import { createReadStream as createReadStream2 } from "node:fs";
17352
+ import { opendir, realpath as realpath2, stat } from "node:fs/promises";
17353
+ import os2 from "node:os";
17354
+ import path4 from "node:path";
17355
+ import { createInterface } from "node:readline";
17356
+
17357
+ // ../../harness-adapter/dist/session-import.js
17358
+ import { lstat } from "node:fs/promises";
17359
+ var SessionImportChangedError = class extends Error {
17360
+ constructor(message3 = "Native Session changed during discovery; refresh and retry") {
17361
+ super(message3);
17362
+ this.name = "SessionImportChangedError";
17363
+ }
17364
+ };
17365
+ function isMissingFileError(error51) {
17366
+ return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "ENOENT";
17367
+ }
17368
+ function sameFileFingerprint(left, right) {
17369
+ 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;
17370
+ }
17371
+ var STORAGE_ACCESS_ERRORS = /* @__PURE__ */ new Set(["EACCES", "EPERM", "EIO", "EMFILE", "ENFILE"]);
17372
+ function isStorageAccessError(error51) {
17373
+ return typeof error51 === "object" && error51 !== null && "code" in error51 && typeof error51.code === "string" && STORAGE_ACCESS_ERRORS.has(error51.code);
17374
+ }
17375
+ async function optionalLstat(file2) {
17376
+ try {
17377
+ return await lstat(file2);
17378
+ } catch (error51) {
17379
+ if (isMissingFileError(error51))
17380
+ return null;
17381
+ throw error51;
17382
+ }
17383
+ }
17384
+ async function readStableFiles(files, read) {
17385
+ const before = await Promise.all(files.map(optionalLstat));
17386
+ const value = await read(before);
17387
+ const after = await Promise.all(files.map(optionalLstat));
17388
+ if (before.some((info, index) => !sameFileFingerprint(info, after[index] ?? null)))
17389
+ throw new SessionImportChangedError();
17390
+ return value;
17391
+ }
17392
+ function sessionImportTitle(value, maxLength = HARNESS_SESSION_IMPORT_TITLE_MAX_LENGTH) {
17393
+ if (typeof value !== "string")
17394
+ return null;
17395
+ const normalized = value.replaceAll("\0", "").replaceAll(/\s+/gu, " ").trim();
17396
+ if (!normalized)
17397
+ return null;
17398
+ if (normalized.length <= maxLength)
17399
+ return normalized;
17400
+ const characters = [...normalized];
17401
+ if (characters.length <= maxLength)
17402
+ return normalized;
17403
+ return `${characters.slice(0, maxLength - 1).join("").trimEnd()}…`;
17404
+ }
17405
+ function sessionImportCandidate(input) {
17406
+ const time3 = typeof input.updatedAt === "number" ? input.updatedAt : typeof input.updatedAt === "string" ? Date.parse(input.updatedAt) : Number.NaN;
17407
+ const parsed = harnessSessionImportCandidateSchema.safeParse({
17408
+ nativeSessionId: input.nativeSessionId,
17409
+ cwd: input.cwd,
17410
+ title: typeof input.title === "string" && input.title.trim().length > 0 ? input.title : null,
17411
+ updatedAt: Math.floor(time3),
17412
+ // Unknown must stay unknown; only an explicit boolean is a native statement.
17413
+ running: typeof input.running === "boolean" ? input.running : null
17414
+ });
17415
+ return parsed.success ? parsed.data : null;
17416
+ }
17417
+ var SessionImportScope = class {
17418
+ #abort = new AbortController();
17419
+ #options;
17420
+ #pending = /* @__PURE__ */ new Set();
17421
+ constructor(options) {
17422
+ this.#options = options;
17423
+ }
17424
+ #closed() {
17425
+ return {
17426
+ ok: false,
17427
+ error: { code: "invalidState", message: this.#options.closedMessage, retryable: false }
17428
+ };
17429
+ }
17430
+ read(operation) {
17431
+ const signal = this.#abort.signal;
17432
+ if (signal.aborted)
17433
+ return Promise.resolve(this.#closed());
17434
+ let started;
17435
+ try {
17436
+ started = operation(signal);
17437
+ } catch (error51) {
17438
+ started = Promise.reject(error51 instanceof Error ? error51 : new Error("Session read failed"));
17439
+ }
17440
+ const request = started.then((value) => signal.aborted ? this.#closed() : { ok: true, value }).catch(() => signal.aborted ? this.#closed() : {
17441
+ ok: false,
17442
+ error: {
17443
+ code: "unavailable",
17444
+ message: this.#options.unavailableMessage,
17445
+ retryable: true
17446
+ }
17447
+ }).finally(() => this.#pending.delete(request));
17448
+ this.#pending.add(request);
17449
+ return request;
17450
+ }
17451
+ /** `read` for `resolveCandidate`: a null source is the selected Session having disappeared. */
17452
+ async resolve(operation) {
17453
+ const result = await this.read(operation);
17454
+ if (!result.ok)
17455
+ return result;
17456
+ return result.value ? { ok: true, value: result.value } : {
17457
+ ok: false,
17458
+ error: {
17459
+ code: "sessionNotFound",
17460
+ message: this.#options.notFoundMessage,
17461
+ retryable: false
17462
+ }
17463
+ };
17464
+ }
17465
+ /** Idempotent. Resolves after every started read has settled. */
17466
+ async close() {
17467
+ this.#abort.abort();
17468
+ await Promise.allSettled(this.#pending);
17469
+ }
17470
+ };
17471
+
17472
+ // dist/session-import.js
17473
+ function isRecord6(value) {
17474
+ return typeof value === "object" && value !== null && !Array.isArray(value);
17475
+ }
17476
+ function expandDirectory(value, home) {
17477
+ return path4.resolve(value === "~" ? home : value.startsWith(`~${path4.sep}`) || value.startsWith("~/") ? path4.join(home, value.slice(2)) : value);
17478
+ }
17479
+ function ompSessionImportDirectory(environment) {
17480
+ const home = (process.platform === "win32" ? environment.USERPROFILE : environment.HOME) || os2.homedir();
17481
+ const custom2 = environment.PI_CODING_AGENT_SESSION_DIR;
17482
+ if (custom2)
17483
+ return { directory: expandDirectory(custom2, home), flat: true };
17484
+ const agent = environment.PI_CODING_AGENT_DIR;
17485
+ return {
17486
+ directory: path4.join(agent ? expandDirectory(agent, home) : path4.join(home, ".omp", "agent"), "sessions"),
17487
+ flat: false
17488
+ };
17489
+ }
17490
+ function messageText(content) {
17491
+ if (typeof content === "string")
17492
+ return content;
17493
+ if (!Array.isArray(content))
17494
+ return "";
17495
+ return content.filter((part) => isRecord6(part) && part.type === "text" && typeof part.text === "string").map((part) => String(part.text)).join(" ");
17496
+ }
17497
+ async function readFacts(file2, signal) {
17498
+ const stream = createReadStream2(file2, { encoding: "utf8", signal });
17499
+ const lines = createInterface({ input: stream, crlfDelay: Infinity });
17500
+ let header = null;
17501
+ let nativeTitle = null;
17502
+ let firstPrompt = null;
17503
+ let updatedAt = null;
17504
+ let leafHasUser = false;
17505
+ const hasUserAncestry = /* @__PURE__ */ new Map();
17506
+ try {
17507
+ for await (const line of lines) {
17508
+ signal.throwIfAborted();
17509
+ if (!line.trim())
17510
+ continue;
17511
+ let entry;
17512
+ try {
17513
+ entry = JSON.parse(line);
17514
+ } catch {
17515
+ continue;
17516
+ }
17517
+ if (!isRecord6(entry))
17518
+ continue;
17519
+ if (entry.type === "title") {
17520
+ nativeTitle = sessionImportTitle(entry.title);
17521
+ continue;
17522
+ }
17523
+ if (entry.type === "session") {
17524
+ if (header)
17525
+ return null;
17526
+ if (typeof entry.id !== "string" || entry.id.length === 0 || typeof entry.cwd !== "string" || !path4.isAbsolute(entry.cwd))
17527
+ return null;
17528
+ header = { id: entry.id, cwd: entry.cwd };
17529
+ continue;
17530
+ }
17531
+ if (typeof entry.id !== "string" || entry.id.length === 0)
17532
+ continue;
17533
+ const message3 = isRecord6(entry.message) ? entry.message : null;
17534
+ const isUser = entry.type === "message" && message3?.role === "user";
17535
+ if (isUser)
17536
+ firstPrompt ??= sessionImportTitle(messageText(message3?.content));
17537
+ leafHasUser = isUser || typeof entry.parentId === "string" && hasUserAncestry.get(entry.parentId) === true;
17538
+ hasUserAncestry.set(entry.id, leafHasUser);
17539
+ if (entry.type === "message" && (message3?.role === "user" || message3?.role === "assistant")) {
17540
+ const time3 = typeof message3.timestamp === "number" ? message3.timestamp : typeof entry.timestamp === "string" ? Date.parse(entry.timestamp) : Number.NaN;
17541
+ if (Number.isFinite(time3) && time3 >= 0)
17542
+ updatedAt = time3;
17543
+ }
17544
+ }
17545
+ } finally {
17546
+ lines.close();
17547
+ stream.destroy();
17548
+ }
17549
+ if (!header || !leafHasUser)
17550
+ return null;
17551
+ return {
17552
+ nativeSessionId: header.id,
17553
+ cwd: header.cwd,
17554
+ title: nativeTitle ?? firstPrompt,
17555
+ updatedAt
17556
+ };
17557
+ }
17558
+ var OmpSessionImport = class {
17559
+ #location;
17560
+ #scope = new SessionImportScope({
17561
+ closedMessage: "Omp Session import is closed",
17562
+ unavailableMessage: "Omp sessions could not be read; close native clients, check storage access and retry",
17563
+ notFoundMessage: "Omp Session is no longer importable"
17564
+ });
17565
+ constructor(environment) {
17566
+ this.#location = ompSessionImportDirectory(environment);
17567
+ }
17568
+ listCandidates() {
17569
+ return this.#scope.read(async (signal) => [...(await this.#sources(signal)).values()].flatMap((sources) => (
17570
+ // One identity in two files cannot be resumed unambiguously.
17571
+ sources.length === 1 && sources[0] ? [sources[0].candidate] : []
17572
+ )));
17573
+ }
17574
+ resolveCandidate(nativeSessionId) {
17575
+ return this.#scope.resolve(async (signal) => {
17576
+ const sources = (await this.#sources(signal)).get(nativeSessionId);
17577
+ if (sources?.length !== 1 || !sources[0])
17578
+ return null;
17579
+ const source = await this.#source(sources[0].file, signal);
17580
+ return source?.nativeRef.nativeSessionId === nativeSessionId ? { candidate: source.candidate, nativeRef: source.nativeRef } : null;
17581
+ });
17582
+ }
17583
+ close() {
17584
+ return this.#scope.close();
17585
+ }
17586
+ async #sessionFiles(signal) {
17587
+ const { directory, flat } = this.#location;
17588
+ const info = await optionalLstat(directory);
17589
+ if (!info)
17590
+ return [];
17591
+ if (!info.isDirectory())
17592
+ throw new Error("Omp Session store is not a directory");
17593
+ const files = [];
17594
+ const visit = async (current, projectLevel) => {
17595
+ const entries = await opendir(current).catch((error51) => {
17596
+ if (isMissingFileError(error51))
17597
+ return null;
17598
+ throw error51;
17599
+ });
17600
+ if (!entries)
17601
+ return;
17602
+ for await (const entry of entries) {
17603
+ signal.throwIfAborted();
17604
+ if (projectLevel && entry.isDirectory())
17605
+ await visit(path4.join(current, entry.name), false);
17606
+ else if (!projectLevel && entry.isFile() && entry.name.endsWith(".jsonl"))
17607
+ files.push(path4.join(current, entry.name));
17608
+ }
17609
+ };
17610
+ await visit(directory, !flat);
17611
+ return files;
17612
+ }
17613
+ /** Session ID to every readable file claiming it. Files changing under the read are skipped. */
17614
+ async #sources(signal) {
17615
+ const found = /* @__PURE__ */ new Map();
17616
+ for (const file2 of await this.#sessionFiles(signal)) {
17617
+ signal.throwIfAborted();
17618
+ try {
17619
+ const source = await this.#source(file2, signal);
17620
+ if (!source)
17621
+ continue;
17622
+ const sources = found.get(source.nativeRef.nativeSessionId) ?? [];
17623
+ sources.push(source);
17624
+ found.set(source.nativeRef.nativeSessionId, sources);
17625
+ } catch (error51) {
17626
+ if (!(error51 instanceof SessionImportChangedError))
17627
+ throw error51;
17628
+ }
17629
+ }
17630
+ return found;
17631
+ }
17632
+ async #source(file2, signal) {
17633
+ signal.throwIfAborted();
17634
+ return readStableFiles([file2], async ([info]) => {
17635
+ if (!info?.isFile() || info.size === 0)
17636
+ return null;
17637
+ try {
17638
+ const facts = await readFacts(file2, signal);
17639
+ if (!facts)
17640
+ return null;
17641
+ const cwd = await realpath2(facts.cwd);
17642
+ if (!(await stat(cwd)).isDirectory())
17643
+ return null;
17644
+ const candidate = sessionImportCandidate({
17645
+ nativeSessionId: facts.nativeSessionId,
17646
+ cwd,
17647
+ title: facts.title,
17648
+ updatedAt: facts.updatedAt ?? info.mtimeMs
17649
+ // OMP has no cross-process activity marker: idleness cannot be established.
17650
+ });
17651
+ if (!candidate)
17652
+ return null;
17653
+ return {
17654
+ file: file2,
17655
+ candidate,
17656
+ // Resume needs the file itself: OMP is started with `--session <file>`.
17657
+ nativeRef: nativeSessionRefSchema.parse({
17658
+ harnessId: "omp",
17659
+ nativeSessionId: facts.nativeSessionId,
17660
+ locator: { sessionFile: await realpath2(file2) },
17661
+ formatVersion: 1
17662
+ })
17663
+ };
17664
+ } catch (error51) {
17665
+ signal.throwIfAborted();
17666
+ if (isStorageAccessError(error51))
17667
+ throw error51;
17668
+ return null;
17669
+ }
17670
+ });
17671
+ }
17672
+ };
16803
17673
 
16804
17674
  // dist/omp-last-turn-rollback.js
16805
17675
  function modelFromState(state) {
@@ -16856,230 +17726,7 @@ async function rollbackOmpLastTurn(transport, sourceSessionId, cwd) {
16856
17726
  // dist/omp-rpc-session.js
16857
17727
  import { spawn, spawnSync } from "node:child_process";
16858
17728
  import { randomUUID } from "node:crypto";
16859
- import path3 from "node:path";
16860
-
16861
- // ../../harness-discovery/dist/environment.js
16862
- import fs from "node:fs";
16863
- import path from "node:path";
16864
- function targetPath(platform) {
16865
- return platform === "win32" ? path.win32 : path.posix;
16866
- }
16867
- function environmentValue(environment, name) {
16868
- const lowered = name.toLowerCase();
16869
- for (const [key, value] of Object.entries(environment)) {
16870
- if (key.toLowerCase() === lowered)
16871
- return value;
16872
- }
16873
- return void 0;
16874
- }
16875
- function pathDelimiter(platform) {
16876
- return platform === "win32" ? ";" : ":";
16877
- }
16878
- function pathDirectories(environment, platform) {
16879
- return (environmentValue(environment, "PATH") ?? "").split(pathDelimiter(platform)).map((directory) => directory.trim().replace(/^"|"$/gu, "")).filter(Boolean);
16880
- }
16881
- function executableExtensions(command, platform, environment) {
16882
- if (platform !== "win32")
16883
- return [""];
16884
- if (targetPath(platform).extname(command) !== "")
16885
- return [""];
16886
- return (environmentValue(environment, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter(Boolean);
16887
- }
16888
- function isExecutableFile(filePath, platform) {
16889
- try {
16890
- fs.accessSync(filePath, platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK);
16891
- return fs.statSync(filePath).isFile();
16892
- } catch {
16893
- return false;
16894
- }
16895
- }
16896
- function subdirectoryNames(directory) {
16897
- try {
16898
- return fs.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
16899
- } catch {
16900
- return [];
16901
- }
16902
- }
16903
- function newestFirst(names) {
16904
- return [...names].sort((left, right) => right.localeCompare(left, void 0, { numeric: true }));
16905
- }
16906
-
16907
- // ../../harness-discovery/dist/node-runtime.js
16908
- import path2 from "node:path";
16909
- function withNodeRuntimeOnPath(environment, runtimeExecutable = process.execPath, platform = process.platform) {
16910
- const pathKey = Object.keys(environment).find((name) => name.toLowerCase() === "path") ?? "PATH";
16911
- const delimiter = platform === "win32" ? ";" : ":";
16912
- const runtimeDirectory = path2.dirname(runtimeExecutable);
16913
- const directories = (environment[pathKey] ?? "").split(delimiter).filter(Boolean);
16914
- const equal = platform === "win32" ? (value) => value.toLowerCase() : (value) => value;
16915
- if (!directories.some((directory) => equal(directory) === equal(runtimeDirectory))) {
16916
- directories.push(runtimeDirectory);
16917
- }
16918
- return { ...environment, [pathKey]: directories.join(delimiter) };
16919
- }
16920
-
16921
- // ../../harness-discovery/dist/resolve.js
16922
- import os from "node:os";
16923
-
16924
- // ../../harness-discovery/dist/version-managers.js
16925
- function versionManagerBinaryDirectories(context) {
16926
- const { platform, environment, home } = context;
16927
- const list = context.subdirectories ?? subdirectoryNames;
16928
- const pathFlavor = targetPath(platform);
16929
- const value = (name) => environmentValue(environment, name);
16930
- const directories = [];
16931
- const versioned = (root, ...tail) => {
16932
- for (const version2 of newestFirst(list(root))) {
16933
- directories.push(pathFlavor.join(root, version2, ...tail));
16934
- }
16935
- };
16936
- if (platform === "win32") {
16937
- const appData = value("APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming");
16938
- const localAppData = value("LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local");
16939
- versioned(pathFlavor.join(appData, "nvm"));
16940
- versioned(value("FNM_DIR") ?? pathFlavor.join(appData, "fnm", "node-versions"), "installation");
16941
- directories.push(pathFlavor.join(localAppData, "Volta", "bin"));
16942
- directories.push(pathFlavor.join(home, ".bun", "bin"));
16943
- const pnpmHome2 = value("PNPM_HOME");
16944
- if (pnpmHome2)
16945
- directories.push(pnpmHome2);
16946
- directories.push(pathFlavor.join(localAppData, "pnpm"));
16947
- return directories;
16948
- }
16949
- versioned(pathFlavor.join(value("NVM_DIR") ?? pathFlavor.join(home, ".nvm"), "versions", "node"), "bin");
16950
- const fnmRoots = [
16951
- value("FNM_DIR"),
16952
- pathFlavor.join(home, ".local", "share", "fnm"),
16953
- pathFlavor.join(home, "Library", "Application Support", "fnm")
16954
- ].filter((root) => root !== void 0);
16955
- for (const root of fnmRoots) {
16956
- versioned(pathFlavor.join(root, "node-versions"), "installation", "bin");
16957
- }
16958
- const voltaHome = value("VOLTA_HOME") ?? pathFlavor.join(home, ".volta");
16959
- versioned(pathFlavor.join(voltaHome, "tools", "image", "node"), "bin");
16960
- directories.push(pathFlavor.join(voltaHome, "bin"));
16961
- const asdfHome = value("ASDF_DATA_DIR") ?? pathFlavor.join(home, ".asdf");
16962
- versioned(pathFlavor.join(asdfHome, "installs", "nodejs"), "bin");
16963
- directories.push(pathFlavor.join(asdfHome, "shims"));
16964
- const nodenvHome = value("NODENV_ROOT") ?? pathFlavor.join(home, ".nodenv");
16965
- versioned(pathFlavor.join(nodenvHome, "versions"), "bin");
16966
- directories.push(pathFlavor.join(nodenvHome, "shims"));
16967
- versioned(pathFlavor.join(value("N_PREFIX") ?? "/usr/local", "n", "versions", "node"), "bin");
16968
- directories.push(pathFlavor.join(home, ".bun", "bin"));
16969
- const pnpmHome = value("PNPM_HOME");
16970
- if (pnpmHome)
16971
- directories.push(pnpmHome);
16972
- directories.push(pathFlavor.join(home, "Library", "pnpm"));
16973
- directories.push(pathFlavor.join(home, ".local", "share", "pnpm"));
16974
- for (const prefix of ["/opt/homebrew/opt", "/usr/local/opt"]) {
16975
- for (const formula of newestFirst(list(prefix).filter((name) => name.startsWith("node@")))) {
16976
- directories.push(pathFlavor.join(prefix, formula, "bin"));
16977
- }
16978
- }
16979
- return directories;
16980
- }
16981
-
16982
- // ../../harness-discovery/dist/resolve.js
16983
- var VERSION_MANAGER_ROOTS = "<version-managers>";
16984
- function installRootExtensions(platform) {
16985
- return platform === "win32" ? [".exe", ".cmd"] : [""];
16986
- }
16987
- function resolveHomeDirectory(input) {
16988
- return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
16989
- }
16990
- function templateVariables(environment, platform, home) {
16991
- const pathFlavor = targetPath(platform);
16992
- return {
16993
- HOME: home,
16994
- USERPROFILE: home,
16995
- APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
16996
- LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
16997
- };
16998
- }
16999
- function joinTemplate(platform, value) {
17000
- const pathFlavor = targetPath(platform);
17001
- const segments = value.split("/");
17002
- const head = segments[0] ?? "";
17003
- const tail = segments.slice(1);
17004
- if (head === "")
17005
- return pathFlavor.join(pathFlavor.sep, ...tail);
17006
- return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
17007
- }
17008
- function expandInstallRoot(template, environment, platform, home) {
17009
- const variables = templateVariables(environment, platform, home);
17010
- let unresolved = false;
17011
- const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
17012
- const value = variables[name] ?? environmentValue(environment, name);
17013
- if (value === void 0 || value === "") {
17014
- unresolved = true;
17015
- return "";
17016
- }
17017
- return value;
17018
- });
17019
- return unresolved ? void 0 : joinTemplate(platform, substituted);
17020
- }
17021
- function installRootDirectories(spec, input, dependencies, platform, home) {
17022
- const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
17023
- const directories = [];
17024
- for (const template of templates) {
17025
- if (template === VERSION_MANAGER_ROOTS) {
17026
- directories.push(...versionManagerBinaryDirectories({
17027
- platform,
17028
- environment: input.environment,
17029
- home,
17030
- ...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
17031
- }));
17032
- continue;
17033
- }
17034
- const directory = expandInstallRoot(template, input.environment, platform, home);
17035
- if (directory !== void 0)
17036
- directories.push(directory);
17037
- }
17038
- return directories;
17039
- }
17040
- function harnessCandidates(spec, input, dependencies = {}) {
17041
- const platform = input.platform ?? process.platform;
17042
- const pathFlavor = targetPath(platform);
17043
- const configured = input.command ?? (spec.commandEnvironmentVariable ? environmentValue(input.environment, spec.commandEnvironmentVariable) : void 0);
17044
- const command = configured ?? spec.command;
17045
- if (pathFlavor.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
17046
- return [{ candidate: command, source: "configured" }];
17047
- }
17048
- const candidates = [];
17049
- const extensions = executableExtensions(command, platform, input.environment);
17050
- for (const directory of pathDirectories(input.environment, platform)) {
17051
- for (const extension of extensions) {
17052
- candidates.push({
17053
- candidate: pathFlavor.join(directory, command + extension),
17054
- source: "path"
17055
- });
17056
- }
17057
- }
17058
- if (configured !== void 0)
17059
- return candidates;
17060
- const home = resolveHomeDirectory(input);
17061
- for (const directory of installRootDirectories(spec, input, dependencies, platform, home)) {
17062
- for (const extension of installRootExtensions(platform)) {
17063
- candidates.push({
17064
- candidate: pathFlavor.join(directory, spec.command + extension),
17065
- source: "install-root"
17066
- });
17067
- }
17068
- }
17069
- return candidates;
17070
- }
17071
- function resolveHarnessExecutable(spec, input, dependencies = {}) {
17072
- const platform = input.platform ?? process.platform;
17073
- const isExecutable = dependencies.isExecutable ?? ((candidate) => isExecutableFile(candidate, platform));
17074
- const runnable = spec.runnableCandidate ?? ((candidate) => candidate);
17075
- const context = { platform, isExecutable };
17076
- for (const { candidate, source } of harnessCandidates(spec, input, dependencies)) {
17077
- const executable = runnable(candidate, context);
17078
- if (executable !== void 0 && isExecutable(executable))
17079
- return { executable, source };
17080
- }
17081
- return void 0;
17082
- }
17729
+ import path5 from "node:path";
17083
17730
 
17084
17731
  // dist/command.js
17085
17732
  var ompDiscoverySpec = {
@@ -17108,14 +17755,14 @@ function resolveOmpExecutable(input, dependencies = {}) {
17108
17755
  }
17109
17756
 
17110
17757
  // dist/omp-usage.js
17111
- function isRecord6(value) {
17758
+ function isRecord7(value) {
17112
17759
  return typeof value === "object" && value !== null && !Array.isArray(value);
17113
17760
  }
17114
17761
  function nonNegativeSafeInteger(value) {
17115
17762
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
17116
17763
  }
17117
17764
  function optionalOmpCacheHitRatePercent(value) {
17118
- if (!isRecord6(value) || value.role !== "assistant" || !isRecord6(value.usage))
17765
+ if (!isRecord7(value) || value.role !== "assistant" || !isRecord7(value.usage))
17119
17766
  return null;
17120
17767
  const input = nonNegativeSafeInteger(value.usage.input);
17121
17768
  const cacheRead = nonNegativeSafeInteger(value.usage.cacheRead);
@@ -17128,20 +17775,20 @@ function optionalOmpCacheHitRatePercent(value) {
17128
17775
  function latestOmpCacheHitRatePercent(history) {
17129
17776
  let latest = null;
17130
17777
  for (const entry of activeOmpEntries(history)) {
17131
- if (entry.type === "message" && isRecord6(entry.message) && entry.message.role === "assistant") {
17778
+ if (entry.type === "message" && isRecord7(entry.message) && entry.message.role === "assistant") {
17132
17779
  latest = optionalOmpCacheHitRatePercent(entry.message);
17133
17780
  }
17134
17781
  }
17135
17782
  return latest;
17136
17783
  }
17137
17784
  function responseData(response, operation) {
17138
- if (!isRecord6(response.data)) {
17785
+ if (!isRecord7(response.data)) {
17139
17786
  throw new Error(`Omp RPC ${operation} response has no data`);
17140
17787
  }
17141
17788
  return response.data;
17142
17789
  }
17143
17790
  function contextUsage(value) {
17144
- if (!isRecord6(value))
17791
+ if (!isRecord7(value))
17145
17792
  throw new Error("Omp RPC context Usage is invalid");
17146
17793
  return parseHostUsage({
17147
17794
  contextUsedTokens: value.tokens,
@@ -17151,15 +17798,15 @@ function contextUsage(value) {
17151
17798
  function parseOmpSessionUsage(response) {
17152
17799
  const data = responseData(response, "Session stats");
17153
17800
  const tokens = data.tokens;
17154
- if (tokens !== void 0 && !isRecord6(tokens)) {
17801
+ if (tokens !== void 0 && !isRecord7(tokens)) {
17155
17802
  throw new Error("Omp RPC Session stats tokens are invalid");
17156
17803
  }
17157
17804
  return parseHostUsage({
17158
- ...isRecord6(tokens) && tokens.input !== void 0 ? { inputTokens: tokens.input } : {},
17159
- ...isRecord6(tokens) && tokens.cacheRead !== void 0 ? { cachedInputTokens: tokens.cacheRead } : {},
17160
- ...isRecord6(tokens) && tokens.cacheWrite !== void 0 ? { cacheWriteInputTokens: tokens.cacheWrite } : {},
17161
- ...isRecord6(tokens) && tokens.output !== void 0 ? { outputTokens: tokens.output } : {},
17162
- ...isRecord6(tokens) && tokens.total !== void 0 ? { totalTokens: tokens.total } : {},
17805
+ ...isRecord7(tokens) && tokens.input !== void 0 ? { inputTokens: tokens.input } : {},
17806
+ ...isRecord7(tokens) && tokens.cacheRead !== void 0 ? { cachedInputTokens: tokens.cacheRead } : {},
17807
+ ...isRecord7(tokens) && tokens.cacheWrite !== void 0 ? { cacheWriteInputTokens: tokens.cacheWrite } : {},
17808
+ ...isRecord7(tokens) && tokens.output !== void 0 ? { outputTokens: tokens.output } : {},
17809
+ ...isRecord7(tokens) && tokens.total !== void 0 ? { totalTokens: tokens.total } : {},
17163
17810
  ...data.cost !== void 0 ? { totalCostUsd: data.cost } : {},
17164
17811
  ...data.contextUsage !== void 0 ? contextUsage(data.contextUsage) : {}
17165
17812
  });
@@ -17274,7 +17921,7 @@ var OmpRpcUnsupportedCommandError = class extends Error {
17274
17921
  }
17275
17922
  };
17276
17923
  var textDecoder = new TextDecoder("utf-8", { fatal: true });
17277
- function isRecord7(value) {
17924
+ function isRecord8(value) {
17278
17925
  return typeof value === "object" && value !== null && !Array.isArray(value);
17279
17926
  }
17280
17927
  function message2(value) {
@@ -17286,13 +17933,13 @@ function nonBlankString(value) {
17286
17933
  function parseNativeModel(value, context) {
17287
17934
  if (value === null || value === void 0)
17288
17935
  return null;
17289
- if (!isRecord7(value) || !nonBlankString(value.provider) || !nonBlankString(value.id)) {
17936
+ if (!isRecord8(value) || !nonBlankString(value.provider) || !nonBlankString(value.id)) {
17290
17937
  throw new OmpRpcFaultError("protocolError", `Omp RPC returned an invalid ${context} Model`);
17291
17938
  }
17292
17939
  return { provider: value.provider, id: value.id };
17293
17940
  }
17294
17941
  function sessionStateData(response) {
17295
- const data = isRecord7(response.data) ? response.data : null;
17942
+ const data = isRecord8(response.data) ? response.data : null;
17296
17943
  if (!data)
17297
17944
  throw new OmpRpcFaultError("protocolError", "Omp RPC state response has no data");
17298
17945
  return data;
@@ -17307,7 +17954,7 @@ function parseSessionState(response) {
17307
17954
  if (thinkingLevel !== null && !thinkingLevel.success) {
17308
17955
  throw new OmpRpcFaultError("protocolError", "Omp RPC state has an invalid Thinking level");
17309
17956
  }
17310
- const thinking = isRecord7(data.model) && isRecord7(data.model.thinking) ? data.model.thinking : null;
17957
+ const thinking = isRecord8(data.model) && isRecord8(data.model.thinking) ? data.model.thinking : null;
17311
17958
  const availableThinkingLevels = thinking && Array.isArray(thinking.efforts) ? thinking.efforts.flatMap((level) => {
17312
17959
  const parsed = harnessThinkingOptionIdSchema.safeParse(level);
17313
17960
  return parsed.success ? [parsed.data] : [];
@@ -17330,25 +17977,25 @@ function parseSessionStreaming(response) {
17330
17977
  return isStreaming;
17331
17978
  }
17332
17979
  function parseAvailableModels(response) {
17333
- const data = isRecord7(response.data) ? response.data : null;
17980
+ const data = isRecord8(response.data) ? response.data : null;
17334
17981
  if (!data || !Array.isArray(data.models)) {
17335
17982
  throw new OmpRpcFaultError("protocolError", "Omp RPC Model catalog response has no models");
17336
17983
  }
17337
17984
  return data.models.map((model) => {
17338
17985
  const parsed = parseNativeModel(model, "catalog");
17339
- if (!parsed || !isRecord7(model) || typeof model.reasoning !== "boolean") {
17986
+ if (!parsed || !isRecord8(model) || typeof model.reasoning !== "boolean") {
17340
17987
  throw new OmpRpcFaultError("protocolError", "Omp RPC catalog contains a Model without reasoning capability");
17341
17988
  }
17342
17989
  return { ...parsed, reasoning: model.reasoning };
17343
17990
  });
17344
17991
  }
17345
17992
  function parseSubagentMessages(response) {
17346
- const data = isRecord7(response.data) ? response.data : null;
17993
+ const data = isRecord8(response.data) ? response.data : null;
17347
17994
  if (!data || !nonBlankString(data.sessionFile) || !Number.isSafeInteger(data.fromByte) || !Number.isSafeInteger(data.nextByte) || data.fromByte < 0 || data.nextByte < data.fromByte || typeof data.reset !== "boolean" || !Array.isArray(data.entries) || !Array.isArray(data.messages)) {
17348
17995
  throw new OmpRpcFaultError("protocolError", "Omp RPC Subagent transcript response is invalid");
17349
17996
  }
17350
- const entries = data.entries.flatMap((value) => isRecord7(value) ? [value] : []);
17351
- const messages = data.messages.flatMap((value) => isRecord7(value) ? [value] : []);
17997
+ const entries = data.entries.flatMap((value) => isRecord8(value) ? [value] : []);
17998
+ const messages = data.messages.flatMap((value) => isRecord8(value) ? [value] : []);
17352
17999
  if (entries.length !== data.entries.length || messages.length !== data.messages.length) {
17353
18000
  throw new OmpRpcFaultError("protocolError", "Omp RPC Subagent transcript contains invalid data");
17354
18001
  }
@@ -17369,17 +18016,17 @@ function subagentStatus(value) {
17369
18016
  throw new OmpRpcFaultError("protocolError", "Omp RPC Subagent status is invalid");
17370
18017
  }
17371
18018
  function assistantText(value) {
17372
- if (!isRecord7(value) || value.role !== "assistant" || !Array.isArray(value.content))
18019
+ if (!isRecord8(value) || value.role !== "assistant" || !Array.isArray(value.content))
17373
18020
  return null;
17374
- return value.content.filter((content) => isRecord7(content) && content.type === "text" && typeof content.text === "string").map((content) => content.text).join("");
18021
+ return value.content.filter((content) => isRecord8(content) && content.type === "text" && typeof content.text === "string").map((content) => content.text).join("");
17375
18022
  }
17376
18023
  function assistantMessageId(value) {
17377
- if (!isRecord7(value) || value.role !== "assistant")
18024
+ if (!isRecord8(value) || value.role !== "assistant")
17378
18025
  return null;
17379
18026
  return nonBlankString(value.responseId) ? value.responseId : null;
17380
18027
  }
17381
18028
  function extractReasoningText(content) {
17382
- if (!isRecord7(content))
18029
+ if (!isRecord8(content))
17383
18030
  return null;
17384
18031
  const type = String(content.type ?? "");
17385
18032
  if (type === "thinking" || type === "reasoning" || type === "thought") {
@@ -17389,12 +18036,12 @@ function extractReasoningText(content) {
17389
18036
  return null;
17390
18037
  }
17391
18038
  function assistantReasoning(value) {
17392
- if (!isRecord7(value) || value.role !== "assistant" || !Array.isArray(value.content))
18039
+ if (!isRecord8(value) || value.role !== "assistant" || !Array.isArray(value.content))
17393
18040
  return null;
17394
18041
  return value.content.map(extractReasoningText).filter((text) => typeof text === "string").join("");
17395
18042
  }
17396
18043
  function assistantFailure(value) {
17397
- if (!isRecord7(value) || value.role !== "assistant")
18044
+ if (!isRecord8(value) || value.role !== "assistant")
17398
18045
  return void 0;
17399
18046
  if (value.stopReason !== "error" && value.stopReason !== "aborted")
17400
18047
  return null;
@@ -17414,7 +18061,7 @@ function signalProcessTree(child, signal) {
17414
18061
  try {
17415
18062
  process.kill(-child.pid, signal);
17416
18063
  } catch (error51) {
17417
- if (!isRecord7(error51) || error51.code !== "ESRCH")
18064
+ if (!isRecord8(error51) || error51.code !== "ESRCH")
17418
18065
  throw error51;
17419
18066
  }
17420
18067
  }
@@ -17453,7 +18100,7 @@ function ompRpcProcessCommand(options, dependencies = {}) {
17453
18100
  ...modelArguments,
17454
18101
  ...sessionArguments
17455
18102
  ];
17456
- const extension = path3.win32.extname(command).toLowerCase();
18103
+ const extension = path5.win32.extname(command).toLowerCase();
17457
18104
  if (platform !== "win32" || ![".cmd", ".bat"].includes(extension)) {
17458
18105
  return { command, arguments: arguments_, windowsVerbatimArguments: false };
17459
18106
  }
@@ -17496,6 +18143,10 @@ var OmpRpcSession = class {
17496
18143
  #manualCompaction = null;
17497
18144
  #stderrTail = "";
17498
18145
  #frameDecoder = new OmpFrameDecoder();
18146
+ #startupFaultResolve = null;
18147
+ #startupFault = new Promise((resolve) => {
18148
+ this.#startupFaultResolve = resolve;
18149
+ });
17499
18150
  #readyResolve = null;
17500
18151
  #ready = new Promise((resolve) => {
17501
18152
  this.#readyResolve = resolve;
@@ -17552,7 +18203,7 @@ var OmpRpcSession = class {
17552
18203
  this.#stderrTail = sanitizeDiagnosticTail(`${this.#stderrTail}${chunk.toString()}`);
17553
18204
  });
17554
18205
  child.once("error", (error51) => {
17555
- const kind = isRecord7(error51) && error51.code === "ENOENT" ? "notInstalled" : "unavailable";
18206
+ const kind = isRecord8(error51) && error51.code === "ENOENT" ? "notInstalled" : "unavailable";
17556
18207
  this.#fail(new OmpRpcFaultError(kind, `Omp RPC failed to start: ${error51.message}`, this.stderrTail));
17557
18208
  });
17558
18209
  child.once("exit", (code, signal) => {
@@ -17567,10 +18218,20 @@ var OmpRpcSession = class {
17567
18218
  }),
17568
18219
  new Promise((_resolve, reject) => setTimeout(() => reject(new Error("Omp RPC start timed out")), this.#options.commandTimeoutMs))
17569
18220
  ]);
17570
- await Promise.race([
17571
- this.#ready,
17572
- new Promise((_resolve, reject) => setTimeout(() => reject(new Error("Omp RPC ready signal timed out")), this.#options.commandTimeoutMs))
17573
- ]);
18221
+ let readyTimeout;
18222
+ try {
18223
+ await Promise.race([
18224
+ this.#ready,
18225
+ this.#startupFault.then((error51) => {
18226
+ throw error51;
18227
+ }),
18228
+ new Promise((_resolve, reject) => {
18229
+ readyTimeout = setTimeout(() => reject(new Error("Omp RPC ready signal timed out")), this.#options.commandTimeoutMs);
18230
+ })
18231
+ ]);
18232
+ } finally {
18233
+ clearTimeout(readyTimeout);
18234
+ }
17574
18235
  await this.#send("negotiate_protocol", { protocolVersion: 2 }).catch(() => void 0);
17575
18236
  if (this.#options.subscribeSubagentEvents !== false) {
17576
18237
  await this.#send("set_subagent_subscription", { level: "events" }).catch(() => void 0);
@@ -17590,17 +18251,17 @@ var OmpRpcSession = class {
17590
18251
  return await readOmpSessionHistory(this.state.sessionFile);
17591
18252
  }
17592
18253
  const response = await this.#send("get_messages", {});
17593
- const data = isRecord7(response.data) ? response.data : null;
18254
+ const data = isRecord8(response.data) ? response.data : null;
17594
18255
  if (!data || !Array.isArray(data.messages)) {
17595
18256
  throw new OmpRpcFaultError("protocolError", "Omp RPC messages response has no messages");
17596
18257
  }
17597
18258
  let branchEntryIds = null;
17598
18259
  try {
17599
18260
  const branchResponse = await this.#send("get_branch_messages", {});
17600
- const branchData = isRecord7(branchResponse.data) ? branchResponse.data : null;
18261
+ const branchData = isRecord8(branchResponse.data) ? branchResponse.data : null;
17601
18262
  if (branchData && Array.isArray(branchData.messages)) {
17602
18263
  const parsed = branchData.messages.flatMap((entry) => {
17603
- if (!isRecord7(entry) || !nonBlankString(entry.entryId))
18264
+ if (!isRecord8(entry) || !nonBlankString(entry.entryId))
17604
18265
  return [];
17605
18266
  return [entry.entryId];
17606
18267
  });
@@ -17614,11 +18275,11 @@ var OmpRpcSession = class {
17614
18275
  let userIndex = 0;
17615
18276
  let parentId = null;
17616
18277
  const entries = data.messages.map((nativeMessage, index) => {
17617
- const role = isRecord7(nativeMessage) ? nativeMessage.role : void 0;
18278
+ const role = isRecord8(nativeMessage) ? nativeMessage.role : void 0;
17618
18279
  const branchId = role === "user" ? branchEntryIds?.[userIndex] : void 0;
17619
18280
  if (branchId)
17620
18281
  userIndex += 1;
17621
- const id = branchId ?? (isRecord7(nativeMessage) && nonBlankString(nativeMessage.id) ? nativeMessage.id : `omp-message-${index}`);
18282
+ const id = branchId ?? (isRecord8(nativeMessage) && nonBlankString(nativeMessage.id) ? nativeMessage.id : `omp-message-${index}`);
17622
18283
  const entry = { id, parentId, type: "message", message: nativeMessage };
17623
18284
  parentId = id;
17624
18285
  return entry;
@@ -17698,7 +18359,7 @@ var OmpRpcSession = class {
17698
18359
  throw new Error("Omp RPC Fork requires an Entry identity");
17699
18360
  try {
17700
18361
  const response = await this.#send("branch", { entryId });
17701
- const data = isRecord7(response.data) ? response.data : null;
18362
+ const data = isRecord8(response.data) ? response.data : null;
17702
18363
  if (!data || data.cancelled === true) {
17703
18364
  throw new OmpRpcFaultError("unavailable", "Omp RPC Fork was cancelled");
17704
18365
  }
@@ -17891,7 +18552,7 @@ var OmpRpcSession = class {
17891
18552
  continue;
17892
18553
  }
17893
18554
  const value = decoded;
17894
- if (!isRecord7(value) || typeof value.type !== "string") {
18555
+ if (!isRecord8(value) || typeof value.type !== "string") {
17895
18556
  throw new OmpRpcFaultError("protocolError", "Omp RPC returned an invalid envelope");
17896
18557
  }
17897
18558
  this.#handle(value);
@@ -17950,7 +18611,7 @@ var OmpRpcSession = class {
17950
18611
  this.#armCommandTimeout(id, pending);
17951
18612
  }
17952
18613
  }
17953
- const outcome = value.aborted === true ? "cancelled" : isRecord7(value.result) ? "succeeded" : "failed";
18614
+ const outcome = value.aborted === true ? "cancelled" : isRecord8(value.result) ? "succeeded" : "failed";
17954
18615
  const event = {
17955
18616
  type: "compaction.completed",
17956
18617
  outcome,
@@ -17983,12 +18644,12 @@ var OmpRpcSession = class {
17983
18644
  this.#startAssistantMessage(active, value.message);
17984
18645
  return;
17985
18646
  }
17986
- if (value.type === "message_update" && isRecord7(value.assistantMessageEvent)) {
18647
+ if (value.type === "message_update" && isRecord8(value.assistantMessageEvent)) {
17987
18648
  const event = value.assistantMessageEvent;
17988
18649
  const eventType = String(event.type ?? "");
17989
18650
  const isThinking = eventType === "thinking_delta" || eventType === "reasoning_delta" || eventType === "thought_delta" || eventType === "thinking" || eventType === "reasoning";
17990
18651
  const isText = eventType === "text_delta" || eventType === "text" || eventType === "content_block_delta";
17991
- const delta = typeof event.delta === "string" ? event.delta : typeof event.thinking === "string" ? event.thinking : typeof event.reasoning === "string" ? event.reasoning : typeof event.text === "string" ? event.text : isRecord7(event.delta) && typeof event.delta.thinking === "string" ? event.delta.thinking : isRecord7(event.delta) && typeof event.delta.text === "string" ? event.delta.text : null;
18652
+ const delta = typeof event.delta === "string" ? event.delta : typeof event.thinking === "string" ? event.thinking : typeof event.reasoning === "string" ? event.reasoning : typeof event.text === "string" ? event.text : isRecord8(event.delta) && typeof event.delta.thinking === "string" ? event.delta.thinking : isRecord8(event.delta) && typeof event.delta.text === "string" ? event.delta.text : null;
17992
18653
  if (isThinking && delta !== null && delta.length > 0) {
17993
18654
  const messageId = this.#ensureAssistantMessage(active, value.message);
17994
18655
  active.reasoningMessageOpen = true;
@@ -18028,7 +18689,7 @@ var OmpRpcSession = class {
18028
18689
  if (value.type === "agent_end" && Array.isArray(value.messages)) {
18029
18690
  for (let index = value.messages.length - 1; index >= 0; index -= 1) {
18030
18691
  const message3 = value.messages[index];
18031
- if (!isRecord7(message3) || message3.role !== "assistant")
18692
+ if (!isRecord8(message3) || message3.role !== "assistant")
18032
18693
  continue;
18033
18694
  this.#finalizeAssistantMessage(active, message3);
18034
18695
  break;
@@ -18045,8 +18706,8 @@ var OmpRpcSession = class {
18045
18706
  if (value.type !== "subagent_lifecycle" && value.type !== "subagent_progress" && value.type !== "subagent_event") {
18046
18707
  return false;
18047
18708
  }
18048
- const payload = isRecord7(value.payload) ? value.payload : null;
18049
- const progressPayload = value.type === "subagent_progress" && payload && isRecord7(payload.progress) ? payload.progress : null;
18709
+ const payload = isRecord8(value.payload) ? value.payload : null;
18710
+ const progressPayload = value.type === "subagent_progress" && payload && isRecord8(payload.progress) ? payload.progress : null;
18050
18711
  const nativeIdValue = progressPayload?.id ?? payload?.id;
18051
18712
  if (!payload || !nonBlankString(nativeIdValue)) {
18052
18713
  throw new OmpRpcFaultError("protocolError", "Omp RPC Subagent frame has no stable ID");
@@ -18463,6 +19124,8 @@ var OmpRpcSession = class {
18463
19124
  if (this.#closed || this.#failed)
18464
19125
  return;
18465
19126
  this.#failed = true;
19127
+ this.#startupFaultResolve?.(error51);
19128
+ this.#startupFaultResolve = null;
18466
19129
  this.#rejectAll(error51);
18467
19130
  this.#options.onFault?.(error51);
18468
19131
  }
@@ -18623,7 +19286,7 @@ var ompCommandCatalog = harnessCommandCatalogSchema.parse({
18623
19286
  ]
18624
19287
  });
18625
19288
  var DEFAULT_TOOL_OUTPUT_LIMIT = 64e3;
18626
- function isRecord8(value) {
19289
+ function isRecord9(value) {
18627
19290
  return typeof value === "object" && value !== null && !Array.isArray(value);
18628
19291
  }
18629
19292
  function errorMessage(error51) {
@@ -18638,7 +19301,7 @@ var OmpAdapterFaultError = class extends Error {
18638
19301
  }
18639
19302
  };
18640
19303
  function normalizedError(error51, fallbackCode) {
18641
- if (isRecord8(error51) && error51.code === "ENOENT") {
19304
+ if (isRecord9(error51) && error51.code === "ENOENT") {
18642
19305
  return { code: "notInstalled", message: errorMessage(error51), retryable: false };
18643
19306
  }
18644
19307
  if (error51 instanceof OmpAdapterFaultError)
@@ -18715,7 +19378,7 @@ function nativeModelForHistory(state) {
18715
19378
  return nativeModelFromState(state);
18716
19379
  }
18717
19380
  function sessionFileFromRef(ref) {
18718
- if (ref.harnessId !== ompHarnessId2 || !isRecord8(ref.locator) || typeof ref.locator.sessionFile !== "string" || ref.locator.sessionFile.length === 0) {
19381
+ if (ref.harnessId !== ompHarnessId2 || !isRecord9(ref.locator) || typeof ref.locator.sessionFile !== "string" || ref.locator.sessionFile.length === 0) {
18719
19382
  throw new Error("Omp Native Session Ref has no resumable Session file");
18720
19383
  }
18721
19384
  return ref.locator.sessionFile;
@@ -18725,7 +19388,7 @@ function subagentTranscriptPath(parentSessionFile, nativeSubagentId) {
18725
19388
  if (nativeSubagentId.includes("/") || nativeSubagentId.includes("\\") || nativeSubagentId.includes("\0") || nativeSubagentId === "." || nativeSubagentId === "..") {
18726
19389
  throw new Error("Omp Subagent ID is not a plain transcript file name");
18727
19390
  }
18728
- if (!parentSessionFile.endsWith(".jsonl") || !path4.isAbsolute(parentSessionFile)) {
19391
+ if (!parentSessionFile.endsWith(".jsonl") || !path6.isAbsolute(parentSessionFile)) {
18729
19392
  return null;
18730
19393
  }
18731
19394
  return `${parentSessionFile.slice(0, -".jsonl".length)}/${nativeSubagentId}.jsonl`;
@@ -18734,10 +19397,10 @@ async function readSubagentTranscriptFile(parentSessionFile, nativeSubagentId) {
18734
19397
  const transcriptFile = subagentTranscriptPath(parentSessionFile, nativeSubagentId);
18735
19398
  if (transcriptFile === null)
18736
19399
  return { status: "missing" };
18737
- const parentDirectory = path4.dirname(transcriptFile);
19400
+ const parentDirectory = path6.dirname(transcriptFile);
18738
19401
  let metadata;
18739
19402
  try {
18740
- metadata = await stat(transcriptFile);
19403
+ metadata = await stat2(transcriptFile);
18741
19404
  } catch (error51) {
18742
19405
  if (error51.code === "ENOENT")
18743
19406
  return { status: "missing" };
@@ -18749,10 +19412,10 @@ async function readSubagentTranscriptFile(parentSessionFile, nativeSubagentId) {
18749
19412
  throw new Error("Omp Subagent transcript exceeds the supported size");
18750
19413
  }
18751
19414
  const [resolvedTranscript, resolvedParentDirectory] = await Promise.all([
18752
- realpath2(transcriptFile),
18753
- realpath2(parentDirectory)
19415
+ realpath3(transcriptFile),
19416
+ realpath3(parentDirectory)
18754
19417
  ]);
18755
- if (path4.dirname(resolvedTranscript) !== resolvedParentDirectory) {
19418
+ if (path6.dirname(resolvedTranscript) !== resolvedParentDirectory) {
18756
19419
  throw new Error("Omp Subagent transcript resolves outside its parent Session directory");
18757
19420
  }
18758
19421
  return {
@@ -18770,9 +19433,9 @@ function toolFailure(toolName) {
18770
19433
  function nativeText(value) {
18771
19434
  if (typeof value === "string")
18772
19435
  return value;
18773
- if (!isRecord8(value) || !Array.isArray(value.content))
19436
+ if (!isRecord9(value) || !Array.isArray(value.content))
18774
19437
  return "";
18775
- return value.content.filter((content) => isRecord8(content) && content.type === "text" && typeof content.text === "string").map(({ text }) => text).join("");
19438
+ return value.content.filter((content) => isRecord9(content) && content.type === "text" && typeof content.text === "string").map(({ text }) => text).join("");
18776
19439
  }
18777
19440
  function boundedOutput(value, limit) {
18778
19441
  const text = nativeText(value);
@@ -18788,17 +19451,17 @@ function outputText(output) {
18788
19451
  return output?.content.filter((content) => content.type === "text").map(({ text }) => text).join("") ?? "";
18789
19452
  }
18790
19453
  function stringField2(value, key) {
18791
- if (!isRecord8(value))
19454
+ if (!isRecord9(value))
18792
19455
  return void 0;
18793
19456
  const field = value[key];
18794
19457
  if (typeof field === "string" && field.length > 0)
18795
19458
  return field;
18796
- if (isRecord8(value.input)) {
19459
+ if (isRecord9(value.input)) {
18797
19460
  const nested = value.input[key];
18798
19461
  if (typeof nested === "string" && nested.length > 0)
18799
19462
  return nested;
18800
19463
  }
18801
- if (isRecord8(value.arguments)) {
19464
+ if (isRecord9(value.arguments)) {
18802
19465
  const nested = value.arguments[key];
18803
19466
  if (typeof nested === "string" && nested.length > 0)
18804
19467
  return nested;
@@ -18806,7 +19469,7 @@ function stringField2(value, key) {
18806
19469
  return void 0;
18807
19470
  }
18808
19471
  function numberField(value, key) {
18809
- if (!isRecord8(value))
19472
+ if (!isRecord9(value))
18810
19473
  return void 0;
18811
19474
  const field = value[key];
18812
19475
  return typeof field === "number" || field === null ? field : void 0;
@@ -18817,10 +19480,10 @@ function stripDiffPrefix(pathString) {
18817
19480
  return pathString.startsWith("a/") || pathString.startsWith("b/") ? pathString.slice(2) : pathString;
18818
19481
  }
18819
19482
  function displayPath(nativePath, cwd) {
18820
- const resolvedCwd = path4.resolve(cwd);
18821
- const resolvedPath = path4.isAbsolute(nativePath) ? path4.resolve(nativePath) : path4.resolve(cwd, nativePath);
18822
- const relative = path4.relative(resolvedCwd, resolvedPath);
18823
- const inside = relative.length > 0 && relative !== ".." && !relative.startsWith(`..${path4.sep}`);
19483
+ const resolvedCwd = path6.resolve(cwd);
19484
+ const resolvedPath = path6.isAbsolute(nativePath) ? path6.resolve(nativePath) : path6.resolve(cwd, nativePath);
19485
+ const relative = path6.relative(resolvedCwd, resolvedPath);
19486
+ const inside = relative.length > 0 && relative !== ".." && !relative.startsWith(`..${path6.sep}`);
18824
19487
  const selected = inside ? relative : resolvedPath;
18825
19488
  const normalized = selected.replaceAll("\\", "/");
18826
19489
  if (normalized.length === 0 || normalized === ".")
@@ -18845,7 +19508,7 @@ function fileMutatingKind(toolName) {
18845
19508
  return null;
18846
19509
  }
18847
19510
  function nestedToolString(value, keys) {
18848
- if (!isRecord8(value))
19511
+ if (!isRecord9(value))
18849
19512
  return void 0;
18850
19513
  for (const key of keys) {
18851
19514
  const field = value[key];
@@ -18860,14 +19523,14 @@ function nestedToolString(value, keys) {
18860
19523
  return void 0;
18861
19524
  }
18862
19525
  function patchFromResult(result) {
18863
- if (!isRecord8(result))
19526
+ if (!isRecord9(result))
18864
19527
  return void 0;
18865
19528
  for (const key of ["patch", "diff", "unifiedDiff"]) {
18866
19529
  const field = result[key];
18867
19530
  if (typeof field === "string" && field.length > 0)
18868
19531
  return field;
18869
19532
  }
18870
- if (isRecord8(result.details)) {
19533
+ if (isRecord9(result.details)) {
18871
19534
  for (const key of ["patch", "diff", "unifiedDiff"]) {
18872
19535
  const field = result.details[key];
18873
19536
  if (typeof field === "string" && field.length > 0)
@@ -20349,6 +21012,7 @@ var OmpAdapter = class {
20349
21012
  commandCatalog = ompCommandCatalog;
20350
21013
  liveCommandCatalog = true;
20351
21014
  harnessId = ompHarnessId2;
21015
+ sessionImport;
20352
21016
  subagents = {
20353
21017
  readSnapshot: async (input) => {
20354
21018
  if (input.parent.harnessId !== this.harnessId || input.nativeSubagentId.trim().length === 0 || input.cwd.length === 0) {
@@ -20408,6 +21072,7 @@ var OmpAdapter = class {
20408
21072
  createTransport: (sessionOptions) => new OmpRpcSession({ ...options, ...sessionOptions })
20409
21073
  }) {
20410
21074
  this.#createTransport = dependencies.createTransport;
21075
+ this.sessionImport = new OmpSessionImport({ ...process.env, ...options.environment });
20411
21076
  this.#closeTimeoutMs = options.closeTimeoutMs ?? 2e3;
20412
21077
  this.#toolOutputLimit = options.toolOutputLimit ?? DEFAULT_TOOL_OUTPUT_LIMIT;
20413
21078
  }
@@ -20479,7 +21144,11 @@ var OmpAdapter = class {
20479
21144
  };
20480
21145
  } catch (error51) {
20481
21146
  await transport.close().catch(() => void 0);
20482
- const normalized = normalizedError(error51, "unavailable");
21147
+ const normalized = stage === "startup" && /No models available\.\s*Use \/login or set an API key environment variable\./i.test(transport.stderrTail ?? "") ? {
21148
+ code: "configurationRequired",
21149
+ message: "No models are configured for use in Oh My Pi. Configure a Provider and its API key or models.yml, then run `omp` and use `/model` to select a model. For Providers that support it, `/login` configures Provider authentication, not an Oh My Pi account.",
21150
+ retryable: false
21151
+ } : normalizedError(error51, "unavailable");
20483
21152
  return {
20484
21153
  status: normalized.code === "notInstalled" ? "notInstalled" : "error",
20485
21154
  error: {
@@ -20669,6 +21338,7 @@ var OmpAdapter = class {
20669
21338
  close() {
20670
21339
  if (!this.#closePromise) {
20671
21340
  this.#closePromise = Promise.all([
21341
+ this.sessionImport.close(),
20672
21342
  ...[...this.#inspections].map((transport) => transport.close()),
20673
21343
  ...[...this.#sessions].map((session) => session.close())
20674
21344
  ]).then(() => void 0);
@@ -20677,13 +21347,60 @@ var OmpAdapter = class {
20677
21347
  }
20678
21348
  };
20679
21349
 
21350
+ // dist/installation.js
21351
+ import { realpath as realpath4 } from "node:fs/promises";
21352
+ import path7 from "node:path";
21353
+ function createOmpInstallation(environment, command) {
21354
+ let executable;
21355
+ let env;
21356
+ return createInstallationManager({
21357
+ async check() {
21358
+ executable = resolveOmpExecutable({ environment, ...command ? { command } : {} });
21359
+ const selected = await realpath4(executable);
21360
+ const pathKey = Object.keys(environment).find((key) => key.toLowerCase() === "path") ?? "PATH";
21361
+ env = {
21362
+ ...environment,
21363
+ [pathKey]: `${path7.dirname(executable)}${path7.delimiter}${environment[pathKey] ?? ""}`
21364
+ };
21365
+ const target = resolveHarnessExecutable({ id: "omp", command: "omp", installRoots: { posix: [], windows: [] } }, { environment: env });
21366
+ const canUpdate = !selected.includes("/nix/store/") && !!target && await realpath4(target.executable) === selected;
21367
+ const output = await runInstallationCommand(executable, ["update", "--check"], env);
21368
+ const currentVersion = versionFromOutput(output);
21369
+ const available = output.match(/New version available:\s*(\S+)/i);
21370
+ if (!available && !/already up to date/i.test(output))
21371
+ throw new Error("OMP update check returned an unknown response");
21372
+ const latestVersion = available ? installationVersion(available[1]) : currentVersion;
21373
+ return {
21374
+ currentVersion,
21375
+ latestVersion,
21376
+ updateAvailable: newerInstallationVersion(currentVersion, latestVersion),
21377
+ canUpdate,
21378
+ ...!canUpdate ? {
21379
+ messageCode: "original-installer",
21380
+ message: "Update this installation with its original package manager or launcher."
21381
+ } : {}
21382
+ };
21383
+ },
21384
+ async update() {
21385
+ await runInstallationCommand(executable, ["update"], env, 3e5);
21386
+ }
21387
+ });
21388
+ }
21389
+
20680
21390
  // dist/plugin.js
20681
21391
  var OMP_COMMAND_ENV = "CODEXHOST_OMP_COMMAND";
20682
21392
  function createHarnessAdapter(context) {
20683
21393
  const environment = { ...context.environment };
20684
- return new OmpAdapter({
21394
+ return Object.assign(new OmpAdapter({
20685
21395
  ...environment[OMP_COMMAND_ENV] ? { command: environment[OMP_COMMAND_ENV] } : {},
20686
21396
  environment
21397
+ }), {
21398
+ installation: createOmpInstallation(environment, environment[OMP_COMMAND_ENV]),
21399
+ install: createHarnessInstaller(environment, {
21400
+ posix: "https://omp.sh/install",
21401
+ windows: "https://omp.sh/install.ps1",
21402
+ shell: "sh"
21403
+ })
20687
21404
  });
20688
21405
  }
20689
21406
  export {