@codexhost/cli-darwin-x64 0.11.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/app/codexhost-distribution.json +1 -1
- package/app/console-server.mjs +16496 -16342
- package/app/console-web.js +4290 -2314
- package/app/desktop-controller.mjs +16266 -360
- package/app/host-runtime.mjs +4707 -986
- package/app/plugins/antigravity/plugin.mjs +1201 -1044
- package/app/plugins/claude-code/plugin.mjs +517 -139
- package/app/plugins/codebuddy/plugin.mjs +1521 -868
- package/app/plugins/cursor-cli/plugin.mjs +824 -436
- package/app/plugins/deepseek-harness/plugin.mjs +25516 -26242
- package/app/plugins/enabled.json +2 -1
- package/app/plugins/grok/plugin.mjs +995 -515
- package/app/plugins/hermes/plugin.mjs +18815 -23119
- package/app/plugins/kimi-code/plugin.mjs +1105 -713
- package/app/plugins/kiro-cli/plugin.mjs +1018 -600
- package/app/plugins/omp/plugin.mjs +1097 -586
- package/app/plugins/opencode/plugin.mjs +1020 -710
- package/app/plugins/pi/plugin.mjs +15952 -15716
- package/app/plugins/qoder/plugin.mjs +738 -385
- package/app/plugins/qoder-cn/plugin.mjs +404 -49
- package/app/plugins/workbuddy/plugin.mjs +715 -108
- package/app/plugins/zcode/assets/icon.svg +8 -0
- package/app/plugins/zcode/manifest.json +14 -0
- package/app/plugins/zcode/plugin.mjs +19251 -0
- package/app/renderer-extension.js +2854 -630
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- 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(
|
|
109
|
-
const last =
|
|
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:
|
|
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:
|
|
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
|
|
531
|
-
import
|
|
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,
|
|
1300
|
-
if (!
|
|
1702
|
+
function getElementAtPath(obj, path8) {
|
|
1703
|
+
if (!path8)
|
|
1301
1704
|
return obj;
|
|
1302
|
-
return
|
|
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(
|
|
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(
|
|
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,
|
|
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 }, [...
|
|
2268
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
1866
2269
|
} else if (issue2.code === "invalid_key") {
|
|
1867
|
-
processError({ issues: issue2.issues }, [...
|
|
2270
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
1868
2271
|
} else if (issue2.code === "invalid_element") {
|
|
1869
|
-
processError({ issues: issue2.issues }, [...
|
|
2272
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
1870
2273
|
} else {
|
|
1871
|
-
const fullpath = [...
|
|
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,
|
|
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 }, [...
|
|
2305
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
1903
2306
|
} else if (issue2.code === "invalid_key") {
|
|
1904
|
-
processError({ issues: issue2.issues }, [...
|
|
2307
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
1905
2308
|
} else if (issue2.code === "invalid_element") {
|
|
1906
|
-
processError({ issues: issue2.issues }, [...
|
|
2309
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
1907
2310
|
} else {
|
|
1908
|
-
const fullpath = [...
|
|
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
|
|
1941
|
-
for (const seg of
|
|
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
|
|
14634
|
-
if (
|
|
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 (
|
|
14639
|
-
const key =
|
|
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
|
}
|
|
@@ -15114,6 +15517,20 @@ var harnessDisplaySetSchema = external_exports.strictObject({
|
|
|
15114
15517
|
initializeOnly: external_exports.boolean().optional()
|
|
15115
15518
|
});
|
|
15116
15519
|
|
|
15520
|
+
// ../../shared-contracts/dist/ids.js
|
|
15521
|
+
var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
|
|
15522
|
+
message: "Identifier must not be empty or whitespace"
|
|
15523
|
+
});
|
|
15524
|
+
var harnessIdSchema = opaqueIdSchema.brand();
|
|
15525
|
+
var hostThreadIdSchema = opaqueIdSchema.brand();
|
|
15526
|
+
var hostTurnIdSchema = opaqueIdSchema.brand();
|
|
15527
|
+
var hostItemIdSchema = opaqueIdSchema.brand();
|
|
15528
|
+
var hostInteractionIdSchema = opaqueIdSchema.brand();
|
|
15529
|
+
|
|
15530
|
+
// ../../shared-contracts/dist/thread-prewarm.js
|
|
15531
|
+
var threadPrewarmDiscardParamsSchema = external_exports.object({ threadId: hostThreadIdSchema });
|
|
15532
|
+
var threadPrewarmDiscardResultSchema = external_exports.object({ discarded: external_exports.boolean() });
|
|
15533
|
+
|
|
15117
15534
|
// ../../shared-contracts/dist/console.js
|
|
15118
15535
|
var consoleAnnouncementSchema = external_exports.strictObject({
|
|
15119
15536
|
title: external_exports.string().trim().min(1).max(200),
|
|
@@ -15126,10 +15543,14 @@ var consoleOpenResultSchema = external_exports.strictObject({
|
|
|
15126
15543
|
url: external_exports.string().max(2048).regex(/^http:\/\/(?:127\.0\.0\.1|localhost):\d{1,5}\/(?:\?.*)?$/u)
|
|
15127
15544
|
});
|
|
15128
15545
|
var CONSOLE_HOST_METHODS = Object.freeze([
|
|
15546
|
+
"codexhost/console/remote-connections",
|
|
15547
|
+
"codexhost/runtime/status",
|
|
15548
|
+
"codexhost/remote/ssh-setup",
|
|
15129
15549
|
"codexhost/harness/plugins/list",
|
|
15130
15550
|
"codexhost/harness/display-settings/get",
|
|
15131
15551
|
"codexhost/harness/display-settings/set",
|
|
15132
15552
|
"codexhost/harness/inspect",
|
|
15553
|
+
"codexhost/harness/installation",
|
|
15133
15554
|
"codexhost/harness/launch-settings/get",
|
|
15134
15555
|
"codexhost/harness/launch-settings/set",
|
|
15135
15556
|
"codexhost/harness/web-ui/open",
|
|
@@ -15191,16 +15612,6 @@ var loadedSessionsSchema = external_exports.array(external_exports.strictObject(
|
|
|
15191
15612
|
inactiveMs: external_exports.number().nonnegative()
|
|
15192
15613
|
}));
|
|
15193
15614
|
|
|
15194
|
-
// ../../shared-contracts/dist/ids.js
|
|
15195
|
-
var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
|
|
15196
|
-
message: "Identifier must not be empty or whitespace"
|
|
15197
|
-
});
|
|
15198
|
-
var harnessIdSchema = opaqueIdSchema.brand();
|
|
15199
|
-
var hostThreadIdSchema = opaqueIdSchema.brand();
|
|
15200
|
-
var hostTurnIdSchema = opaqueIdSchema.brand();
|
|
15201
|
-
var hostItemIdSchema = opaqueIdSchema.brand();
|
|
15202
|
-
var hostInteractionIdSchema = opaqueIdSchema.brand();
|
|
15203
|
-
|
|
15204
15615
|
// ../../shared-contracts/dist/manual-compaction.js
|
|
15205
15616
|
var threadManualCompactionStartedSchema = external_exports.strictObject({
|
|
15206
15617
|
threadId: hostThreadIdSchema,
|
|
@@ -15776,14 +16187,17 @@ var harnessLaunchSettingsSchema = external_exports.object({
|
|
|
15776
16187
|
// ../../shared-contracts/dist/harness-installation.js
|
|
15777
16188
|
var harnessInstallationParamsSchema = external_exports.object({
|
|
15778
16189
|
harnessId: harnessIdSchema,
|
|
15779
|
-
action: external_exports.enum(["check", "update"])
|
|
16190
|
+
action: external_exports.enum(["check", "update", "install"])
|
|
15780
16191
|
}).strict();
|
|
15781
16192
|
var harnessInstallationStateSchema = external_exports.object({
|
|
15782
16193
|
currentVersion: external_exports.string().min(1).max(128),
|
|
15783
16194
|
latestVersion: external_exports.string().min(1).max(128),
|
|
15784
16195
|
updateAvailable: external_exports.boolean(),
|
|
15785
16196
|
canUpdate: external_exports.boolean(),
|
|
15786
|
-
|
|
16197
|
+
// Adapter-owned diagnostic text; UI uses messageCode rather than displaying it verbatim.
|
|
16198
|
+
message: external_exports.string().max(2048).optional(),
|
|
16199
|
+
messageCode: external_exports.string().min(1).max(128).optional(),
|
|
16200
|
+
latestVersionKind: external_exports.enum(["unknown", "tracking-branch"]).optional()
|
|
15787
16201
|
}).strict();
|
|
15788
16202
|
|
|
15789
16203
|
// ../../shared-contracts/dist/codex-accounts.js
|
|
@@ -16085,6 +16499,80 @@ var updateStatusResultSchema = external_exports.strictObject({
|
|
|
16085
16499
|
status: updateStatusSchema.nullable()
|
|
16086
16500
|
});
|
|
16087
16501
|
|
|
16502
|
+
// ../../shared-contracts/dist/remote-runtime.js
|
|
16503
|
+
var remoteUpdatePhaseSchema = external_exports.enum([
|
|
16504
|
+
"idle",
|
|
16505
|
+
"installing",
|
|
16506
|
+
"restarting",
|
|
16507
|
+
"succeeded",
|
|
16508
|
+
"failed"
|
|
16509
|
+
]);
|
|
16510
|
+
var runtimeStatusSchema = external_exports.object({
|
|
16511
|
+
runningVersion: external_exports.string().nullable(),
|
|
16512
|
+
installedVersion: external_exports.string().nullable(),
|
|
16513
|
+
restartRequired: external_exports.boolean(),
|
|
16514
|
+
remote: external_exports.boolean(),
|
|
16515
|
+
updateSupported: external_exports.boolean(),
|
|
16516
|
+
update: external_exports.object({
|
|
16517
|
+
phase: remoteUpdatePhaseSchema,
|
|
16518
|
+
targetVersion: external_exports.string().nullable(),
|
|
16519
|
+
error: external_exports.string().nullable()
|
|
16520
|
+
})
|
|
16521
|
+
});
|
|
16522
|
+
var remoteUpdateParamsSchema = external_exports.object({
|
|
16523
|
+
version: external_exports.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
|
|
16524
|
+
}).strict();
|
|
16525
|
+
var remoteSshSetupParamsSchema = external_exports.object({
|
|
16526
|
+
hostname: external_exports.string().min(1).max(1024).refine((value) => !value.startsWith("-") && !/\s/u.test(value)),
|
|
16527
|
+
port: external_exports.number().int().min(1).max(65535).nullable(),
|
|
16528
|
+
identity: external_exports.string().max(4096).nullable(),
|
|
16529
|
+
action: external_exports.enum(["inspect", "install", "update", "repair", "uninstall"]),
|
|
16530
|
+
uninstallPackage: external_exports.boolean().optional(),
|
|
16531
|
+
version: external_exports.string().regex(/^\d+\.\d+\.\d+$/u).nullable()
|
|
16532
|
+
}).strict();
|
|
16533
|
+
var remoteSshSetupResultSchema = external_exports.object({ state: external_exports.enum(["installed", "not-installed"]) }).strict();
|
|
16534
|
+
|
|
16535
|
+
// ../../shared-contracts/dist/remote-connections.js
|
|
16536
|
+
var hostId = external_exports.string().min(1).max(1024);
|
|
16537
|
+
var codexSshConnectionSchema = external_exports.object({
|
|
16538
|
+
hostId,
|
|
16539
|
+
displayName: external_exports.string().min(1).max(1024),
|
|
16540
|
+
source: external_exports.enum(["codex-managed", "discovered"]),
|
|
16541
|
+
sshAlias: external_exports.string().max(1024).nullable(),
|
|
16542
|
+
sshHost: external_exports.string().min(1).max(1024),
|
|
16543
|
+
sshPort: external_exports.number().int().min(1).max(65535).nullable(),
|
|
16544
|
+
identity: external_exports.string().max(4096).nullable(),
|
|
16545
|
+
autoConnect: external_exports.boolean(),
|
|
16546
|
+
connectionAnalyticsId: external_exports.string().max(1024).optional()
|
|
16547
|
+
});
|
|
16548
|
+
var codexSshDraftSchema = external_exports.strictObject({
|
|
16549
|
+
displayName: external_exports.string().min(1).max(1024),
|
|
16550
|
+
hostname: external_exports.string().min(1).max(1024),
|
|
16551
|
+
sshPort: external_exports.number().int().min(1).max(65535).nullable(),
|
|
16552
|
+
identity: external_exports.string().max(4096).nullable()
|
|
16553
|
+
});
|
|
16554
|
+
var remoteConnectionsRequestSchema = external_exports.discriminatedUnion("action", [
|
|
16555
|
+
external_exports.strictObject({ action: external_exports.literal("list") }),
|
|
16556
|
+
external_exports.strictObject({
|
|
16557
|
+
action: external_exports.literal("save"),
|
|
16558
|
+
draft: codexSshDraftSchema,
|
|
16559
|
+
previous: codexSshConnectionSchema.nullable()
|
|
16560
|
+
}),
|
|
16561
|
+
external_exports.strictObject({ action: external_exports.literal("remove"), previous: codexSshConnectionSchema }),
|
|
16562
|
+
external_exports.strictObject({ action: external_exports.literal("connect"), hostId, enabled: external_exports.boolean() }),
|
|
16563
|
+
external_exports.strictObject({ action: external_exports.literal("state"), hostId }),
|
|
16564
|
+
external_exports.strictObject({ action: external_exports.literal("runtime"), hostId }),
|
|
16565
|
+
external_exports.strictObject({
|
|
16566
|
+
action: external_exports.literal("update"),
|
|
16567
|
+
hostId: hostId.refine((id) => id !== "local"),
|
|
16568
|
+
version: remoteUpdateParamsSchema.shape.version
|
|
16569
|
+
})
|
|
16570
|
+
]);
|
|
16571
|
+
var remoteConnectionsReplySchema = external_exports.union([
|
|
16572
|
+
external_exports.strictObject({ result: jsonValueSchema }),
|
|
16573
|
+
external_exports.strictObject({ error: external_exports.strictObject({ code: external_exports.number().int(), message: external_exports.string() }) })
|
|
16574
|
+
]);
|
|
16575
|
+
|
|
16088
16576
|
// ../../shared-contracts/dist/index.js
|
|
16089
16577
|
var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
|
|
16090
16578
|
|
|
@@ -16792,512 +17280,502 @@ function mapOmpSnapshot(history, state) {
|
|
|
16792
17280
|
const changed = modelChange(entry);
|
|
16793
17281
|
if (changed)
|
|
16794
17282
|
effectiveModel = changed;
|
|
16795
|
-
}
|
|
16796
|
-
index = end;
|
|
16797
|
-
}
|
|
16798
|
-
return { turns };
|
|
16799
|
-
}
|
|
16800
|
-
function resolveOmpLastTurnBoundary(history) {
|
|
16801
|
-
const users = activeOmpEntries(history).filter((entry) => messageRole(entry) === "user");
|
|
16802
|
-
const last = users.at(-1);
|
|
16803
|
-
return last ? { lastUserEntryId: last.id, sourceTurnCount: users.length } : null;
|
|
16804
|
-
}
|
|
16805
|
-
function resolveOmpForkBoundary(history, checkpointId) {
|
|
16806
|
-
const active = activeOmpEntries(history);
|
|
16807
|
-
const users = active.filter((entry) => messageRole(entry) === "user");
|
|
16808
|
-
const targetTurnIndex = users.findIndex((entry) => entry.id === checkpointId);
|
|
16809
|
-
if (targetTurnIndex < 0)
|
|
16810
|
-
throw new Error("Omp Checkpoint is not on the active branch");
|
|
16811
|
-
return {
|
|
16812
|
-
targetTurnIndex,
|
|
16813
|
-
nextUserEntryId: users[targetTurnIndex + 1]?.id ?? null
|
|
16814
|
-
};
|
|
16815
|
-
}
|
|
16816
|
-
|
|
16817
|
-
// dist/omp-session-file.js
|
|
16818
|
-
import { createReadStream } from "node:fs";
|
|
16819
|
-
import { open, realpath } from "node:fs/promises";
|
|
16820
|
-
import readline from "node:readline";
|
|
16821
|
-
var MAX_SESSION_HEADER_BYTES = 64 * 1024;
|
|
16822
|
-
var utf8Decoder = new TextDecoder("utf-8", { fatal: true });
|
|
16823
|
-
function isRecord5(value) {
|
|
16824
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16825
|
-
}
|
|
16826
|
-
function historyEntry(value) {
|
|
16827
|
-
if (!isRecord5(value) || value.type === "title" || value.type === "session" || typeof value.id !== "string" || value.id.length === 0 || value.parentId !== null && typeof value.parentId !== "string" || typeof value.type !== "string") {
|
|
16828
|
-
return null;
|
|
16829
|
-
}
|
|
16830
|
-
return value;
|
|
16831
|
-
}
|
|
16832
|
-
async function readOmpSessionHistory(sessionFile, maxBytes) {
|
|
16833
|
-
const entries = [];
|
|
16834
|
-
let leafId = null;
|
|
16835
|
-
const lines = readline.createInterface({
|
|
16836
|
-
input: createReadStream(sessionFile, {
|
|
16837
|
-
encoding: "utf8",
|
|
16838
|
-
...maxBytes === void 0 ? {} : { end: maxBytes - 1 }
|
|
16839
|
-
}),
|
|
16840
|
-
crlfDelay: Number.POSITIVE_INFINITY
|
|
16841
|
-
});
|
|
16842
|
-
try {
|
|
16843
|
-
for await (const line of lines) {
|
|
16844
|
-
if (line.length === 0)
|
|
16845
|
-
continue;
|
|
16846
|
-
let parsed;
|
|
16847
|
-
try {
|
|
16848
|
-
parsed = JSON.parse(line);
|
|
16849
|
-
} catch {
|
|
16850
|
-
continue;
|
|
16851
|
-
}
|
|
16852
|
-
const entry = historyEntry(parsed);
|
|
16853
|
-
if (!entry)
|
|
16854
|
-
continue;
|
|
16855
|
-
entries.push(entry);
|
|
16856
|
-
leafId = entry.id;
|
|
16857
|
-
}
|
|
16858
|
-
} finally {
|
|
16859
|
-
lines.close();
|
|
16860
|
-
}
|
|
16861
|
-
return { entries, leafId };
|
|
16862
|
-
}
|
|
16863
|
-
async function readOmpSessionHeader(sessionFile) {
|
|
16864
|
-
const handle = await open(sessionFile, "r");
|
|
16865
|
-
try {
|
|
16866
|
-
const buffer = Buffer.allocUnsafe(MAX_SESSION_HEADER_BYTES);
|
|
16867
|
-
const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
|
|
16868
|
-
const contents = buffer.subarray(0, bytesRead);
|
|
16869
|
-
const newline = contents.indexOf(10);
|
|
16870
|
-
if (newline < 0 && bytesRead === buffer.length) {
|
|
16871
|
-
throw new Error("Omp Session header exceeds the supported size");
|
|
16872
|
-
}
|
|
16873
|
-
const contentsText = utf8Decoder.decode(contents);
|
|
16874
|
-
for (const line of contentsText.split("\n")) {
|
|
16875
|
-
if (line.length === 0)
|
|
16876
|
-
continue;
|
|
16877
|
-
let parsed;
|
|
16878
|
-
try {
|
|
16879
|
-
parsed = JSON.parse(line);
|
|
16880
|
-
} catch {
|
|
16881
|
-
continue;
|
|
16882
|
-
}
|
|
16883
|
-
if (!isRecord5(parsed) || parsed.type !== "session")
|
|
16884
|
-
continue;
|
|
16885
|
-
if (typeof parsed.id !== "string" || parsed.id.length === 0 || typeof parsed.cwd !== "string" || parsed.cwd.length === 0) {
|
|
16886
|
-
throw new Error("Omp Session header is invalid");
|
|
16887
|
-
}
|
|
16888
|
-
return { type: "session", id: parsed.id, cwd: parsed.cwd };
|
|
16889
|
-
}
|
|
16890
|
-
throw new Error("Omp Session header is invalid");
|
|
16891
|
-
} finally {
|
|
16892
|
-
await handle.close();
|
|
16893
|
-
}
|
|
16894
|
-
}
|
|
16895
|
-
async function verifyOmpSessionCwd(input) {
|
|
16896
|
-
if (!input.sessionFile)
|
|
16897
|
-
throw new Error("Omp Fork Session has no persisted Session file");
|
|
16898
|
-
const header = await readOmpSessionHeader(input.sessionFile);
|
|
16899
|
-
if (header.id !== input.sessionId) {
|
|
16900
|
-
throw new Error("Omp Fork Session header identity does not match RPC state");
|
|
16901
|
-
}
|
|
16902
|
-
const [actualCwd, expectedCwd] = await Promise.all([
|
|
16903
|
-
realpath(header.cwd),
|
|
16904
|
-
realpath(input.expectedCwd)
|
|
16905
|
-
]);
|
|
16906
|
-
if (actualCwd !== expectedCwd) {
|
|
16907
|
-
throw new Error("Omp Fork Session did not bind the requested cwd");
|
|
16908
|
-
}
|
|
16909
|
-
}
|
|
16910
|
-
|
|
16911
|
-
// dist/omp-last-turn-rollback.js
|
|
16912
|
-
function modelFromState(state) {
|
|
16913
|
-
if (state.provider === null && state.modelId === null)
|
|
16914
|
-
return null;
|
|
16915
|
-
if (state.provider === null || state.modelId === null) {
|
|
16916
|
-
throw new Error("Omp state contains a partial Model identity");
|
|
16917
|
-
}
|
|
16918
|
-
return { provider: state.provider, id: state.modelId };
|
|
16919
|
-
}
|
|
16920
|
-
async function rollbackOmpLastTurn(transport, sourceSessionId, cwd) {
|
|
16921
|
-
const startupState = transport.state;
|
|
16922
|
-
const startupSessionId = startupState.sessionId;
|
|
16923
|
-
const currentModel = modelFromState(startupState);
|
|
16924
|
-
const currentThinking = startupState.thinkingLevel;
|
|
16925
|
-
const copiedHistory = await transport.getEntries();
|
|
16926
|
-
const boundary = resolveOmpLastTurnBoundary(copiedHistory);
|
|
16927
|
-
if (!boundary)
|
|
16928
|
-
return { ok: false, reason: "empty" };
|
|
16929
|
-
const sourceSnapshot = mapOmpSnapshot(copiedHistory, {
|
|
16930
|
-
sessionId: startupSessionId,
|
|
16931
|
-
model: currentModel
|
|
16932
|
-
});
|
|
16933
|
-
let state = await transport.fork(boundary.lastUserEntryId);
|
|
16934
|
-
if (state.sessionId === sourceSessionId || state.sessionId === startupSessionId) {
|
|
16935
|
-
throw new Error("Omp last-Turn rollback did not create a distinct Native Session");
|
|
16936
|
-
}
|
|
16937
|
-
if (!sameOmpModel(modelFromState(state), currentModel)) {
|
|
16938
|
-
if (!currentModel)
|
|
16939
|
-
throw new Error("Omp last-Turn rollback changed the current Model");
|
|
16940
|
-
state = await transport.selectModel(currentModel);
|
|
16941
|
-
}
|
|
16942
|
-
if (state.thinkingLevel !== currentThinking) {
|
|
16943
|
-
if (!currentThinking)
|
|
16944
|
-
throw new Error("Omp last-Turn rollback changed current Thinking");
|
|
16945
|
-
state = await transport.selectThinkingOption(currentThinking);
|
|
16946
|
-
}
|
|
16947
|
-
if (!sameOmpModel(modelFromState(state), currentModel) || state.thinkingLevel !== currentThinking) {
|
|
16948
|
-
throw new Error("Omp last-Turn rollback could not restore current Model and Thinking");
|
|
16949
|
-
}
|
|
16950
|
-
const snapshot = mapOmpSnapshot(await transport.getEntries(), {
|
|
16951
|
-
sessionId: state.sessionId,
|
|
16952
|
-
model: modelFromState(state)
|
|
16953
|
-
});
|
|
16954
|
-
const expectedTurnKeys = sourceSnapshot.turns.slice(0, -1).map((turn) => turn.nativeTurnRef.nativeTurnKey);
|
|
16955
|
-
const actualTurnKeys = snapshot.turns.map((turn) => turn.nativeTurnRef.nativeTurnKey);
|
|
16956
|
-
if (snapshot.turns.length !== boundary.sourceTurnCount - 1 || actualTurnKeys.some((key, index) => key !== expectedTurnKeys[index])) {
|
|
16957
|
-
throw new Error("Omp last-Turn rollback did not produce the exact retained history prefix");
|
|
16958
|
-
}
|
|
16959
|
-
await transport.verifySessionCwd(cwd);
|
|
16960
|
-
return { ok: true };
|
|
16961
|
-
}
|
|
16962
|
-
|
|
16963
|
-
// dist/omp-rpc-session.js
|
|
16964
|
-
import { spawn, spawnSync } from "node:child_process";
|
|
16965
|
-
import { randomUUID } from "node:crypto";
|
|
16966
|
-
import path4 from "node:path";
|
|
16967
|
-
|
|
16968
|
-
// ../../harness-discovery/dist/environment.js
|
|
16969
|
-
import fs from "node:fs";
|
|
16970
|
-
import path from "node:path";
|
|
16971
|
-
function targetPath(platform) {
|
|
16972
|
-
return platform === "win32" ? path.win32 : path.posix;
|
|
16973
|
-
}
|
|
16974
|
-
function environmentValue(environment, name) {
|
|
16975
|
-
const lowered = name.toLowerCase();
|
|
16976
|
-
for (const [key, value] of Object.entries(environment)) {
|
|
16977
|
-
if (key.toLowerCase() === lowered)
|
|
16978
|
-
return value;
|
|
16979
|
-
}
|
|
16980
|
-
return void 0;
|
|
16981
|
-
}
|
|
16982
|
-
function pathDelimiter(platform) {
|
|
16983
|
-
return platform === "win32" ? ";" : ":";
|
|
16984
|
-
}
|
|
16985
|
-
function pathDirectories(environment, platform) {
|
|
16986
|
-
return (environmentValue(environment, "PATH") ?? "").split(pathDelimiter(platform)).map((directory) => directory.trim().replace(/^"|"$/gu, "")).filter(Boolean);
|
|
16987
|
-
}
|
|
16988
|
-
function executableExtensions(command, platform, environment) {
|
|
16989
|
-
if (platform !== "win32")
|
|
16990
|
-
return [""];
|
|
16991
|
-
if (targetPath(platform).extname(command) !== "")
|
|
16992
|
-
return [""];
|
|
16993
|
-
return (environmentValue(environment, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter(Boolean);
|
|
16994
|
-
}
|
|
16995
|
-
function isExecutableFile(filePath, platform) {
|
|
16996
|
-
try {
|
|
16997
|
-
fs.accessSync(filePath, platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK);
|
|
16998
|
-
return fs.statSync(filePath).isFile();
|
|
16999
|
-
} catch {
|
|
17000
|
-
return false;
|
|
17001
|
-
}
|
|
17002
|
-
}
|
|
17003
|
-
function subdirectoryNames(directory) {
|
|
17004
|
-
try {
|
|
17005
|
-
return fs.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
17006
|
-
} catch {
|
|
17007
|
-
return [];
|
|
17283
|
+
}
|
|
17284
|
+
index = end;
|
|
17008
17285
|
}
|
|
17286
|
+
return { turns };
|
|
17009
17287
|
}
|
|
17010
|
-
function
|
|
17011
|
-
|
|
17288
|
+
function resolveOmpLastTurnBoundary(history) {
|
|
17289
|
+
const users = activeOmpEntries(history).filter((entry) => messageRole(entry) === "user");
|
|
17290
|
+
const last = users.at(-1);
|
|
17291
|
+
return last ? { lastUserEntryId: last.id, sourceTurnCount: users.length } : null;
|
|
17012
17292
|
}
|
|
17013
|
-
|
|
17014
|
-
|
|
17015
|
-
|
|
17016
|
-
|
|
17017
|
-
|
|
17018
|
-
|
|
17019
|
-
return { command, arguments: [...arguments_], windowsVerbatimArguments: false };
|
|
17020
|
-
}
|
|
17021
|
-
const quote = (value) => `"${value.replaceAll("%", "%%").replaceAll('"', '""')}"`;
|
|
17022
|
-
const commandLine = [command, ...arguments_].map(quote).join(" ");
|
|
17293
|
+
function resolveOmpForkBoundary(history, checkpointId) {
|
|
17294
|
+
const active = activeOmpEntries(history);
|
|
17295
|
+
const users = active.filter((entry) => messageRole(entry) === "user");
|
|
17296
|
+
const targetTurnIndex = users.findIndex((entry) => entry.id === checkpointId);
|
|
17297
|
+
if (targetTurnIndex < 0)
|
|
17298
|
+
throw new Error("Omp Checkpoint is not on the active branch");
|
|
17023
17299
|
return {
|
|
17024
|
-
|
|
17025
|
-
|
|
17026
|
-
windowsVerbatimArguments: true
|
|
17300
|
+
targetTurnIndex,
|
|
17301
|
+
nextUserEntryId: users[targetTurnIndex + 1]?.id ?? null
|
|
17027
17302
|
};
|
|
17028
17303
|
}
|
|
17029
17304
|
|
|
17030
|
-
//
|
|
17031
|
-
import
|
|
17032
|
-
|
|
17033
|
-
|
|
17034
|
-
|
|
17035
|
-
|
|
17036
|
-
|
|
17037
|
-
|
|
17038
|
-
|
|
17039
|
-
|
|
17305
|
+
// dist/omp-session-file.js
|
|
17306
|
+
import { createReadStream } from "node:fs";
|
|
17307
|
+
import { open, realpath } from "node:fs/promises";
|
|
17308
|
+
import readline from "node:readline";
|
|
17309
|
+
var MAX_SESSION_HEADER_BYTES = 64 * 1024;
|
|
17310
|
+
var utf8Decoder = new TextDecoder("utf-8", { fatal: true });
|
|
17311
|
+
function isRecord5(value) {
|
|
17312
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17313
|
+
}
|
|
17314
|
+
function historyEntry(value) {
|
|
17315
|
+
if (!isRecord5(value) || value.type === "title" || value.type === "session" || typeof value.id !== "string" || value.id.length === 0 || value.parentId !== null && typeof value.parentId !== "string" || typeof value.type !== "string") {
|
|
17316
|
+
return null;
|
|
17040
17317
|
}
|
|
17041
|
-
return
|
|
17318
|
+
return value;
|
|
17042
17319
|
}
|
|
17043
|
-
|
|
17044
|
-
|
|
17045
|
-
|
|
17046
|
-
|
|
17047
|
-
|
|
17048
|
-
|
|
17049
|
-
|
|
17050
|
-
|
|
17051
|
-
|
|
17052
|
-
|
|
17053
|
-
|
|
17054
|
-
|
|
17055
|
-
|
|
17056
|
-
|
|
17320
|
+
async function readOmpSessionHistory(sessionFile, maxBytes) {
|
|
17321
|
+
const entries = [];
|
|
17322
|
+
let leafId = null;
|
|
17323
|
+
const lines = readline.createInterface({
|
|
17324
|
+
input: createReadStream(sessionFile, {
|
|
17325
|
+
encoding: "utf8",
|
|
17326
|
+
...maxBytes === void 0 ? {} : { end: maxBytes - 1 }
|
|
17327
|
+
}),
|
|
17328
|
+
crlfDelay: Number.POSITIVE_INFINITY
|
|
17329
|
+
});
|
|
17330
|
+
try {
|
|
17331
|
+
for await (const line of lines) {
|
|
17332
|
+
if (line.length === 0)
|
|
17333
|
+
continue;
|
|
17334
|
+
let parsed;
|
|
17335
|
+
try {
|
|
17336
|
+
parsed = JSON.parse(line);
|
|
17337
|
+
} catch {
|
|
17338
|
+
continue;
|
|
17339
|
+
}
|
|
17340
|
+
const entry = historyEntry(parsed);
|
|
17341
|
+
if (!entry)
|
|
17342
|
+
continue;
|
|
17343
|
+
entries.push(entry);
|
|
17344
|
+
leafId = entry.id;
|
|
17057
17345
|
}
|
|
17058
|
-
}
|
|
17059
|
-
|
|
17060
|
-
const appData = value("APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming");
|
|
17061
|
-
const localAppData = value("LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local");
|
|
17062
|
-
versioned(pathFlavor.join(appData, "nvm"));
|
|
17063
|
-
versioned(value("FNM_DIR") ?? pathFlavor.join(appData, "fnm", "node-versions"), "installation");
|
|
17064
|
-
directories.push(pathFlavor.join(localAppData, "Volta", "bin"));
|
|
17065
|
-
directories.push(pathFlavor.join(home, ".bun", "bin"));
|
|
17066
|
-
const pnpmHome2 = value("PNPM_HOME");
|
|
17067
|
-
if (pnpmHome2)
|
|
17068
|
-
directories.push(pnpmHome2);
|
|
17069
|
-
directories.push(pathFlavor.join(localAppData, "pnpm"));
|
|
17070
|
-
return directories;
|
|
17071
|
-
}
|
|
17072
|
-
versioned(pathFlavor.join(value("NVM_DIR") ?? pathFlavor.join(home, ".nvm"), "versions", "node"), "bin");
|
|
17073
|
-
const fnmRoots = [
|
|
17074
|
-
value("FNM_DIR"),
|
|
17075
|
-
pathFlavor.join(home, ".local", "share", "fnm"),
|
|
17076
|
-
pathFlavor.join(home, "Library", "Application Support", "fnm")
|
|
17077
|
-
].filter((root) => root !== void 0);
|
|
17078
|
-
for (const root of fnmRoots) {
|
|
17079
|
-
versioned(pathFlavor.join(root, "node-versions"), "installation", "bin");
|
|
17346
|
+
} finally {
|
|
17347
|
+
lines.close();
|
|
17080
17348
|
}
|
|
17081
|
-
|
|
17082
|
-
|
|
17083
|
-
|
|
17084
|
-
const
|
|
17085
|
-
|
|
17086
|
-
|
|
17087
|
-
|
|
17088
|
-
|
|
17089
|
-
|
|
17090
|
-
|
|
17091
|
-
|
|
17092
|
-
|
|
17093
|
-
|
|
17094
|
-
|
|
17095
|
-
|
|
17096
|
-
|
|
17097
|
-
|
|
17098
|
-
|
|
17099
|
-
|
|
17349
|
+
return { entries, leafId };
|
|
17350
|
+
}
|
|
17351
|
+
async function readOmpSessionHeader(sessionFile) {
|
|
17352
|
+
const handle = await open(sessionFile, "r");
|
|
17353
|
+
try {
|
|
17354
|
+
const buffer = Buffer.allocUnsafe(MAX_SESSION_HEADER_BYTES);
|
|
17355
|
+
const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
|
|
17356
|
+
const contents = buffer.subarray(0, bytesRead);
|
|
17357
|
+
const newline = contents.indexOf(10);
|
|
17358
|
+
if (newline < 0 && bytesRead === buffer.length) {
|
|
17359
|
+
throw new Error("Omp Session header exceeds the supported size");
|
|
17360
|
+
}
|
|
17361
|
+
const contentsText = utf8Decoder.decode(contents);
|
|
17362
|
+
for (const line of contentsText.split("\n")) {
|
|
17363
|
+
if (line.length === 0)
|
|
17364
|
+
continue;
|
|
17365
|
+
let parsed;
|
|
17366
|
+
try {
|
|
17367
|
+
parsed = JSON.parse(line);
|
|
17368
|
+
} catch {
|
|
17369
|
+
continue;
|
|
17370
|
+
}
|
|
17371
|
+
if (!isRecord5(parsed) || parsed.type !== "session")
|
|
17372
|
+
continue;
|
|
17373
|
+
if (typeof parsed.id !== "string" || parsed.id.length === 0 || typeof parsed.cwd !== "string" || parsed.cwd.length === 0) {
|
|
17374
|
+
throw new Error("Omp Session header is invalid");
|
|
17375
|
+
}
|
|
17376
|
+
return { type: "session", id: parsed.id, cwd: parsed.cwd };
|
|
17100
17377
|
}
|
|
17378
|
+
throw new Error("Omp Session header is invalid");
|
|
17379
|
+
} finally {
|
|
17380
|
+
await handle.close();
|
|
17101
17381
|
}
|
|
17102
|
-
return directories;
|
|
17103
17382
|
}
|
|
17104
|
-
|
|
17105
|
-
|
|
17106
|
-
|
|
17107
|
-
|
|
17108
|
-
|
|
17109
|
-
|
|
17110
|
-
|
|
17111
|
-
|
|
17383
|
+
async function verifyOmpSessionCwd(input) {
|
|
17384
|
+
if (!input.sessionFile)
|
|
17385
|
+
throw new Error("Omp Fork Session has no persisted Session file");
|
|
17386
|
+
const header = await readOmpSessionHeader(input.sessionFile);
|
|
17387
|
+
if (header.id !== input.sessionId) {
|
|
17388
|
+
throw new Error("Omp Fork Session header identity does not match RPC state");
|
|
17389
|
+
}
|
|
17390
|
+
const [actualCwd, expectedCwd] = await Promise.all([
|
|
17391
|
+
realpath(header.cwd),
|
|
17392
|
+
realpath(input.expectedCwd)
|
|
17393
|
+
]);
|
|
17394
|
+
if (actualCwd !== expectedCwd) {
|
|
17395
|
+
throw new Error("Omp Fork Session did not bind the requested cwd");
|
|
17396
|
+
}
|
|
17112
17397
|
}
|
|
17113
|
-
|
|
17114
|
-
|
|
17115
|
-
|
|
17116
|
-
|
|
17117
|
-
|
|
17118
|
-
|
|
17119
|
-
|
|
17120
|
-
|
|
17398
|
+
|
|
17399
|
+
// dist/session-import.js
|
|
17400
|
+
import { createReadStream as createReadStream2 } from "node:fs";
|
|
17401
|
+
import { opendir, realpath as realpath2, stat } from "node:fs/promises";
|
|
17402
|
+
import os2 from "node:os";
|
|
17403
|
+
import path4 from "node:path";
|
|
17404
|
+
import { createInterface } from "node:readline";
|
|
17405
|
+
|
|
17406
|
+
// ../../harness-adapter/dist/session-import.js
|
|
17407
|
+
import { lstat } from "node:fs/promises";
|
|
17408
|
+
var SessionImportChangedError = class extends Error {
|
|
17409
|
+
constructor(message3 = "Native Session changed during discovery; refresh and retry") {
|
|
17410
|
+
super(message3);
|
|
17411
|
+
this.name = "SessionImportChangedError";
|
|
17412
|
+
}
|
|
17413
|
+
};
|
|
17414
|
+
function isMissingFileError(error51) {
|
|
17415
|
+
return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "ENOENT";
|
|
17121
17416
|
}
|
|
17122
|
-
function
|
|
17123
|
-
|
|
17124
|
-
const segments = value.split("/");
|
|
17125
|
-
const head = segments[0] ?? "";
|
|
17126
|
-
const tail = segments.slice(1);
|
|
17127
|
-
if (head === "")
|
|
17128
|
-
return pathFlavor.join(pathFlavor.sep, ...tail);
|
|
17129
|
-
return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
|
|
17417
|
+
function sameFileFingerprint(left, right) {
|
|
17418
|
+
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;
|
|
17130
17419
|
}
|
|
17131
|
-
|
|
17132
|
-
|
|
17133
|
-
|
|
17134
|
-
const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
|
|
17135
|
-
const value = variables[name] ?? environmentValue(environment, name);
|
|
17136
|
-
if (value === void 0 || value === "") {
|
|
17137
|
-
unresolved = true;
|
|
17138
|
-
return "";
|
|
17139
|
-
}
|
|
17140
|
-
return value;
|
|
17141
|
-
});
|
|
17142
|
-
return unresolved ? void 0 : joinTemplate(platform, substituted);
|
|
17420
|
+
var STORAGE_ACCESS_ERRORS = /* @__PURE__ */ new Set(["EACCES", "EPERM", "EIO", "EMFILE", "ENFILE"]);
|
|
17421
|
+
function isStorageAccessError(error51) {
|
|
17422
|
+
return typeof error51 === "object" && error51 !== null && "code" in error51 && typeof error51.code === "string" && STORAGE_ACCESS_ERRORS.has(error51.code);
|
|
17143
17423
|
}
|
|
17144
|
-
function
|
|
17145
|
-
|
|
17146
|
-
|
|
17147
|
-
|
|
17148
|
-
if (
|
|
17149
|
-
|
|
17150
|
-
|
|
17151
|
-
environment: input.environment,
|
|
17152
|
-
home,
|
|
17153
|
-
...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
|
|
17154
|
-
}));
|
|
17155
|
-
continue;
|
|
17156
|
-
}
|
|
17157
|
-
const directory = expandInstallRoot(template, input.environment, platform, home);
|
|
17158
|
-
if (directory !== void 0)
|
|
17159
|
-
directories.push(directory);
|
|
17424
|
+
async function optionalLstat(file2) {
|
|
17425
|
+
try {
|
|
17426
|
+
return await lstat(file2);
|
|
17427
|
+
} catch (error51) {
|
|
17428
|
+
if (isMissingFileError(error51))
|
|
17429
|
+
return null;
|
|
17430
|
+
throw error51;
|
|
17160
17431
|
}
|
|
17161
|
-
return directories;
|
|
17162
17432
|
}
|
|
17163
|
-
function
|
|
17164
|
-
const
|
|
17165
|
-
const
|
|
17166
|
-
const
|
|
17167
|
-
|
|
17168
|
-
|
|
17169
|
-
|
|
17433
|
+
async function readStableFiles(files, read) {
|
|
17434
|
+
const before = await Promise.all(files.map(optionalLstat));
|
|
17435
|
+
const value = await read(before);
|
|
17436
|
+
const after = await Promise.all(files.map(optionalLstat));
|
|
17437
|
+
if (before.some((info, index) => !sameFileFingerprint(info, after[index] ?? null)))
|
|
17438
|
+
throw new SessionImportChangedError();
|
|
17439
|
+
return value;
|
|
17440
|
+
}
|
|
17441
|
+
function sessionImportTitle(value, maxLength = HARNESS_SESSION_IMPORT_TITLE_MAX_LENGTH) {
|
|
17442
|
+
if (typeof value !== "string")
|
|
17443
|
+
return null;
|
|
17444
|
+
const normalized = value.replaceAll("\0", "").replaceAll(/\s+/gu, " ").trim();
|
|
17445
|
+
if (!normalized)
|
|
17446
|
+
return null;
|
|
17447
|
+
if (normalized.length <= maxLength)
|
|
17448
|
+
return normalized;
|
|
17449
|
+
const characters = [...normalized];
|
|
17450
|
+
if (characters.length <= maxLength)
|
|
17451
|
+
return normalized;
|
|
17452
|
+
return `${characters.slice(0, maxLength - 1).join("").trimEnd()}…`;
|
|
17453
|
+
}
|
|
17454
|
+
function sessionImportCandidate(input) {
|
|
17455
|
+
const time3 = typeof input.updatedAt === "number" ? input.updatedAt : typeof input.updatedAt === "string" ? Date.parse(input.updatedAt) : Number.NaN;
|
|
17456
|
+
const parsed = harnessSessionImportCandidateSchema.safeParse({
|
|
17457
|
+
nativeSessionId: input.nativeSessionId,
|
|
17458
|
+
cwd: input.cwd,
|
|
17459
|
+
title: typeof input.title === "string" && input.title.trim().length > 0 ? input.title : null,
|
|
17460
|
+
updatedAt: Math.floor(time3),
|
|
17461
|
+
// Unknown must stay unknown; only an explicit boolean is a native statement.
|
|
17462
|
+
running: typeof input.running === "boolean" ? input.running : null
|
|
17463
|
+
});
|
|
17464
|
+
return parsed.success ? parsed.data : null;
|
|
17465
|
+
}
|
|
17466
|
+
var SessionImportScope = class {
|
|
17467
|
+
#abort = new AbortController();
|
|
17468
|
+
#options;
|
|
17469
|
+
#pending = /* @__PURE__ */ new Set();
|
|
17470
|
+
constructor(options) {
|
|
17471
|
+
this.#options = options;
|
|
17170
17472
|
}
|
|
17171
|
-
|
|
17172
|
-
|
|
17173
|
-
|
|
17174
|
-
|
|
17175
|
-
|
|
17176
|
-
candidate: pathFlavor.join(directory, command + extension),
|
|
17177
|
-
source: "path"
|
|
17178
|
-
});
|
|
17179
|
-
}
|
|
17473
|
+
#closed() {
|
|
17474
|
+
return {
|
|
17475
|
+
ok: false,
|
|
17476
|
+
error: { code: "invalidState", message: this.#options.closedMessage, retryable: false }
|
|
17477
|
+
};
|
|
17180
17478
|
}
|
|
17181
|
-
|
|
17182
|
-
|
|
17183
|
-
|
|
17184
|
-
|
|
17185
|
-
|
|
17186
|
-
|
|
17187
|
-
|
|
17188
|
-
|
|
17189
|
-
|
|
17479
|
+
read(operation) {
|
|
17480
|
+
const signal = this.#abort.signal;
|
|
17481
|
+
if (signal.aborted)
|
|
17482
|
+
return Promise.resolve(this.#closed());
|
|
17483
|
+
let started;
|
|
17484
|
+
try {
|
|
17485
|
+
started = operation(signal);
|
|
17486
|
+
} catch (error51) {
|
|
17487
|
+
started = Promise.reject(error51 instanceof Error ? error51 : new Error("Session read failed"));
|
|
17190
17488
|
}
|
|
17489
|
+
const request = started.then((value) => signal.aborted ? this.#closed() : { ok: true, value }).catch(() => signal.aborted ? this.#closed() : {
|
|
17490
|
+
ok: false,
|
|
17491
|
+
error: {
|
|
17492
|
+
code: "unavailable",
|
|
17493
|
+
message: this.#options.unavailableMessage,
|
|
17494
|
+
retryable: true
|
|
17495
|
+
}
|
|
17496
|
+
}).finally(() => this.#pending.delete(request));
|
|
17497
|
+
this.#pending.add(request);
|
|
17498
|
+
return request;
|
|
17191
17499
|
}
|
|
17192
|
-
|
|
17193
|
-
|
|
17194
|
-
|
|
17195
|
-
|
|
17196
|
-
|
|
17197
|
-
|
|
17198
|
-
|
|
17199
|
-
|
|
17200
|
-
|
|
17201
|
-
|
|
17202
|
-
|
|
17500
|
+
/** `read` for `resolveCandidate`: a null source is the selected Session having disappeared. */
|
|
17501
|
+
async resolve(operation) {
|
|
17502
|
+
const result = await this.read(operation);
|
|
17503
|
+
if (!result.ok)
|
|
17504
|
+
return result;
|
|
17505
|
+
return result.value ? { ok: true, value: result.value } : {
|
|
17506
|
+
ok: false,
|
|
17507
|
+
error: {
|
|
17508
|
+
code: "sessionNotFound",
|
|
17509
|
+
message: this.#options.notFoundMessage,
|
|
17510
|
+
retryable: false
|
|
17511
|
+
}
|
|
17512
|
+
};
|
|
17203
17513
|
}
|
|
17204
|
-
|
|
17205
|
-
|
|
17514
|
+
/** Idempotent. Resolves after every started read has settled. */
|
|
17515
|
+
async close() {
|
|
17516
|
+
this.#abort.abort();
|
|
17517
|
+
await Promise.allSettled(this.#pending);
|
|
17518
|
+
}
|
|
17519
|
+
};
|
|
17206
17520
|
|
|
17207
|
-
//
|
|
17208
|
-
|
|
17209
|
-
|
|
17210
|
-
function runInstallationCommand(command, args, environment, timeout = 3e4) {
|
|
17211
|
-
const env = withNodeRuntimeOnPath(environment);
|
|
17212
|
-
const invocation = /\.[cm]?js$/i.test(command) ? commandInvocation(process.execPath, [command, ...args], env) : commandInvocation(command, args, env);
|
|
17213
|
-
return new Promise((resolve, reject) => {
|
|
17214
|
-
const child = execFile(invocation.command, invocation.arguments, {
|
|
17215
|
-
env,
|
|
17216
|
-
cwd: env.HOME ?? env.USERPROFILE ?? homedir(),
|
|
17217
|
-
encoding: "utf8",
|
|
17218
|
-
timeout,
|
|
17219
|
-
killSignal: "SIGKILL",
|
|
17220
|
-
maxBuffer: 1024 * 1024,
|
|
17221
|
-
windowsHide: true,
|
|
17222
|
-
windowsVerbatimArguments: invocation.windowsVerbatimArguments
|
|
17223
|
-
}, (error51, stdout, stderr) => {
|
|
17224
|
-
if (error51)
|
|
17225
|
-
reject(new Error(error51.killed ? "Harness command timed out" : "Harness command failed; check the native installation and retry"));
|
|
17226
|
-
else
|
|
17227
|
-
resolve((stdout || stderr).trim());
|
|
17228
|
-
});
|
|
17229
|
-
child.stdin?.end();
|
|
17230
|
-
});
|
|
17521
|
+
// dist/session-import.js
|
|
17522
|
+
function isRecord6(value) {
|
|
17523
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17231
17524
|
}
|
|
17232
|
-
function
|
|
17233
|
-
|
|
17234
|
-
throw new Error("Harness returned an invalid version");
|
|
17235
|
-
return value.trim().replace(/^v/, "");
|
|
17525
|
+
function expandDirectory(value, home) {
|
|
17526
|
+
return path4.resolve(value === "~" ? home : value.startsWith(`~${path4.sep}`) || value.startsWith("~/") ? path4.join(home, value.slice(2)) : value);
|
|
17236
17527
|
}
|
|
17237
|
-
function
|
|
17238
|
-
|
|
17528
|
+
function ompSessionImportDirectory(environment) {
|
|
17529
|
+
const home = (process.platform === "win32" ? environment.USERPROFILE : environment.HOME) || os2.homedir();
|
|
17530
|
+
const custom2 = environment.PI_CODING_AGENT_SESSION_DIR;
|
|
17531
|
+
if (custom2)
|
|
17532
|
+
return { directory: expandDirectory(custom2, home), flat: true };
|
|
17533
|
+
const agent = environment.PI_CODING_AGENT_DIR;
|
|
17534
|
+
return {
|
|
17535
|
+
directory: path4.join(agent ? expandDirectory(agent, home) : path4.join(home, ".omp", "agent"), "sessions"),
|
|
17536
|
+
flat: false
|
|
17537
|
+
};
|
|
17239
17538
|
}
|
|
17240
|
-
function
|
|
17241
|
-
|
|
17242
|
-
|
|
17243
|
-
|
|
17244
|
-
|
|
17245
|
-
|
|
17246
|
-
|
|
17247
|
-
|
|
17248
|
-
}
|
|
17249
|
-
const
|
|
17250
|
-
|
|
17251
|
-
|
|
17252
|
-
|
|
17253
|
-
|
|
17254
|
-
|
|
17255
|
-
|
|
17256
|
-
|
|
17257
|
-
|
|
17258
|
-
|
|
17259
|
-
|
|
17260
|
-
const numericX = /^\d+$/.test(x);
|
|
17261
|
-
const numericY = /^\d+$/.test(y);
|
|
17262
|
-
if (numericX && numericY) {
|
|
17263
|
-
if (BigInt(x) === BigInt(y))
|
|
17539
|
+
function messageText(content) {
|
|
17540
|
+
if (typeof content === "string")
|
|
17541
|
+
return content;
|
|
17542
|
+
if (!Array.isArray(content))
|
|
17543
|
+
return "";
|
|
17544
|
+
return content.filter((part) => isRecord6(part) && part.type === "text" && typeof part.text === "string").map((part) => String(part.text)).join(" ");
|
|
17545
|
+
}
|
|
17546
|
+
async function readFacts(file2, signal) {
|
|
17547
|
+
const stream = createReadStream2(file2, { encoding: "utf8", signal });
|
|
17548
|
+
const lines = createInterface({ input: stream, crlfDelay: Infinity });
|
|
17549
|
+
let header = null;
|
|
17550
|
+
let nativeTitle = null;
|
|
17551
|
+
let firstPrompt = null;
|
|
17552
|
+
let updatedAt = null;
|
|
17553
|
+
let leafHasUser = false;
|
|
17554
|
+
const hasUserAncestry = /* @__PURE__ */ new Map();
|
|
17555
|
+
try {
|
|
17556
|
+
for await (const line of lines) {
|
|
17557
|
+
signal.throwIfAborted();
|
|
17558
|
+
if (!line.trim())
|
|
17264
17559
|
continue;
|
|
17265
|
-
|
|
17560
|
+
let entry;
|
|
17561
|
+
try {
|
|
17562
|
+
entry = JSON.parse(line);
|
|
17563
|
+
} catch {
|
|
17564
|
+
continue;
|
|
17565
|
+
}
|
|
17566
|
+
if (!isRecord6(entry))
|
|
17567
|
+
continue;
|
|
17568
|
+
if (entry.type === "title") {
|
|
17569
|
+
nativeTitle = sessionImportTitle(entry.title);
|
|
17570
|
+
continue;
|
|
17571
|
+
}
|
|
17572
|
+
if (entry.type === "session") {
|
|
17573
|
+
if (header)
|
|
17574
|
+
return null;
|
|
17575
|
+
if (typeof entry.id !== "string" || entry.id.length === 0 || typeof entry.cwd !== "string" || !path4.isAbsolute(entry.cwd))
|
|
17576
|
+
return null;
|
|
17577
|
+
header = { id: entry.id, cwd: entry.cwd };
|
|
17578
|
+
continue;
|
|
17579
|
+
}
|
|
17580
|
+
if (typeof entry.id !== "string" || entry.id.length === 0)
|
|
17581
|
+
continue;
|
|
17582
|
+
const message3 = isRecord6(entry.message) ? entry.message : null;
|
|
17583
|
+
const isUser = entry.type === "message" && message3?.role === "user";
|
|
17584
|
+
if (isUser)
|
|
17585
|
+
firstPrompt ??= sessionImportTitle(messageText(message3?.content));
|
|
17586
|
+
leafHasUser = isUser || typeof entry.parentId === "string" && hasUserAncestry.get(entry.parentId) === true;
|
|
17587
|
+
hasUserAncestry.set(entry.id, leafHasUser);
|
|
17588
|
+
if (entry.type === "message" && (message3?.role === "user" || message3?.role === "assistant")) {
|
|
17589
|
+
const time3 = typeof message3.timestamp === "number" ? message3.timestamp : typeof entry.timestamp === "string" ? Date.parse(entry.timestamp) : Number.NaN;
|
|
17590
|
+
if (Number.isFinite(time3) && time3 >= 0)
|
|
17591
|
+
updatedAt = time3;
|
|
17592
|
+
}
|
|
17266
17593
|
}
|
|
17267
|
-
|
|
17268
|
-
|
|
17269
|
-
|
|
17594
|
+
} finally {
|
|
17595
|
+
lines.close();
|
|
17596
|
+
stream.destroy();
|
|
17270
17597
|
}
|
|
17271
|
-
|
|
17272
|
-
|
|
17273
|
-
|
|
17274
|
-
|
|
17275
|
-
|
|
17276
|
-
|
|
17277
|
-
|
|
17598
|
+
if (!header || !leafHasUser)
|
|
17599
|
+
return null;
|
|
17600
|
+
return {
|
|
17601
|
+
nativeSessionId: header.id,
|
|
17602
|
+
cwd: header.cwd,
|
|
17603
|
+
title: nativeTitle ?? firstPrompt,
|
|
17604
|
+
updatedAt
|
|
17605
|
+
};
|
|
17606
|
+
}
|
|
17607
|
+
var OmpSessionImport = class {
|
|
17608
|
+
#location;
|
|
17609
|
+
#scope = new SessionImportScope({
|
|
17610
|
+
closedMessage: "Omp Session import is closed",
|
|
17611
|
+
unavailableMessage: "Omp sessions could not be read; close native clients, check storage access and retry",
|
|
17612
|
+
notFoundMessage: "Omp Session is no longer importable"
|
|
17278
17613
|
});
|
|
17279
|
-
|
|
17280
|
-
|
|
17281
|
-
|
|
17282
|
-
|
|
17283
|
-
|
|
17284
|
-
|
|
17285
|
-
|
|
17286
|
-
|
|
17287
|
-
|
|
17288
|
-
|
|
17289
|
-
|
|
17290
|
-
await
|
|
17291
|
-
|
|
17292
|
-
|
|
17293
|
-
|
|
17294
|
-
return
|
|
17295
|
-
})().finally(() => {
|
|
17296
|
-
updating = void 0;
|
|
17614
|
+
constructor(environment) {
|
|
17615
|
+
this.#location = ompSessionImportDirectory(environment);
|
|
17616
|
+
}
|
|
17617
|
+
listCandidates() {
|
|
17618
|
+
return this.#scope.read(async (signal) => [...(await this.#sources(signal)).values()].flatMap((sources) => (
|
|
17619
|
+
// One identity in two files cannot be resumed unambiguously.
|
|
17620
|
+
sources.length === 1 && sources[0] ? [sources[0].candidate] : []
|
|
17621
|
+
)));
|
|
17622
|
+
}
|
|
17623
|
+
resolveCandidate(nativeSessionId) {
|
|
17624
|
+
return this.#scope.resolve(async (signal) => {
|
|
17625
|
+
const sources = (await this.#sources(signal)).get(nativeSessionId);
|
|
17626
|
+
if (sources?.length !== 1 || !sources[0])
|
|
17627
|
+
return null;
|
|
17628
|
+
const source = await this.#source(sources[0].file, signal);
|
|
17629
|
+
return source?.nativeRef.nativeSessionId === nativeSessionId ? { candidate: source.candidate, nativeRef: source.nativeRef } : null;
|
|
17297
17630
|
});
|
|
17298
|
-
|
|
17299
|
-
|
|
17631
|
+
}
|
|
17632
|
+
close() {
|
|
17633
|
+
return this.#scope.close();
|
|
17634
|
+
}
|
|
17635
|
+
async #sessionFiles(signal) {
|
|
17636
|
+
const { directory, flat } = this.#location;
|
|
17637
|
+
const info = await optionalLstat(directory);
|
|
17638
|
+
if (!info)
|
|
17639
|
+
return [];
|
|
17640
|
+
if (!info.isDirectory())
|
|
17641
|
+
throw new Error("Omp Session store is not a directory");
|
|
17642
|
+
const files = [];
|
|
17643
|
+
const visit = async (current, projectLevel) => {
|
|
17644
|
+
const entries = await opendir(current).catch((error51) => {
|
|
17645
|
+
if (isMissingFileError(error51))
|
|
17646
|
+
return null;
|
|
17647
|
+
throw error51;
|
|
17648
|
+
});
|
|
17649
|
+
if (!entries)
|
|
17650
|
+
return;
|
|
17651
|
+
for await (const entry of entries) {
|
|
17652
|
+
signal.throwIfAborted();
|
|
17653
|
+
if (projectLevel && entry.isDirectory())
|
|
17654
|
+
await visit(path4.join(current, entry.name), false);
|
|
17655
|
+
else if (!projectLevel && entry.isFile() && entry.name.endsWith(".jsonl"))
|
|
17656
|
+
files.push(path4.join(current, entry.name));
|
|
17657
|
+
}
|
|
17658
|
+
};
|
|
17659
|
+
await visit(directory, !flat);
|
|
17660
|
+
return files;
|
|
17661
|
+
}
|
|
17662
|
+
/** Session ID to every readable file claiming it. Files changing under the read are skipped. */
|
|
17663
|
+
async #sources(signal) {
|
|
17664
|
+
const found = /* @__PURE__ */ new Map();
|
|
17665
|
+
for (const file2 of await this.#sessionFiles(signal)) {
|
|
17666
|
+
signal.throwIfAborted();
|
|
17667
|
+
try {
|
|
17668
|
+
const source = await this.#source(file2, signal);
|
|
17669
|
+
if (!source)
|
|
17670
|
+
continue;
|
|
17671
|
+
const sources = found.get(source.nativeRef.nativeSessionId) ?? [];
|
|
17672
|
+
sources.push(source);
|
|
17673
|
+
found.set(source.nativeRef.nativeSessionId, sources);
|
|
17674
|
+
} catch (error51) {
|
|
17675
|
+
if (!(error51 instanceof SessionImportChangedError))
|
|
17676
|
+
throw error51;
|
|
17677
|
+
}
|
|
17678
|
+
}
|
|
17679
|
+
return found;
|
|
17680
|
+
}
|
|
17681
|
+
async #source(file2, signal) {
|
|
17682
|
+
signal.throwIfAborted();
|
|
17683
|
+
return readStableFiles([file2], async ([info]) => {
|
|
17684
|
+
if (!info?.isFile() || info.size === 0)
|
|
17685
|
+
return null;
|
|
17686
|
+
try {
|
|
17687
|
+
const facts = await readFacts(file2, signal);
|
|
17688
|
+
if (!facts)
|
|
17689
|
+
return null;
|
|
17690
|
+
const cwd = await realpath2(facts.cwd);
|
|
17691
|
+
if (!(await stat(cwd)).isDirectory())
|
|
17692
|
+
return null;
|
|
17693
|
+
const candidate = sessionImportCandidate({
|
|
17694
|
+
nativeSessionId: facts.nativeSessionId,
|
|
17695
|
+
cwd,
|
|
17696
|
+
title: facts.title,
|
|
17697
|
+
updatedAt: facts.updatedAt ?? info.mtimeMs
|
|
17698
|
+
// OMP has no cross-process activity marker: idleness cannot be established.
|
|
17699
|
+
});
|
|
17700
|
+
if (!candidate)
|
|
17701
|
+
return null;
|
|
17702
|
+
return {
|
|
17703
|
+
file: file2,
|
|
17704
|
+
candidate,
|
|
17705
|
+
// Resume needs the file itself: OMP is started with `--session <file>`.
|
|
17706
|
+
nativeRef: nativeSessionRefSchema.parse({
|
|
17707
|
+
harnessId: "omp",
|
|
17708
|
+
nativeSessionId: facts.nativeSessionId,
|
|
17709
|
+
locator: { sessionFile: await realpath2(file2) },
|
|
17710
|
+
formatVersion: 1
|
|
17711
|
+
})
|
|
17712
|
+
};
|
|
17713
|
+
} catch (error51) {
|
|
17714
|
+
signal.throwIfAborted();
|
|
17715
|
+
if (isStorageAccessError(error51))
|
|
17716
|
+
throw error51;
|
|
17717
|
+
return null;
|
|
17718
|
+
}
|
|
17719
|
+
});
|
|
17720
|
+
}
|
|
17721
|
+
};
|
|
17722
|
+
|
|
17723
|
+
// dist/omp-last-turn-rollback.js
|
|
17724
|
+
function modelFromState(state) {
|
|
17725
|
+
if (state.provider === null && state.modelId === null)
|
|
17726
|
+
return null;
|
|
17727
|
+
if (state.provider === null || state.modelId === null) {
|
|
17728
|
+
throw new Error("Omp state contains a partial Model identity");
|
|
17729
|
+
}
|
|
17730
|
+
return { provider: state.provider, id: state.modelId };
|
|
17300
17731
|
}
|
|
17732
|
+
async function rollbackOmpLastTurn(transport, sourceSessionId, cwd) {
|
|
17733
|
+
const startupState = transport.state;
|
|
17734
|
+
const startupSessionId = startupState.sessionId;
|
|
17735
|
+
const currentModel = modelFromState(startupState);
|
|
17736
|
+
const currentThinking = startupState.thinkingLevel;
|
|
17737
|
+
const copiedHistory = await transport.getEntries();
|
|
17738
|
+
const boundary = resolveOmpLastTurnBoundary(copiedHistory);
|
|
17739
|
+
if (!boundary)
|
|
17740
|
+
return { ok: false, reason: "empty" };
|
|
17741
|
+
const sourceSnapshot = mapOmpSnapshot(copiedHistory, {
|
|
17742
|
+
sessionId: startupSessionId,
|
|
17743
|
+
model: currentModel
|
|
17744
|
+
});
|
|
17745
|
+
let state = await transport.fork(boundary.lastUserEntryId);
|
|
17746
|
+
if (state.sessionId === sourceSessionId || state.sessionId === startupSessionId) {
|
|
17747
|
+
throw new Error("Omp last-Turn rollback did not create a distinct Native Session");
|
|
17748
|
+
}
|
|
17749
|
+
if (!sameOmpModel(modelFromState(state), currentModel)) {
|
|
17750
|
+
if (!currentModel)
|
|
17751
|
+
throw new Error("Omp last-Turn rollback changed the current Model");
|
|
17752
|
+
state = await transport.selectModel(currentModel);
|
|
17753
|
+
}
|
|
17754
|
+
if (state.thinkingLevel !== currentThinking) {
|
|
17755
|
+
if (!currentThinking)
|
|
17756
|
+
throw new Error("Omp last-Turn rollback changed current Thinking");
|
|
17757
|
+
state = await transport.selectThinkingOption(currentThinking);
|
|
17758
|
+
}
|
|
17759
|
+
if (!sameOmpModel(modelFromState(state), currentModel) || state.thinkingLevel !== currentThinking) {
|
|
17760
|
+
throw new Error("Omp last-Turn rollback could not restore current Model and Thinking");
|
|
17761
|
+
}
|
|
17762
|
+
const snapshot = mapOmpSnapshot(await transport.getEntries(), {
|
|
17763
|
+
sessionId: state.sessionId,
|
|
17764
|
+
model: modelFromState(state)
|
|
17765
|
+
});
|
|
17766
|
+
const expectedTurnKeys = sourceSnapshot.turns.slice(0, -1).map((turn) => turn.nativeTurnRef.nativeTurnKey);
|
|
17767
|
+
const actualTurnKeys = snapshot.turns.map((turn) => turn.nativeTurnRef.nativeTurnKey);
|
|
17768
|
+
if (snapshot.turns.length !== boundary.sourceTurnCount - 1 || actualTurnKeys.some((key, index) => key !== expectedTurnKeys[index])) {
|
|
17769
|
+
throw new Error("Omp last-Turn rollback did not produce the exact retained history prefix");
|
|
17770
|
+
}
|
|
17771
|
+
await transport.verifySessionCwd(cwd);
|
|
17772
|
+
return { ok: true };
|
|
17773
|
+
}
|
|
17774
|
+
|
|
17775
|
+
// dist/omp-rpc-session.js
|
|
17776
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
17777
|
+
import { randomUUID } from "node:crypto";
|
|
17778
|
+
import path5 from "node:path";
|
|
17301
17779
|
|
|
17302
17780
|
// dist/command.js
|
|
17303
17781
|
var ompDiscoverySpec = {
|
|
@@ -17326,14 +17804,14 @@ function resolveOmpExecutable(input, dependencies = {}) {
|
|
|
17326
17804
|
}
|
|
17327
17805
|
|
|
17328
17806
|
// dist/omp-usage.js
|
|
17329
|
-
function
|
|
17807
|
+
function isRecord7(value) {
|
|
17330
17808
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17331
17809
|
}
|
|
17332
17810
|
function nonNegativeSafeInteger(value) {
|
|
17333
17811
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
|
|
17334
17812
|
}
|
|
17335
17813
|
function optionalOmpCacheHitRatePercent(value) {
|
|
17336
|
-
if (!
|
|
17814
|
+
if (!isRecord7(value) || value.role !== "assistant" || !isRecord7(value.usage))
|
|
17337
17815
|
return null;
|
|
17338
17816
|
const input = nonNegativeSafeInteger(value.usage.input);
|
|
17339
17817
|
const cacheRead = nonNegativeSafeInteger(value.usage.cacheRead);
|
|
@@ -17346,20 +17824,20 @@ function optionalOmpCacheHitRatePercent(value) {
|
|
|
17346
17824
|
function latestOmpCacheHitRatePercent(history) {
|
|
17347
17825
|
let latest = null;
|
|
17348
17826
|
for (const entry of activeOmpEntries(history)) {
|
|
17349
|
-
if (entry.type === "message" &&
|
|
17827
|
+
if (entry.type === "message" && isRecord7(entry.message) && entry.message.role === "assistant") {
|
|
17350
17828
|
latest = optionalOmpCacheHitRatePercent(entry.message);
|
|
17351
17829
|
}
|
|
17352
17830
|
}
|
|
17353
17831
|
return latest;
|
|
17354
17832
|
}
|
|
17355
17833
|
function responseData(response, operation) {
|
|
17356
|
-
if (!
|
|
17834
|
+
if (!isRecord7(response.data)) {
|
|
17357
17835
|
throw new Error(`Omp RPC ${operation} response has no data`);
|
|
17358
17836
|
}
|
|
17359
17837
|
return response.data;
|
|
17360
17838
|
}
|
|
17361
17839
|
function contextUsage(value) {
|
|
17362
|
-
if (!
|
|
17840
|
+
if (!isRecord7(value))
|
|
17363
17841
|
throw new Error("Omp RPC context Usage is invalid");
|
|
17364
17842
|
return parseHostUsage({
|
|
17365
17843
|
contextUsedTokens: value.tokens,
|
|
@@ -17369,15 +17847,15 @@ function contextUsage(value) {
|
|
|
17369
17847
|
function parseOmpSessionUsage(response) {
|
|
17370
17848
|
const data = responseData(response, "Session stats");
|
|
17371
17849
|
const tokens = data.tokens;
|
|
17372
|
-
if (tokens !== void 0 && !
|
|
17850
|
+
if (tokens !== void 0 && !isRecord7(tokens)) {
|
|
17373
17851
|
throw new Error("Omp RPC Session stats tokens are invalid");
|
|
17374
17852
|
}
|
|
17375
17853
|
return parseHostUsage({
|
|
17376
|
-
...
|
|
17377
|
-
...
|
|
17378
|
-
...
|
|
17379
|
-
...
|
|
17380
|
-
...
|
|
17854
|
+
...isRecord7(tokens) && tokens.input !== void 0 ? { inputTokens: tokens.input } : {},
|
|
17855
|
+
...isRecord7(tokens) && tokens.cacheRead !== void 0 ? { cachedInputTokens: tokens.cacheRead } : {},
|
|
17856
|
+
...isRecord7(tokens) && tokens.cacheWrite !== void 0 ? { cacheWriteInputTokens: tokens.cacheWrite } : {},
|
|
17857
|
+
...isRecord7(tokens) && tokens.output !== void 0 ? { outputTokens: tokens.output } : {},
|
|
17858
|
+
...isRecord7(tokens) && tokens.total !== void 0 ? { totalTokens: tokens.total } : {},
|
|
17381
17859
|
...data.cost !== void 0 ? { totalCostUsd: data.cost } : {},
|
|
17382
17860
|
...data.contextUsage !== void 0 ? contextUsage(data.contextUsage) : {}
|
|
17383
17861
|
});
|
|
@@ -17492,7 +17970,7 @@ var OmpRpcUnsupportedCommandError = class extends Error {
|
|
|
17492
17970
|
}
|
|
17493
17971
|
};
|
|
17494
17972
|
var textDecoder = new TextDecoder("utf-8", { fatal: true });
|
|
17495
|
-
function
|
|
17973
|
+
function isRecord8(value) {
|
|
17496
17974
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17497
17975
|
}
|
|
17498
17976
|
function message2(value) {
|
|
@@ -17504,13 +17982,13 @@ function nonBlankString(value) {
|
|
|
17504
17982
|
function parseNativeModel(value, context) {
|
|
17505
17983
|
if (value === null || value === void 0)
|
|
17506
17984
|
return null;
|
|
17507
|
-
if (!
|
|
17985
|
+
if (!isRecord8(value) || !nonBlankString(value.provider) || !nonBlankString(value.id)) {
|
|
17508
17986
|
throw new OmpRpcFaultError("protocolError", `Omp RPC returned an invalid ${context} Model`);
|
|
17509
17987
|
}
|
|
17510
17988
|
return { provider: value.provider, id: value.id };
|
|
17511
17989
|
}
|
|
17512
17990
|
function sessionStateData(response) {
|
|
17513
|
-
const data =
|
|
17991
|
+
const data = isRecord8(response.data) ? response.data : null;
|
|
17514
17992
|
if (!data)
|
|
17515
17993
|
throw new OmpRpcFaultError("protocolError", "Omp RPC state response has no data");
|
|
17516
17994
|
return data;
|
|
@@ -17525,7 +18003,7 @@ function parseSessionState(response) {
|
|
|
17525
18003
|
if (thinkingLevel !== null && !thinkingLevel.success) {
|
|
17526
18004
|
throw new OmpRpcFaultError("protocolError", "Omp RPC state has an invalid Thinking level");
|
|
17527
18005
|
}
|
|
17528
|
-
const thinking =
|
|
18006
|
+
const thinking = isRecord8(data.model) && isRecord8(data.model.thinking) ? data.model.thinking : null;
|
|
17529
18007
|
const availableThinkingLevels = thinking && Array.isArray(thinking.efforts) ? thinking.efforts.flatMap((level) => {
|
|
17530
18008
|
const parsed = harnessThinkingOptionIdSchema.safeParse(level);
|
|
17531
18009
|
return parsed.success ? [parsed.data] : [];
|
|
@@ -17548,25 +18026,25 @@ function parseSessionStreaming(response) {
|
|
|
17548
18026
|
return isStreaming;
|
|
17549
18027
|
}
|
|
17550
18028
|
function parseAvailableModels(response) {
|
|
17551
|
-
const data =
|
|
18029
|
+
const data = isRecord8(response.data) ? response.data : null;
|
|
17552
18030
|
if (!data || !Array.isArray(data.models)) {
|
|
17553
18031
|
throw new OmpRpcFaultError("protocolError", "Omp RPC Model catalog response has no models");
|
|
17554
18032
|
}
|
|
17555
18033
|
return data.models.map((model) => {
|
|
17556
18034
|
const parsed = parseNativeModel(model, "catalog");
|
|
17557
|
-
if (!parsed || !
|
|
18035
|
+
if (!parsed || !isRecord8(model) || typeof model.reasoning !== "boolean") {
|
|
17558
18036
|
throw new OmpRpcFaultError("protocolError", "Omp RPC catalog contains a Model without reasoning capability");
|
|
17559
18037
|
}
|
|
17560
18038
|
return { ...parsed, reasoning: model.reasoning };
|
|
17561
18039
|
});
|
|
17562
18040
|
}
|
|
17563
18041
|
function parseSubagentMessages(response) {
|
|
17564
|
-
const data =
|
|
18042
|
+
const data = isRecord8(response.data) ? response.data : null;
|
|
17565
18043
|
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)) {
|
|
17566
18044
|
throw new OmpRpcFaultError("protocolError", "Omp RPC Subagent transcript response is invalid");
|
|
17567
18045
|
}
|
|
17568
|
-
const entries = data.entries.flatMap((value) =>
|
|
17569
|
-
const messages = data.messages.flatMap((value) =>
|
|
18046
|
+
const entries = data.entries.flatMap((value) => isRecord8(value) ? [value] : []);
|
|
18047
|
+
const messages = data.messages.flatMap((value) => isRecord8(value) ? [value] : []);
|
|
17570
18048
|
if (entries.length !== data.entries.length || messages.length !== data.messages.length) {
|
|
17571
18049
|
throw new OmpRpcFaultError("protocolError", "Omp RPC Subagent transcript contains invalid data");
|
|
17572
18050
|
}
|
|
@@ -17587,17 +18065,17 @@ function subagentStatus(value) {
|
|
|
17587
18065
|
throw new OmpRpcFaultError("protocolError", "Omp RPC Subagent status is invalid");
|
|
17588
18066
|
}
|
|
17589
18067
|
function assistantText(value) {
|
|
17590
|
-
if (!
|
|
18068
|
+
if (!isRecord8(value) || value.role !== "assistant" || !Array.isArray(value.content))
|
|
17591
18069
|
return null;
|
|
17592
|
-
return value.content.filter((content) =>
|
|
18070
|
+
return value.content.filter((content) => isRecord8(content) && content.type === "text" && typeof content.text === "string").map((content) => content.text).join("");
|
|
17593
18071
|
}
|
|
17594
18072
|
function assistantMessageId(value) {
|
|
17595
|
-
if (!
|
|
18073
|
+
if (!isRecord8(value) || value.role !== "assistant")
|
|
17596
18074
|
return null;
|
|
17597
18075
|
return nonBlankString(value.responseId) ? value.responseId : null;
|
|
17598
18076
|
}
|
|
17599
18077
|
function extractReasoningText(content) {
|
|
17600
|
-
if (!
|
|
18078
|
+
if (!isRecord8(content))
|
|
17601
18079
|
return null;
|
|
17602
18080
|
const type = String(content.type ?? "");
|
|
17603
18081
|
if (type === "thinking" || type === "reasoning" || type === "thought") {
|
|
@@ -17607,12 +18085,12 @@ function extractReasoningText(content) {
|
|
|
17607
18085
|
return null;
|
|
17608
18086
|
}
|
|
17609
18087
|
function assistantReasoning(value) {
|
|
17610
|
-
if (!
|
|
18088
|
+
if (!isRecord8(value) || value.role !== "assistant" || !Array.isArray(value.content))
|
|
17611
18089
|
return null;
|
|
17612
18090
|
return value.content.map(extractReasoningText).filter((text) => typeof text === "string").join("");
|
|
17613
18091
|
}
|
|
17614
18092
|
function assistantFailure(value) {
|
|
17615
|
-
if (!
|
|
18093
|
+
if (!isRecord8(value) || value.role !== "assistant")
|
|
17616
18094
|
return void 0;
|
|
17617
18095
|
if (value.stopReason !== "error" && value.stopReason !== "aborted")
|
|
17618
18096
|
return null;
|
|
@@ -17632,7 +18110,7 @@ function signalProcessTree(child, signal) {
|
|
|
17632
18110
|
try {
|
|
17633
18111
|
process.kill(-child.pid, signal);
|
|
17634
18112
|
} catch (error51) {
|
|
17635
|
-
if (!
|
|
18113
|
+
if (!isRecord8(error51) || error51.code !== "ESRCH")
|
|
17636
18114
|
throw error51;
|
|
17637
18115
|
}
|
|
17638
18116
|
}
|
|
@@ -17671,7 +18149,7 @@ function ompRpcProcessCommand(options, dependencies = {}) {
|
|
|
17671
18149
|
...modelArguments,
|
|
17672
18150
|
...sessionArguments
|
|
17673
18151
|
];
|
|
17674
|
-
const extension =
|
|
18152
|
+
const extension = path5.win32.extname(command).toLowerCase();
|
|
17675
18153
|
if (platform !== "win32" || ![".cmd", ".bat"].includes(extension)) {
|
|
17676
18154
|
return { command, arguments: arguments_, windowsVerbatimArguments: false };
|
|
17677
18155
|
}
|
|
@@ -17714,6 +18192,10 @@ var OmpRpcSession = class {
|
|
|
17714
18192
|
#manualCompaction = null;
|
|
17715
18193
|
#stderrTail = "";
|
|
17716
18194
|
#frameDecoder = new OmpFrameDecoder();
|
|
18195
|
+
#startupFaultResolve = null;
|
|
18196
|
+
#startupFault = new Promise((resolve) => {
|
|
18197
|
+
this.#startupFaultResolve = resolve;
|
|
18198
|
+
});
|
|
17717
18199
|
#readyResolve = null;
|
|
17718
18200
|
#ready = new Promise((resolve) => {
|
|
17719
18201
|
this.#readyResolve = resolve;
|
|
@@ -17770,7 +18252,7 @@ var OmpRpcSession = class {
|
|
|
17770
18252
|
this.#stderrTail = sanitizeDiagnosticTail(`${this.#stderrTail}${chunk.toString()}`);
|
|
17771
18253
|
});
|
|
17772
18254
|
child.once("error", (error51) => {
|
|
17773
|
-
const kind =
|
|
18255
|
+
const kind = isRecord8(error51) && error51.code === "ENOENT" ? "notInstalled" : "unavailable";
|
|
17774
18256
|
this.#fail(new OmpRpcFaultError(kind, `Omp RPC failed to start: ${error51.message}`, this.stderrTail));
|
|
17775
18257
|
});
|
|
17776
18258
|
child.once("exit", (code, signal) => {
|
|
@@ -17785,10 +18267,20 @@ var OmpRpcSession = class {
|
|
|
17785
18267
|
}),
|
|
17786
18268
|
new Promise((_resolve, reject) => setTimeout(() => reject(new Error("Omp RPC start timed out")), this.#options.commandTimeoutMs))
|
|
17787
18269
|
]);
|
|
17788
|
-
|
|
17789
|
-
|
|
17790
|
-
|
|
17791
|
-
|
|
18270
|
+
let readyTimeout;
|
|
18271
|
+
try {
|
|
18272
|
+
await Promise.race([
|
|
18273
|
+
this.#ready,
|
|
18274
|
+
this.#startupFault.then((error51) => {
|
|
18275
|
+
throw error51;
|
|
18276
|
+
}),
|
|
18277
|
+
new Promise((_resolve, reject) => {
|
|
18278
|
+
readyTimeout = setTimeout(() => reject(new Error("Omp RPC ready signal timed out")), this.#options.commandTimeoutMs);
|
|
18279
|
+
})
|
|
18280
|
+
]);
|
|
18281
|
+
} finally {
|
|
18282
|
+
clearTimeout(readyTimeout);
|
|
18283
|
+
}
|
|
17792
18284
|
await this.#send("negotiate_protocol", { protocolVersion: 2 }).catch(() => void 0);
|
|
17793
18285
|
if (this.#options.subscribeSubagentEvents !== false) {
|
|
17794
18286
|
await this.#send("set_subagent_subscription", { level: "events" }).catch(() => void 0);
|
|
@@ -17808,17 +18300,17 @@ var OmpRpcSession = class {
|
|
|
17808
18300
|
return await readOmpSessionHistory(this.state.sessionFile);
|
|
17809
18301
|
}
|
|
17810
18302
|
const response = await this.#send("get_messages", {});
|
|
17811
|
-
const data =
|
|
18303
|
+
const data = isRecord8(response.data) ? response.data : null;
|
|
17812
18304
|
if (!data || !Array.isArray(data.messages)) {
|
|
17813
18305
|
throw new OmpRpcFaultError("protocolError", "Omp RPC messages response has no messages");
|
|
17814
18306
|
}
|
|
17815
18307
|
let branchEntryIds = null;
|
|
17816
18308
|
try {
|
|
17817
18309
|
const branchResponse = await this.#send("get_branch_messages", {});
|
|
17818
|
-
const branchData =
|
|
18310
|
+
const branchData = isRecord8(branchResponse.data) ? branchResponse.data : null;
|
|
17819
18311
|
if (branchData && Array.isArray(branchData.messages)) {
|
|
17820
18312
|
const parsed = branchData.messages.flatMap((entry) => {
|
|
17821
|
-
if (!
|
|
18313
|
+
if (!isRecord8(entry) || !nonBlankString(entry.entryId))
|
|
17822
18314
|
return [];
|
|
17823
18315
|
return [entry.entryId];
|
|
17824
18316
|
});
|
|
@@ -17832,11 +18324,11 @@ var OmpRpcSession = class {
|
|
|
17832
18324
|
let userIndex = 0;
|
|
17833
18325
|
let parentId = null;
|
|
17834
18326
|
const entries = data.messages.map((nativeMessage, index) => {
|
|
17835
|
-
const role =
|
|
18327
|
+
const role = isRecord8(nativeMessage) ? nativeMessage.role : void 0;
|
|
17836
18328
|
const branchId = role === "user" ? branchEntryIds?.[userIndex] : void 0;
|
|
17837
18329
|
if (branchId)
|
|
17838
18330
|
userIndex += 1;
|
|
17839
|
-
const id = branchId ?? (
|
|
18331
|
+
const id = branchId ?? (isRecord8(nativeMessage) && nonBlankString(nativeMessage.id) ? nativeMessage.id : `omp-message-${index}`);
|
|
17840
18332
|
const entry = { id, parentId, type: "message", message: nativeMessage };
|
|
17841
18333
|
parentId = id;
|
|
17842
18334
|
return entry;
|
|
@@ -17916,7 +18408,7 @@ var OmpRpcSession = class {
|
|
|
17916
18408
|
throw new Error("Omp RPC Fork requires an Entry identity");
|
|
17917
18409
|
try {
|
|
17918
18410
|
const response = await this.#send("branch", { entryId });
|
|
17919
|
-
const data =
|
|
18411
|
+
const data = isRecord8(response.data) ? response.data : null;
|
|
17920
18412
|
if (!data || data.cancelled === true) {
|
|
17921
18413
|
throw new OmpRpcFaultError("unavailable", "Omp RPC Fork was cancelled");
|
|
17922
18414
|
}
|
|
@@ -18109,7 +18601,7 @@ var OmpRpcSession = class {
|
|
|
18109
18601
|
continue;
|
|
18110
18602
|
}
|
|
18111
18603
|
const value = decoded;
|
|
18112
|
-
if (!
|
|
18604
|
+
if (!isRecord8(value) || typeof value.type !== "string") {
|
|
18113
18605
|
throw new OmpRpcFaultError("protocolError", "Omp RPC returned an invalid envelope");
|
|
18114
18606
|
}
|
|
18115
18607
|
this.#handle(value);
|
|
@@ -18168,7 +18660,7 @@ var OmpRpcSession = class {
|
|
|
18168
18660
|
this.#armCommandTimeout(id, pending);
|
|
18169
18661
|
}
|
|
18170
18662
|
}
|
|
18171
|
-
const outcome = value.aborted === true ? "cancelled" :
|
|
18663
|
+
const outcome = value.aborted === true ? "cancelled" : isRecord8(value.result) ? "succeeded" : "failed";
|
|
18172
18664
|
const event = {
|
|
18173
18665
|
type: "compaction.completed",
|
|
18174
18666
|
outcome,
|
|
@@ -18201,12 +18693,12 @@ var OmpRpcSession = class {
|
|
|
18201
18693
|
this.#startAssistantMessage(active, value.message);
|
|
18202
18694
|
return;
|
|
18203
18695
|
}
|
|
18204
|
-
if (value.type === "message_update" &&
|
|
18696
|
+
if (value.type === "message_update" && isRecord8(value.assistantMessageEvent)) {
|
|
18205
18697
|
const event = value.assistantMessageEvent;
|
|
18206
18698
|
const eventType = String(event.type ?? "");
|
|
18207
18699
|
const isThinking = eventType === "thinking_delta" || eventType === "reasoning_delta" || eventType === "thought_delta" || eventType === "thinking" || eventType === "reasoning";
|
|
18208
18700
|
const isText = eventType === "text_delta" || eventType === "text" || eventType === "content_block_delta";
|
|
18209
|
-
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 :
|
|
18701
|
+
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;
|
|
18210
18702
|
if (isThinking && delta !== null && delta.length > 0) {
|
|
18211
18703
|
const messageId = this.#ensureAssistantMessage(active, value.message);
|
|
18212
18704
|
active.reasoningMessageOpen = true;
|
|
@@ -18246,7 +18738,7 @@ var OmpRpcSession = class {
|
|
|
18246
18738
|
if (value.type === "agent_end" && Array.isArray(value.messages)) {
|
|
18247
18739
|
for (let index = value.messages.length - 1; index >= 0; index -= 1) {
|
|
18248
18740
|
const message3 = value.messages[index];
|
|
18249
|
-
if (!
|
|
18741
|
+
if (!isRecord8(message3) || message3.role !== "assistant")
|
|
18250
18742
|
continue;
|
|
18251
18743
|
this.#finalizeAssistantMessage(active, message3);
|
|
18252
18744
|
break;
|
|
@@ -18263,8 +18755,8 @@ var OmpRpcSession = class {
|
|
|
18263
18755
|
if (value.type !== "subagent_lifecycle" && value.type !== "subagent_progress" && value.type !== "subagent_event") {
|
|
18264
18756
|
return false;
|
|
18265
18757
|
}
|
|
18266
|
-
const payload =
|
|
18267
|
-
const progressPayload = value.type === "subagent_progress" && payload &&
|
|
18758
|
+
const payload = isRecord8(value.payload) ? value.payload : null;
|
|
18759
|
+
const progressPayload = value.type === "subagent_progress" && payload && isRecord8(payload.progress) ? payload.progress : null;
|
|
18268
18760
|
const nativeIdValue = progressPayload?.id ?? payload?.id;
|
|
18269
18761
|
if (!payload || !nonBlankString(nativeIdValue)) {
|
|
18270
18762
|
throw new OmpRpcFaultError("protocolError", "Omp RPC Subagent frame has no stable ID");
|
|
@@ -18681,6 +19173,8 @@ var OmpRpcSession = class {
|
|
|
18681
19173
|
if (this.#closed || this.#failed)
|
|
18682
19174
|
return;
|
|
18683
19175
|
this.#failed = true;
|
|
19176
|
+
this.#startupFaultResolve?.(error51);
|
|
19177
|
+
this.#startupFaultResolve = null;
|
|
18684
19178
|
this.#rejectAll(error51);
|
|
18685
19179
|
this.#options.onFault?.(error51);
|
|
18686
19180
|
}
|
|
@@ -18841,7 +19335,7 @@ var ompCommandCatalog = harnessCommandCatalogSchema.parse({
|
|
|
18841
19335
|
]
|
|
18842
19336
|
});
|
|
18843
19337
|
var DEFAULT_TOOL_OUTPUT_LIMIT = 64e3;
|
|
18844
|
-
function
|
|
19338
|
+
function isRecord9(value) {
|
|
18845
19339
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18846
19340
|
}
|
|
18847
19341
|
function errorMessage(error51) {
|
|
@@ -18856,7 +19350,7 @@ var OmpAdapterFaultError = class extends Error {
|
|
|
18856
19350
|
}
|
|
18857
19351
|
};
|
|
18858
19352
|
function normalizedError(error51, fallbackCode) {
|
|
18859
|
-
if (
|
|
19353
|
+
if (isRecord9(error51) && error51.code === "ENOENT") {
|
|
18860
19354
|
return { code: "notInstalled", message: errorMessage(error51), retryable: false };
|
|
18861
19355
|
}
|
|
18862
19356
|
if (error51 instanceof OmpAdapterFaultError)
|
|
@@ -18933,7 +19427,7 @@ function nativeModelForHistory(state) {
|
|
|
18933
19427
|
return nativeModelFromState(state);
|
|
18934
19428
|
}
|
|
18935
19429
|
function sessionFileFromRef(ref) {
|
|
18936
|
-
if (ref.harnessId !== ompHarnessId2 || !
|
|
19430
|
+
if (ref.harnessId !== ompHarnessId2 || !isRecord9(ref.locator) || typeof ref.locator.sessionFile !== "string" || ref.locator.sessionFile.length === 0) {
|
|
18937
19431
|
throw new Error("Omp Native Session Ref has no resumable Session file");
|
|
18938
19432
|
}
|
|
18939
19433
|
return ref.locator.sessionFile;
|
|
@@ -18943,7 +19437,7 @@ function subagentTranscriptPath(parentSessionFile, nativeSubagentId) {
|
|
|
18943
19437
|
if (nativeSubagentId.includes("/") || nativeSubagentId.includes("\\") || nativeSubagentId.includes("\0") || nativeSubagentId === "." || nativeSubagentId === "..") {
|
|
18944
19438
|
throw new Error("Omp Subagent ID is not a plain transcript file name");
|
|
18945
19439
|
}
|
|
18946
|
-
if (!parentSessionFile.endsWith(".jsonl") || !
|
|
19440
|
+
if (!parentSessionFile.endsWith(".jsonl") || !path6.isAbsolute(parentSessionFile)) {
|
|
18947
19441
|
return null;
|
|
18948
19442
|
}
|
|
18949
19443
|
return `${parentSessionFile.slice(0, -".jsonl".length)}/${nativeSubagentId}.jsonl`;
|
|
@@ -18952,10 +19446,10 @@ async function readSubagentTranscriptFile(parentSessionFile, nativeSubagentId) {
|
|
|
18952
19446
|
const transcriptFile = subagentTranscriptPath(parentSessionFile, nativeSubagentId);
|
|
18953
19447
|
if (transcriptFile === null)
|
|
18954
19448
|
return { status: "missing" };
|
|
18955
|
-
const parentDirectory =
|
|
19449
|
+
const parentDirectory = path6.dirname(transcriptFile);
|
|
18956
19450
|
let metadata;
|
|
18957
19451
|
try {
|
|
18958
|
-
metadata = await
|
|
19452
|
+
metadata = await stat2(transcriptFile);
|
|
18959
19453
|
} catch (error51) {
|
|
18960
19454
|
if (error51.code === "ENOENT")
|
|
18961
19455
|
return { status: "missing" };
|
|
@@ -18967,10 +19461,10 @@ async function readSubagentTranscriptFile(parentSessionFile, nativeSubagentId) {
|
|
|
18967
19461
|
throw new Error("Omp Subagent transcript exceeds the supported size");
|
|
18968
19462
|
}
|
|
18969
19463
|
const [resolvedTranscript, resolvedParentDirectory] = await Promise.all([
|
|
18970
|
-
|
|
18971
|
-
|
|
19464
|
+
realpath3(transcriptFile),
|
|
19465
|
+
realpath3(parentDirectory)
|
|
18972
19466
|
]);
|
|
18973
|
-
if (
|
|
19467
|
+
if (path6.dirname(resolvedTranscript) !== resolvedParentDirectory) {
|
|
18974
19468
|
throw new Error("Omp Subagent transcript resolves outside its parent Session directory");
|
|
18975
19469
|
}
|
|
18976
19470
|
return {
|
|
@@ -18988,9 +19482,9 @@ function toolFailure(toolName) {
|
|
|
18988
19482
|
function nativeText(value) {
|
|
18989
19483
|
if (typeof value === "string")
|
|
18990
19484
|
return value;
|
|
18991
|
-
if (!
|
|
19485
|
+
if (!isRecord9(value) || !Array.isArray(value.content))
|
|
18992
19486
|
return "";
|
|
18993
|
-
return value.content.filter((content) =>
|
|
19487
|
+
return value.content.filter((content) => isRecord9(content) && content.type === "text" && typeof content.text === "string").map(({ text }) => text).join("");
|
|
18994
19488
|
}
|
|
18995
19489
|
function boundedOutput(value, limit) {
|
|
18996
19490
|
const text = nativeText(value);
|
|
@@ -19006,17 +19500,17 @@ function outputText(output) {
|
|
|
19006
19500
|
return output?.content.filter((content) => content.type === "text").map(({ text }) => text).join("") ?? "";
|
|
19007
19501
|
}
|
|
19008
19502
|
function stringField2(value, key) {
|
|
19009
|
-
if (!
|
|
19503
|
+
if (!isRecord9(value))
|
|
19010
19504
|
return void 0;
|
|
19011
19505
|
const field = value[key];
|
|
19012
19506
|
if (typeof field === "string" && field.length > 0)
|
|
19013
19507
|
return field;
|
|
19014
|
-
if (
|
|
19508
|
+
if (isRecord9(value.input)) {
|
|
19015
19509
|
const nested = value.input[key];
|
|
19016
19510
|
if (typeof nested === "string" && nested.length > 0)
|
|
19017
19511
|
return nested;
|
|
19018
19512
|
}
|
|
19019
|
-
if (
|
|
19513
|
+
if (isRecord9(value.arguments)) {
|
|
19020
19514
|
const nested = value.arguments[key];
|
|
19021
19515
|
if (typeof nested === "string" && nested.length > 0)
|
|
19022
19516
|
return nested;
|
|
@@ -19024,7 +19518,7 @@ function stringField2(value, key) {
|
|
|
19024
19518
|
return void 0;
|
|
19025
19519
|
}
|
|
19026
19520
|
function numberField(value, key) {
|
|
19027
|
-
if (!
|
|
19521
|
+
if (!isRecord9(value))
|
|
19028
19522
|
return void 0;
|
|
19029
19523
|
const field = value[key];
|
|
19030
19524
|
return typeof field === "number" || field === null ? field : void 0;
|
|
@@ -19035,10 +19529,10 @@ function stripDiffPrefix(pathString) {
|
|
|
19035
19529
|
return pathString.startsWith("a/") || pathString.startsWith("b/") ? pathString.slice(2) : pathString;
|
|
19036
19530
|
}
|
|
19037
19531
|
function displayPath(nativePath, cwd) {
|
|
19038
|
-
const resolvedCwd =
|
|
19039
|
-
const resolvedPath =
|
|
19040
|
-
const relative =
|
|
19041
|
-
const inside = relative.length > 0 && relative !== ".." && !relative.startsWith(`..${
|
|
19532
|
+
const resolvedCwd = path6.resolve(cwd);
|
|
19533
|
+
const resolvedPath = path6.isAbsolute(nativePath) ? path6.resolve(nativePath) : path6.resolve(cwd, nativePath);
|
|
19534
|
+
const relative = path6.relative(resolvedCwd, resolvedPath);
|
|
19535
|
+
const inside = relative.length > 0 && relative !== ".." && !relative.startsWith(`..${path6.sep}`);
|
|
19042
19536
|
const selected = inside ? relative : resolvedPath;
|
|
19043
19537
|
const normalized = selected.replaceAll("\\", "/");
|
|
19044
19538
|
if (normalized.length === 0 || normalized === ".")
|
|
@@ -19063,7 +19557,7 @@ function fileMutatingKind(toolName) {
|
|
|
19063
19557
|
return null;
|
|
19064
19558
|
}
|
|
19065
19559
|
function nestedToolString(value, keys) {
|
|
19066
|
-
if (!
|
|
19560
|
+
if (!isRecord9(value))
|
|
19067
19561
|
return void 0;
|
|
19068
19562
|
for (const key of keys) {
|
|
19069
19563
|
const field = value[key];
|
|
@@ -19078,14 +19572,14 @@ function nestedToolString(value, keys) {
|
|
|
19078
19572
|
return void 0;
|
|
19079
19573
|
}
|
|
19080
19574
|
function patchFromResult(result) {
|
|
19081
|
-
if (!
|
|
19575
|
+
if (!isRecord9(result))
|
|
19082
19576
|
return void 0;
|
|
19083
19577
|
for (const key of ["patch", "diff", "unifiedDiff"]) {
|
|
19084
19578
|
const field = result[key];
|
|
19085
19579
|
if (typeof field === "string" && field.length > 0)
|
|
19086
19580
|
return field;
|
|
19087
19581
|
}
|
|
19088
|
-
if (
|
|
19582
|
+
if (isRecord9(result.details)) {
|
|
19089
19583
|
for (const key of ["patch", "diff", "unifiedDiff"]) {
|
|
19090
19584
|
const field = result.details[key];
|
|
19091
19585
|
if (typeof field === "string" && field.length > 0)
|
|
@@ -20567,6 +21061,7 @@ var OmpAdapter = class {
|
|
|
20567
21061
|
commandCatalog = ompCommandCatalog;
|
|
20568
21062
|
liveCommandCatalog = true;
|
|
20569
21063
|
harnessId = ompHarnessId2;
|
|
21064
|
+
sessionImport;
|
|
20570
21065
|
subagents = {
|
|
20571
21066
|
readSnapshot: async (input) => {
|
|
20572
21067
|
if (input.parent.harnessId !== this.harnessId || input.nativeSubagentId.trim().length === 0 || input.cwd.length === 0) {
|
|
@@ -20626,6 +21121,7 @@ var OmpAdapter = class {
|
|
|
20626
21121
|
createTransport: (sessionOptions) => new OmpRpcSession({ ...options, ...sessionOptions })
|
|
20627
21122
|
}) {
|
|
20628
21123
|
this.#createTransport = dependencies.createTransport;
|
|
21124
|
+
this.sessionImport = new OmpSessionImport({ ...process.env, ...options.environment });
|
|
20629
21125
|
this.#closeTimeoutMs = options.closeTimeoutMs ?? 2e3;
|
|
20630
21126
|
this.#toolOutputLimit = options.toolOutputLimit ?? DEFAULT_TOOL_OUTPUT_LIMIT;
|
|
20631
21127
|
}
|
|
@@ -20697,7 +21193,11 @@ var OmpAdapter = class {
|
|
|
20697
21193
|
};
|
|
20698
21194
|
} catch (error51) {
|
|
20699
21195
|
await transport.close().catch(() => void 0);
|
|
20700
|
-
const normalized =
|
|
21196
|
+
const normalized = stage === "startup" && /No models available\.\s*Use \/login or set an API key environment variable\./i.test(transport.stderrTail ?? "") ? {
|
|
21197
|
+
code: "configurationRequired",
|
|
21198
|
+
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.",
|
|
21199
|
+
retryable: false
|
|
21200
|
+
} : normalizedError(error51, "unavailable");
|
|
20701
21201
|
return {
|
|
20702
21202
|
status: normalized.code === "notInstalled" ? "notInstalled" : "error",
|
|
20703
21203
|
error: {
|
|
@@ -20887,6 +21387,7 @@ var OmpAdapter = class {
|
|
|
20887
21387
|
close() {
|
|
20888
21388
|
if (!this.#closePromise) {
|
|
20889
21389
|
this.#closePromise = Promise.all([
|
|
21390
|
+
this.sessionImport.close(),
|
|
20890
21391
|
...[...this.#inspections].map((transport) => transport.close()),
|
|
20891
21392
|
...[...this.#sessions].map((session) => session.close())
|
|
20892
21393
|
]).then(() => void 0);
|
|
@@ -20896,22 +21397,22 @@ var OmpAdapter = class {
|
|
|
20896
21397
|
};
|
|
20897
21398
|
|
|
20898
21399
|
// dist/installation.js
|
|
20899
|
-
import { realpath as
|
|
20900
|
-
import
|
|
21400
|
+
import { realpath as realpath4 } from "node:fs/promises";
|
|
21401
|
+
import path7 from "node:path";
|
|
20901
21402
|
function createOmpInstallation(environment, command) {
|
|
20902
21403
|
let executable;
|
|
20903
21404
|
let env;
|
|
20904
21405
|
return createInstallationManager({
|
|
20905
21406
|
async check() {
|
|
20906
21407
|
executable = resolveOmpExecutable({ environment, ...command ? { command } : {} });
|
|
20907
|
-
const selected = await
|
|
21408
|
+
const selected = await realpath4(executable);
|
|
20908
21409
|
const pathKey = Object.keys(environment).find((key) => key.toLowerCase() === "path") ?? "PATH";
|
|
20909
21410
|
env = {
|
|
20910
21411
|
...environment,
|
|
20911
|
-
[pathKey]: `${
|
|
21412
|
+
[pathKey]: `${path7.dirname(executable)}${path7.delimiter}${environment[pathKey] ?? ""}`
|
|
20912
21413
|
};
|
|
20913
21414
|
const target = resolveHarnessExecutable({ id: "omp", command: "omp", installRoots: { posix: [], windows: [] } }, { environment: env });
|
|
20914
|
-
const canUpdate = !selected.includes("/nix/store/") && !!target && await
|
|
21415
|
+
const canUpdate = !selected.includes("/nix/store/") && !!target && await realpath4(target.executable) === selected;
|
|
20915
21416
|
const output = await runInstallationCommand(executable, ["update", "--check"], env);
|
|
20916
21417
|
const currentVersion = versionFromOutput(output);
|
|
20917
21418
|
const available = output.match(/New version available:\s*(\S+)/i);
|
|
@@ -20923,7 +21424,10 @@ function createOmpInstallation(environment, command) {
|
|
|
20923
21424
|
latestVersion,
|
|
20924
21425
|
updateAvailable: newerInstallationVersion(currentVersion, latestVersion),
|
|
20925
21426
|
canUpdate,
|
|
20926
|
-
...!canUpdate ? {
|
|
21427
|
+
...!canUpdate ? {
|
|
21428
|
+
messageCode: "original-installer",
|
|
21429
|
+
message: "Update this installation with its original package manager or launcher."
|
|
21430
|
+
} : {}
|
|
20927
21431
|
};
|
|
20928
21432
|
},
|
|
20929
21433
|
async update() {
|
|
@@ -20939,7 +21443,14 @@ function createHarnessAdapter(context) {
|
|
|
20939
21443
|
return Object.assign(new OmpAdapter({
|
|
20940
21444
|
...environment[OMP_COMMAND_ENV] ? { command: environment[OMP_COMMAND_ENV] } : {},
|
|
20941
21445
|
environment
|
|
20942
|
-
}), {
|
|
21446
|
+
}), {
|
|
21447
|
+
installation: createOmpInstallation(environment, environment[OMP_COMMAND_ENV]),
|
|
21448
|
+
install: createHarnessInstaller(environment, {
|
|
21449
|
+
posix: "https://omp.sh/install",
|
|
21450
|
+
windows: "https://omp.sh/install.ps1",
|
|
21451
|
+
shell: "sh"
|
|
21452
|
+
})
|
|
21453
|
+
});
|
|
20943
21454
|
}
|
|
20944
21455
|
export {
|
|
20945
21456
|
OMP_COMMAND_ENV,
|