@codexhost/cli-darwin-x64 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/app/codexhost-distribution.json +1 -1
- package/app/console-server.mjs +44 -2
- package/app/console-web.js +2216 -492
- package/app/desktop-controller.mjs +391 -189
- package/app/host-runtime.mjs +3917 -625
- package/app/plugins/antigravity/plugin.mjs +15634 -15526
- package/app/plugins/claude-code/plugin.mjs +215 -70
- package/app/plugins/codebuddy/plugin.mjs +1260 -827
- package/app/plugins/cursor-cli/plugin.mjs +529 -370
- package/app/plugins/deepseek-harness/plugin.mjs +25467 -26242
- package/app/plugins/enabled.json +2 -1
- package/app/plugins/grok/plugin.mjs +936 -505
- package/app/plugins/hermes/plugin.mjs +18659 -23012
- package/app/plugins/kimi-code/plugin.mjs +1046 -703
- package/app/plugins/kiro-cli/plugin.mjs +959 -590
- package/app/plugins/omp/plugin.mjs +1038 -576
- package/app/plugins/opencode/plugin.mjs +961 -700
- package/app/plugins/pi/plugin.mjs +15911 -15724
- package/app/plugins/qoder/plugin.mjs +679 -375
- package/app/plugins/qoder-cn/plugin.mjs +345 -39
- package/app/plugins/workbuddy/plugin.mjs +417 -40
- package/app/plugins/zcode/assets/icon.svg +8 -0
- package/app/plugins/zcode/manifest.json +14 -0
- package/app/plugins/zcode/plugin.mjs +19202 -0
- package/app/renderer-extension.js +2495 -486
- 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,488 @@ var __export = (target, all) => {
|
|
|
5
5
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
+
// ../../harness-discovery/dist/environment.js
|
|
9
|
+
import fs from "node:fs";
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
function targetPath(platform) {
|
|
12
|
+
return platform === "win32" ? path.win32 : path.posix;
|
|
13
|
+
}
|
|
14
|
+
function environmentValue(environment, name) {
|
|
15
|
+
const lowered = name.toLowerCase();
|
|
16
|
+
for (const [key, value] of Object.entries(environment)) {
|
|
17
|
+
if (key.toLowerCase() === lowered)
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
return void 0;
|
|
21
|
+
}
|
|
22
|
+
function pathDelimiter(platform) {
|
|
23
|
+
return platform === "win32" ? ";" : ":";
|
|
24
|
+
}
|
|
25
|
+
function pathDirectories(environment, platform) {
|
|
26
|
+
return (environmentValue(environment, "PATH") ?? "").split(pathDelimiter(platform)).map((directory) => directory.trim().replace(/^"|"$/gu, "")).filter(Boolean);
|
|
27
|
+
}
|
|
28
|
+
function executableExtensions(command, platform, environment) {
|
|
29
|
+
if (platform !== "win32")
|
|
30
|
+
return [""];
|
|
31
|
+
if (targetPath(platform).extname(command) !== "")
|
|
32
|
+
return [""];
|
|
33
|
+
return (environmentValue(environment, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter(Boolean);
|
|
34
|
+
}
|
|
35
|
+
function isExecutableFile(filePath, platform) {
|
|
36
|
+
try {
|
|
37
|
+
fs.accessSync(filePath, platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK);
|
|
38
|
+
return fs.statSync(filePath).isFile();
|
|
39
|
+
} catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function subdirectoryNames(directory) {
|
|
44
|
+
try {
|
|
45
|
+
return fs.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
46
|
+
} catch {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function newestFirst(names) {
|
|
51
|
+
return [...names].sort((left, right) => right.localeCompare(left, void 0, { numeric: true }));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ../../harness-discovery/dist/invocation.js
|
|
55
|
+
import path2 from "node:path";
|
|
56
|
+
function commandInvocation(command, arguments_, environment, platform = process.platform) {
|
|
57
|
+
const extension = path2.win32.extname(command).toLowerCase();
|
|
58
|
+
if (platform !== "win32" || ![".cmd", ".bat"].includes(extension)) {
|
|
59
|
+
return { command, arguments: [...arguments_], windowsVerbatimArguments: false };
|
|
60
|
+
}
|
|
61
|
+
const quote = (value) => `"${value.replaceAll("%", "%%").replaceAll('"', '""')}"`;
|
|
62
|
+
const commandLine = [command, ...arguments_].map(quote).join(" ");
|
|
63
|
+
return {
|
|
64
|
+
command: environmentValue(environment, "ComSpec") ?? "cmd.exe",
|
|
65
|
+
arguments: ["/d", "/v:off", "/s", "/c", `"${commandLine}"`],
|
|
66
|
+
windowsVerbatimArguments: true
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ../../harness-discovery/dist/node-runtime.js
|
|
71
|
+
import path3 from "node:path";
|
|
72
|
+
function withNodeRuntimeOnPath(environment, runtimeExecutable = process.execPath, platform = process.platform) {
|
|
73
|
+
const pathKey = Object.keys(environment).find((name) => name.toLowerCase() === "path") ?? "PATH";
|
|
74
|
+
const delimiter = platform === "win32" ? ";" : ":";
|
|
75
|
+
const runtimeDirectory = path3.dirname(runtimeExecutable);
|
|
76
|
+
const directories = (environment[pathKey] ?? "").split(delimiter).filter(Boolean);
|
|
77
|
+
const equal = platform === "win32" ? (value) => value.toLowerCase() : (value) => value;
|
|
78
|
+
if (!directories.some((directory) => equal(directory) === equal(runtimeDirectory))) {
|
|
79
|
+
directories.push(runtimeDirectory);
|
|
80
|
+
}
|
|
81
|
+
return { ...environment, [pathKey]: directories.join(delimiter) };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ../../harness-discovery/dist/resolve.js
|
|
85
|
+
import os from "node:os";
|
|
86
|
+
|
|
87
|
+
// ../../harness-discovery/dist/version-managers.js
|
|
88
|
+
function versionManagerBinaryDirectories(context) {
|
|
89
|
+
const { platform, environment, home } = context;
|
|
90
|
+
const list = context.subdirectories ?? subdirectoryNames;
|
|
91
|
+
const pathFlavor = targetPath(platform);
|
|
92
|
+
const value = (name) => environmentValue(environment, name);
|
|
93
|
+
const directories = [];
|
|
94
|
+
const versioned = (root, ...tail) => {
|
|
95
|
+
for (const version2 of newestFirst(list(root))) {
|
|
96
|
+
directories.push(pathFlavor.join(root, version2, ...tail));
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
if (platform === "win32") {
|
|
100
|
+
const appData = value("APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming");
|
|
101
|
+
const localAppData = value("LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local");
|
|
102
|
+
versioned(pathFlavor.join(appData, "nvm"));
|
|
103
|
+
versioned(value("FNM_DIR") ?? pathFlavor.join(appData, "fnm", "node-versions"), "installation");
|
|
104
|
+
directories.push(pathFlavor.join(localAppData, "Volta", "bin"));
|
|
105
|
+
directories.push(pathFlavor.join(home, ".bun", "bin"));
|
|
106
|
+
const pnpmHome2 = value("PNPM_HOME");
|
|
107
|
+
if (pnpmHome2)
|
|
108
|
+
directories.push(pnpmHome2);
|
|
109
|
+
directories.push(pathFlavor.join(localAppData, "pnpm"));
|
|
110
|
+
return directories;
|
|
111
|
+
}
|
|
112
|
+
versioned(pathFlavor.join(value("NVM_DIR") ?? pathFlavor.join(home, ".nvm"), "versions", "node"), "bin");
|
|
113
|
+
const fnmRoots = [
|
|
114
|
+
value("FNM_DIR"),
|
|
115
|
+
pathFlavor.join(home, ".local", "share", "fnm"),
|
|
116
|
+
pathFlavor.join(home, "Library", "Application Support", "fnm")
|
|
117
|
+
].filter((root) => root !== void 0);
|
|
118
|
+
for (const root of fnmRoots) {
|
|
119
|
+
versioned(pathFlavor.join(root, "node-versions"), "installation", "bin");
|
|
120
|
+
}
|
|
121
|
+
const voltaHome = value("VOLTA_HOME") ?? pathFlavor.join(home, ".volta");
|
|
122
|
+
versioned(pathFlavor.join(voltaHome, "tools", "image", "node"), "bin");
|
|
123
|
+
directories.push(pathFlavor.join(voltaHome, "bin"));
|
|
124
|
+
const asdfHome = value("ASDF_DATA_DIR") ?? pathFlavor.join(home, ".asdf");
|
|
125
|
+
versioned(pathFlavor.join(asdfHome, "installs", "nodejs"), "bin");
|
|
126
|
+
directories.push(pathFlavor.join(asdfHome, "shims"));
|
|
127
|
+
const nodenvHome = value("NODENV_ROOT") ?? pathFlavor.join(home, ".nodenv");
|
|
128
|
+
versioned(pathFlavor.join(nodenvHome, "versions"), "bin");
|
|
129
|
+
directories.push(pathFlavor.join(nodenvHome, "shims"));
|
|
130
|
+
versioned(pathFlavor.join(value("N_PREFIX") ?? "/usr/local", "n", "versions", "node"), "bin");
|
|
131
|
+
directories.push(pathFlavor.join(home, ".bun", "bin"));
|
|
132
|
+
const pnpmHome = value("PNPM_HOME");
|
|
133
|
+
if (pnpmHome)
|
|
134
|
+
directories.push(pnpmHome);
|
|
135
|
+
directories.push(pathFlavor.join(home, "Library", "pnpm"));
|
|
136
|
+
directories.push(pathFlavor.join(home, ".local", "share", "pnpm"));
|
|
137
|
+
for (const prefix of ["/opt/homebrew/opt", "/usr/local/opt"]) {
|
|
138
|
+
for (const formula of newestFirst(list(prefix).filter((name) => name.startsWith("node@")))) {
|
|
139
|
+
directories.push(pathFlavor.join(prefix, formula, "bin"));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return directories;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ../../harness-discovery/dist/resolve.js
|
|
146
|
+
var VERSION_MANAGER_ROOTS = "<version-managers>";
|
|
147
|
+
function installRootExtensions(platform) {
|
|
148
|
+
return platform === "win32" ? [".exe", ".cmd"] : [""];
|
|
149
|
+
}
|
|
150
|
+
function resolveHomeDirectory(input) {
|
|
151
|
+
return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
|
|
152
|
+
}
|
|
153
|
+
function templateVariables(environment, platform, home) {
|
|
154
|
+
const pathFlavor = targetPath(platform);
|
|
155
|
+
return {
|
|
156
|
+
HOME: home,
|
|
157
|
+
USERPROFILE: home,
|
|
158
|
+
APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
|
|
159
|
+
LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function joinTemplate(platform, value) {
|
|
163
|
+
const pathFlavor = targetPath(platform);
|
|
164
|
+
const segments = value.split("/");
|
|
165
|
+
const head = segments[0] ?? "";
|
|
166
|
+
const tail = segments.slice(1);
|
|
167
|
+
if (head === "")
|
|
168
|
+
return pathFlavor.join(pathFlavor.sep, ...tail);
|
|
169
|
+
return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
|
|
170
|
+
}
|
|
171
|
+
function expandInstallRoot(template, environment, platform, home) {
|
|
172
|
+
const variables = templateVariables(environment, platform, home);
|
|
173
|
+
let unresolved = false;
|
|
174
|
+
const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
|
|
175
|
+
const value = variables[name] ?? environmentValue(environment, name);
|
|
176
|
+
if (value === void 0 || value === "") {
|
|
177
|
+
unresolved = true;
|
|
178
|
+
return "";
|
|
179
|
+
}
|
|
180
|
+
return value;
|
|
181
|
+
});
|
|
182
|
+
return unresolved ? void 0 : joinTemplate(platform, substituted);
|
|
183
|
+
}
|
|
184
|
+
function installRootDirectories(spec, input, dependencies, platform, home) {
|
|
185
|
+
const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
|
|
186
|
+
const directories = [];
|
|
187
|
+
for (const template of templates) {
|
|
188
|
+
if (template === VERSION_MANAGER_ROOTS) {
|
|
189
|
+
directories.push(...versionManagerBinaryDirectories({
|
|
190
|
+
platform,
|
|
191
|
+
environment: input.environment,
|
|
192
|
+
home,
|
|
193
|
+
...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
|
|
194
|
+
}));
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const directory = expandInstallRoot(template, input.environment, platform, home);
|
|
198
|
+
if (directory !== void 0)
|
|
199
|
+
directories.push(directory);
|
|
200
|
+
}
|
|
201
|
+
return directories;
|
|
202
|
+
}
|
|
203
|
+
function harnessCandidates(spec, input, dependencies = {}) {
|
|
204
|
+
const platform = input.platform ?? process.platform;
|
|
205
|
+
const pathFlavor = targetPath(platform);
|
|
206
|
+
const configured = input.command ?? (spec.commandEnvironmentVariable ? environmentValue(input.environment, spec.commandEnvironmentVariable) : void 0);
|
|
207
|
+
const command = configured ?? spec.command;
|
|
208
|
+
if (pathFlavor.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
|
|
209
|
+
return [{ candidate: command, source: "configured" }];
|
|
210
|
+
}
|
|
211
|
+
const candidates = [];
|
|
212
|
+
const extensions = executableExtensions(command, platform, input.environment);
|
|
213
|
+
for (const directory of pathDirectories(input.environment, platform)) {
|
|
214
|
+
for (const extension of extensions) {
|
|
215
|
+
candidates.push({
|
|
216
|
+
candidate: pathFlavor.join(directory, command + extension),
|
|
217
|
+
source: "path"
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (configured !== void 0)
|
|
222
|
+
return candidates;
|
|
223
|
+
const home = resolveHomeDirectory(input);
|
|
224
|
+
for (const directory of installRootDirectories(spec, input, dependencies, platform, home)) {
|
|
225
|
+
for (const extension of installRootExtensions(platform)) {
|
|
226
|
+
candidates.push({
|
|
227
|
+
candidate: pathFlavor.join(directory, spec.command + extension),
|
|
228
|
+
source: "install-root"
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return candidates;
|
|
233
|
+
}
|
|
234
|
+
function resolveHarnessExecutable(spec, input, dependencies = {}) {
|
|
235
|
+
const platform = input.platform ?? process.platform;
|
|
236
|
+
const isExecutable = dependencies.isExecutable ?? ((candidate) => isExecutableFile(candidate, platform));
|
|
237
|
+
const runnable = spec.runnableCandidate ?? ((candidate) => candidate);
|
|
238
|
+
const context = { platform, isExecutable };
|
|
239
|
+
for (const { candidate, source } of harnessCandidates(spec, input, dependencies)) {
|
|
240
|
+
const executable = runnable(candidate, context);
|
|
241
|
+
if (executable !== void 0 && isExecutable(executable))
|
|
242
|
+
return { executable, source };
|
|
243
|
+
}
|
|
244
|
+
return void 0;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// ../../harness-discovery/dist/installation.js
|
|
248
|
+
import { execFile } from "node:child_process";
|
|
249
|
+
import { homedir } from "node:os";
|
|
250
|
+
function runInstallationCommand(command, args, environment, timeout = 3e4) {
|
|
251
|
+
const env = withNodeRuntimeOnPath(environment);
|
|
252
|
+
const invocation = /\.[cm]?js$/i.test(command) ? commandInvocation(process.execPath, [command, ...args], env) : commandInvocation(command, args, env);
|
|
253
|
+
return new Promise((resolve, reject) => {
|
|
254
|
+
const child = execFile(invocation.command, invocation.arguments, {
|
|
255
|
+
env,
|
|
256
|
+
cwd: env.HOME ?? env.USERPROFILE ?? homedir(),
|
|
257
|
+
encoding: "utf8",
|
|
258
|
+
timeout,
|
|
259
|
+
killSignal: "SIGKILL",
|
|
260
|
+
maxBuffer: 1024 * 1024,
|
|
261
|
+
windowsHide: true,
|
|
262
|
+
windowsVerbatimArguments: invocation.windowsVerbatimArguments
|
|
263
|
+
}, (error51, stdout, stderr) => {
|
|
264
|
+
if (error51)
|
|
265
|
+
reject(new Error(error51.killed ? "Harness command timed out" : "Harness command failed; check the native installation and retry"));
|
|
266
|
+
else
|
|
267
|
+
resolve((stdout || stderr).trim());
|
|
268
|
+
});
|
|
269
|
+
child.stdin?.end();
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
function installationVersion(value) {
|
|
273
|
+
if (typeof value !== "string" || !/^v?\d+(?:\.\d+){1,3}(?:-[\w.-]+)?(?:\+[\w.-]+)?$/.test(value.trim()))
|
|
274
|
+
throw new Error("Harness returned an invalid version");
|
|
275
|
+
return value.trim().replace(/^v/, "");
|
|
276
|
+
}
|
|
277
|
+
function versionFromOutput(output) {
|
|
278
|
+
return installationVersion(output.match(/\b\d+(?:\.\d+){1,3}(?:-[\w.-]+)?(?:\+[\w.-]+)?\b/)?.[0]);
|
|
279
|
+
}
|
|
280
|
+
function newerInstallationVersion(current, latest) {
|
|
281
|
+
const a = installationVersion(current).replace(/\+.*/, "");
|
|
282
|
+
const b = installationVersion(latest).replace(/\+.*/, "");
|
|
283
|
+
const coreA = a.replace(/-.*/, "").split(".").map(BigInt);
|
|
284
|
+
const coreB = b.replace(/-.*/, "").split(".").map(BigInt);
|
|
285
|
+
for (let i = 0; i < Math.max(coreA.length, coreB.length); i++) {
|
|
286
|
+
if ((coreA[i] ?? 0n) !== (coreB[i] ?? 0n))
|
|
287
|
+
return (coreB[i] ?? 0n) > (coreA[i] ?? 0n);
|
|
288
|
+
}
|
|
289
|
+
const preA = a.includes("-") ? a.slice(a.indexOf("-") + 1).split(".") : [];
|
|
290
|
+
const preB = b.includes("-") ? b.slice(b.indexOf("-") + 1).split(".") : [];
|
|
291
|
+
if (!preA.length || !preB.length)
|
|
292
|
+
return !!preA.length && !preB.length;
|
|
293
|
+
for (let i = 0; i < Math.max(preA.length, preB.length); i++) {
|
|
294
|
+
const x = preA[i];
|
|
295
|
+
const y = preB[i];
|
|
296
|
+
if (x === y)
|
|
297
|
+
continue;
|
|
298
|
+
if (x === void 0 || y === void 0)
|
|
299
|
+
return x === void 0;
|
|
300
|
+
const numericX = /^\d+$/.test(x);
|
|
301
|
+
const numericY = /^\d+$/.test(y);
|
|
302
|
+
if (numericX && numericY) {
|
|
303
|
+
if (BigInt(x) === BigInt(y))
|
|
304
|
+
continue;
|
|
305
|
+
return BigInt(y) > BigInt(x);
|
|
306
|
+
}
|
|
307
|
+
if (numericX !== numericY)
|
|
308
|
+
return numericX;
|
|
309
|
+
return y > x;
|
|
310
|
+
}
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
function createInstallationManager(options) {
|
|
314
|
+
let checking;
|
|
315
|
+
let updating;
|
|
316
|
+
const check2 = () => checking ??= options.check().finally(() => {
|
|
317
|
+
checking = void 0;
|
|
318
|
+
});
|
|
319
|
+
return (action) => {
|
|
320
|
+
if (updating)
|
|
321
|
+
return updating;
|
|
322
|
+
if (action === "check")
|
|
323
|
+
return check2();
|
|
324
|
+
updating = (async () => {
|
|
325
|
+
const before = await check2();
|
|
326
|
+
if (!before.updateAvailable)
|
|
327
|
+
return before;
|
|
328
|
+
if (!before.canUpdate)
|
|
329
|
+
throw new Error(before.message ?? "This installation cannot be updated automatically");
|
|
330
|
+
await options.update(before);
|
|
331
|
+
const after = await check2();
|
|
332
|
+
if (after.currentVersion === before.currentVersion)
|
|
333
|
+
throw new Error("The Harness version did not change; check the native updater and retry");
|
|
334
|
+
return after;
|
|
335
|
+
})().finally(() => {
|
|
336
|
+
updating = void 0;
|
|
337
|
+
});
|
|
338
|
+
return updating;
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
async function fetchInstallationText(url2) {
|
|
342
|
+
const request = async () => {
|
|
343
|
+
const response = await fetch(url2, { signal: AbortSignal.timeout(15e3) });
|
|
344
|
+
if (!response.ok)
|
|
345
|
+
throw new Error("Could not check the latest Harness version");
|
|
346
|
+
return response.text();
|
|
347
|
+
};
|
|
348
|
+
try {
|
|
349
|
+
return await request();
|
|
350
|
+
} catch (error51) {
|
|
351
|
+
if (error51 instanceof DOMException && (error51.name === "AbortError" || error51.name === "TimeoutError"))
|
|
352
|
+
throw error51;
|
|
353
|
+
return request();
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// ../../harness-discovery/dist/npm-installation.js
|
|
358
|
+
import { readFile, realpath } from "node:fs/promises";
|
|
359
|
+
import path4 from "node:path";
|
|
360
|
+
function referencesNpmBin(shim, name, bin) {
|
|
361
|
+
if (bin.includes(".."))
|
|
362
|
+
return false;
|
|
363
|
+
const target = `node_modules/${name}/${bin.replace(/^\.\//, "")}`.toLowerCase();
|
|
364
|
+
const text2 = shim.replaceAll("\\", "/").toLowerCase();
|
|
365
|
+
return text2.includes(`%dp0%/${target}"`) || text2.includes(`%~dp0/${target}"`);
|
|
366
|
+
}
|
|
367
|
+
async function npmInstallation(command, packages, environment) {
|
|
368
|
+
let selected = await realpath(command);
|
|
369
|
+
if (process.platform === "win32" && /\.(cmd|bat)$/i.test(selected)) {
|
|
370
|
+
const shim = (await readFile(selected, "utf8")).replaceAll("\\", "/");
|
|
371
|
+
const root = path4.dirname(selected);
|
|
372
|
+
for (const name of packages) {
|
|
373
|
+
const directory2 = path4.join(root, "node_modules", ...name.split("/"));
|
|
374
|
+
const metadata = await readFile(path4.join(directory2, "package.json"), "utf8").then((text2) => JSON.parse(text2)).catch(() => null);
|
|
375
|
+
const bins = typeof metadata?.bin === "string" ? [metadata.bin] : Object.values(metadata?.bin ?? {});
|
|
376
|
+
const bin = bins.find((entry) => referencesNpmBin(shim, name, entry));
|
|
377
|
+
if (bin) {
|
|
378
|
+
selected = await realpath(path4.join(directory2, bin));
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
let directory = path4.dirname(selected);
|
|
384
|
+
for (let depth = 0; depth < 8; depth++) {
|
|
385
|
+
const metadata = await readFile(path4.join(directory, "package.json"), "utf8").then((text2) => JSON.parse(text2)).catch(() => null);
|
|
386
|
+
if (metadata?.name && packages.includes(metadata.name)) {
|
|
387
|
+
const name = metadata.name;
|
|
388
|
+
const currentVersion = installationVersion(metadata.version);
|
|
389
|
+
const segments = name.split("/");
|
|
390
|
+
let modules = directory;
|
|
391
|
+
for (let index = 0; index < segments.length; index++)
|
|
392
|
+
modules = path4.dirname(modules);
|
|
393
|
+
const prefix = process.platform === "win32" ? path4.dirname(modules) : path4.dirname(path4.dirname(modules));
|
|
394
|
+
const globalRoot = process.platform === "win32" ? path4.join(prefix, "node_modules") : path4.join(prefix, "lib", "node_modules");
|
|
395
|
+
const env = withNodeRuntimeOnPath(environment);
|
|
396
|
+
const npm = resolveHarnessExecutable({ id: "npm", command: "npm", installRoots: { posix: [], windows: [] } }, { environment: env });
|
|
397
|
+
let globalInstall = modules === globalRoot;
|
|
398
|
+
if (process.platform === "win32") {
|
|
399
|
+
const project = (await Promise.all(["package.json", "package-lock.json", "npm-shrinkwrap.json"].map((file2) => readFile(path4.join(prefix, file2), "utf8").then(() => true, (error51) => error51.code !== "ENOENT")))).some(Boolean);
|
|
400
|
+
const bins = typeof metadata.bin === "string" ? { [name.split("/").at(-1) ?? name]: metadata.bin } : metadata.bin ?? {};
|
|
401
|
+
const launchers = await Promise.all(Object.entries(bins).map(async ([bin, entry]) => {
|
|
402
|
+
if (path4.basename(bin) !== bin || entry.includes(".."))
|
|
403
|
+
return false;
|
|
404
|
+
const target = await realpath(path4.join(directory, entry)).catch(() => "");
|
|
405
|
+
if (target.toLowerCase() !== selected.toLowerCase())
|
|
406
|
+
return false;
|
|
407
|
+
const shim = await readFile(path4.join(prefix, `${bin}.cmd`), "utf8").catch(() => "");
|
|
408
|
+
return referencesNpmBin(shim, name, entry);
|
|
409
|
+
}));
|
|
410
|
+
globalInstall = globalInstall && !project && launchers.some(Boolean);
|
|
411
|
+
}
|
|
412
|
+
const canUpdate = globalInstall && !!npm;
|
|
413
|
+
return {
|
|
414
|
+
prefix,
|
|
415
|
+
currentVersion,
|
|
416
|
+
canUpdate,
|
|
417
|
+
latest: async () => {
|
|
418
|
+
const data = JSON.parse(await fetchInstallationText(`https://registry.npmjs.org/${encodeURIComponent(name)}/latest`));
|
|
419
|
+
return installationVersion(data.version);
|
|
420
|
+
},
|
|
421
|
+
update: async (version2) => {
|
|
422
|
+
if (!canUpdate || !npm)
|
|
423
|
+
throw new Error("Use the original package manager to update this installation");
|
|
424
|
+
await runInstallationCommand(npm.executable, ["install", "--global", "--prefix", prefix, `${name}@${installationVersion(version2)}`], env, 3e5);
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
const parent = path4.dirname(directory);
|
|
429
|
+
if (parent === directory)
|
|
430
|
+
break;
|
|
431
|
+
directory = parent;
|
|
432
|
+
}
|
|
433
|
+
return null;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// ../../harness-discovery/dist/installer.js
|
|
437
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
438
|
+
import { tmpdir } from "node:os";
|
|
439
|
+
import { join } from "node:path";
|
|
440
|
+
function createHarnessInstaller(environment, source) {
|
|
441
|
+
return async () => {
|
|
442
|
+
if (!["darwin", "linux", "win32"].includes(process.platform))
|
|
443
|
+
throw new Error("Unsupported installation platform");
|
|
444
|
+
const env = withNodeRuntimeOnPath(environment);
|
|
445
|
+
if ("npm" in source) {
|
|
446
|
+
const npm = resolveHarnessExecutable({
|
|
447
|
+
id: "npm",
|
|
448
|
+
command: "npm",
|
|
449
|
+
installRoots: {
|
|
450
|
+
posix: [
|
|
451
|
+
"~/.npm-global/bin",
|
|
452
|
+
"~/.local/bin",
|
|
453
|
+
VERSION_MANAGER_ROOTS,
|
|
454
|
+
"/opt/homebrew/bin",
|
|
455
|
+
"/usr/local/bin",
|
|
456
|
+
"/usr/bin"
|
|
457
|
+
],
|
|
458
|
+
windows: [
|
|
459
|
+
"${APPDATA}/npm",
|
|
460
|
+
VERSION_MANAGER_ROOTS,
|
|
461
|
+
"${ProgramFiles}/nodejs",
|
|
462
|
+
"${LOCALAPPDATA}/Programs/nodejs"
|
|
463
|
+
]
|
|
464
|
+
}
|
|
465
|
+
}, { environment: env });
|
|
466
|
+
if (!npm)
|
|
467
|
+
throw new Error("Install Node.js and npm first");
|
|
468
|
+
await runInstallationCommand(npm.executable, ["install", "--global", source.npm], {
|
|
469
|
+
...env,
|
|
470
|
+
...source.allowScripts ? { npm_config_allow_scripts: source.allowScripts } : {}
|
|
471
|
+
}, 6e5);
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
const windows = process.platform === "win32";
|
|
475
|
+
const url2 = windows ? source.windows : source.posix;
|
|
476
|
+
if (new URL(url2).protocol !== "https:")
|
|
477
|
+
throw new Error("Installer requires HTTPS");
|
|
478
|
+
const script = await fetchInstallationText(url2);
|
|
479
|
+
const directory = await mkdtemp(join(tmpdir(), "codexhost-installer-"));
|
|
480
|
+
try {
|
|
481
|
+
const file2 = join(directory, windows ? "install.ps1" : "install.sh");
|
|
482
|
+
await writeFile(file2, script, { mode: 384 });
|
|
483
|
+
await runInstallationCommand(windows ? "powershell.exe" : source.shell ?? "bash", windows ? ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", file2] : [file2], env, 6e5);
|
|
484
|
+
} finally {
|
|
485
|
+
await rm(directory, { recursive: true, force: true });
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
|
|
8
490
|
// ../../../node_modules/zod/v4/classic/external.js
|
|
9
491
|
var external_exports = {};
|
|
10
492
|
__export(external_exports, {
|
|
@@ -771,10 +1253,10 @@ function mergeDefs(...defs) {
|
|
|
771
1253
|
function cloneDef(schema) {
|
|
772
1254
|
return mergeDefs(schema._zod.def);
|
|
773
1255
|
}
|
|
774
|
-
function getElementAtPath(obj,
|
|
775
|
-
if (!
|
|
1256
|
+
function getElementAtPath(obj, path10) {
|
|
1257
|
+
if (!path10)
|
|
776
1258
|
return obj;
|
|
777
|
-
return
|
|
1259
|
+
return path10.reduce((acc, key) => acc?.[key], obj);
|
|
778
1260
|
}
|
|
779
1261
|
function promiseAllObject(promisesObj) {
|
|
780
1262
|
const keys = Object.keys(promisesObj);
|
|
@@ -1183,11 +1665,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
1183
1665
|
}
|
|
1184
1666
|
return false;
|
|
1185
1667
|
}
|
|
1186
|
-
function prefixIssues(
|
|
1668
|
+
function prefixIssues(path10, issues) {
|
|
1187
1669
|
return issues.map((iss) => {
|
|
1188
1670
|
var _a3;
|
|
1189
1671
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
1190
|
-
iss.path.unshift(
|
|
1672
|
+
iss.path.unshift(path10);
|
|
1191
1673
|
return iss;
|
|
1192
1674
|
});
|
|
1193
1675
|
}
|
|
@@ -1334,16 +1816,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1334
1816
|
}
|
|
1335
1817
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
1336
1818
|
const fieldErrors = { _errors: [] };
|
|
1337
|
-
const processError = (error52,
|
|
1819
|
+
const processError = (error52, path10 = []) => {
|
|
1338
1820
|
for (const issue2 of error52.issues) {
|
|
1339
1821
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1340
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
1822
|
+
issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
|
|
1341
1823
|
} else if (issue2.code === "invalid_key") {
|
|
1342
|
-
processError({ issues: issue2.issues }, [...
|
|
1824
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
1343
1825
|
} else if (issue2.code === "invalid_element") {
|
|
1344
|
-
processError({ issues: issue2.issues }, [...
|
|
1826
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
1345
1827
|
} else {
|
|
1346
|
-
const fullpath = [...
|
|
1828
|
+
const fullpath = [...path10, ...issue2.path];
|
|
1347
1829
|
if (fullpath.length === 0) {
|
|
1348
1830
|
fieldErrors._errors.push(mapper(issue2));
|
|
1349
1831
|
} else {
|
|
@@ -1370,17 +1852,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1370
1852
|
}
|
|
1371
1853
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
1372
1854
|
const result = { errors: [] };
|
|
1373
|
-
const processError = (error52,
|
|
1855
|
+
const processError = (error52, path10 = []) => {
|
|
1374
1856
|
var _a3, _b;
|
|
1375
1857
|
for (const issue2 of error52.issues) {
|
|
1376
1858
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1377
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
1859
|
+
issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
|
|
1378
1860
|
} else if (issue2.code === "invalid_key") {
|
|
1379
|
-
processError({ issues: issue2.issues }, [...
|
|
1861
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
1380
1862
|
} else if (issue2.code === "invalid_element") {
|
|
1381
|
-
processError({ issues: issue2.issues }, [...
|
|
1863
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
1382
1864
|
} else {
|
|
1383
|
-
const fullpath = [...
|
|
1865
|
+
const fullpath = [...path10, ...issue2.path];
|
|
1384
1866
|
if (fullpath.length === 0) {
|
|
1385
1867
|
result.errors.push(mapper(issue2));
|
|
1386
1868
|
continue;
|
|
@@ -1412,8 +1894,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1412
1894
|
}
|
|
1413
1895
|
function toDotPath(_path) {
|
|
1414
1896
|
const segs = [];
|
|
1415
|
-
const
|
|
1416
|
-
for (const seg of
|
|
1897
|
+
const path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
1898
|
+
for (const seg of path10) {
|
|
1417
1899
|
if (typeof seg === "number")
|
|
1418
1900
|
segs.push(`[${seg}]`);
|
|
1419
1901
|
else if (typeof seg === "symbol")
|
|
@@ -14105,13 +14587,13 @@ function resolveRef(ref, ctx) {
|
|
|
14105
14587
|
if (!ref.startsWith("#")) {
|
|
14106
14588
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
14107
14589
|
}
|
|
14108
|
-
const
|
|
14109
|
-
if (
|
|
14590
|
+
const path10 = ref.slice(1).split("/").filter(Boolean);
|
|
14591
|
+
if (path10.length === 0) {
|
|
14110
14592
|
return ctx.rootSchema;
|
|
14111
14593
|
}
|
|
14112
14594
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
14113
|
-
if (
|
|
14114
|
-
const key =
|
|
14595
|
+
if (path10[0] === defsKey) {
|
|
14596
|
+
const key = path10[1];
|
|
14115
14597
|
if (!key || !ctx.defs[key]) {
|
|
14116
14598
|
throw new Error(`Reference not found: ${ref}`);
|
|
14117
14599
|
}
|
|
@@ -14605,6 +15087,7 @@ var CONSOLE_HOST_METHODS = Object.freeze([
|
|
|
14605
15087
|
"codexhost/harness/display-settings/get",
|
|
14606
15088
|
"codexhost/harness/display-settings/set",
|
|
14607
15089
|
"codexhost/harness/inspect",
|
|
15090
|
+
"codexhost/harness/installation",
|
|
14608
15091
|
"codexhost/harness/launch-settings/get",
|
|
14609
15092
|
"codexhost/harness/launch-settings/set",
|
|
14610
15093
|
"codexhost/harness/web-ui/open",
|
|
@@ -15251,14 +15734,17 @@ var harnessLaunchSettingsSchema = external_exports.object({
|
|
|
15251
15734
|
// ../../shared-contracts/dist/harness-installation.js
|
|
15252
15735
|
var harnessInstallationParamsSchema = external_exports.object({
|
|
15253
15736
|
harnessId: harnessIdSchema,
|
|
15254
|
-
action: external_exports.enum(["check", "update"])
|
|
15737
|
+
action: external_exports.enum(["check", "update", "install"])
|
|
15255
15738
|
}).strict();
|
|
15256
15739
|
var harnessInstallationStateSchema = external_exports.object({
|
|
15257
15740
|
currentVersion: external_exports.string().min(1).max(128),
|
|
15258
15741
|
latestVersion: external_exports.string().min(1).max(128),
|
|
15259
15742
|
updateAvailable: external_exports.boolean(),
|
|
15260
15743
|
canUpdate: external_exports.boolean(),
|
|
15261
|
-
|
|
15744
|
+
// Adapter-owned diagnostic text; UI uses messageCode rather than displaying it verbatim.
|
|
15745
|
+
message: external_exports.string().max(2048).optional(),
|
|
15746
|
+
messageCode: external_exports.string().min(1).max(128).optional(),
|
|
15747
|
+
latestVersionKind: external_exports.enum(["unknown", "tracking-branch"]).optional()
|
|
15262
15748
|
}).strict();
|
|
15263
15749
|
|
|
15264
15750
|
// ../../shared-contracts/dist/codex-accounts.js
|
|
@@ -15560,6 +16046,38 @@ var updateStatusResultSchema = external_exports.strictObject({
|
|
|
15560
16046
|
status: updateStatusSchema.nullable()
|
|
15561
16047
|
});
|
|
15562
16048
|
|
|
16049
|
+
// ../../shared-contracts/dist/remote-runtime.js
|
|
16050
|
+
var remoteUpdatePhaseSchema = external_exports.enum([
|
|
16051
|
+
"idle",
|
|
16052
|
+
"installing",
|
|
16053
|
+
"restarting",
|
|
16054
|
+
"succeeded",
|
|
16055
|
+
"failed"
|
|
16056
|
+
]);
|
|
16057
|
+
var runtimeStatusSchema = external_exports.object({
|
|
16058
|
+
runningVersion: external_exports.string().nullable(),
|
|
16059
|
+
installedVersion: external_exports.string().nullable(),
|
|
16060
|
+
restartRequired: external_exports.boolean(),
|
|
16061
|
+
remote: external_exports.boolean(),
|
|
16062
|
+
updateSupported: external_exports.boolean(),
|
|
16063
|
+
update: external_exports.object({
|
|
16064
|
+
phase: remoteUpdatePhaseSchema,
|
|
16065
|
+
targetVersion: external_exports.string().nullable(),
|
|
16066
|
+
error: external_exports.string().nullable()
|
|
16067
|
+
})
|
|
16068
|
+
});
|
|
16069
|
+
var remoteUpdateParamsSchema = external_exports.object({
|
|
16070
|
+
version: external_exports.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
|
|
16071
|
+
}).strict();
|
|
16072
|
+
var remoteSshSetupParamsSchema = external_exports.object({
|
|
16073
|
+
hostname: external_exports.string().min(1).max(1024).refine((value) => !value.startsWith("-") && !/\s/u.test(value)),
|
|
16074
|
+
port: external_exports.number().int().min(1).max(65535).nullable(),
|
|
16075
|
+
identity: external_exports.string().max(4096).nullable(),
|
|
16076
|
+
action: external_exports.enum(["inspect", "install", "update", "repair"]),
|
|
16077
|
+
version: external_exports.string().regex(/^\d+\.\d+\.\d+$/u).nullable()
|
|
16078
|
+
}).strict();
|
|
16079
|
+
var remoteSshSetupResultSchema = external_exports.object({ state: external_exports.enum(["installed", "not-installed"]) }).strict();
|
|
16080
|
+
|
|
15563
16081
|
// ../../shared-contracts/dist/index.js
|
|
15564
16082
|
var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
|
|
15565
16083
|
|
|
@@ -15980,7 +16498,7 @@ function commandPrompt(command, catalog, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
|
15980
16498
|
}
|
|
15981
16499
|
|
|
15982
16500
|
// dist/codebuddy-adapter.js
|
|
15983
|
-
import { stat as
|
|
16501
|
+
import { stat as stat3 } from "node:fs/promises";
|
|
15984
16502
|
|
|
15985
16503
|
// dist/acp-client.js
|
|
15986
16504
|
import { execFile as execFile2, spawn } from "node:child_process";
|
|
@@ -19781,861 +20299,433 @@ var ClientSideConnection = class {
|
|
|
19781
20299
|
* The request may include `additionalDirectories` to set the complete list of
|
|
19782
20300
|
* additional workspace roots for the loaded session.
|
|
19783
20301
|
*
|
|
19784
|
-
* See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
|
|
19785
|
-
*/
|
|
19786
|
-
loadSession(params) {
|
|
19787
|
-
return this.connection.sendRequest(AGENT_METHODS.session_load, params, emptyObjectResponse);
|
|
19788
|
-
}
|
|
19789
|
-
/**
|
|
19790
|
-
* **UNSTABLE**
|
|
19791
|
-
*
|
|
19792
|
-
* This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
19793
|
-
*
|
|
19794
|
-
* Forks an existing session to create a new independent session.
|
|
19795
|
-
*
|
|
19796
|
-
* Creates a new session based on the context of an existing one, allowing
|
|
19797
|
-
* operations like generating summaries without affecting the original session's history.
|
|
19798
|
-
*
|
|
19799
|
-
* The request may include `additionalDirectories` to set the complete list of
|
|
19800
|
-
* additional workspace roots for the forked session.
|
|
19801
|
-
*
|
|
19802
|
-
* This method is only available if the agent advertises the `session.fork` capability.
|
|
19803
|
-
*
|
|
19804
|
-
* @experimental
|
|
19805
|
-
*/
|
|
19806
|
-
unstable_forkSession(params) {
|
|
19807
|
-
return this.connection.sendRequest(AGENT_METHODS.session_fork, params);
|
|
19808
|
-
}
|
|
19809
|
-
/**
|
|
19810
|
-
* Lists existing sessions from the agent.
|
|
19811
|
-
*
|
|
19812
|
-
* This method is only available if the agent advertises the `listSessions` capability.
|
|
19813
|
-
*
|
|
19814
|
-
* Returns a list of sessions with metadata like session ID, working directory,
|
|
19815
|
-
* title, and last update time. Supports filtering by working directory,
|
|
19816
|
-
* `additionalDirectories`, and cursor-based pagination.
|
|
19817
|
-
*/
|
|
19818
|
-
listSessions(params) {
|
|
19819
|
-
return this.connection.sendRequest(AGENT_METHODS.session_list, params);
|
|
19820
|
-
}
|
|
19821
|
-
/**
|
|
19822
|
-
* Deletes an existing session returned by `session/list`.
|
|
19823
|
-
*
|
|
19824
|
-
* This method is only available if the agent advertises the `sessionCapabilities.delete` capability.
|
|
19825
|
-
*/
|
|
19826
|
-
deleteSession(params) {
|
|
19827
|
-
return this.connection.sendRequest(AGENT_METHODS.session_delete, params, emptyObjectResponse);
|
|
19828
|
-
}
|
|
19829
|
-
/**
|
|
19830
|
-
* Resumes an existing session without returning previous messages.
|
|
19831
|
-
*
|
|
19832
|
-
* This method is only available if the agent advertises the `session.resume` capability.
|
|
19833
|
-
*
|
|
19834
|
-
* The agent should resume the session context, allowing the conversation to continue
|
|
19835
|
-
* without replaying the message history (unlike `session/load`).
|
|
19836
|
-
*
|
|
19837
|
-
* The request may include `additionalDirectories` to set the complete list of
|
|
19838
|
-
* additional workspace roots for the resumed session.
|
|
19839
|
-
*/
|
|
19840
|
-
resumeSession(params) {
|
|
19841
|
-
return this.connection.sendRequest(AGENT_METHODS.session_resume, params);
|
|
19842
|
-
}
|
|
19843
|
-
/**
|
|
19844
|
-
* Closes an active session and frees up any resources associated with it.
|
|
19845
|
-
*
|
|
19846
|
-
* This method is only available if the agent advertises the `session.close` capability.
|
|
19847
|
-
*
|
|
19848
|
-
* The agent must cancel any ongoing work (as if `session/cancel` was called)
|
|
19849
|
-
* and then free up any resources associated with the session.
|
|
19850
|
-
*/
|
|
19851
|
-
closeSession(params) {
|
|
19852
|
-
return this.connection.sendRequest(AGENT_METHODS.session_close, params, emptyObjectResponse);
|
|
19853
|
-
}
|
|
19854
|
-
/**
|
|
19855
|
-
* Sets the operational mode for a session.
|
|
19856
|
-
*
|
|
19857
|
-
* Allows switching between different agent modes (e.g., "ask", "architect", "code")
|
|
19858
|
-
* that affect system prompts, tool availability, and permission behaviors.
|
|
19859
|
-
*
|
|
19860
|
-
* The mode must be one of the modes advertised in `availableModes` during session
|
|
19861
|
-
* creation or loading. Agents may also change modes autonomously and notify the
|
|
19862
|
-
* client via `current_mode_update` notifications.
|
|
19863
|
-
*
|
|
19864
|
-
* This method can be called at any time during a session, whether the Agent is
|
|
19865
|
-
* idle or actively generating a turn.
|
|
19866
|
-
*
|
|
19867
|
-
* See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
|
|
19868
|
-
*/
|
|
19869
|
-
setSessionMode(params) {
|
|
19870
|
-
return this.connection.sendRequest(AGENT_METHODS.session_set_mode, params, emptyObjectResponse);
|
|
19871
|
-
}
|
|
19872
|
-
/**
|
|
19873
|
-
* Set a configuration option for a given session.
|
|
19874
|
-
*
|
|
19875
|
-
* The response contains the full set of configuration options and their current values,
|
|
19876
|
-
* as changing one option may affect the available values or state of other options.
|
|
19877
|
-
*/
|
|
19878
|
-
setSessionConfigOption(params) {
|
|
19879
|
-
return this.connection.sendRequest(AGENT_METHODS.session_set_config_option, params);
|
|
19880
|
-
}
|
|
19881
|
-
/**
|
|
19882
|
-
* Authenticates the client using the specified authentication method.
|
|
19883
|
-
*
|
|
19884
|
-
* Called when the agent requires authentication before allowing session creation.
|
|
19885
|
-
* The client provides the authentication method ID that was advertised during initialization.
|
|
19886
|
-
*
|
|
19887
|
-
* After successful authentication, the client can proceed to create sessions with
|
|
19888
|
-
* `newSession` without receiving an `auth_required` error.
|
|
19889
|
-
*
|
|
19890
|
-
* See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
|
|
19891
|
-
*/
|
|
19892
|
-
authenticate(params) {
|
|
19893
|
-
return this.connection.sendRequest(AGENT_METHODS.authenticate, params, emptyObjectResponse);
|
|
19894
|
-
}
|
|
19895
|
-
/**
|
|
19896
|
-
* **UNSTABLE**
|
|
19897
|
-
*
|
|
19898
|
-
* This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
19899
|
-
*
|
|
19900
|
-
* Lists providers that can be configured by the client.
|
|
19901
|
-
*
|
|
19902
|
-
* This method is only available if the agent advertises the `providers` capability.
|
|
19903
|
-
*
|
|
19904
|
-
* @experimental
|
|
19905
|
-
*/
|
|
19906
|
-
unstable_listProviders(params) {
|
|
19907
|
-
return this.connection.sendRequest(AGENT_METHODS.providers_list, params);
|
|
19908
|
-
}
|
|
19909
|
-
/**
|
|
19910
|
-
* **UNSTABLE**
|
|
19911
|
-
*
|
|
19912
|
-
* This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
19913
|
-
*
|
|
19914
|
-
* Replaces the configuration for a provider.
|
|
19915
|
-
*
|
|
19916
|
-
* This method is only available if the agent advertises the `providers` capability.
|
|
19917
|
-
*
|
|
19918
|
-
* @experimental
|
|
19919
|
-
*/
|
|
19920
|
-
unstable_setProvider(params) {
|
|
19921
|
-
return this.connection.sendRequest(AGENT_METHODS.providers_set, params, emptyObjectResponse);
|
|
19922
|
-
}
|
|
19923
|
-
/**
|
|
19924
|
-
* **UNSTABLE**
|
|
19925
|
-
*
|
|
19926
|
-
* This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
19927
|
-
*
|
|
19928
|
-
* Disables a provider.
|
|
19929
|
-
*
|
|
19930
|
-
* This method is only available if the agent advertises the `providers` capability.
|
|
19931
|
-
*
|
|
19932
|
-
* @experimental
|
|
19933
|
-
*/
|
|
19934
|
-
unstable_disableProvider(params) {
|
|
19935
|
-
return this.connection.sendRequest(AGENT_METHODS.providers_disable, params, emptyObjectResponse);
|
|
19936
|
-
}
|
|
19937
|
-
/**
|
|
19938
|
-
* Logout of the current authentication method.
|
|
19939
|
-
*/
|
|
19940
|
-
logout(params) {
|
|
19941
|
-
return this.connection.sendRequest(AGENT_METHODS.logout, params, emptyObjectResponse);
|
|
19942
|
-
}
|
|
19943
|
-
/**
|
|
19944
|
-
* Processes a user prompt within a session.
|
|
19945
|
-
*
|
|
19946
|
-
* This method handles the whole lifecycle of a prompt:
|
|
19947
|
-
* - Receives user messages with optional context (files, images, etc.)
|
|
19948
|
-
* - Processes the prompt using language models
|
|
19949
|
-
* - Reports language model content and tool calls to the Clients
|
|
19950
|
-
* - Requests permission to run tools
|
|
19951
|
-
* - Executes any requested tool calls
|
|
19952
|
-
* - Returns when the turn is complete with a stop reason
|
|
19953
|
-
*
|
|
19954
|
-
* See protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)
|
|
19955
|
-
*/
|
|
19956
|
-
prompt(params) {
|
|
19957
|
-
return this.connection.sendRequest(AGENT_METHODS.session_prompt, params);
|
|
19958
|
-
}
|
|
19959
|
-
/**
|
|
19960
|
-
* Cancels ongoing operations for a session.
|
|
19961
|
-
*
|
|
19962
|
-
* This is a notification sent by the client to cancel an ongoing prompt turn.
|
|
19963
|
-
*
|
|
19964
|
-
* Upon receiving this notification, the Agent SHOULD:
|
|
19965
|
-
* - Stop all language model requests as soon as possible
|
|
19966
|
-
* - Abort all tool call invocations in progress
|
|
19967
|
-
* - Send any pending `session/update` notifications
|
|
19968
|
-
* - Respond to the original `session/prompt` request with `StopReason::Cancelled`
|
|
19969
|
-
*
|
|
19970
|
-
* See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
|
|
19971
|
-
*/
|
|
19972
|
-
cancel(params) {
|
|
19973
|
-
return this.connection.sendNotification(AGENT_METHODS.session_cancel, params);
|
|
19974
|
-
}
|
|
19975
|
-
/**
|
|
19976
|
-
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
19977
|
-
*
|
|
19978
|
-
* Starts a NES (Next Edit Suggestions) session.
|
|
19979
|
-
*
|
|
19980
|
-
* @experimental
|
|
19981
|
-
*/
|
|
19982
|
-
unstable_startNes(params) {
|
|
19983
|
-
return this.connection.sendRequest(AGENT_METHODS.nes_start, params);
|
|
19984
|
-
}
|
|
19985
|
-
/**
|
|
19986
|
-
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
19987
|
-
*
|
|
19988
|
-
* Sends a NES suggestion request.
|
|
19989
|
-
*
|
|
19990
|
-
* @experimental
|
|
19991
|
-
*/
|
|
19992
|
-
unstable_suggestNes(params) {
|
|
19993
|
-
return this.connection.sendRequest(AGENT_METHODS.nes_suggest, params);
|
|
19994
|
-
}
|
|
19995
|
-
/**
|
|
19996
|
-
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
19997
|
-
*
|
|
19998
|
-
* Closes a NES session.
|
|
19999
|
-
*
|
|
20000
|
-
* @experimental
|
|
20302
|
+
* See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
|
|
20001
20303
|
*/
|
|
20002
|
-
|
|
20003
|
-
return this.connection.sendRequest(AGENT_METHODS.
|
|
20304
|
+
loadSession(params) {
|
|
20305
|
+
return this.connection.sendRequest(AGENT_METHODS.session_load, params, emptyObjectResponse);
|
|
20004
20306
|
}
|
|
20005
20307
|
/**
|
|
20006
|
-
* **UNSTABLE
|
|
20308
|
+
* **UNSTABLE**
|
|
20007
20309
|
*
|
|
20008
|
-
*
|
|
20310
|
+
* This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20009
20311
|
*
|
|
20010
|
-
*
|
|
20011
|
-
*/
|
|
20012
|
-
unstable_didOpenDocument(params) {
|
|
20013
|
-
return this.connection.sendNotification(AGENT_METHODS.document_did_open, params);
|
|
20014
|
-
}
|
|
20015
|
-
/**
|
|
20016
|
-
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20312
|
+
* Forks an existing session to create a new independent session.
|
|
20017
20313
|
*
|
|
20018
|
-
*
|
|
20314
|
+
* Creates a new session based on the context of an existing one, allowing
|
|
20315
|
+
* operations like generating summaries without affecting the original session's history.
|
|
20316
|
+
*
|
|
20317
|
+
* The request may include `additionalDirectories` to set the complete list of
|
|
20318
|
+
* additional workspace roots for the forked session.
|
|
20319
|
+
*
|
|
20320
|
+
* This method is only available if the agent advertises the `session.fork` capability.
|
|
20019
20321
|
*
|
|
20020
20322
|
* @experimental
|
|
20021
20323
|
*/
|
|
20022
|
-
|
|
20023
|
-
return this.connection.
|
|
20324
|
+
unstable_forkSession(params) {
|
|
20325
|
+
return this.connection.sendRequest(AGENT_METHODS.session_fork, params);
|
|
20024
20326
|
}
|
|
20025
20327
|
/**
|
|
20026
|
-
*
|
|
20328
|
+
* Lists existing sessions from the agent.
|
|
20027
20329
|
*
|
|
20028
|
-
*
|
|
20330
|
+
* This method is only available if the agent advertises the `listSessions` capability.
|
|
20029
20331
|
*
|
|
20030
|
-
*
|
|
20332
|
+
* Returns a list of sessions with metadata like session ID, working directory,
|
|
20333
|
+
* title, and last update time. Supports filtering by working directory,
|
|
20334
|
+
* `additionalDirectories`, and cursor-based pagination.
|
|
20031
20335
|
*/
|
|
20032
|
-
|
|
20033
|
-
return this.connection.
|
|
20336
|
+
listSessions(params) {
|
|
20337
|
+
return this.connection.sendRequest(AGENT_METHODS.session_list, params);
|
|
20034
20338
|
}
|
|
20035
20339
|
/**
|
|
20036
|
-
*
|
|
20037
|
-
*
|
|
20038
|
-
* Notifies the agent that a document was saved.
|
|
20340
|
+
* Deletes an existing session returned by `session/list`.
|
|
20039
20341
|
*
|
|
20040
|
-
*
|
|
20342
|
+
* This method is only available if the agent advertises the `sessionCapabilities.delete` capability.
|
|
20041
20343
|
*/
|
|
20042
|
-
|
|
20043
|
-
return this.connection.
|
|
20344
|
+
deleteSession(params) {
|
|
20345
|
+
return this.connection.sendRequest(AGENT_METHODS.session_delete, params, emptyObjectResponse);
|
|
20044
20346
|
}
|
|
20045
20347
|
/**
|
|
20046
|
-
*
|
|
20348
|
+
* Resumes an existing session without returning previous messages.
|
|
20047
20349
|
*
|
|
20048
|
-
*
|
|
20350
|
+
* This method is only available if the agent advertises the `session.resume` capability.
|
|
20049
20351
|
*
|
|
20050
|
-
*
|
|
20352
|
+
* The agent should resume the session context, allowing the conversation to continue
|
|
20353
|
+
* without replaying the message history (unlike `session/load`).
|
|
20354
|
+
*
|
|
20355
|
+
* The request may include `additionalDirectories` to set the complete list of
|
|
20356
|
+
* additional workspace roots for the resumed session.
|
|
20051
20357
|
*/
|
|
20052
|
-
|
|
20053
|
-
return this.connection.
|
|
20358
|
+
resumeSession(params) {
|
|
20359
|
+
return this.connection.sendRequest(AGENT_METHODS.session_resume, params);
|
|
20054
20360
|
}
|
|
20055
20361
|
/**
|
|
20056
|
-
*
|
|
20362
|
+
* Closes an active session and frees up any resources associated with it.
|
|
20057
20363
|
*
|
|
20058
|
-
*
|
|
20364
|
+
* This method is only available if the agent advertises the `session.close` capability.
|
|
20059
20365
|
*
|
|
20060
|
-
*
|
|
20366
|
+
* The agent must cancel any ongoing work (as if `session/cancel` was called)
|
|
20367
|
+
* and then free up any resources associated with the session.
|
|
20061
20368
|
*/
|
|
20062
|
-
|
|
20063
|
-
return this.connection.
|
|
20369
|
+
closeSession(params) {
|
|
20370
|
+
return this.connection.sendRequest(AGENT_METHODS.session_close, params, emptyObjectResponse);
|
|
20064
20371
|
}
|
|
20065
20372
|
/**
|
|
20066
|
-
*
|
|
20373
|
+
* Sets the operational mode for a session.
|
|
20067
20374
|
*
|
|
20068
|
-
*
|
|
20375
|
+
* Allows switching between different agent modes (e.g., "ask", "architect", "code")
|
|
20376
|
+
* that affect system prompts, tool availability, and permission behaviors.
|
|
20069
20377
|
*
|
|
20070
|
-
*
|
|
20378
|
+
* The mode must be one of the modes advertised in `availableModes` during session
|
|
20379
|
+
* creation or loading. Agents may also change modes autonomously and notify the
|
|
20380
|
+
* client via `current_mode_update` notifications.
|
|
20381
|
+
*
|
|
20382
|
+
* This method can be called at any time during a session, whether the Agent is
|
|
20383
|
+
* idle or actively generating a turn.
|
|
20384
|
+
*
|
|
20385
|
+
* See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
|
|
20071
20386
|
*/
|
|
20072
|
-
|
|
20073
|
-
return this.connection.
|
|
20074
|
-
}
|
|
20075
|
-
request(method, params, options) {
|
|
20076
|
-
const spec = agentRequestSpecsByMethod[method];
|
|
20077
|
-
return this.connection.sendRequest(method, params, spec?.mapResponse, options);
|
|
20078
|
-
}
|
|
20079
|
-
notify(method, params) {
|
|
20080
|
-
return this.connection.sendNotification(method, params);
|
|
20387
|
+
setSessionMode(params) {
|
|
20388
|
+
return this.connection.sendRequest(AGENT_METHODS.session_set_mode, params, emptyObjectResponse);
|
|
20081
20389
|
}
|
|
20082
20390
|
/**
|
|
20083
|
-
*
|
|
20391
|
+
* Set a configuration option for a given session.
|
|
20084
20392
|
*
|
|
20085
|
-
*
|
|
20393
|
+
* The response contains the full set of configuration options and their current values,
|
|
20394
|
+
* as changing one option may affect the available values or state of other options.
|
|
20086
20395
|
*/
|
|
20087
|
-
|
|
20088
|
-
return this.
|
|
20396
|
+
setSessionConfigOption(params) {
|
|
20397
|
+
return this.connection.sendRequest(AGENT_METHODS.session_set_config_option, params);
|
|
20089
20398
|
}
|
|
20090
20399
|
/**
|
|
20091
|
-
*
|
|
20400
|
+
* Authenticates the client using the specified authentication method.
|
|
20092
20401
|
*
|
|
20093
|
-
*
|
|
20402
|
+
* Called when the agent requires authentication before allowing session creation.
|
|
20403
|
+
* The client provides the authentication method ID that was advertised during initialization.
|
|
20404
|
+
*
|
|
20405
|
+
* After successful authentication, the client can proceed to create sessions with
|
|
20406
|
+
* `newSession` without receiving an `auth_required` error.
|
|
20407
|
+
*
|
|
20408
|
+
* See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
|
|
20094
20409
|
*/
|
|
20095
|
-
|
|
20096
|
-
return this.
|
|
20410
|
+
authenticate(params) {
|
|
20411
|
+
return this.connection.sendRequest(AGENT_METHODS.authenticate, params, emptyObjectResponse);
|
|
20097
20412
|
}
|
|
20098
20413
|
/**
|
|
20099
|
-
*
|
|
20100
|
-
*
|
|
20101
|
-
* This signal can be used to:
|
|
20102
|
-
* - Listen for connection closure: `connection.signal.addEventListener('abort', () => {...})`
|
|
20103
|
-
* - Check connection status synchronously: `if (connection.signal.aborted) {...}`
|
|
20104
|
-
* - Pass to other APIs (fetch, setTimeout) for automatic cancellation
|
|
20105
|
-
*
|
|
20106
|
-
* The connection closes when the underlying stream ends, either normally or due to an error.
|
|
20414
|
+
* **UNSTABLE**
|
|
20107
20415
|
*
|
|
20108
|
-
*
|
|
20109
|
-
* ```typescript
|
|
20110
|
-
* const connection = new ClientSideConnection(client, stream);
|
|
20416
|
+
* This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20111
20417
|
*
|
|
20112
|
-
*
|
|
20113
|
-
* connection.signal.addEventListener('abort', () => {
|
|
20114
|
-
* console.log('Connection closed - performing cleanup');
|
|
20115
|
-
* });
|
|
20418
|
+
* Lists providers that can be configured by the client.
|
|
20116
20419
|
*
|
|
20117
|
-
*
|
|
20118
|
-
* if (connection.signal.aborted) {
|
|
20119
|
-
* console.log('Connection is already closed');
|
|
20120
|
-
* }
|
|
20420
|
+
* This method is only available if the agent advertises the `providers` capability.
|
|
20121
20421
|
*
|
|
20122
|
-
*
|
|
20123
|
-
* fetch(url, { signal: connection.signal });
|
|
20124
|
-
* ```
|
|
20422
|
+
* @experimental
|
|
20125
20423
|
*/
|
|
20126
|
-
|
|
20127
|
-
return this.connection.
|
|
20424
|
+
unstable_listProviders(params) {
|
|
20425
|
+
return this.connection.sendRequest(AGENT_METHODS.providers_list, params);
|
|
20128
20426
|
}
|
|
20129
20427
|
/**
|
|
20130
|
-
*
|
|
20428
|
+
* **UNSTABLE**
|
|
20131
20429
|
*
|
|
20132
|
-
*
|
|
20133
|
-
* Once closed, the connection cannot send or receive any more messages.
|
|
20430
|
+
* This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20134
20431
|
*
|
|
20135
|
-
*
|
|
20432
|
+
* Replaces the configuration for a provider.
|
|
20136
20433
|
*
|
|
20137
|
-
*
|
|
20138
|
-
*
|
|
20139
|
-
*
|
|
20140
|
-
* await connection.closed;
|
|
20141
|
-
* console.log('Connection closed - performing cleanup');
|
|
20142
|
-
* ```
|
|
20434
|
+
* This method is only available if the agent advertises the `providers` capability.
|
|
20435
|
+
*
|
|
20436
|
+
* @experimental
|
|
20143
20437
|
*/
|
|
20144
|
-
|
|
20145
|
-
return this.connection.
|
|
20146
|
-
}
|
|
20147
|
-
};
|
|
20148
|
-
|
|
20149
|
-
// dist/copy-cleanup.js
|
|
20150
|
-
import { randomBytes } from "node:crypto";
|
|
20151
|
-
import { createInterface } from "node:readline";
|
|
20152
|
-
import { stripVTControlCharacters } from "node:util";
|
|
20153
|
-
import { Readable } from "node:stream";
|
|
20154
|
-
var CodeBuddyCopyCleanup = class {
|
|
20155
|
-
copyId;
|
|
20156
|
-
cwd;
|
|
20157
|
-
password = randomBytes(32).toString("base64url");
|
|
20158
|
-
arguments = [
|
|
20159
|
-
"--acp",
|
|
20160
|
-
"--serve",
|
|
20161
|
-
"--host",
|
|
20162
|
-
"127.0.0.1",
|
|
20163
|
-
"--port",
|
|
20164
|
-
"0",
|
|
20165
|
-
"--auth",
|
|
20166
|
-
"password"
|
|
20167
|
-
];
|
|
20168
|
-
#endpoint;
|
|
20169
|
-
constructor(copyId, cwd) {
|
|
20170
|
-
this.copyId = copyId;
|
|
20171
|
-
this.cwd = cwd;
|
|
20172
|
-
}
|
|
20173
|
-
environment(environment) {
|
|
20174
|
-
return {
|
|
20175
|
-
...environment,
|
|
20176
|
-
CODEBUDDY_GATEWAY_AUTH: "password",
|
|
20177
|
-
CODEBUDDY_GATEWAY_PASSWORD: this.password,
|
|
20178
|
-
CODEBUDDY_GATEWAY_BASE_PATH: ""
|
|
20179
|
-
};
|
|
20180
|
-
}
|
|
20181
|
-
/** Native --serve banners include its password; never pass them to the ACP parser/logs. */
|
|
20182
|
-
protocolOutput(stdout) {
|
|
20183
|
-
return Readable.from(this.#protocolLines(stdout));
|
|
20184
|
-
}
|
|
20185
|
-
async *#protocolLines(stdout) {
|
|
20186
|
-
for await (const line of createInterface({ input: stdout })) {
|
|
20187
|
-
const endpoint = /^\s*Endpoint\s+(http:\/\/127\.0\.0\.1:\d+)\s*$/u.exec(stripVTControlCharacters(line));
|
|
20188
|
-
if (endpoint)
|
|
20189
|
-
this.#endpoint = endpoint[1];
|
|
20190
|
-
if (line.trimStart().startsWith("{"))
|
|
20191
|
-
yield Buffer.from(`${line}
|
|
20192
|
-
`);
|
|
20193
|
-
}
|
|
20194
|
-
}
|
|
20195
|
-
async remove() {
|
|
20196
|
-
if (!this.#endpoint)
|
|
20197
|
-
throw new CodeBuddyError("nativeFailure", `Native cleanup endpoint was not reported; temporary Session ${this.copyId} remains`);
|
|
20198
|
-
const response = await fetch(`${this.#endpoint}/api/v1/sessions/${encodeURIComponent(this.copyId)}?cwd=${encodeURIComponent(this.cwd)}`, {
|
|
20199
|
-
method: "DELETE",
|
|
20200
|
-
headers: { Authorization: `Bearer ${this.password}`, "x-codebuddy-request": "true" },
|
|
20201
|
-
signal: AbortSignal.timeout(5e3),
|
|
20202
|
-
redirect: "error"
|
|
20203
|
-
}).catch(() => {
|
|
20204
|
-
throw new CodeBuddyError("nativeFailure", `Native cleanup request failed; temporary Session ${this.copyId} remains`);
|
|
20205
|
-
});
|
|
20206
|
-
await response.body?.cancel();
|
|
20207
|
-
if (response.status !== 204)
|
|
20208
|
-
throw new CodeBuddyError("nativeFailure", `Native cleanup failed (${response.status}); temporary Session ${this.copyId} remains`);
|
|
20438
|
+
unstable_setProvider(params) {
|
|
20439
|
+
return this.connection.sendRequest(AGENT_METHODS.providers_set, params, emptyObjectResponse);
|
|
20209
20440
|
}
|
|
20210
|
-
|
|
20211
|
-
|
|
20212
|
-
|
|
20213
|
-
|
|
20214
|
-
|
|
20215
|
-
|
|
20216
|
-
|
|
20217
|
-
|
|
20218
|
-
|
|
20219
|
-
|
|
20220
|
-
|
|
20221
|
-
|
|
20222
|
-
|
|
20441
|
+
/**
|
|
20442
|
+
* **UNSTABLE**
|
|
20443
|
+
*
|
|
20444
|
+
* This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20445
|
+
*
|
|
20446
|
+
* Disables a provider.
|
|
20447
|
+
*
|
|
20448
|
+
* This method is only available if the agent advertises the `providers` capability.
|
|
20449
|
+
*
|
|
20450
|
+
* @experimental
|
|
20451
|
+
*/
|
|
20452
|
+
unstable_disableProvider(params) {
|
|
20453
|
+
return this.connection.sendRequest(AGENT_METHODS.providers_disable, params, emptyObjectResponse);
|
|
20223
20454
|
}
|
|
20224
|
-
|
|
20225
|
-
|
|
20226
|
-
|
|
20227
|
-
|
|
20228
|
-
|
|
20229
|
-
function pathDirectories(environment, platform) {
|
|
20230
|
-
return (environmentValue(environment, "PATH") ?? "").split(pathDelimiter(platform)).map((directory) => directory.trim().replace(/^"|"$/gu, "")).filter(Boolean);
|
|
20231
|
-
}
|
|
20232
|
-
function executableExtensions(command, platform, environment) {
|
|
20233
|
-
if (platform !== "win32")
|
|
20234
|
-
return [""];
|
|
20235
|
-
if (targetPath(platform).extname(command) !== "")
|
|
20236
|
-
return [""];
|
|
20237
|
-
return (environmentValue(environment, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter(Boolean);
|
|
20238
|
-
}
|
|
20239
|
-
function isExecutableFile(filePath, platform) {
|
|
20240
|
-
try {
|
|
20241
|
-
fs.accessSync(filePath, platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK);
|
|
20242
|
-
return fs.statSync(filePath).isFile();
|
|
20243
|
-
} catch {
|
|
20244
|
-
return false;
|
|
20455
|
+
/**
|
|
20456
|
+
* Logout of the current authentication method.
|
|
20457
|
+
*/
|
|
20458
|
+
logout(params) {
|
|
20459
|
+
return this.connection.sendRequest(AGENT_METHODS.logout, params, emptyObjectResponse);
|
|
20245
20460
|
}
|
|
20246
|
-
|
|
20247
|
-
|
|
20248
|
-
|
|
20249
|
-
|
|
20250
|
-
|
|
20251
|
-
|
|
20461
|
+
/**
|
|
20462
|
+
* Processes a user prompt within a session.
|
|
20463
|
+
*
|
|
20464
|
+
* This method handles the whole lifecycle of a prompt:
|
|
20465
|
+
* - Receives user messages with optional context (files, images, etc.)
|
|
20466
|
+
* - Processes the prompt using language models
|
|
20467
|
+
* - Reports language model content and tool calls to the Clients
|
|
20468
|
+
* - Requests permission to run tools
|
|
20469
|
+
* - Executes any requested tool calls
|
|
20470
|
+
* - Returns when the turn is complete with a stop reason
|
|
20471
|
+
*
|
|
20472
|
+
* See protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)
|
|
20473
|
+
*/
|
|
20474
|
+
prompt(params) {
|
|
20475
|
+
return this.connection.sendRequest(AGENT_METHODS.session_prompt, params);
|
|
20252
20476
|
}
|
|
20253
|
-
|
|
20254
|
-
|
|
20255
|
-
|
|
20256
|
-
|
|
20257
|
-
|
|
20258
|
-
|
|
20259
|
-
|
|
20260
|
-
|
|
20261
|
-
|
|
20262
|
-
|
|
20263
|
-
|
|
20477
|
+
/**
|
|
20478
|
+
* Cancels ongoing operations for a session.
|
|
20479
|
+
*
|
|
20480
|
+
* This is a notification sent by the client to cancel an ongoing prompt turn.
|
|
20481
|
+
*
|
|
20482
|
+
* Upon receiving this notification, the Agent SHOULD:
|
|
20483
|
+
* - Stop all language model requests as soon as possible
|
|
20484
|
+
* - Abort all tool call invocations in progress
|
|
20485
|
+
* - Send any pending `session/update` notifications
|
|
20486
|
+
* - Respond to the original `session/prompt` request with `StopReason::Cancelled`
|
|
20487
|
+
*
|
|
20488
|
+
* See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
|
|
20489
|
+
*/
|
|
20490
|
+
cancel(params) {
|
|
20491
|
+
return this.connection.sendNotification(AGENT_METHODS.session_cancel, params);
|
|
20264
20492
|
}
|
|
20265
|
-
|
|
20266
|
-
|
|
20267
|
-
|
|
20268
|
-
|
|
20269
|
-
|
|
20270
|
-
|
|
20271
|
-
|
|
20272
|
-
|
|
20273
|
-
|
|
20274
|
-
// ../../harness-discovery/dist/node-runtime.js
|
|
20275
|
-
import path3 from "node:path";
|
|
20276
|
-
function withNodeRuntimeOnPath(environment, runtimeExecutable = process.execPath, platform = process.platform) {
|
|
20277
|
-
const pathKey = Object.keys(environment).find((name) => name.toLowerCase() === "path") ?? "PATH";
|
|
20278
|
-
const delimiter = platform === "win32" ? ";" : ":";
|
|
20279
|
-
const runtimeDirectory = path3.dirname(runtimeExecutable);
|
|
20280
|
-
const directories = (environment[pathKey] ?? "").split(delimiter).filter(Boolean);
|
|
20281
|
-
const equal = platform === "win32" ? (value) => value.toLowerCase() : (value) => value;
|
|
20282
|
-
if (!directories.some((directory) => equal(directory) === equal(runtimeDirectory))) {
|
|
20283
|
-
directories.push(runtimeDirectory);
|
|
20493
|
+
/**
|
|
20494
|
+
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20495
|
+
*
|
|
20496
|
+
* Starts a NES (Next Edit Suggestions) session.
|
|
20497
|
+
*
|
|
20498
|
+
* @experimental
|
|
20499
|
+
*/
|
|
20500
|
+
unstable_startNes(params) {
|
|
20501
|
+
return this.connection.sendRequest(AGENT_METHODS.nes_start, params);
|
|
20284
20502
|
}
|
|
20285
|
-
|
|
20286
|
-
|
|
20287
|
-
|
|
20288
|
-
|
|
20289
|
-
|
|
20290
|
-
|
|
20291
|
-
|
|
20292
|
-
|
|
20293
|
-
|
|
20294
|
-
const list = context.subdirectories ?? subdirectoryNames;
|
|
20295
|
-
const pathFlavor = targetPath(platform);
|
|
20296
|
-
const value = (name) => environmentValue(environment, name);
|
|
20297
|
-
const directories = [];
|
|
20298
|
-
const versioned = (root, ...tail) => {
|
|
20299
|
-
for (const version2 of newestFirst(list(root))) {
|
|
20300
|
-
directories.push(pathFlavor.join(root, version2, ...tail));
|
|
20301
|
-
}
|
|
20302
|
-
};
|
|
20303
|
-
if (platform === "win32") {
|
|
20304
|
-
const appData = value("APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming");
|
|
20305
|
-
const localAppData = value("LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local");
|
|
20306
|
-
versioned(pathFlavor.join(appData, "nvm"));
|
|
20307
|
-
versioned(value("FNM_DIR") ?? pathFlavor.join(appData, "fnm", "node-versions"), "installation");
|
|
20308
|
-
directories.push(pathFlavor.join(localAppData, "Volta", "bin"));
|
|
20309
|
-
directories.push(pathFlavor.join(home, ".bun", "bin"));
|
|
20310
|
-
const pnpmHome2 = value("PNPM_HOME");
|
|
20311
|
-
if (pnpmHome2)
|
|
20312
|
-
directories.push(pnpmHome2);
|
|
20313
|
-
directories.push(pathFlavor.join(localAppData, "pnpm"));
|
|
20314
|
-
return directories;
|
|
20503
|
+
/**
|
|
20504
|
+
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20505
|
+
*
|
|
20506
|
+
* Sends a NES suggestion request.
|
|
20507
|
+
*
|
|
20508
|
+
* @experimental
|
|
20509
|
+
*/
|
|
20510
|
+
unstable_suggestNes(params) {
|
|
20511
|
+
return this.connection.sendRequest(AGENT_METHODS.nes_suggest, params);
|
|
20315
20512
|
}
|
|
20316
|
-
|
|
20317
|
-
|
|
20318
|
-
|
|
20319
|
-
|
|
20320
|
-
|
|
20321
|
-
|
|
20322
|
-
|
|
20323
|
-
|
|
20513
|
+
/**
|
|
20514
|
+
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20515
|
+
*
|
|
20516
|
+
* Closes a NES session.
|
|
20517
|
+
*
|
|
20518
|
+
* @experimental
|
|
20519
|
+
*/
|
|
20520
|
+
unstable_closeNes(params) {
|
|
20521
|
+
return this.connection.sendRequest(AGENT_METHODS.nes_close, params, emptyObjectResponse);
|
|
20324
20522
|
}
|
|
20325
|
-
|
|
20326
|
-
|
|
20327
|
-
|
|
20328
|
-
|
|
20329
|
-
|
|
20330
|
-
|
|
20331
|
-
|
|
20332
|
-
|
|
20333
|
-
|
|
20334
|
-
versioned(pathFlavor.join(value("N_PREFIX") ?? "/usr/local", "n", "versions", "node"), "bin");
|
|
20335
|
-
directories.push(pathFlavor.join(home, ".bun", "bin"));
|
|
20336
|
-
const pnpmHome = value("PNPM_HOME");
|
|
20337
|
-
if (pnpmHome)
|
|
20338
|
-
directories.push(pnpmHome);
|
|
20339
|
-
directories.push(pathFlavor.join(home, "Library", "pnpm"));
|
|
20340
|
-
directories.push(pathFlavor.join(home, ".local", "share", "pnpm"));
|
|
20341
|
-
for (const prefix of ["/opt/homebrew/opt", "/usr/local/opt"]) {
|
|
20342
|
-
for (const formula of newestFirst(list(prefix).filter((name) => name.startsWith("node@")))) {
|
|
20343
|
-
directories.push(pathFlavor.join(prefix, formula, "bin"));
|
|
20344
|
-
}
|
|
20523
|
+
/**
|
|
20524
|
+
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20525
|
+
*
|
|
20526
|
+
* Notifies the agent that a document was opened.
|
|
20527
|
+
*
|
|
20528
|
+
* @experimental
|
|
20529
|
+
*/
|
|
20530
|
+
unstable_didOpenDocument(params) {
|
|
20531
|
+
return this.connection.sendNotification(AGENT_METHODS.document_did_open, params);
|
|
20345
20532
|
}
|
|
20346
|
-
|
|
20347
|
-
|
|
20348
|
-
|
|
20349
|
-
|
|
20350
|
-
|
|
20351
|
-
|
|
20352
|
-
|
|
20353
|
-
|
|
20354
|
-
|
|
20355
|
-
return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
|
|
20356
|
-
}
|
|
20357
|
-
function templateVariables(environment, platform, home) {
|
|
20358
|
-
const pathFlavor = targetPath(platform);
|
|
20359
|
-
return {
|
|
20360
|
-
HOME: home,
|
|
20361
|
-
USERPROFILE: home,
|
|
20362
|
-
APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
|
|
20363
|
-
LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
|
|
20364
|
-
};
|
|
20365
|
-
}
|
|
20366
|
-
function joinTemplate(platform, value) {
|
|
20367
|
-
const pathFlavor = targetPath(platform);
|
|
20368
|
-
const segments = value.split("/");
|
|
20369
|
-
const head = segments[0] ?? "";
|
|
20370
|
-
const tail = segments.slice(1);
|
|
20371
|
-
if (head === "")
|
|
20372
|
-
return pathFlavor.join(pathFlavor.sep, ...tail);
|
|
20373
|
-
return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
|
|
20374
|
-
}
|
|
20375
|
-
function expandInstallRoot(template, environment, platform, home) {
|
|
20376
|
-
const variables = templateVariables(environment, platform, home);
|
|
20377
|
-
let unresolved = false;
|
|
20378
|
-
const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
|
|
20379
|
-
const value = variables[name] ?? environmentValue(environment, name);
|
|
20380
|
-
if (value === void 0 || value === "") {
|
|
20381
|
-
unresolved = true;
|
|
20382
|
-
return "";
|
|
20383
|
-
}
|
|
20384
|
-
return value;
|
|
20385
|
-
});
|
|
20386
|
-
return unresolved ? void 0 : joinTemplate(platform, substituted);
|
|
20387
|
-
}
|
|
20388
|
-
function installRootDirectories(spec, input, dependencies, platform, home) {
|
|
20389
|
-
const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
|
|
20390
|
-
const directories = [];
|
|
20391
|
-
for (const template of templates) {
|
|
20392
|
-
if (template === VERSION_MANAGER_ROOTS) {
|
|
20393
|
-
directories.push(...versionManagerBinaryDirectories({
|
|
20394
|
-
platform,
|
|
20395
|
-
environment: input.environment,
|
|
20396
|
-
home,
|
|
20397
|
-
...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
|
|
20398
|
-
}));
|
|
20399
|
-
continue;
|
|
20400
|
-
}
|
|
20401
|
-
const directory = expandInstallRoot(template, input.environment, platform, home);
|
|
20402
|
-
if (directory !== void 0)
|
|
20403
|
-
directories.push(directory);
|
|
20533
|
+
/**
|
|
20534
|
+
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20535
|
+
*
|
|
20536
|
+
* Notifies the agent that a document was changed.
|
|
20537
|
+
*
|
|
20538
|
+
* @experimental
|
|
20539
|
+
*/
|
|
20540
|
+
unstable_didChangeDocument(params) {
|
|
20541
|
+
return this.connection.sendNotification(AGENT_METHODS.document_did_change, params);
|
|
20404
20542
|
}
|
|
20405
|
-
|
|
20406
|
-
|
|
20407
|
-
|
|
20408
|
-
|
|
20409
|
-
|
|
20410
|
-
|
|
20411
|
-
|
|
20412
|
-
|
|
20413
|
-
return
|
|
20543
|
+
/**
|
|
20544
|
+
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20545
|
+
*
|
|
20546
|
+
* Notifies the agent that a document was closed.
|
|
20547
|
+
*
|
|
20548
|
+
* @experimental
|
|
20549
|
+
*/
|
|
20550
|
+
unstable_didCloseDocument(params) {
|
|
20551
|
+
return this.connection.sendNotification(AGENT_METHODS.document_did_close, params);
|
|
20414
20552
|
}
|
|
20415
|
-
|
|
20416
|
-
|
|
20417
|
-
|
|
20418
|
-
|
|
20419
|
-
|
|
20420
|
-
|
|
20421
|
-
|
|
20422
|
-
|
|
20423
|
-
|
|
20553
|
+
/**
|
|
20554
|
+
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20555
|
+
*
|
|
20556
|
+
* Notifies the agent that a document was saved.
|
|
20557
|
+
*
|
|
20558
|
+
* @experimental
|
|
20559
|
+
*/
|
|
20560
|
+
unstable_didSaveDocument(params) {
|
|
20561
|
+
return this.connection.sendNotification(AGENT_METHODS.document_did_save, params);
|
|
20424
20562
|
}
|
|
20425
|
-
|
|
20426
|
-
|
|
20427
|
-
|
|
20428
|
-
|
|
20429
|
-
|
|
20430
|
-
|
|
20431
|
-
|
|
20432
|
-
|
|
20433
|
-
|
|
20434
|
-
}
|
|
20563
|
+
/**
|
|
20564
|
+
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20565
|
+
*
|
|
20566
|
+
* Notifies the agent that a document received focus.
|
|
20567
|
+
*
|
|
20568
|
+
* @experimental
|
|
20569
|
+
*/
|
|
20570
|
+
unstable_didFocusDocument(params) {
|
|
20571
|
+
return this.connection.sendNotification(AGENT_METHODS.document_did_focus, params);
|
|
20435
20572
|
}
|
|
20436
|
-
|
|
20437
|
-
|
|
20438
|
-
|
|
20439
|
-
|
|
20440
|
-
|
|
20441
|
-
|
|
20442
|
-
|
|
20443
|
-
|
|
20444
|
-
|
|
20445
|
-
if (executable !== void 0 && isExecutable(executable))
|
|
20446
|
-
return { executable, source };
|
|
20573
|
+
/**
|
|
20574
|
+
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20575
|
+
*
|
|
20576
|
+
* Notifies the agent that a NES suggestion was accepted.
|
|
20577
|
+
*
|
|
20578
|
+
* @experimental
|
|
20579
|
+
*/
|
|
20580
|
+
unstable_acceptNes(params) {
|
|
20581
|
+
return this.connection.sendNotification(AGENT_METHODS.nes_accept, params);
|
|
20447
20582
|
}
|
|
20448
|
-
|
|
20449
|
-
|
|
20450
|
-
|
|
20451
|
-
|
|
20452
|
-
|
|
20453
|
-
|
|
20454
|
-
|
|
20455
|
-
|
|
20456
|
-
|
|
20457
|
-
return new Promise((resolve, reject) => {
|
|
20458
|
-
const child = execFile(invocation.command, invocation.arguments, {
|
|
20459
|
-
env,
|
|
20460
|
-
cwd: env.HOME ?? env.USERPROFILE ?? homedir(),
|
|
20461
|
-
encoding: "utf8",
|
|
20462
|
-
timeout,
|
|
20463
|
-
killSignal: "SIGKILL",
|
|
20464
|
-
maxBuffer: 1024 * 1024,
|
|
20465
|
-
windowsHide: true,
|
|
20466
|
-
windowsVerbatimArguments: invocation.windowsVerbatimArguments
|
|
20467
|
-
}, (error51, stdout, stderr) => {
|
|
20468
|
-
if (error51)
|
|
20469
|
-
reject(new Error(error51.killed ? "Harness command timed out" : "Harness command failed; check the native installation and retry"));
|
|
20470
|
-
else
|
|
20471
|
-
resolve((stdout || stderr).trim());
|
|
20472
|
-
});
|
|
20473
|
-
child.stdin?.end();
|
|
20474
|
-
});
|
|
20475
|
-
}
|
|
20476
|
-
function installationVersion(value) {
|
|
20477
|
-
if (typeof value !== "string" || !/^v?\d+(?:\.\d+){1,3}(?:-[\w.-]+)?(?:\+[\w.-]+)?$/.test(value.trim()))
|
|
20478
|
-
throw new Error("Harness returned an invalid version");
|
|
20479
|
-
return value.trim().replace(/^v/, "");
|
|
20480
|
-
}
|
|
20481
|
-
function versionFromOutput(output) {
|
|
20482
|
-
return installationVersion(output.match(/\b\d+(?:\.\d+){1,3}(?:-[\w.-]+)?(?:\+[\w.-]+)?\b/)?.[0]);
|
|
20483
|
-
}
|
|
20484
|
-
function newerInstallationVersion(current, latest) {
|
|
20485
|
-
const a = installationVersion(current).replace(/\+.*/, "");
|
|
20486
|
-
const b = installationVersion(latest).replace(/\+.*/, "");
|
|
20487
|
-
const coreA = a.replace(/-.*/, "").split(".").map(BigInt);
|
|
20488
|
-
const coreB = b.replace(/-.*/, "").split(".").map(BigInt);
|
|
20489
|
-
for (let i = 0; i < Math.max(coreA.length, coreB.length); i++) {
|
|
20490
|
-
if ((coreA[i] ?? 0n) !== (coreB[i] ?? 0n))
|
|
20491
|
-
return (coreB[i] ?? 0n) > (coreA[i] ?? 0n);
|
|
20583
|
+
/**
|
|
20584
|
+
* **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.
|
|
20585
|
+
*
|
|
20586
|
+
* Notifies the agent that a NES suggestion was rejected.
|
|
20587
|
+
*
|
|
20588
|
+
* @experimental
|
|
20589
|
+
*/
|
|
20590
|
+
unstable_rejectNes(params) {
|
|
20591
|
+
return this.connection.sendNotification(AGENT_METHODS.nes_reject, params);
|
|
20492
20592
|
}
|
|
20493
|
-
|
|
20494
|
-
|
|
20495
|
-
|
|
20496
|
-
return !!preA.length && !preB.length;
|
|
20497
|
-
for (let i = 0; i < Math.max(preA.length, preB.length); i++) {
|
|
20498
|
-
const x = preA[i];
|
|
20499
|
-
const y = preB[i];
|
|
20500
|
-
if (x === y)
|
|
20501
|
-
continue;
|
|
20502
|
-
if (x === void 0 || y === void 0)
|
|
20503
|
-
return x === void 0;
|
|
20504
|
-
const numericX = /^\d+$/.test(x);
|
|
20505
|
-
const numericY = /^\d+$/.test(y);
|
|
20506
|
-
if (numericX && numericY) {
|
|
20507
|
-
if (BigInt(x) === BigInt(y))
|
|
20508
|
-
continue;
|
|
20509
|
-
return BigInt(y) > BigInt(x);
|
|
20510
|
-
}
|
|
20511
|
-
if (numericX !== numericY)
|
|
20512
|
-
return numericX;
|
|
20513
|
-
return y > x;
|
|
20593
|
+
request(method, params, options) {
|
|
20594
|
+
const spec = agentRequestSpecsByMethod[method];
|
|
20595
|
+
return this.connection.sendRequest(method, params, spec?.mapResponse, options);
|
|
20514
20596
|
}
|
|
20515
|
-
|
|
20516
|
-
|
|
20517
|
-
|
|
20518
|
-
|
|
20519
|
-
|
|
20520
|
-
|
|
20521
|
-
|
|
20522
|
-
|
|
20523
|
-
|
|
20524
|
-
|
|
20525
|
-
|
|
20526
|
-
|
|
20527
|
-
|
|
20528
|
-
|
|
20529
|
-
|
|
20530
|
-
|
|
20531
|
-
|
|
20532
|
-
|
|
20533
|
-
|
|
20534
|
-
|
|
20535
|
-
|
|
20536
|
-
|
|
20537
|
-
|
|
20538
|
-
|
|
20539
|
-
|
|
20540
|
-
|
|
20541
|
-
|
|
20542
|
-
|
|
20543
|
-
|
|
20544
|
-
|
|
20545
|
-
|
|
20546
|
-
|
|
20547
|
-
|
|
20548
|
-
|
|
20549
|
-
|
|
20550
|
-
|
|
20551
|
-
|
|
20552
|
-
|
|
20553
|
-
|
|
20554
|
-
|
|
20555
|
-
|
|
20556
|
-
|
|
20557
|
-
|
|
20597
|
+
notify(method, params) {
|
|
20598
|
+
return this.connection.sendNotification(method, params);
|
|
20599
|
+
}
|
|
20600
|
+
/**
|
|
20601
|
+
* Extension method.
|
|
20602
|
+
*
|
|
20603
|
+
* @deprecated Use {@link request}.
|
|
20604
|
+
*/
|
|
20605
|
+
extMethod(method, params) {
|
|
20606
|
+
return this.request(method, params);
|
|
20607
|
+
}
|
|
20608
|
+
/**
|
|
20609
|
+
* Extension notification.
|
|
20610
|
+
*
|
|
20611
|
+
* @deprecated Use {@link notify}.
|
|
20612
|
+
*/
|
|
20613
|
+
extNotification(method, params) {
|
|
20614
|
+
return this.notify(method, params);
|
|
20615
|
+
}
|
|
20616
|
+
/**
|
|
20617
|
+
* AbortSignal that aborts when the connection closes.
|
|
20618
|
+
*
|
|
20619
|
+
* This signal can be used to:
|
|
20620
|
+
* - Listen for connection closure: `connection.signal.addEventListener('abort', () => {...})`
|
|
20621
|
+
* - Check connection status synchronously: `if (connection.signal.aborted) {...}`
|
|
20622
|
+
* - Pass to other APIs (fetch, setTimeout) for automatic cancellation
|
|
20623
|
+
*
|
|
20624
|
+
* The connection closes when the underlying stream ends, either normally or due to an error.
|
|
20625
|
+
*
|
|
20626
|
+
* @example
|
|
20627
|
+
* ```typescript
|
|
20628
|
+
* const connection = new ClientSideConnection(client, stream);
|
|
20629
|
+
*
|
|
20630
|
+
* // Listen for closure
|
|
20631
|
+
* connection.signal.addEventListener('abort', () => {
|
|
20632
|
+
* console.log('Connection closed - performing cleanup');
|
|
20633
|
+
* });
|
|
20634
|
+
*
|
|
20635
|
+
* // Check status
|
|
20636
|
+
* if (connection.signal.aborted) {
|
|
20637
|
+
* console.log('Connection is already closed');
|
|
20638
|
+
* }
|
|
20639
|
+
*
|
|
20640
|
+
* // Pass to other APIs
|
|
20641
|
+
* fetch(url, { signal: connection.signal });
|
|
20642
|
+
* ```
|
|
20643
|
+
*/
|
|
20644
|
+
get signal() {
|
|
20645
|
+
return this.connection.signal;
|
|
20646
|
+
}
|
|
20647
|
+
/**
|
|
20648
|
+
* Promise that resolves when the connection closes.
|
|
20649
|
+
*
|
|
20650
|
+
* The connection closes when the underlying stream ends, either normally or due to an error.
|
|
20651
|
+
* Once closed, the connection cannot send or receive any more messages.
|
|
20652
|
+
*
|
|
20653
|
+
* This is useful for async/await style cleanup:
|
|
20654
|
+
*
|
|
20655
|
+
* @example
|
|
20656
|
+
* ```typescript
|
|
20657
|
+
* const connection = new ClientSideConnection(client, stream);
|
|
20658
|
+
* await connection.closed;
|
|
20659
|
+
* console.log('Connection closed - performing cleanup');
|
|
20660
|
+
* ```
|
|
20661
|
+
*/
|
|
20662
|
+
get closed() {
|
|
20663
|
+
return this.connection.closed;
|
|
20558
20664
|
}
|
|
20559
|
-
}
|
|
20665
|
+
};
|
|
20560
20666
|
|
|
20561
|
-
//
|
|
20562
|
-
import {
|
|
20563
|
-
import
|
|
20564
|
-
|
|
20565
|
-
|
|
20566
|
-
|
|
20567
|
-
|
|
20568
|
-
|
|
20569
|
-
|
|
20570
|
-
|
|
20571
|
-
|
|
20572
|
-
|
|
20573
|
-
|
|
20574
|
-
|
|
20575
|
-
|
|
20576
|
-
|
|
20577
|
-
|
|
20578
|
-
|
|
20579
|
-
|
|
20580
|
-
|
|
20581
|
-
|
|
20582
|
-
|
|
20583
|
-
|
|
20584
|
-
}
|
|
20585
|
-
}
|
|
20667
|
+
// dist/copy-cleanup.js
|
|
20668
|
+
import { randomBytes } from "node:crypto";
|
|
20669
|
+
import { createInterface } from "node:readline";
|
|
20670
|
+
import { stripVTControlCharacters } from "node:util";
|
|
20671
|
+
import { Readable } from "node:stream";
|
|
20672
|
+
var CodeBuddyCopyCleanup = class {
|
|
20673
|
+
copyId;
|
|
20674
|
+
cwd;
|
|
20675
|
+
password = randomBytes(32).toString("base64url");
|
|
20676
|
+
arguments = [
|
|
20677
|
+
"--acp",
|
|
20678
|
+
"--serve",
|
|
20679
|
+
"--host",
|
|
20680
|
+
"127.0.0.1",
|
|
20681
|
+
"--port",
|
|
20682
|
+
"0",
|
|
20683
|
+
"--auth",
|
|
20684
|
+
"password"
|
|
20685
|
+
];
|
|
20686
|
+
#endpoint;
|
|
20687
|
+
constructor(copyId, cwd) {
|
|
20688
|
+
this.copyId = copyId;
|
|
20689
|
+
this.cwd = cwd;
|
|
20586
20690
|
}
|
|
20587
|
-
|
|
20588
|
-
|
|
20589
|
-
|
|
20590
|
-
|
|
20591
|
-
|
|
20592
|
-
|
|
20593
|
-
|
|
20594
|
-
|
|
20595
|
-
|
|
20596
|
-
|
|
20597
|
-
|
|
20598
|
-
|
|
20599
|
-
|
|
20600
|
-
|
|
20601
|
-
|
|
20602
|
-
if (
|
|
20603
|
-
|
|
20604
|
-
|
|
20605
|
-
|
|
20606
|
-
|
|
20607
|
-
return false;
|
|
20608
|
-
const target = await realpath(path4.join(directory, entry)).catch(() => "");
|
|
20609
|
-
if (target.toLowerCase() !== selected.toLowerCase())
|
|
20610
|
-
return false;
|
|
20611
|
-
const shim = await readFile(path4.join(prefix, `${bin}.cmd`), "utf8").catch(() => "");
|
|
20612
|
-
return referencesNpmBin(shim, name, entry);
|
|
20613
|
-
}));
|
|
20614
|
-
globalInstall = globalInstall && !project && launchers.some(Boolean);
|
|
20615
|
-
}
|
|
20616
|
-
const canUpdate = globalInstall && !!npm;
|
|
20617
|
-
return {
|
|
20618
|
-
prefix,
|
|
20619
|
-
currentVersion,
|
|
20620
|
-
canUpdate,
|
|
20621
|
-
latest: async () => {
|
|
20622
|
-
const data = JSON.parse(await fetchInstallationText(`https://registry.npmjs.org/${encodeURIComponent(name)}/latest`));
|
|
20623
|
-
return installationVersion(data.version);
|
|
20624
|
-
},
|
|
20625
|
-
update: async (version2) => {
|
|
20626
|
-
if (!canUpdate || !npm)
|
|
20627
|
-
throw new Error("Use the original package manager to update this installation");
|
|
20628
|
-
await runInstallationCommand(npm.executable, ["install", "--global", "--prefix", prefix, `${name}@${installationVersion(version2)}`], env, 3e5);
|
|
20629
|
-
}
|
|
20630
|
-
};
|
|
20691
|
+
environment(environment) {
|
|
20692
|
+
return {
|
|
20693
|
+
...environment,
|
|
20694
|
+
CODEBUDDY_GATEWAY_AUTH: "password",
|
|
20695
|
+
CODEBUDDY_GATEWAY_PASSWORD: this.password,
|
|
20696
|
+
CODEBUDDY_GATEWAY_BASE_PATH: ""
|
|
20697
|
+
};
|
|
20698
|
+
}
|
|
20699
|
+
/** Native --serve banners include its password; never pass them to the ACP parser/logs. */
|
|
20700
|
+
protocolOutput(stdout) {
|
|
20701
|
+
return Readable.from(this.#protocolLines(stdout));
|
|
20702
|
+
}
|
|
20703
|
+
async *#protocolLines(stdout) {
|
|
20704
|
+
for await (const line of createInterface({ input: stdout })) {
|
|
20705
|
+
const endpoint = /^\s*Endpoint\s+(http:\/\/127\.0\.0\.1:\d+)\s*$/u.exec(stripVTControlCharacters(line));
|
|
20706
|
+
if (endpoint)
|
|
20707
|
+
this.#endpoint = endpoint[1];
|
|
20708
|
+
if (line.trimStart().startsWith("{"))
|
|
20709
|
+
yield Buffer.from(`${line}
|
|
20710
|
+
`);
|
|
20631
20711
|
}
|
|
20632
|
-
const parent = path4.dirname(directory);
|
|
20633
|
-
if (parent === directory)
|
|
20634
|
-
break;
|
|
20635
|
-
directory = parent;
|
|
20636
20712
|
}
|
|
20637
|
-
|
|
20638
|
-
|
|
20713
|
+
async remove() {
|
|
20714
|
+
if (!this.#endpoint)
|
|
20715
|
+
throw new CodeBuddyError("nativeFailure", `Native cleanup endpoint was not reported; temporary Session ${this.copyId} remains`);
|
|
20716
|
+
const response = await fetch(`${this.#endpoint}/api/v1/sessions/${encodeURIComponent(this.copyId)}?cwd=${encodeURIComponent(this.cwd)}`, {
|
|
20717
|
+
method: "DELETE",
|
|
20718
|
+
headers: { Authorization: `Bearer ${this.password}`, "x-codebuddy-request": "true" },
|
|
20719
|
+
signal: AbortSignal.timeout(5e3),
|
|
20720
|
+
redirect: "error"
|
|
20721
|
+
}).catch(() => {
|
|
20722
|
+
throw new CodeBuddyError("nativeFailure", `Native cleanup request failed; temporary Session ${this.copyId} remains`);
|
|
20723
|
+
});
|
|
20724
|
+
await response.body?.cancel();
|
|
20725
|
+
if (response.status !== 204)
|
|
20726
|
+
throw new CodeBuddyError("nativeFailure", `Native cleanup failed (${response.status}); temporary Session ${this.copyId} remains`);
|
|
20727
|
+
}
|
|
20728
|
+
};
|
|
20639
20729
|
|
|
20640
20730
|
// dist/command.js
|
|
20641
20731
|
var codeBuddyDiscoverySpec = {
|
|
@@ -20922,7 +21012,7 @@ function confirmedConfiguration(response, id, value, profile = CODEBUDDY_RUNTIME
|
|
|
20922
21012
|
// dist/derivation.js
|
|
20923
21013
|
import { randomUUID } from "node:crypto";
|
|
20924
21014
|
import { execFile as execFile3, spawn as spawn2 } from "node:child_process";
|
|
20925
|
-
import { lstat, mkdir, readFile as readFile3, realpath as realpath5, unlink, writeFile } from "node:fs/promises";
|
|
21015
|
+
import { lstat, mkdir, readFile as readFile3, realpath as realpath5, unlink, writeFile as writeFile2 } from "node:fs/promises";
|
|
20926
21016
|
import path6 from "node:path";
|
|
20927
21017
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
|
|
20928
21018
|
|
|
@@ -21034,16 +21124,16 @@ var Diff = class {
|
|
|
21034
21124
|
}
|
|
21035
21125
|
}
|
|
21036
21126
|
}
|
|
21037
|
-
addToPath(
|
|
21038
|
-
const last =
|
|
21127
|
+
addToPath(path10, added, removed, oldPosInc, options) {
|
|
21128
|
+
const last = path10.lastComponent;
|
|
21039
21129
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
21040
21130
|
return {
|
|
21041
|
-
oldPos:
|
|
21131
|
+
oldPos: path10.oldPos + oldPosInc,
|
|
21042
21132
|
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
21043
21133
|
};
|
|
21044
21134
|
} else {
|
|
21045
21135
|
return {
|
|
21046
|
-
oldPos:
|
|
21136
|
+
oldPos: path10.oldPos + oldPosInc,
|
|
21047
21137
|
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
21048
21138
|
};
|
|
21049
21139
|
}
|
|
@@ -22424,7 +22514,7 @@ async function bridgeCopyToTarget(sourceCwd, targetCwd, ref, contents, environme
|
|
|
22424
22514
|
if (!sameResolvedPath(realTargetDirectory, path6.join(realProjects, codeBuddyProjectSlug(targetCwd, profile))))
|
|
22425
22515
|
throw new CodeBuddyError("invalidRequest", "Cross-directory history bridge target escaped the native projects root");
|
|
22426
22516
|
const expected = Buffer.from(contents, "utf8");
|
|
22427
|
-
await
|
|
22517
|
+
await writeFile2(targetFile, expected, { flag: "wx", mode: 384 });
|
|
22428
22518
|
const bridge = { file: targetFile, expected };
|
|
22429
22519
|
try {
|
|
22430
22520
|
const persisted = await readFile3(targetFile);
|
|
@@ -22554,7 +22644,7 @@ async function verifiedChildFile(file2, expected) {
|
|
|
22554
22644
|
}
|
|
22555
22645
|
async function persistChildCopy(file2, expected) {
|
|
22556
22646
|
try {
|
|
22557
|
-
await
|
|
22647
|
+
await writeFile2(file2, expected, { flag: "wx", mode: 384 });
|
|
22558
22648
|
} catch (error51) {
|
|
22559
22649
|
if (record2(error51).code !== "EEXIST")
|
|
22560
22650
|
throw error51;
|
|
@@ -22849,6 +22939,345 @@ async function deriveCodeBuddySession(options) {
|
|
|
22849
22939
|
}
|
|
22850
22940
|
}
|
|
22851
22941
|
|
|
22942
|
+
// dist/session-import.js
|
|
22943
|
+
import { createReadStream } from "node:fs";
|
|
22944
|
+
import { opendir, readFile as readFile4, stat as stat2 } from "node:fs/promises";
|
|
22945
|
+
import path7 from "node:path";
|
|
22946
|
+
import { createInterface as createInterface2 } from "node:readline";
|
|
22947
|
+
|
|
22948
|
+
// ../../harness-adapter/dist/session-import.js
|
|
22949
|
+
import { lstat as lstat2 } from "node:fs/promises";
|
|
22950
|
+
var SessionImportChangedError = class extends Error {
|
|
22951
|
+
constructor(message = "Native Session changed during discovery; refresh and retry") {
|
|
22952
|
+
super(message);
|
|
22953
|
+
this.name = "SessionImportChangedError";
|
|
22954
|
+
}
|
|
22955
|
+
};
|
|
22956
|
+
function isMissingFileError(error51) {
|
|
22957
|
+
return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "ENOENT";
|
|
22958
|
+
}
|
|
22959
|
+
function sameFileFingerprint(left, right) {
|
|
22960
|
+
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;
|
|
22961
|
+
}
|
|
22962
|
+
var STORAGE_ACCESS_ERRORS = /* @__PURE__ */ new Set(["EACCES", "EPERM", "EIO", "EMFILE", "ENFILE"]);
|
|
22963
|
+
function isStorageAccessError(error51) {
|
|
22964
|
+
return typeof error51 === "object" && error51 !== null && "code" in error51 && typeof error51.code === "string" && STORAGE_ACCESS_ERRORS.has(error51.code);
|
|
22965
|
+
}
|
|
22966
|
+
async function optionalLstat(file2) {
|
|
22967
|
+
try {
|
|
22968
|
+
return await lstat2(file2);
|
|
22969
|
+
} catch (error51) {
|
|
22970
|
+
if (isMissingFileError(error51))
|
|
22971
|
+
return null;
|
|
22972
|
+
throw error51;
|
|
22973
|
+
}
|
|
22974
|
+
}
|
|
22975
|
+
async function readStableFiles(files, read) {
|
|
22976
|
+
const before = await Promise.all(files.map(optionalLstat));
|
|
22977
|
+
const value = await read(before);
|
|
22978
|
+
const after = await Promise.all(files.map(optionalLstat));
|
|
22979
|
+
if (before.some((info, index) => !sameFileFingerprint(info, after[index] ?? null)))
|
|
22980
|
+
throw new SessionImportChangedError();
|
|
22981
|
+
return value;
|
|
22982
|
+
}
|
|
22983
|
+
function sessionImportTitle(value, maxLength = HARNESS_SESSION_IMPORT_TITLE_MAX_LENGTH) {
|
|
22984
|
+
if (typeof value !== "string")
|
|
22985
|
+
return null;
|
|
22986
|
+
const normalized = value.replaceAll("\0", "").replaceAll(/\s+/gu, " ").trim();
|
|
22987
|
+
if (!normalized)
|
|
22988
|
+
return null;
|
|
22989
|
+
if (normalized.length <= maxLength)
|
|
22990
|
+
return normalized;
|
|
22991
|
+
const characters = [...normalized];
|
|
22992
|
+
if (characters.length <= maxLength)
|
|
22993
|
+
return normalized;
|
|
22994
|
+
return `${characters.slice(0, maxLength - 1).join("").trimEnd()}…`;
|
|
22995
|
+
}
|
|
22996
|
+
function sessionImportCandidate(input) {
|
|
22997
|
+
const time3 = typeof input.updatedAt === "number" ? input.updatedAt : typeof input.updatedAt === "string" ? Date.parse(input.updatedAt) : Number.NaN;
|
|
22998
|
+
const parsed = harnessSessionImportCandidateSchema.safeParse({
|
|
22999
|
+
nativeSessionId: input.nativeSessionId,
|
|
23000
|
+
cwd: input.cwd,
|
|
23001
|
+
title: typeof input.title === "string" && input.title.trim().length > 0 ? input.title : null,
|
|
23002
|
+
updatedAt: Math.floor(time3),
|
|
23003
|
+
// Unknown must stay unknown; only an explicit boolean is a native statement.
|
|
23004
|
+
running: typeof input.running === "boolean" ? input.running : null
|
|
23005
|
+
});
|
|
23006
|
+
return parsed.success ? parsed.data : null;
|
|
23007
|
+
}
|
|
23008
|
+
var SessionImportScope = class {
|
|
23009
|
+
#abort = new AbortController();
|
|
23010
|
+
#options;
|
|
23011
|
+
#pending = /* @__PURE__ */ new Set();
|
|
23012
|
+
constructor(options) {
|
|
23013
|
+
this.#options = options;
|
|
23014
|
+
}
|
|
23015
|
+
#closed() {
|
|
23016
|
+
return {
|
|
23017
|
+
ok: false,
|
|
23018
|
+
error: { code: "invalidState", message: this.#options.closedMessage, retryable: false }
|
|
23019
|
+
};
|
|
23020
|
+
}
|
|
23021
|
+
read(operation) {
|
|
23022
|
+
const signal = this.#abort.signal;
|
|
23023
|
+
if (signal.aborted)
|
|
23024
|
+
return Promise.resolve(this.#closed());
|
|
23025
|
+
let started;
|
|
23026
|
+
try {
|
|
23027
|
+
started = operation(signal);
|
|
23028
|
+
} catch (error51) {
|
|
23029
|
+
started = Promise.reject(error51 instanceof Error ? error51 : new Error("Session read failed"));
|
|
23030
|
+
}
|
|
23031
|
+
const request = started.then((value) => signal.aborted ? this.#closed() : { ok: true, value }).catch(() => signal.aborted ? this.#closed() : {
|
|
23032
|
+
ok: false,
|
|
23033
|
+
error: {
|
|
23034
|
+
code: "unavailable",
|
|
23035
|
+
message: this.#options.unavailableMessage,
|
|
23036
|
+
retryable: true
|
|
23037
|
+
}
|
|
23038
|
+
}).finally(() => this.#pending.delete(request));
|
|
23039
|
+
this.#pending.add(request);
|
|
23040
|
+
return request;
|
|
23041
|
+
}
|
|
23042
|
+
/** `read` for `resolveCandidate`: a null source is the selected Session having disappeared. */
|
|
23043
|
+
async resolve(operation) {
|
|
23044
|
+
const result = await this.read(operation);
|
|
23045
|
+
if (!result.ok)
|
|
23046
|
+
return result;
|
|
23047
|
+
return result.value ? { ok: true, value: result.value } : {
|
|
23048
|
+
ok: false,
|
|
23049
|
+
error: {
|
|
23050
|
+
code: "sessionNotFound",
|
|
23051
|
+
message: this.#options.notFoundMessage,
|
|
23052
|
+
retryable: false
|
|
23053
|
+
}
|
|
23054
|
+
};
|
|
23055
|
+
}
|
|
23056
|
+
/** Idempotent. Resolves after every started read has settled. */
|
|
23057
|
+
async close() {
|
|
23058
|
+
this.#abort.abort();
|
|
23059
|
+
await Promise.allSettled(this.#pending);
|
|
23060
|
+
}
|
|
23061
|
+
};
|
|
23062
|
+
|
|
23063
|
+
// dist/session-import.js
|
|
23064
|
+
var SESSION_FILE = /^([A-Za-z0-9][A-Za-z0-9_-]{0,199})\.jsonl$/u;
|
|
23065
|
+
var MAX_HISTORY_BYTES = 64e6;
|
|
23066
|
+
var MAX_MARKER_BYTES = 64 * 1024;
|
|
23067
|
+
function processAlive(pid) {
|
|
23068
|
+
if (typeof pid !== "number" || !Number.isSafeInteger(pid) || pid <= 0)
|
|
23069
|
+
return false;
|
|
23070
|
+
try {
|
|
23071
|
+
process.kill(pid, 0);
|
|
23072
|
+
return true;
|
|
23073
|
+
} catch (error51) {
|
|
23074
|
+
return record2(error51).code === "EPERM";
|
|
23075
|
+
}
|
|
23076
|
+
}
|
|
23077
|
+
function userText(row) {
|
|
23078
|
+
if (row.type !== "message" || row.role !== "user")
|
|
23079
|
+
return null;
|
|
23080
|
+
const { content } = row;
|
|
23081
|
+
if (typeof content === "string")
|
|
23082
|
+
return content;
|
|
23083
|
+
if (!Array.isArray(content))
|
|
23084
|
+
return "";
|
|
23085
|
+
return content.map((part) => record2(part)).filter((part) => typeof part.text === "string").map((part) => String(part.text)).join(" ");
|
|
23086
|
+
}
|
|
23087
|
+
async function readFacts(file2, signal) {
|
|
23088
|
+
const stream = createReadStream(file2, { encoding: "utf8", signal });
|
|
23089
|
+
const lines = createInterface2({ input: stream, crlfDelay: Infinity });
|
|
23090
|
+
let cwd = null;
|
|
23091
|
+
let customTitle = null;
|
|
23092
|
+
let generatedTitle = null;
|
|
23093
|
+
let firstPrompt = null;
|
|
23094
|
+
let hasUser = false;
|
|
23095
|
+
let updatedAt = null;
|
|
23096
|
+
try {
|
|
23097
|
+
for await (const line of lines) {
|
|
23098
|
+
signal.throwIfAborted();
|
|
23099
|
+
if (!line.trim())
|
|
23100
|
+
continue;
|
|
23101
|
+
let parsed;
|
|
23102
|
+
try {
|
|
23103
|
+
parsed = JSON.parse(line);
|
|
23104
|
+
} catch {
|
|
23105
|
+
return null;
|
|
23106
|
+
}
|
|
23107
|
+
const row = record2(parsed);
|
|
23108
|
+
if (typeof row.cwd === "string" && path7.isAbsolute(row.cwd))
|
|
23109
|
+
cwd ??= row.cwd;
|
|
23110
|
+
if (typeof row.timestamp === "number" && Number.isFinite(row.timestamp))
|
|
23111
|
+
updatedAt = row.timestamp;
|
|
23112
|
+
if (row.type === "custom-title")
|
|
23113
|
+
customTitle = sessionImportTitle(row.customTitle);
|
|
23114
|
+
else if (row.type === "ai-title")
|
|
23115
|
+
generatedTitle = sessionImportTitle(row.aiTitle);
|
|
23116
|
+
else {
|
|
23117
|
+
const text2 = userText(row);
|
|
23118
|
+
if (text2 !== null) {
|
|
23119
|
+
hasUser = true;
|
|
23120
|
+
firstPrompt ??= sessionImportTitle(text2);
|
|
23121
|
+
}
|
|
23122
|
+
}
|
|
23123
|
+
}
|
|
23124
|
+
} finally {
|
|
23125
|
+
lines.close();
|
|
23126
|
+
stream.destroy();
|
|
23127
|
+
}
|
|
23128
|
+
if (!hasUser || !cwd)
|
|
23129
|
+
return null;
|
|
23130
|
+
return { cwd, title: customTitle ?? generatedTitle ?? firstPrompt, updatedAt };
|
|
23131
|
+
}
|
|
23132
|
+
var CodeBuddySessionImport = class {
|
|
23133
|
+
#environment;
|
|
23134
|
+
#profile;
|
|
23135
|
+
#scope;
|
|
23136
|
+
constructor(environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
23137
|
+
this.#environment = { ...environment };
|
|
23138
|
+
this.#profile = profile;
|
|
23139
|
+
this.#scope = new SessionImportScope({
|
|
23140
|
+
closedMessage: `${profile.displayName} Session import is closed`,
|
|
23141
|
+
unavailableMessage: `${profile.displayName} sessions could not be read; close native clients, check storage access and retry`,
|
|
23142
|
+
notFoundMessage: `${profile.displayName} Session is no longer importable`
|
|
23143
|
+
});
|
|
23144
|
+
}
|
|
23145
|
+
listCandidates() {
|
|
23146
|
+
return this.#scope.read(async (signal) => {
|
|
23147
|
+
const active = await this.#activeSessions(signal);
|
|
23148
|
+
const candidates = [];
|
|
23149
|
+
for (const [nativeSessionId, files] of await this.#sessionFiles(signal)) {
|
|
23150
|
+
if (files.length !== 1 || !files[0])
|
|
23151
|
+
continue;
|
|
23152
|
+
try {
|
|
23153
|
+
const source = await this.#source(nativeSessionId, files[0], active, signal);
|
|
23154
|
+
if (source)
|
|
23155
|
+
candidates.push(source.candidate);
|
|
23156
|
+
} catch (error51) {
|
|
23157
|
+
if (!(error51 instanceof SessionImportChangedError))
|
|
23158
|
+
throw error51;
|
|
23159
|
+
}
|
|
23160
|
+
}
|
|
23161
|
+
return candidates;
|
|
23162
|
+
});
|
|
23163
|
+
}
|
|
23164
|
+
resolveCandidate(nativeSessionId) {
|
|
23165
|
+
return this.#scope.resolve(async (signal) => {
|
|
23166
|
+
const files = (await this.#sessionFiles(signal)).get(nativeSessionId);
|
|
23167
|
+
if (files?.length !== 1 || !files[0])
|
|
23168
|
+
return null;
|
|
23169
|
+
return this.#source(nativeSessionId, files[0], await this.#activeSessions(signal), signal);
|
|
23170
|
+
});
|
|
23171
|
+
}
|
|
23172
|
+
close() {
|
|
23173
|
+
return this.#scope.close();
|
|
23174
|
+
}
|
|
23175
|
+
#root() {
|
|
23176
|
+
return codeBuddyConfigRoot(this.#environment, this.#profile);
|
|
23177
|
+
}
|
|
23178
|
+
/** IDs a live native process registered in `<config>/sessions/<pid>.json`. */
|
|
23179
|
+
async #activeSessions(signal) {
|
|
23180
|
+
const active = /* @__PURE__ */ new Set();
|
|
23181
|
+
const directory = path7.join(this.#root(), "sessions");
|
|
23182
|
+
const markers = await opendir(directory).catch((error51) => {
|
|
23183
|
+
if (isMissingFileError(error51) || record2(error51).code === "ENOTDIR")
|
|
23184
|
+
return null;
|
|
23185
|
+
throw error51;
|
|
23186
|
+
});
|
|
23187
|
+
if (!markers)
|
|
23188
|
+
return active;
|
|
23189
|
+
for await (const marker of markers) {
|
|
23190
|
+
signal.throwIfAborted();
|
|
23191
|
+
if (!marker.isFile() || !marker.name.endsWith(".json"))
|
|
23192
|
+
continue;
|
|
23193
|
+
try {
|
|
23194
|
+
const file2 = path7.join(directory, marker.name);
|
|
23195
|
+
if ((await stat2(file2)).size > MAX_MARKER_BYTES)
|
|
23196
|
+
continue;
|
|
23197
|
+
const entry = record2(JSON.parse(await readFile4(file2, { encoding: "utf8", signal })));
|
|
23198
|
+
if (typeof entry.sessionId === "string" && processAlive(entry.pid))
|
|
23199
|
+
active.add(entry.sessionId);
|
|
23200
|
+
} catch (error51) {
|
|
23201
|
+
signal.throwIfAborted();
|
|
23202
|
+
if (isStorageAccessError(error51))
|
|
23203
|
+
throw error51;
|
|
23204
|
+
}
|
|
23205
|
+
}
|
|
23206
|
+
return active;
|
|
23207
|
+
}
|
|
23208
|
+
/** Session ID to every project file claiming it. Enumerated links are not followed. */
|
|
23209
|
+
async #sessionFiles(signal) {
|
|
23210
|
+
const root = path7.join(this.#root(), "projects");
|
|
23211
|
+
const found = /* @__PURE__ */ new Map();
|
|
23212
|
+
const info = await optionalLstat(root);
|
|
23213
|
+
if (!info)
|
|
23214
|
+
return found;
|
|
23215
|
+
if (!info.isDirectory())
|
|
23216
|
+
throw new Error(`${this.#profile.displayName} Session store is not a directory`);
|
|
23217
|
+
for await (const project of await opendir(root)) {
|
|
23218
|
+
signal.throwIfAborted();
|
|
23219
|
+
if (!project.isDirectory())
|
|
23220
|
+
continue;
|
|
23221
|
+
const projectDirectory = path7.join(root, project.name);
|
|
23222
|
+
const entries = await opendir(projectDirectory).catch((error51) => {
|
|
23223
|
+
if (isMissingFileError(error51))
|
|
23224
|
+
return null;
|
|
23225
|
+
throw error51;
|
|
23226
|
+
});
|
|
23227
|
+
if (!entries)
|
|
23228
|
+
continue;
|
|
23229
|
+
for await (const entry of entries) {
|
|
23230
|
+
signal.throwIfAborted();
|
|
23231
|
+
const nativeSessionId = entry.isFile() ? SESSION_FILE.exec(entry.name)?.[1] : void 0;
|
|
23232
|
+
if (!nativeSessionId)
|
|
23233
|
+
continue;
|
|
23234
|
+
const files = found.get(nativeSessionId) ?? [];
|
|
23235
|
+
files.push(path7.join(projectDirectory, entry.name));
|
|
23236
|
+
found.set(nativeSessionId, files);
|
|
23237
|
+
}
|
|
23238
|
+
}
|
|
23239
|
+
return found;
|
|
23240
|
+
}
|
|
23241
|
+
async #source(nativeSessionId, file2, active, signal) {
|
|
23242
|
+
signal.throwIfAborted();
|
|
23243
|
+
return readStableFiles([file2], async ([info]) => {
|
|
23244
|
+
if (!info?.isFile() || info.size === 0 || info.size > MAX_HISTORY_BYTES)
|
|
23245
|
+
return null;
|
|
23246
|
+
try {
|
|
23247
|
+
const facts = await readFacts(file2, signal);
|
|
23248
|
+
if (!facts)
|
|
23249
|
+
return null;
|
|
23250
|
+
const cwd = path7.resolve(facts.cwd);
|
|
23251
|
+
if (!(await stat2(cwd)).isDirectory())
|
|
23252
|
+
return null;
|
|
23253
|
+
const nativeRef = nativeSessionRefSchema.parse({
|
|
23254
|
+
harnessId: this.#profile.harnessId,
|
|
23255
|
+
nativeSessionId,
|
|
23256
|
+
formatVersion: 1
|
|
23257
|
+
});
|
|
23258
|
+
signal.throwIfAborted();
|
|
23259
|
+
const history = await codeBuddyNativeHistory(cwd, nativeRef, this.#environment, this.#profile);
|
|
23260
|
+
if (path7.resolve(history.file) !== path7.resolve(file2))
|
|
23261
|
+
return null;
|
|
23262
|
+
const candidate = sessionImportCandidate({
|
|
23263
|
+
nativeSessionId,
|
|
23264
|
+
cwd,
|
|
23265
|
+
title: facts.title,
|
|
23266
|
+
updatedAt: facts.updatedAt ?? info.mtimeMs,
|
|
23267
|
+
// A registered live process holds the Session. Absence is not proof of idleness.
|
|
23268
|
+
running: active.has(nativeSessionId) ? true : null
|
|
23269
|
+
});
|
|
23270
|
+
return candidate ? { candidate, nativeRef } : null;
|
|
23271
|
+
} catch (error51) {
|
|
23272
|
+
signal.throwIfAborted();
|
|
23273
|
+
if (isStorageAccessError(error51))
|
|
23274
|
+
throw error51;
|
|
23275
|
+
return null;
|
|
23276
|
+
}
|
|
23277
|
+
});
|
|
23278
|
+
}
|
|
23279
|
+
};
|
|
23280
|
+
|
|
22852
23281
|
// dist/interactions.js
|
|
22853
23282
|
var CodeBuddyInteractions = class {
|
|
22854
23283
|
emit;
|
|
@@ -22992,7 +23421,7 @@ var CodeBuddyInteractions = class {
|
|
|
22992
23421
|
|
|
22993
23422
|
// dist/subagent-history.js
|
|
22994
23423
|
import { readdir as readdir2, realpath as realpath6 } from "node:fs/promises";
|
|
22995
|
-
import
|
|
23424
|
+
import path8 from "node:path";
|
|
22996
23425
|
var equalPath2 = (a, b) => process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
22997
23426
|
var MAX_CACHED_CHILDREN = 16;
|
|
22998
23427
|
var CodeBuddyChildObserver = class {
|
|
@@ -23056,8 +23485,8 @@ var CodeBuddyChildObserver = class {
|
|
|
23056
23485
|
}
|
|
23057
23486
|
async #directory() {
|
|
23058
23487
|
const history = await this.#parentHistory();
|
|
23059
|
-
const project =
|
|
23060
|
-
const expected =
|
|
23488
|
+
const project = path8.dirname(await realpath6(history.file));
|
|
23489
|
+
const expected = path8.join(project, this.parent.nativeSessionId, "subagents");
|
|
23061
23490
|
const actual = await realpath6(expected);
|
|
23062
23491
|
this.#assertOpen();
|
|
23063
23492
|
if (!equalPath2(actual, expected))
|
|
@@ -23067,7 +23496,7 @@ var CodeBuddyChildObserver = class {
|
|
|
23067
23496
|
async #child(directory, childId) {
|
|
23068
23497
|
if (!validCodeBuddyChildId(childId))
|
|
23069
23498
|
throw new CodeBuddyError("invalidRequest", "Invalid native Subagent ID");
|
|
23070
|
-
const file2 =
|
|
23499
|
+
const file2 = path8.join(directory, `${childId}.jsonl`);
|
|
23071
23500
|
const before = await codeBuddyFileVersion(file2);
|
|
23072
23501
|
if (!equalPath2(before.realFile, file2))
|
|
23073
23502
|
throw new CodeBuddyError("invalidRequest", "Redirected Subagent transcript");
|
|
@@ -23779,6 +24208,7 @@ var CodeBuddyAdapter = class {
|
|
|
23779
24208
|
harnessId;
|
|
23780
24209
|
commandCatalog;
|
|
23781
24210
|
liveCommandCatalog = true;
|
|
24211
|
+
sessionImport;
|
|
23782
24212
|
subagents = {
|
|
23783
24213
|
readSnapshot: async ({ parent, nativeSubagentId, cwd }) => {
|
|
23784
24214
|
try {
|
|
@@ -23812,6 +24242,7 @@ var CodeBuddyAdapter = class {
|
|
|
23812
24242
|
this.commandCatalog = commandCatalog2;
|
|
23813
24243
|
}
|
|
23814
24244
|
this.#environment = { ...options.environment ?? process.env };
|
|
24245
|
+
this.sessionImport = new CodeBuddySessionImport(this.#environment, this.#profile);
|
|
23815
24246
|
this.#invocation = options.invocationFactory ?? codeBuddyInvocation;
|
|
23816
24247
|
this.#factory = options.clientFactory ?? ((clientOptions) => new CodeBuddyAcpClient(clientOptions, void 0, this.#invocation));
|
|
23817
24248
|
}
|
|
@@ -23831,7 +24262,7 @@ var CodeBuddyAdapter = class {
|
|
|
23831
24262
|
try {
|
|
23832
24263
|
if (this.#closed)
|
|
23833
24264
|
throw new CodeBuddyError("invalidState", "Adapter is closed");
|
|
23834
|
-
if (!(await
|
|
24265
|
+
if (!(await stat3(cwd)).isDirectory())
|
|
23835
24266
|
throw new CodeBuddyError("invalidRequest", "Working directory is not a directory");
|
|
23836
24267
|
client2 = this.#factory({
|
|
23837
24268
|
cwd,
|
|
@@ -23877,7 +24308,7 @@ var CodeBuddyAdapter = class {
|
|
|
23877
24308
|
return failure("invalidRequest", "Unattended execution requires native fullAccess permissions", this.#profile);
|
|
23878
24309
|
let session;
|
|
23879
24310
|
try {
|
|
23880
|
-
if (!(await
|
|
24311
|
+
if (!(await stat3(input.cwd)).isDirectory())
|
|
23881
24312
|
throw new CodeBuddyError("invalidRequest", "Working directory is not a directory");
|
|
23882
24313
|
if (this.#closed)
|
|
23883
24314
|
throw new CodeBuddyError("invalidState", "Adapter closed while opening Session");
|
|
@@ -23940,7 +24371,7 @@ var CodeBuddyAdapter = class {
|
|
|
23940
24371
|
async close() {
|
|
23941
24372
|
this.#closed = true;
|
|
23942
24373
|
this.#abort.abort();
|
|
23943
|
-
await Promise.allSettled([...this.#derivations]);
|
|
24374
|
+
await Promise.allSettled([this.sessionImport.close(), ...this.#derivations]);
|
|
23944
24375
|
const results = await Promise.allSettled([...this.#sessions, ...this.#inspections].map((resource) => resource.close()));
|
|
23945
24376
|
this.#sessions.clear();
|
|
23946
24377
|
this.#inspections.clear();
|
|
@@ -23970,6 +24401,7 @@ function createCodeBuddyInstallation(environment) {
|
|
|
23970
24401
|
updateAvailable: !!npm && newerInstallationVersion(currentVersion, latestVersion),
|
|
23971
24402
|
canUpdate,
|
|
23972
24403
|
...!canUpdate ? {
|
|
24404
|
+
messageCode: "codebuddy-npm-required",
|
|
23973
24405
|
message: "Use CodeBuddy's native updater or original package manager for this installation. Latest-version checks here require an identified npm installation."
|
|
23974
24406
|
} : {}
|
|
23975
24407
|
};
|
|
@@ -23984,7 +24416,7 @@ function createCodeBuddyInstallation(environment) {
|
|
|
23984
24416
|
|
|
23985
24417
|
// ../../harness-broker/dist/client.js
|
|
23986
24418
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
23987
|
-
import { lstat as
|
|
24419
|
+
import { lstat as lstat3, readFile as readFile5 } from "node:fs/promises";
|
|
23988
24420
|
import net, {} from "node:net";
|
|
23989
24421
|
|
|
23990
24422
|
// ../../harness-broker/dist/protocol.js
|
|
@@ -24099,18 +24531,18 @@ function consumeBrokerFrames(socket, onFrame, onError) {
|
|
|
24099
24531
|
|
|
24100
24532
|
// ../../harness-broker/dist/paths.js
|
|
24101
24533
|
import os2 from "node:os";
|
|
24102
|
-
import
|
|
24534
|
+
import path9 from "node:path";
|
|
24103
24535
|
var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
|
|
24104
24536
|
var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
|
|
24105
24537
|
function defaultHarnessBrokerDirectory(environment = process.env) {
|
|
24106
24538
|
const home = environment.HOME || os2.homedir();
|
|
24107
|
-
return
|
|
24539
|
+
return path9.join(home, ".codexhost", "harness-broker");
|
|
24108
24540
|
}
|
|
24109
24541
|
function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
|
|
24110
24542
|
harnessPluginIdSchema.parse(harnessId);
|
|
24111
24543
|
if (harnessId !== "claude-code")
|
|
24112
|
-
return
|
|
24113
|
-
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ??
|
|
24544
|
+
return path9.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
|
|
24545
|
+
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path9.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
|
|
24114
24546
|
}
|
|
24115
24547
|
|
|
24116
24548
|
// ../../harness-broker/dist/validation.js
|
|
@@ -24389,7 +24821,7 @@ function parseSessionMetadata(value) {
|
|
|
24389
24821
|
};
|
|
24390
24822
|
}
|
|
24391
24823
|
async function readDescriptor(descriptorPath) {
|
|
24392
|
-
const metadata = await
|
|
24824
|
+
const metadata = await lstat3(descriptorPath);
|
|
24393
24825
|
if (metadata.isSymbolicLink())
|
|
24394
24826
|
throw new Error("Aqua Harness broker descriptor must not be a symlink");
|
|
24395
24827
|
if (!metadata.isFile())
|
|
@@ -24401,12 +24833,12 @@ async function readDescriptor(descriptorPath) {
|
|
|
24401
24833
|
throw new Error("Aqua Harness broker descriptor belongs to another user");
|
|
24402
24834
|
}
|
|
24403
24835
|
}
|
|
24404
|
-
const descriptor = harnessBrokerDescriptorSchema.parse(JSON.parse(await
|
|
24836
|
+
const descriptor = harnessBrokerDescriptorSchema.parse(JSON.parse(await readFile5(descriptorPath, "utf8")));
|
|
24405
24837
|
if (process.platform === "darwin" && Buffer.byteLength(descriptor.socketPath) > 103) {
|
|
24406
24838
|
throw new Error("Aqua Harness broker socket path is too long for macOS");
|
|
24407
24839
|
}
|
|
24408
24840
|
if (process.platform !== "win32") {
|
|
24409
|
-
const socket = await
|
|
24841
|
+
const socket = await lstat3(descriptor.socketPath);
|
|
24410
24842
|
if (socket.isSymbolicLink() || !socket.isSocket()) {
|
|
24411
24843
|
throw new Error("Aqua Harness broker endpoint is not a Unix socket");
|
|
24412
24844
|
}
|
|
@@ -24909,7 +25341,8 @@ function createHarnessAdapter(context) {
|
|
|
24909
25341
|
});
|
|
24910
25342
|
const environment = { ...context.environment };
|
|
24911
25343
|
return Object.assign(new CodeBuddyAdapter({ environment }), {
|
|
24912
|
-
installation: createCodeBuddyInstallation(environment)
|
|
25344
|
+
installation: createCodeBuddyInstallation(environment),
|
|
25345
|
+
install: createHarnessInstaller(environment, { npm: "@tencent-ai/codebuddy-code" })
|
|
24913
25346
|
});
|
|
24914
25347
|
}
|
|
24915
25348
|
export {
|