@liberseek/boft-cli-win32-arm64 0.6.9 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/THIRD_PARTY_NOTICES.txt +12 -4
- package/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +287 -170
- package/app/host-runtime.mjs +2450 -1044
- package/app/plugins/antigravity/plugin.mjs +167 -16
- package/app/plugins/claude-code/plugin.mjs +311 -58
- package/app/plugins/codebuddy/plugin.mjs +2355 -894
- package/app/plugins/cursor-cli/plugin.mjs +35973 -10933
- package/app/plugins/deepseek-harness/plugin.mjs +125 -7
- package/app/plugins/enabled.json +4 -1
- package/app/plugins/grok/plugin.mjs +261 -97
- package/app/plugins/hermes/plugin.mjs +2486 -99
- package/app/plugins/kiro-cli/plugin.mjs +120 -3
- package/app/plugins/muse/plugin.mjs +110 -0
- package/app/plugins/omp/plugin.mjs +145 -10
- package/app/plugins/opencode/plugin.mjs +162 -46
- package/app/plugins/pi/plugin.mjs +2891 -1678
- package/app/plugins/qoder/assets/icon.svg +1 -0
- package/app/plugins/qoder/manifest.json +12 -0
- package/app/plugins/qoder/plugin.mjs +52352 -0
- package/app/plugins/qoder-cn/assets/icon.svg +1 -0
- package/app/plugins/qoder-cn/manifest.json +12 -0
- package/app/plugins/qoder-cn/plugin.mjs +52350 -0
- package/app/plugins/workbuddy/assets/icon.svg +29 -0
- package/app/plugins/workbuddy/manifest.json +14 -0
- package/app/plugins/workbuddy/plugin.mjs +25007 -0
- package/app/renderer-extension.js +6043 -1442
- package/bin/boft.exe +0 -0
- package/libexec/boft-node-repl.exe +0 -0
- package/libexec/boft-shim.exe +0 -0
- package/libexec/boft-updater.exe +0 -0
- package/licenses/Qoder-Agent-SDK-LICENSE.txt +7 -0
- package/licenses/QoderCN-Agent-SDK-LICENSE.txt +7 -0
- package/licenses/{opencodex-LICENSE.txt → tailwindcss-LICENSE.txt} +1 -1
- package/package.json +1 -1
|
@@ -5,9 +5,6 @@ var __export = (target, all) => {
|
|
|
5
5
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
// dist/codebuddy-adapter.js
|
|
9
|
-
import { stat as stat2 } from "node:fs/promises";
|
|
10
|
-
|
|
11
8
|
// ../../../node_modules/zod/v4/classic/external.js
|
|
12
9
|
var external_exports = {};
|
|
13
10
|
__export(external_exports, {
|
|
@@ -774,10 +771,10 @@ function mergeDefs(...defs) {
|
|
|
774
771
|
function cloneDef(schema) {
|
|
775
772
|
return mergeDefs(schema._zod.def);
|
|
776
773
|
}
|
|
777
|
-
function getElementAtPath(obj,
|
|
778
|
-
if (!
|
|
774
|
+
function getElementAtPath(obj, path8) {
|
|
775
|
+
if (!path8)
|
|
779
776
|
return obj;
|
|
780
|
-
return
|
|
777
|
+
return path8.reduce((acc, key) => acc?.[key], obj);
|
|
781
778
|
}
|
|
782
779
|
function promiseAllObject(promisesObj) {
|
|
783
780
|
const keys = Object.keys(promisesObj);
|
|
@@ -1186,11 +1183,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
1186
1183
|
}
|
|
1187
1184
|
return false;
|
|
1188
1185
|
}
|
|
1189
|
-
function prefixIssues(
|
|
1186
|
+
function prefixIssues(path8, issues) {
|
|
1190
1187
|
return issues.map((iss) => {
|
|
1191
1188
|
var _a3;
|
|
1192
1189
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
1193
|
-
iss.path.unshift(
|
|
1190
|
+
iss.path.unshift(path8);
|
|
1194
1191
|
return iss;
|
|
1195
1192
|
});
|
|
1196
1193
|
}
|
|
@@ -1337,16 +1334,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1337
1334
|
}
|
|
1338
1335
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
1339
1336
|
const fieldErrors = { _errors: [] };
|
|
1340
|
-
const processError = (error52,
|
|
1337
|
+
const processError = (error52, path8 = []) => {
|
|
1341
1338
|
for (const issue2 of error52.issues) {
|
|
1342
1339
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1343
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
1340
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
1344
1341
|
} else if (issue2.code === "invalid_key") {
|
|
1345
|
-
processError({ issues: issue2.issues }, [...
|
|
1342
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
1346
1343
|
} else if (issue2.code === "invalid_element") {
|
|
1347
|
-
processError({ issues: issue2.issues }, [...
|
|
1344
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
1348
1345
|
} else {
|
|
1349
|
-
const fullpath = [...
|
|
1346
|
+
const fullpath = [...path8, ...issue2.path];
|
|
1350
1347
|
if (fullpath.length === 0) {
|
|
1351
1348
|
fieldErrors._errors.push(mapper(issue2));
|
|
1352
1349
|
} else {
|
|
@@ -1373,17 +1370,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1373
1370
|
}
|
|
1374
1371
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
1375
1372
|
const result = { errors: [] };
|
|
1376
|
-
const processError = (error52,
|
|
1373
|
+
const processError = (error52, path8 = []) => {
|
|
1377
1374
|
var _a3, _b;
|
|
1378
1375
|
for (const issue2 of error52.issues) {
|
|
1379
1376
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1380
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
1377
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
1381
1378
|
} else if (issue2.code === "invalid_key") {
|
|
1382
|
-
processError({ issues: issue2.issues }, [...
|
|
1379
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
1383
1380
|
} else if (issue2.code === "invalid_element") {
|
|
1384
|
-
processError({ issues: issue2.issues }, [...
|
|
1381
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
1385
1382
|
} else {
|
|
1386
|
-
const fullpath = [...
|
|
1383
|
+
const fullpath = [...path8, ...issue2.path];
|
|
1387
1384
|
if (fullpath.length === 0) {
|
|
1388
1385
|
result.errors.push(mapper(issue2));
|
|
1389
1386
|
continue;
|
|
@@ -1415,8 +1412,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1415
1412
|
}
|
|
1416
1413
|
function toDotPath(_path) {
|
|
1417
1414
|
const segs = [];
|
|
1418
|
-
const
|
|
1419
|
-
for (const seg of
|
|
1415
|
+
const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
1416
|
+
for (const seg of path8) {
|
|
1420
1417
|
if (typeof seg === "number")
|
|
1421
1418
|
segs.push(`[${seg}]`);
|
|
1422
1419
|
else if (typeof seg === "symbol")
|
|
@@ -14108,13 +14105,13 @@ function resolveRef(ref, ctx) {
|
|
|
14108
14105
|
if (!ref.startsWith("#")) {
|
|
14109
14106
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
14110
14107
|
}
|
|
14111
|
-
const
|
|
14112
|
-
if (
|
|
14108
|
+
const path8 = ref.slice(1).split("/").filter(Boolean);
|
|
14109
|
+
if (path8.length === 0) {
|
|
14113
14110
|
return ctx.rootSchema;
|
|
14114
14111
|
}
|
|
14115
14112
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
14116
|
-
if (
|
|
14117
|
-
const key =
|
|
14113
|
+
if (path8[0] === defsKey) {
|
|
14114
|
+
const key = path8[1];
|
|
14118
14115
|
if (!key || !ctx.defs[key]) {
|
|
14119
14116
|
throw new Error(`Reference not found: ${ref}`);
|
|
14120
14117
|
}
|
|
@@ -14522,9 +14519,104 @@ function date4(params) {
|
|
|
14522
14519
|
// ../../../node_modules/zod/v4/classic/external.js
|
|
14523
14520
|
config(en_default());
|
|
14524
14521
|
|
|
14522
|
+
// ../../shared-contracts/dist/credential-imports.js
|
|
14523
|
+
var credentialSourceSchema = external_exports.object({
|
|
14524
|
+
id: external_exports.string().min(1).max(256),
|
|
14525
|
+
harnessId: external_exports.string().min(1),
|
|
14526
|
+
label: external_exports.string().min(1).max(512),
|
|
14527
|
+
provider: external_exports.enum(["openai-codex", "xai"])
|
|
14528
|
+
}).strict();
|
|
14529
|
+
var credentialImportNameSchema = external_exports.string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
14530
|
+
var credentialImportRecordSchema = external_exports.object({
|
|
14531
|
+
name: credentialImportNameSchema,
|
|
14532
|
+
source: credentialSourceSchema,
|
|
14533
|
+
importedAt: external_exports.string()
|
|
14534
|
+
}).strict();
|
|
14535
|
+
var credentialImportsRequestSchema = external_exports.discriminatedUnion("action", [
|
|
14536
|
+
external_exports.object({ action: external_exports.literal("list") }).strict(),
|
|
14537
|
+
external_exports.object({
|
|
14538
|
+
action: external_exports.literal("import"),
|
|
14539
|
+
sourceId: external_exports.string().min(1).max(256),
|
|
14540
|
+
name: credentialImportNameSchema,
|
|
14541
|
+
confirmed: external_exports.literal(true)
|
|
14542
|
+
}).strict(),
|
|
14543
|
+
external_exports.object({
|
|
14544
|
+
action: external_exports.literal("reimport"),
|
|
14545
|
+
sourceId: external_exports.string().min(1).max(256),
|
|
14546
|
+
name: credentialImportNameSchema,
|
|
14547
|
+
confirmed: external_exports.literal(true)
|
|
14548
|
+
}).strict(),
|
|
14549
|
+
external_exports.object({
|
|
14550
|
+
action: external_exports.literal("remove"),
|
|
14551
|
+
name: credentialImportNameSchema,
|
|
14552
|
+
confirmed: external_exports.literal(true)
|
|
14553
|
+
}).strict()
|
|
14554
|
+
]);
|
|
14555
|
+
var credentialOtherLoginSchema = external_exports.object({
|
|
14556
|
+
provider: external_exports.string().min(1).max(128),
|
|
14557
|
+
type: external_exports.enum(["oauth", "api_key", "unknown"]),
|
|
14558
|
+
/** Best-effort account label (e.g. the email in a Codex token), derived locally when present. */
|
|
14559
|
+
label: external_exports.string().min(1).max(512).optional(),
|
|
14560
|
+
/** Recognized credential vendor, derived from the OAuth token issuer. Absent when unknown. */
|
|
14561
|
+
vendor: external_exports.enum(["openai-codex", "xai"]).optional()
|
|
14562
|
+
}).strict();
|
|
14563
|
+
var credentialImportsResultSchema = external_exports.object({
|
|
14564
|
+
sources: external_exports.array(credentialSourceSchema),
|
|
14565
|
+
targets: external_exports.array(external_exports.object({
|
|
14566
|
+
harnessId: external_exports.string(),
|
|
14567
|
+
providers: external_exports.array(external_exports.enum(["openai-codex", "xai"])),
|
|
14568
|
+
imports: external_exports.array(credentialImportRecordSchema),
|
|
14569
|
+
others: external_exports.array(credentialOtherLoginSchema).default([])
|
|
14570
|
+
}).strict())
|
|
14571
|
+
}).strict();
|
|
14572
|
+
var credentialImportsParamsSchema = external_exports.object({
|
|
14573
|
+
targetHarnessId: external_exports.string().min(1).max(128).optional(),
|
|
14574
|
+
request: credentialImportsRequestSchema
|
|
14575
|
+
}).strict();
|
|
14576
|
+
|
|
14525
14577
|
// ../../shared-contracts/dist/version.js
|
|
14526
14578
|
var WORKSPACE_CONTRACT_VERSION = 1;
|
|
14527
14579
|
|
|
14580
|
+
// ../../shared-contracts/dist/idle-release.js
|
|
14581
|
+
var IDLE_RELEASE_TIMEOUT_MINUTES_MIN = 5;
|
|
14582
|
+
var IDLE_RELEASE_TIMEOUT_MINUTES_MAX = 1440;
|
|
14583
|
+
var idleReleaseSettingsSchema = external_exports.strictObject({
|
|
14584
|
+
enabled: external_exports.boolean(),
|
|
14585
|
+
timeoutMinutes: external_exports.number().int().min(IDLE_RELEASE_TIMEOUT_MINUTES_MIN).max(IDLE_RELEASE_TIMEOUT_MINUTES_MAX)
|
|
14586
|
+
});
|
|
14587
|
+
var DEFAULT_IDLE_RELEASE_SETTINGS = Object.freeze({
|
|
14588
|
+
enabled: false,
|
|
14589
|
+
timeoutMinutes: 30
|
|
14590
|
+
});
|
|
14591
|
+
|
|
14592
|
+
// ../../shared-contracts/dist/loaded-sessions.js
|
|
14593
|
+
var loadedSessionStateSchema = external_exports.enum([
|
|
14594
|
+
"idle",
|
|
14595
|
+
"running",
|
|
14596
|
+
"busy",
|
|
14597
|
+
"closing",
|
|
14598
|
+
"failed",
|
|
14599
|
+
"blocked"
|
|
14600
|
+
]);
|
|
14601
|
+
var loadedSessionReasonSchema = external_exports.enum([
|
|
14602
|
+
"none",
|
|
14603
|
+
"disabled",
|
|
14604
|
+
"timeout",
|
|
14605
|
+
"operation",
|
|
14606
|
+
"background",
|
|
14607
|
+
"identity",
|
|
14608
|
+
"persistence",
|
|
14609
|
+
"closeFailed"
|
|
14610
|
+
]);
|
|
14611
|
+
var loadedSessionsSchema = external_exports.array(external_exports.strictObject({
|
|
14612
|
+
threadId: external_exports.string(),
|
|
14613
|
+
title: external_exports.string(),
|
|
14614
|
+
harnessId: external_exports.string(),
|
|
14615
|
+
state: loadedSessionStateSchema,
|
|
14616
|
+
reason: loadedSessionReasonSchema,
|
|
14617
|
+
inactiveMs: external_exports.number().nonnegative()
|
|
14618
|
+
}));
|
|
14619
|
+
|
|
14528
14620
|
// ../../shared-contracts/dist/ids.js
|
|
14529
14621
|
var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
|
|
14530
14622
|
message: "Identifier must not be empty or whitespace"
|
|
@@ -15031,6 +15123,8 @@ var pluginPresentationShape = {
|
|
|
15031
15123
|
id: harnessPluginIdSchema,
|
|
15032
15124
|
name: external_exports.string().trim().min(1).max(128),
|
|
15033
15125
|
version: external_exports.string().min(1).max(128),
|
|
15126
|
+
/** The factory accepts a persisted local entrypoint through its construction context. */
|
|
15127
|
+
launchCommand: external_exports.literal(true).optional(),
|
|
15034
15128
|
links: external_exports.object({
|
|
15035
15129
|
documentation: documentationUrlSchema.optional(),
|
|
15036
15130
|
installation: documentationUrlSchema.optional()
|
|
@@ -15068,6 +15162,19 @@ var harnessPluginRouteSchema = external_exports.object({
|
|
|
15068
15162
|
permissionModeId: harnessPermissionModeIdSchema.optional()
|
|
15069
15163
|
}).strict();
|
|
15070
15164
|
|
|
15165
|
+
// ../../shared-contracts/dist/harness-launch-settings.js
|
|
15166
|
+
var harnessLaunchPathSchema = external_exports.string().trim().min(1).max(4096).refine((value) => !/[\u0000\r\n]/u.test(value), "Invalid entrypoint path");
|
|
15167
|
+
var harnessLaunchSettingsGetSchema = external_exports.object({
|
|
15168
|
+
harnessId: harnessPluginIdSchema
|
|
15169
|
+
}).strict();
|
|
15170
|
+
var harnessLaunchSettingsSetSchema = harnessLaunchSettingsGetSchema.extend({
|
|
15171
|
+
path: harnessLaunchPathSchema.nullable()
|
|
15172
|
+
});
|
|
15173
|
+
var harnessLaunchSettingsSchema = external_exports.object({
|
|
15174
|
+
path: harnessLaunchPathSchema.nullable(),
|
|
15175
|
+
restartRequired: external_exports.boolean()
|
|
15176
|
+
}).strict();
|
|
15177
|
+
|
|
15071
15178
|
// ../../shared-contracts/dist/codex-accounts.js
|
|
15072
15179
|
var accountIdSchema = external_exports.string().min(1).max(256).regex(/^[A-Za-z0-9._~-]+$/u);
|
|
15073
15180
|
var nonBlankTextSchema3 = external_exports.string().trim().min(1);
|
|
@@ -15358,196 +15465,543 @@ var updateStatusResultSchema = external_exports.strictObject({
|
|
|
15358
15465
|
// ../../shared-contracts/dist/index.js
|
|
15359
15466
|
var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
|
|
15360
15467
|
|
|
15361
|
-
// dist/
|
|
15362
|
-
|
|
15363
|
-
|
|
15364
|
-
|
|
15365
|
-
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
|
|
15366
|
-
var AGENT_METHODS = {
|
|
15367
|
-
initialize: "initialize",
|
|
15368
|
-
authenticate: "authenticate",
|
|
15369
|
-
providers_list: "providers/list",
|
|
15370
|
-
providers_set: "providers/set",
|
|
15371
|
-
providers_disable: "providers/disable",
|
|
15372
|
-
session_new: "session/new",
|
|
15373
|
-
session_load: "session/load",
|
|
15374
|
-
session_set_mode: "session/set_mode",
|
|
15375
|
-
session_set_config_option: "session/set_config_option",
|
|
15376
|
-
session_prompt: "session/prompt",
|
|
15377
|
-
session_cancel: "session/cancel",
|
|
15378
|
-
mcp_message: "mcp/message",
|
|
15379
|
-
session_list: "session/list",
|
|
15380
|
-
session_delete: "session/delete",
|
|
15381
|
-
session_fork: "session/fork",
|
|
15382
|
-
session_resume: "session/resume",
|
|
15383
|
-
session_close: "session/close",
|
|
15384
|
-
logout: "logout",
|
|
15385
|
-
nes_start: "nes/start",
|
|
15386
|
-
nes_suggest: "nes/suggest",
|
|
15387
|
-
nes_accept: "nes/accept",
|
|
15388
|
-
nes_reject: "nes/reject",
|
|
15389
|
-
nes_close: "nes/close",
|
|
15390
|
-
document_did_open: "document/didOpen",
|
|
15391
|
-
document_did_change: "document/didChange",
|
|
15392
|
-
document_did_close: "document/didClose",
|
|
15393
|
-
document_did_save: "document/didSave",
|
|
15394
|
-
document_did_focus: "document/didFocus"
|
|
15395
|
-
};
|
|
15396
|
-
var CLIENT_METHODS = {
|
|
15397
|
-
session_request_permission: "session/request_permission",
|
|
15398
|
-
session_update: "session/update",
|
|
15399
|
-
fs_write_text_file: "fs/write_text_file",
|
|
15400
|
-
fs_read_text_file: "fs/read_text_file",
|
|
15401
|
-
terminal_create: "terminal/create",
|
|
15402
|
-
terminal_output: "terminal/output",
|
|
15403
|
-
terminal_release: "terminal/release",
|
|
15404
|
-
terminal_wait_for_exit: "terminal/wait_for_exit",
|
|
15405
|
-
terminal_kill: "terminal/kill",
|
|
15406
|
-
mcp_connect: "mcp/connect",
|
|
15407
|
-
mcp_message: "mcp/message",
|
|
15408
|
-
mcp_disconnect: "mcp/disconnect",
|
|
15409
|
-
elicitation_create: "elicitation/create",
|
|
15410
|
-
elicitation_complete: "elicitation/complete"
|
|
15411
|
-
};
|
|
15412
|
-
var PROTOCOL_METHODS = {
|
|
15413
|
-
cancel_request: "$/cancel_request"
|
|
15414
|
-
};
|
|
15415
|
-
|
|
15416
|
-
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema-deserialize.js
|
|
15417
|
-
var skippedItem = /* @__PURE__ */ Symbol("skippedItem");
|
|
15418
|
-
function defaultOnError(schema, fallback) {
|
|
15419
|
-
return schema.catch(fallback);
|
|
15468
|
+
// ../../harness-adapter/dist/approval.js
|
|
15469
|
+
function invalidRequest(message) {
|
|
15470
|
+
return { code: "invalidRequest", message, retryable: false };
|
|
15420
15471
|
}
|
|
15421
|
-
function
|
|
15422
|
-
|
|
15423
|
-
return external_exports.unknown().transform((value, context) => {
|
|
15424
|
-
if (value !== void 0)
|
|
15425
|
-
return schemaWithCatch.parse(value);
|
|
15426
|
-
context.addIssue({
|
|
15427
|
-
code: "custom",
|
|
15428
|
-
message: "Required value is missing"
|
|
15429
|
-
});
|
|
15430
|
-
return external_exports.NEVER;
|
|
15431
|
-
});
|
|
15472
|
+
function validateHostApprovalResponse(interaction, response) {
|
|
15473
|
+
return interaction.actions.some(({ id }) => id === response.actionId) ? null : invalidRequest("Approval Response contains an undeclared action ID");
|
|
15432
15474
|
}
|
|
15433
|
-
|
|
15434
|
-
|
|
15435
|
-
|
|
15436
|
-
}
|
|
15437
|
-
const tag = value[key];
|
|
15438
|
-
return typeof tag === "string" ? tag : void 0;
|
|
15475
|
+
|
|
15476
|
+
// ../../harness-adapter/dist/question.js
|
|
15477
|
+
function invalidRequest2(message) {
|
|
15478
|
+
return { code: "invalidRequest", message, retryable: false };
|
|
15439
15479
|
}
|
|
15440
|
-
function
|
|
15441
|
-
|
|
15442
|
-
|
|
15443
|
-
|
|
15444
|
-
|
|
15445
|
-
|
|
15446
|
-
|
|
15447
|
-
|
|
15448
|
-
});
|
|
15480
|
+
function validateHostQuestionResponse(interaction, response) {
|
|
15481
|
+
const questionIds = new Set(interaction.questions.map(({ id }) => id));
|
|
15482
|
+
if (response.cancelled) {
|
|
15483
|
+
return Object.keys(response.answers).length === 0 ? null : invalidRequest2("Cancelled Question Response must not contain answers");
|
|
15484
|
+
}
|
|
15485
|
+
for (const answerId of Object.keys(response.answers)) {
|
|
15486
|
+
if (!questionIds.has(answerId)) {
|
|
15487
|
+
return invalidRequest2("Question Response contains an unknown Question ID");
|
|
15449
15488
|
}
|
|
15450
|
-
}
|
|
15451
|
-
|
|
15452
|
-
|
|
15453
|
-
|
|
15454
|
-
|
|
15455
|
-
if (!result.success) {
|
|
15456
|
-
for (const issue2 of result.error.issues) {
|
|
15457
|
-
context.addIssue({ ...issue2, input: value });
|
|
15458
|
-
}
|
|
15459
|
-
return external_exports.NEVER;
|
|
15489
|
+
}
|
|
15490
|
+
for (const question of interaction.questions) {
|
|
15491
|
+
const answers = response.answers[question.id] ?? [];
|
|
15492
|
+
if (!question.optional && answers.length === 0) {
|
|
15493
|
+
return invalidRequest2("Question Response omits a required answer");
|
|
15460
15494
|
}
|
|
15461
|
-
|
|
15462
|
-
|
|
15463
|
-
|
|
15464
|
-
const raw = value;
|
|
15465
|
-
for (const [property, rawValue] of Object.entries(raw)) {
|
|
15466
|
-
if (property === "__proto__")
|
|
15467
|
-
continue;
|
|
15468
|
-
if (!Object.hasOwn(output, property))
|
|
15469
|
-
output[property] = rawValue;
|
|
15495
|
+
if (question.type === "text") {
|
|
15496
|
+
if (answers.length > 1) {
|
|
15497
|
+
return invalidRequest2("Text Question accepts at most one answer");
|
|
15470
15498
|
}
|
|
15499
|
+
continue;
|
|
15471
15500
|
}
|
|
15472
|
-
|
|
15473
|
-
|
|
15501
|
+
if (!question.multiple && answers.length > 1) {
|
|
15502
|
+
return invalidRequest2("Single-choice Question accepts at most one answer");
|
|
15503
|
+
}
|
|
15504
|
+
const declared = new Set(question.options.map(({ value }) => value));
|
|
15505
|
+
if (!question.allowOther && answers.some((answer) => !declared.has(answer))) {
|
|
15506
|
+
return invalidRequest2("Question Response contains an undeclared choice");
|
|
15507
|
+
}
|
|
15508
|
+
}
|
|
15509
|
+
return null;
|
|
15474
15510
|
}
|
|
15475
|
-
|
|
15476
|
-
|
|
15511
|
+
|
|
15512
|
+
// ../../harness-adapter/dist/interaction.js
|
|
15513
|
+
function invalidRequest3(message) {
|
|
15514
|
+
return { code: "invalidRequest", message, retryable: false };
|
|
15515
|
+
}
|
|
15516
|
+
function invalidState(message) {
|
|
15517
|
+
return { code: "invalidState", message, retryable: false };
|
|
15518
|
+
}
|
|
15519
|
+
function validateHostInteractionResponse(interaction, response) {
|
|
15520
|
+
if (!interaction) {
|
|
15521
|
+
return invalidState("Interaction Response must reference a pending Interaction");
|
|
15522
|
+
}
|
|
15523
|
+
if (interaction.type === "question") {
|
|
15524
|
+
return response.type === "question" ? validateHostQuestionResponse(interaction, response) : invalidRequest3("Interaction Response type does not match the pending Interaction");
|
|
15525
|
+
}
|
|
15526
|
+
return response.type === "approval" ? validateHostApprovalResponse(interaction, response) : invalidRequest3("Interaction Response type does not match the pending Interaction");
|
|
15477
15527
|
}
|
|
15478
15528
|
|
|
15479
|
-
//
|
|
15480
|
-
var
|
|
15481
|
-
|
|
15482
|
-
|
|
15483
|
-
|
|
15484
|
-
|
|
15485
|
-
|
|
15486
|
-
|
|
15487
|
-
|
|
15488
|
-
|
|
15489
|
-
|
|
15490
|
-
|
|
15491
|
-
|
|
15492
|
-
|
|
15493
|
-
|
|
15494
|
-
|
|
15495
|
-
|
|
15496
|
-
|
|
15497
|
-
|
|
15498
|
-
}
|
|
15499
|
-
|
|
15500
|
-
|
|
15501
|
-
|
|
15502
|
-
|
|
15503
|
-
|
|
15504
|
-
|
|
15505
|
-
|
|
15506
|
-
|
|
15507
|
-
|
|
15508
|
-
|
|
15509
|
-
|
|
15510
|
-
|
|
15511
|
-
|
|
15512
|
-
|
|
15513
|
-
|
|
15514
|
-
|
|
15515
|
-
|
|
15516
|
-
|
|
15517
|
-
|
|
15518
|
-
|
|
15519
|
-
|
|
15520
|
-
|
|
15521
|
-
|
|
15522
|
-
|
|
15523
|
-
|
|
15524
|
-
|
|
15525
|
-
|
|
15526
|
-
|
|
15527
|
-
|
|
15528
|
-
|
|
15529
|
-
|
|
15530
|
-
var
|
|
15531
|
-
|
|
15532
|
-
|
|
15533
|
-
|
|
15534
|
-
|
|
15535
|
-
|
|
15536
|
-
|
|
15537
|
-
|
|
15538
|
-
|
|
15539
|
-
|
|
15540
|
-
|
|
15541
|
-
|
|
15542
|
-
|
|
15543
|
-
|
|
15544
|
-
|
|
15545
|
-
|
|
15546
|
-
|
|
15547
|
-
|
|
15548
|
-
|
|
15549
|
-
|
|
15550
|
-
|
|
15529
|
+
// ../../harness-adapter/dist/output-channel.js
|
|
15530
|
+
var HarnessOutputChannel = class {
|
|
15531
|
+
outputs;
|
|
15532
|
+
#consumerCreated = false;
|
|
15533
|
+
#ended = false;
|
|
15534
|
+
#pending = [];
|
|
15535
|
+
#values = [];
|
|
15536
|
+
constructor() {
|
|
15537
|
+
this.outputs = {
|
|
15538
|
+
[Symbol.asyncIterator]: () => {
|
|
15539
|
+
if (this.#consumerCreated) {
|
|
15540
|
+
throw new Error("Harness outputs allow only one consumer");
|
|
15541
|
+
}
|
|
15542
|
+
this.#consumerCreated = true;
|
|
15543
|
+
return {
|
|
15544
|
+
next: () => this.#next()
|
|
15545
|
+
};
|
|
15546
|
+
}
|
|
15547
|
+
};
|
|
15548
|
+
}
|
|
15549
|
+
emit(value) {
|
|
15550
|
+
if (this.#ended)
|
|
15551
|
+
return false;
|
|
15552
|
+
const resolve = this.#pending.shift();
|
|
15553
|
+
if (resolve)
|
|
15554
|
+
resolve({ done: false, value });
|
|
15555
|
+
else
|
|
15556
|
+
this.#values.push(value);
|
|
15557
|
+
return true;
|
|
15558
|
+
}
|
|
15559
|
+
end() {
|
|
15560
|
+
if (this.#ended)
|
|
15561
|
+
return;
|
|
15562
|
+
this.#ended = true;
|
|
15563
|
+
if (this.#values.length !== 0)
|
|
15564
|
+
return;
|
|
15565
|
+
for (const resolve of this.#pending.splice(0))
|
|
15566
|
+
resolve({ done: true, value: void 0 });
|
|
15567
|
+
}
|
|
15568
|
+
#next() {
|
|
15569
|
+
const value = this.#values.shift();
|
|
15570
|
+
if (value !== void 0)
|
|
15571
|
+
return Promise.resolve({ done: false, value });
|
|
15572
|
+
if (this.#ended)
|
|
15573
|
+
return Promise.resolve({ done: true, value: void 0 });
|
|
15574
|
+
return new Promise((resolve) => this.#pending.push(resolve));
|
|
15575
|
+
}
|
|
15576
|
+
};
|
|
15577
|
+
|
|
15578
|
+
// ../../harness-adapter/dist/diagnostics.js
|
|
15579
|
+
var DIAGNOSTIC_TAIL_MAX_LENGTH = 8e3;
|
|
15580
|
+
var SENSITIVE_VALUE_PATTERN = /(api[_-]?key|access[_-]?token|auth(?:orization)?|password|secret)(\s*[:=]\s*)([^\s,;]+)/giu;
|
|
15581
|
+
var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/giu;
|
|
15582
|
+
function sanitizeDiagnosticTail(value) {
|
|
15583
|
+
const redacted = value.replace(BEARER_PATTERN, "Bearer [redacted]").replace(SENSITIVE_VALUE_PATTERN, "$1$2[redacted]");
|
|
15584
|
+
return redacted.length <= DIAGNOSTIC_TAIL_MAX_LENGTH ? redacted : redacted.slice(-DIAGNOSTIC_TAIL_MAX_LENGTH);
|
|
15585
|
+
}
|
|
15586
|
+
|
|
15587
|
+
// ../../harness-adapter/dist/usage.js
|
|
15588
|
+
var tokenFields = [
|
|
15589
|
+
"inputTokens",
|
|
15590
|
+
"cachedInputTokens",
|
|
15591
|
+
"cacheWriteInputTokens",
|
|
15592
|
+
"outputTokens",
|
|
15593
|
+
"outputTokensPerSecond",
|
|
15594
|
+
"reasoningOutputTokens",
|
|
15595
|
+
"totalTokens",
|
|
15596
|
+
"contextWindowTokens",
|
|
15597
|
+
"contextUsedTokens"
|
|
15598
|
+
];
|
|
15599
|
+
var safeIntegerFields = [
|
|
15600
|
+
"planFiveHourResetsAtUnix",
|
|
15601
|
+
"planSevenDayResetsAtUnix"
|
|
15602
|
+
];
|
|
15603
|
+
var percentFields = [
|
|
15604
|
+
"cacheHitRatePercent",
|
|
15605
|
+
"planFiveHourUsedPercent",
|
|
15606
|
+
"planSevenDayUsedPercent"
|
|
15607
|
+
];
|
|
15608
|
+
var usageFields = /* @__PURE__ */ new Set([
|
|
15609
|
+
...tokenFields,
|
|
15610
|
+
...safeIntegerFields,
|
|
15611
|
+
...percentFields,
|
|
15612
|
+
"totalCostUsd",
|
|
15613
|
+
"totalCredits",
|
|
15614
|
+
"contextUsagePercent"
|
|
15615
|
+
]);
|
|
15616
|
+
function isRecord(value) {
|
|
15617
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15618
|
+
}
|
|
15619
|
+
function parseHostUsage(value) {
|
|
15620
|
+
if (!isRecord(value))
|
|
15621
|
+
throw new Error("Harness Usage must be an object");
|
|
15622
|
+
const keys = Object.keys(value);
|
|
15623
|
+
if (keys.length === 0)
|
|
15624
|
+
throw new Error("Harness Usage must contain a reliable field");
|
|
15625
|
+
for (const key of keys) {
|
|
15626
|
+
if (!usageFields.has(key)) {
|
|
15627
|
+
throw new Error(`Harness Usage contains unknown field '${key}'`);
|
|
15628
|
+
}
|
|
15629
|
+
}
|
|
15630
|
+
for (const field of ["totalCredits", "contextUsagePercent"]) {
|
|
15631
|
+
const candidate = value[field];
|
|
15632
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)) {
|
|
15633
|
+
throw new Error(`Harness Usage '${field}' must be a finite non-negative number`);
|
|
15634
|
+
}
|
|
15635
|
+
}
|
|
15636
|
+
for (const field of tokenFields) {
|
|
15637
|
+
const candidate = value[field];
|
|
15638
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
15639
|
+
throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
|
|
15640
|
+
}
|
|
15641
|
+
}
|
|
15642
|
+
for (const field of safeIntegerFields) {
|
|
15643
|
+
const candidate = value[field];
|
|
15644
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
15645
|
+
throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
|
|
15646
|
+
}
|
|
15647
|
+
}
|
|
15648
|
+
if (value.outputTokensPerSecond !== void 0 && (typeof value.outputTokensPerSecond !== "number" || !Number.isFinite(value.outputTokensPerSecond) || value.outputTokensPerSecond < 0)) {
|
|
15649
|
+
throw new Error("Harness Usage 'outputTokensPerSecond' must be a finite non-negative number");
|
|
15650
|
+
}
|
|
15651
|
+
if (value.totalCostUsd !== void 0 && (typeof value.totalCostUsd !== "number" || !Number.isFinite(value.totalCostUsd) || value.totalCostUsd < 0)) {
|
|
15652
|
+
throw new Error("Harness Usage 'totalCostUsd' must be a finite non-negative number");
|
|
15653
|
+
}
|
|
15654
|
+
for (const field of ["totalCredits", "contextUsagePercent"]) {
|
|
15655
|
+
const candidate = value[field];
|
|
15656
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)) {
|
|
15657
|
+
throw new Error(`Harness Usage '${field}' must be a finite non-negative number`);
|
|
15658
|
+
}
|
|
15659
|
+
}
|
|
15660
|
+
for (const field of percentFields) {
|
|
15661
|
+
const candidate = value[field];
|
|
15662
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0 || candidate > 100)) {
|
|
15663
|
+
throw new Error(`Harness Usage '${field}' must be between 0 and 100`);
|
|
15664
|
+
}
|
|
15665
|
+
}
|
|
15666
|
+
const hasContextUsed = value.contextUsedTokens !== void 0;
|
|
15667
|
+
const hasContextWindow = value.contextWindowTokens !== void 0;
|
|
15668
|
+
if (hasContextUsed !== hasContextWindow) {
|
|
15669
|
+
throw new Error("Harness Usage context fields must be provided together");
|
|
15670
|
+
}
|
|
15671
|
+
if (hasContextWindow && value.contextWindowTokens === 0) {
|
|
15672
|
+
throw new Error("Harness Usage 'contextWindowTokens' must be greater than zero");
|
|
15673
|
+
}
|
|
15674
|
+
if (value.planFiveHourResetsAtUnix !== void 0 && value.planFiveHourUsedPercent === void 0) {
|
|
15675
|
+
throw new Error("Harness Usage 'planFiveHourResetsAtUnix' must be provided with 'planFiveHourUsedPercent'");
|
|
15676
|
+
}
|
|
15677
|
+
if (value.planSevenDayResetsAtUnix !== void 0 && value.planSevenDayUsedPercent === void 0) {
|
|
15678
|
+
throw new Error("Harness Usage 'planSevenDayResetsAtUnix' must be provided with 'planSevenDayUsedPercent'");
|
|
15679
|
+
}
|
|
15680
|
+
return { ...value };
|
|
15681
|
+
}
|
|
15682
|
+
|
|
15683
|
+
// dist/common.js
|
|
15684
|
+
var CODEBUDDY_ID = harnessIdSchema.parse("codebuddy");
|
|
15685
|
+
var CODEBUDDY_RUNTIME_PROFILE = {
|
|
15686
|
+
harnessId: CODEBUDDY_ID,
|
|
15687
|
+
displayName: "CodeBuddy",
|
|
15688
|
+
interactionIdPrefix: "codebuddy",
|
|
15689
|
+
configDirectoryEnvironmentVariables: ["CODEBUDDY_CONFIG_DIR"],
|
|
15690
|
+
defaultConfigDirectoryName: ".codebuddy"
|
|
15691
|
+
};
|
|
15692
|
+
var OUTPUT_LIMIT = 64e3;
|
|
15693
|
+
var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
15694
|
+
var rows = (value) => Array.isArray(value) ? value.map(record2) : [];
|
|
15695
|
+
var text = (value) => typeof value === "string" ? value : "";
|
|
15696
|
+
var CodeBuddyError = class extends Error {
|
|
15697
|
+
code;
|
|
15698
|
+
constructor(code, message) {
|
|
15699
|
+
super(message);
|
|
15700
|
+
this.code = code;
|
|
15701
|
+
}
|
|
15702
|
+
};
|
|
15703
|
+
function nativeError(error51, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15704
|
+
const diagnostic = sanitizeDiagnosticTail(error51 instanceof Error ? error51.message : String(error51));
|
|
15705
|
+
const nativeCode = record2(error51).code;
|
|
15706
|
+
const code = error51 instanceof CodeBuddyError ? error51.code : nativeCode === -32e3 || /authentication required|not logged in|unauthenticated/iu.test(diagnostic) ? "authenticationRequired" : nativeCode === "ENOENT" ? "notInstalled" : /session.*not found/iu.test(diagnostic) ? "sessionNotFound" : "nativeFailure";
|
|
15707
|
+
return {
|
|
15708
|
+
code,
|
|
15709
|
+
message: `${profile.displayName}: ${diagnostic || "native operation failed"}`,
|
|
15710
|
+
retryable: ["sessionBusy", "unavailable"].includes(code)
|
|
15711
|
+
};
|
|
15712
|
+
}
|
|
15713
|
+
function failure(code, message, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15714
|
+
return { ok: false, error: nativeError(new CodeBuddyError(code, message), profile) };
|
|
15715
|
+
}
|
|
15716
|
+
async function bounded(operation, milliseconds, label, onTimeout) {
|
|
15717
|
+
let timer;
|
|
15718
|
+
try {
|
|
15719
|
+
return await Promise.race([
|
|
15720
|
+
operation,
|
|
15721
|
+
new Promise((_, reject) => {
|
|
15722
|
+
timer = setTimeout(() => {
|
|
15723
|
+
const error51 = new CodeBuddyError("unavailable", `${label} timed out`);
|
|
15724
|
+
try {
|
|
15725
|
+
onTimeout?.(error51);
|
|
15726
|
+
} finally {
|
|
15727
|
+
reject(error51);
|
|
15728
|
+
}
|
|
15729
|
+
}, milliseconds);
|
|
15730
|
+
})
|
|
15731
|
+
]);
|
|
15732
|
+
} finally {
|
|
15733
|
+
clearTimeout(timer);
|
|
15734
|
+
}
|
|
15735
|
+
}
|
|
15736
|
+
|
|
15737
|
+
// dist/slash-commands.js
|
|
15738
|
+
var excluded = /* @__PURE__ */ new Set([
|
|
15739
|
+
"background",
|
|
15740
|
+
"bg",
|
|
15741
|
+
"branch",
|
|
15742
|
+
"fork",
|
|
15743
|
+
"fork-bg",
|
|
15744
|
+
"clear",
|
|
15745
|
+
"resume",
|
|
15746
|
+
"exit",
|
|
15747
|
+
"rewind",
|
|
15748
|
+
"multitask",
|
|
15749
|
+
"agent-mode",
|
|
15750
|
+
"btw",
|
|
15751
|
+
"loop",
|
|
15752
|
+
"goal",
|
|
15753
|
+
"login",
|
|
15754
|
+
"logout",
|
|
15755
|
+
"feedback",
|
|
15756
|
+
"keybindings",
|
|
15757
|
+
"copy",
|
|
15758
|
+
"statusline",
|
|
15759
|
+
"gateway",
|
|
15760
|
+
"remote-control",
|
|
15761
|
+
"_compact"
|
|
15762
|
+
]);
|
|
15763
|
+
function isExcludedInvocation(invocation) {
|
|
15764
|
+
return invocation?.startsWith("/") === true && excluded.has(invocation.slice(1));
|
|
15765
|
+
}
|
|
15766
|
+
function nativeCommandsEnabled(profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15767
|
+
return profile.nativeCommands ?? profile.harnessId === CODEBUDDY_RUNTIME_PROFILE.harnessId;
|
|
15768
|
+
}
|
|
15769
|
+
function commandCatalog(value, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15770
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15771
|
+
return {
|
|
15772
|
+
commands: rows(value).flatMap((entry) => {
|
|
15773
|
+
const name = text(entry.name).replace(/^\//u, "");
|
|
15774
|
+
if (excluded.has(name) || seen.has(name))
|
|
15775
|
+
return [];
|
|
15776
|
+
const parsed = harnessCommandCatalogSchema.safeParse({
|
|
15777
|
+
commands: [
|
|
15778
|
+
{
|
|
15779
|
+
id: `${profile.harnessId}.${name}`,
|
|
15780
|
+
invocation: `/${name}`,
|
|
15781
|
+
label: name,
|
|
15782
|
+
...text(entry.description).trim() ? { description: text(entry.description).trim().slice(0, 512) } : {},
|
|
15783
|
+
argumentMode: name === "compact" || record2(entry.input).hint || record2(entry._meta).type === "skill" ? "text" : "none"
|
|
15784
|
+
}
|
|
15785
|
+
]
|
|
15786
|
+
});
|
|
15787
|
+
if (!parsed.success)
|
|
15788
|
+
return [];
|
|
15789
|
+
seen.add(name);
|
|
15790
|
+
return parsed.data.commands;
|
|
15791
|
+
})
|
|
15792
|
+
};
|
|
15793
|
+
}
|
|
15794
|
+
var CODEBUDDY_COMMAND_CATALOG = commandCatalog([
|
|
15795
|
+
{
|
|
15796
|
+
name: "compact",
|
|
15797
|
+
description: "Summarize conversation context with optional focus instructions"
|
|
15798
|
+
},
|
|
15799
|
+
{ name: "cost", description: "Show current Session usage and cost" }
|
|
15800
|
+
]);
|
|
15801
|
+
function commandPrompt(command, catalog, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15802
|
+
const descriptor = catalog.commands.find((entry) => entry.id === command.commandId);
|
|
15803
|
+
if (!descriptor)
|
|
15804
|
+
return failure("unsupported", "Command is not available in this Session", profile);
|
|
15805
|
+
const args = command.arguments;
|
|
15806
|
+
if (args && (Object.keys(args).some((key) => key !== "text") || args.text !== void 0 && typeof args.text !== "string" || descriptor.argumentMode === "none" && Object.keys(args).length > 0))
|
|
15807
|
+
return failure("invalidRequest", "Command arguments must match the native command", profile);
|
|
15808
|
+
const argument = typeof args?.text === "string" ? args.text.trim() : "";
|
|
15809
|
+
return { ok: true, value: `${descriptor.invocation}${argument ? ` ${argument}` : ""}` };
|
|
15810
|
+
}
|
|
15811
|
+
|
|
15812
|
+
// dist/codebuddy-adapter.js
|
|
15813
|
+
import { stat as stat2 } from "node:fs/promises";
|
|
15814
|
+
|
|
15815
|
+
// dist/acp-client.js
|
|
15816
|
+
import { execFile, spawn } from "node:child_process";
|
|
15817
|
+
import { Readable as Readable2, Writable } from "node:stream";
|
|
15818
|
+
|
|
15819
|
+
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
|
|
15820
|
+
var AGENT_METHODS = {
|
|
15821
|
+
initialize: "initialize",
|
|
15822
|
+
authenticate: "authenticate",
|
|
15823
|
+
providers_list: "providers/list",
|
|
15824
|
+
providers_set: "providers/set",
|
|
15825
|
+
providers_disable: "providers/disable",
|
|
15826
|
+
session_new: "session/new",
|
|
15827
|
+
session_load: "session/load",
|
|
15828
|
+
session_set_mode: "session/set_mode",
|
|
15829
|
+
session_set_config_option: "session/set_config_option",
|
|
15830
|
+
session_prompt: "session/prompt",
|
|
15831
|
+
session_cancel: "session/cancel",
|
|
15832
|
+
mcp_message: "mcp/message",
|
|
15833
|
+
session_list: "session/list",
|
|
15834
|
+
session_delete: "session/delete",
|
|
15835
|
+
session_fork: "session/fork",
|
|
15836
|
+
session_resume: "session/resume",
|
|
15837
|
+
session_close: "session/close",
|
|
15838
|
+
logout: "logout",
|
|
15839
|
+
nes_start: "nes/start",
|
|
15840
|
+
nes_suggest: "nes/suggest",
|
|
15841
|
+
nes_accept: "nes/accept",
|
|
15842
|
+
nes_reject: "nes/reject",
|
|
15843
|
+
nes_close: "nes/close",
|
|
15844
|
+
document_did_open: "document/didOpen",
|
|
15845
|
+
document_did_change: "document/didChange",
|
|
15846
|
+
document_did_close: "document/didClose",
|
|
15847
|
+
document_did_save: "document/didSave",
|
|
15848
|
+
document_did_focus: "document/didFocus"
|
|
15849
|
+
};
|
|
15850
|
+
var CLIENT_METHODS = {
|
|
15851
|
+
session_request_permission: "session/request_permission",
|
|
15852
|
+
session_update: "session/update",
|
|
15853
|
+
fs_write_text_file: "fs/write_text_file",
|
|
15854
|
+
fs_read_text_file: "fs/read_text_file",
|
|
15855
|
+
terminal_create: "terminal/create",
|
|
15856
|
+
terminal_output: "terminal/output",
|
|
15857
|
+
terminal_release: "terminal/release",
|
|
15858
|
+
terminal_wait_for_exit: "terminal/wait_for_exit",
|
|
15859
|
+
terminal_kill: "terminal/kill",
|
|
15860
|
+
mcp_connect: "mcp/connect",
|
|
15861
|
+
mcp_message: "mcp/message",
|
|
15862
|
+
mcp_disconnect: "mcp/disconnect",
|
|
15863
|
+
elicitation_create: "elicitation/create",
|
|
15864
|
+
elicitation_complete: "elicitation/complete"
|
|
15865
|
+
};
|
|
15866
|
+
var PROTOCOL_METHODS = {
|
|
15867
|
+
cancel_request: "$/cancel_request"
|
|
15868
|
+
};
|
|
15869
|
+
|
|
15870
|
+
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema-deserialize.js
|
|
15871
|
+
var skippedItem = /* @__PURE__ */ Symbol("skippedItem");
|
|
15872
|
+
function defaultOnError(schema, fallback) {
|
|
15873
|
+
return schema.catch(fallback);
|
|
15874
|
+
}
|
|
15875
|
+
function requiredDefaultOnError(schema, fallback) {
|
|
15876
|
+
const schemaWithCatch = schema.catch(fallback);
|
|
15877
|
+
return external_exports.unknown().transform((value, context) => {
|
|
15878
|
+
if (value !== void 0)
|
|
15879
|
+
return schemaWithCatch.parse(value);
|
|
15880
|
+
context.addIssue({
|
|
15881
|
+
code: "custom",
|
|
15882
|
+
message: "Required value is missing"
|
|
15883
|
+
});
|
|
15884
|
+
return external_exports.NEVER;
|
|
15885
|
+
});
|
|
15886
|
+
}
|
|
15887
|
+
function stringTag(value, key) {
|
|
15888
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
15889
|
+
return void 0;
|
|
15890
|
+
}
|
|
15891
|
+
const tag = value[key];
|
|
15892
|
+
return typeof tag === "string" ? tag : void 0;
|
|
15893
|
+
}
|
|
15894
|
+
function excludeKnownTags(schema, key, knownTags) {
|
|
15895
|
+
return schema.superRefine((value, context) => {
|
|
15896
|
+
const tag = stringTag(value, key);
|
|
15897
|
+
if (tag !== void 0 && knownTags.includes(tag)) {
|
|
15898
|
+
context.addIssue({
|
|
15899
|
+
code: "custom",
|
|
15900
|
+
path: [key],
|
|
15901
|
+
message: `${key} ${JSON.stringify(tag)} is reserved by a known variant, but the value does not match that variant's schema`
|
|
15902
|
+
});
|
|
15903
|
+
}
|
|
15904
|
+
});
|
|
15905
|
+
}
|
|
15906
|
+
function preserveCustomPayload(schema, key, knownTags) {
|
|
15907
|
+
return external_exports.unknown().transform((value, context) => {
|
|
15908
|
+
const result = schema.safeParse(value);
|
|
15909
|
+
if (!result.success) {
|
|
15910
|
+
for (const issue2 of result.error.issues) {
|
|
15911
|
+
context.addIssue({ ...issue2, input: value });
|
|
15912
|
+
}
|
|
15913
|
+
return external_exports.NEVER;
|
|
15914
|
+
}
|
|
15915
|
+
const output = result.data;
|
|
15916
|
+
const tag = stringTag(value, key);
|
|
15917
|
+
if (tag !== void 0 && !knownTags.includes(tag)) {
|
|
15918
|
+
const raw = value;
|
|
15919
|
+
for (const [property, rawValue] of Object.entries(raw)) {
|
|
15920
|
+
if (property === "__proto__")
|
|
15921
|
+
continue;
|
|
15922
|
+
if (!Object.hasOwn(output, property))
|
|
15923
|
+
output[property] = rawValue;
|
|
15924
|
+
}
|
|
15925
|
+
}
|
|
15926
|
+
return output;
|
|
15927
|
+
});
|
|
15928
|
+
}
|
|
15929
|
+
function vecSkipError(itemSchema) {
|
|
15930
|
+
return external_exports.array(itemSchema.catch(skippedItem)).transform((items) => items.filter((item) => item !== skippedItem));
|
|
15931
|
+
}
|
|
15932
|
+
|
|
15933
|
+
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema/zod.gen.js
|
|
15934
|
+
var zRequestId = union([number2(), string2()]).nullable();
|
|
15935
|
+
var zSessionId = string2();
|
|
15936
|
+
var zWriteTextFileRequest = object({
|
|
15937
|
+
sessionId: zSessionId,
|
|
15938
|
+
path: string2(),
|
|
15939
|
+
content: string2(),
|
|
15940
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15941
|
+
});
|
|
15942
|
+
var zReadTextFileRequest = object({
|
|
15943
|
+
sessionId: zSessionId,
|
|
15944
|
+
path: string2(),
|
|
15945
|
+
line: defaultOnError(int().gte(0).max(4294967295, {
|
|
15946
|
+
error: "Invalid value: Expected uint32 to be <= 4294967295"
|
|
15947
|
+
}).nullish(), () => void 0),
|
|
15948
|
+
limit: defaultOnError(int().gte(0).max(4294967295, {
|
|
15949
|
+
error: "Invalid value: Expected uint32 to be <= 4294967295"
|
|
15950
|
+
}).nullish(), () => void 0),
|
|
15951
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15952
|
+
});
|
|
15953
|
+
var zToolCallId = string2();
|
|
15954
|
+
var zToolKind = union([
|
|
15955
|
+
literal("read"),
|
|
15956
|
+
literal("edit"),
|
|
15957
|
+
literal("delete"),
|
|
15958
|
+
literal("move"),
|
|
15959
|
+
literal("search"),
|
|
15960
|
+
literal("execute"),
|
|
15961
|
+
literal("think"),
|
|
15962
|
+
literal("fetch"),
|
|
15963
|
+
literal("switch_mode"),
|
|
15964
|
+
literal("other")
|
|
15965
|
+
]);
|
|
15966
|
+
var zToolCallStatus = union([
|
|
15967
|
+
literal("pending"),
|
|
15968
|
+
literal("in_progress"),
|
|
15969
|
+
literal("completed"),
|
|
15970
|
+
literal("failed")
|
|
15971
|
+
]);
|
|
15972
|
+
var zRole = union([literal("assistant"), literal("user")]);
|
|
15973
|
+
var zAnnotations = object({
|
|
15974
|
+
audience: defaultOnError(vecSkipError(zRole).nullish(), () => void 0),
|
|
15975
|
+
lastModified: defaultOnError(string2().nullish(), () => void 0),
|
|
15976
|
+
priority: defaultOnError(number2().nullish(), () => void 0),
|
|
15977
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15978
|
+
});
|
|
15979
|
+
var zTextContent = object({
|
|
15980
|
+
annotations: defaultOnError(zAnnotations.nullish(), () => void 0),
|
|
15981
|
+
text: string2(),
|
|
15982
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15983
|
+
});
|
|
15984
|
+
var zImageContent = object({
|
|
15985
|
+
annotations: defaultOnError(zAnnotations.nullish(), () => void 0),
|
|
15986
|
+
data: string2(),
|
|
15987
|
+
mimeType: string2(),
|
|
15988
|
+
uri: defaultOnError(string2().nullish(), () => void 0),
|
|
15989
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15990
|
+
});
|
|
15991
|
+
var zAudioContent = object({
|
|
15992
|
+
annotations: defaultOnError(zAnnotations.nullish(), () => void 0),
|
|
15993
|
+
data: string2(),
|
|
15994
|
+
mimeType: string2(),
|
|
15995
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15996
|
+
});
|
|
15997
|
+
var zResourceLink = object({
|
|
15998
|
+
annotations: defaultOnError(zAnnotations.nullish(), () => void 0),
|
|
15999
|
+
description: defaultOnError(string2().nullish(), () => void 0),
|
|
16000
|
+
mimeType: defaultOnError(string2().nullish(), () => void 0),
|
|
16001
|
+
name: string2(),
|
|
16002
|
+
size: defaultOnError(number2().nullish(), () => void 0),
|
|
16003
|
+
title: defaultOnError(string2().nullish(), () => void 0),
|
|
16004
|
+
uri: string2(),
|
|
15551
16005
|
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15552
16006
|
});
|
|
15553
16007
|
var zTextResourceContents = object({
|
|
@@ -17096,17 +17550,17 @@ function isResponseMessage(value) {
|
|
|
17096
17550
|
function isNotificationMessage(value) {
|
|
17097
17551
|
return isJsonRpcEnvelope(value) && !("id" in value) && typeof value["method"] === "string";
|
|
17098
17552
|
}
|
|
17099
|
-
function
|
|
17553
|
+
function isRecord2(value) {
|
|
17100
17554
|
return typeof value === "object" && value !== null;
|
|
17101
17555
|
}
|
|
17102
17556
|
function isJsonRpcEnvelope(value) {
|
|
17103
|
-
return
|
|
17557
|
+
return isRecord2(value) && value["jsonrpc"] === "2.0";
|
|
17104
17558
|
}
|
|
17105
17559
|
function isJsonRpcId(value) {
|
|
17106
17560
|
return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
17107
17561
|
}
|
|
17108
17562
|
function isResponseShapedMessage(value) {
|
|
17109
|
-
return
|
|
17563
|
+
return isRecord2(value) && !("method" in value) && ("id" in value || "result" in value || "error" in value);
|
|
17110
17564
|
}
|
|
17111
17565
|
function isResponseBatch(batch) {
|
|
17112
17566
|
let hasValidCall = false;
|
|
@@ -17116,7 +17570,7 @@ function isResponseBatch(batch) {
|
|
|
17116
17570
|
for (const entry of batch) {
|
|
17117
17571
|
hasValidCall ||= isRequestMessage(entry) || isNotificationMessage(entry);
|
|
17118
17572
|
hasValidResponse ||= isResponseMessage(entry);
|
|
17119
|
-
if (!
|
|
17573
|
+
if (!isRecord2(entry)) {
|
|
17120
17574
|
continue;
|
|
17121
17575
|
}
|
|
17122
17576
|
hasCallShape ||= "method" in entry;
|
|
@@ -17131,13 +17585,13 @@ function isResponseBatch(batch) {
|
|
|
17131
17585
|
return hasResponseShape && !hasCallShape;
|
|
17132
17586
|
}
|
|
17133
17587
|
function cancelRequestId(params) {
|
|
17134
|
-
if (!
|
|
17588
|
+
if (!isRecord2(params) || !isJsonRpcId(params["requestId"])) {
|
|
17135
17589
|
return void 0;
|
|
17136
17590
|
}
|
|
17137
17591
|
return params["requestId"];
|
|
17138
17592
|
}
|
|
17139
17593
|
function isErrorResponse(value) {
|
|
17140
|
-
return
|
|
17594
|
+
return isRecord2(value) && typeof value["code"] === "number" && Number.isInteger(value["code"]) && typeof value["message"] === "string";
|
|
17141
17595
|
}
|
|
17142
17596
|
var Handled = {
|
|
17143
17597
|
/**
|
|
@@ -17628,7 +18082,7 @@ var Connection = class {
|
|
|
17628
18082
|
this.receiveBatch(message);
|
|
17629
18083
|
return;
|
|
17630
18084
|
}
|
|
17631
|
-
if (!
|
|
18085
|
+
if (!isRecord2(message)) {
|
|
17632
18086
|
console.error("Invalid message", { message });
|
|
17633
18087
|
return;
|
|
17634
18088
|
}
|
|
@@ -17691,7 +18145,7 @@ var Connection = class {
|
|
|
17691
18145
|
if (this.abortController.signal.aborted) {
|
|
17692
18146
|
return Promise.resolve();
|
|
17693
18147
|
}
|
|
17694
|
-
if (!
|
|
18148
|
+
if (!isRecord2(message)) {
|
|
17695
18149
|
console.error("Invalid message", { message });
|
|
17696
18150
|
return Promise.resolve();
|
|
17697
18151
|
}
|
|
@@ -18061,7 +18515,7 @@ function ndJsonStream(output, input) {
|
|
|
18061
18515
|
if (trimmedLine) {
|
|
18062
18516
|
try {
|
|
18063
18517
|
const message = JSON.parse(trimmedLine);
|
|
18064
|
-
if (
|
|
18518
|
+
if (isRecord2(message) || Array.isArray(message)) {
|
|
18065
18519
|
controller.enqueue(message);
|
|
18066
18520
|
} else {
|
|
18067
18521
|
console.warn("Skipping JSON line that is not an object:", trimmedLine);
|
|
@@ -19520,507 +19974,308 @@ var ClientSideConnection = class {
|
|
|
19520
19974
|
get closed() {
|
|
19521
19975
|
return this.connection.closed;
|
|
19522
19976
|
}
|
|
19523
|
-
};
|
|
19524
|
-
|
|
19525
|
-
//
|
|
19526
|
-
import
|
|
19527
|
-
import
|
|
19528
|
-
|
|
19529
|
-
|
|
19530
|
-
|
|
19531
|
-
|
|
19532
|
-
|
|
19533
|
-
|
|
19534
|
-
|
|
19535
|
-
|
|
19536
|
-
|
|
19537
|
-
|
|
19538
|
-
|
|
19539
|
-
|
|
19540
|
-
|
|
19541
|
-
|
|
19542
|
-
|
|
19543
|
-
|
|
19544
|
-
|
|
19545
|
-
|
|
19546
|
-
|
|
19547
|
-
|
|
19548
|
-
if (targetPath(platform).extname(command) !== "")
|
|
19549
|
-
return [""];
|
|
19550
|
-
return (environmentValue(environment, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter(Boolean);
|
|
19551
|
-
}
|
|
19552
|
-
function isExecutableFile(filePath, platform) {
|
|
19553
|
-
try {
|
|
19554
|
-
fs.accessSync(filePath, platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK);
|
|
19555
|
-
return fs.statSync(filePath).isFile();
|
|
19556
|
-
} catch {
|
|
19557
|
-
return false;
|
|
19558
|
-
}
|
|
19559
|
-
}
|
|
19560
|
-
function subdirectoryNames(directory) {
|
|
19561
|
-
try {
|
|
19562
|
-
return fs.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
19563
|
-
} catch {
|
|
19564
|
-
return [];
|
|
19565
|
-
}
|
|
19566
|
-
}
|
|
19567
|
-
function newestFirst(names) {
|
|
19568
|
-
return [...names].sort((left, right) => right.localeCompare(left, void 0, { numeric: true }));
|
|
19569
|
-
}
|
|
19570
|
-
|
|
19571
|
-
// ../../harness-discovery/dist/invocation.js
|
|
19572
|
-
import path2 from "node:path";
|
|
19573
|
-
function commandInvocation(command, arguments_, environment, platform = process.platform) {
|
|
19574
|
-
const extension = path2.win32.extname(command).toLowerCase();
|
|
19575
|
-
if (platform !== "win32" || ![".cmd", ".bat"].includes(extension)) {
|
|
19576
|
-
return { command, arguments: [...arguments_], windowsVerbatimArguments: false };
|
|
19577
|
-
}
|
|
19578
|
-
const quote = (value) => `"${value.replaceAll("%", "%%").replaceAll('"', '""')}"`;
|
|
19579
|
-
const commandLine = [command, ...arguments_].map(quote).join(" ");
|
|
19580
|
-
return {
|
|
19581
|
-
command: environmentValue(environment, "ComSpec") ?? "cmd.exe",
|
|
19582
|
-
arguments: ["/d", "/v:off", "/s", "/c", `"${commandLine}"`],
|
|
19583
|
-
windowsVerbatimArguments: true
|
|
19584
|
-
};
|
|
19585
|
-
}
|
|
19586
|
-
|
|
19587
|
-
// ../../harness-discovery/dist/node-runtime.js
|
|
19588
|
-
import path3 from "node:path";
|
|
19589
|
-
function withNodeRuntimeOnPath(environment, runtimeExecutable = process.execPath, platform = process.platform) {
|
|
19590
|
-
const pathKey = Object.keys(environment).find((name) => name.toLowerCase() === "path") ?? "PATH";
|
|
19591
|
-
const delimiter = platform === "win32" ? ";" : ":";
|
|
19592
|
-
const runtimeDirectory = path3.dirname(runtimeExecutable);
|
|
19593
|
-
const directories = (environment[pathKey] ?? "").split(delimiter).filter(Boolean);
|
|
19594
|
-
const equal = platform === "win32" ? (value) => value.toLowerCase() : (value) => value;
|
|
19595
|
-
if (!directories.some((directory) => equal(directory) === equal(runtimeDirectory))) {
|
|
19596
|
-
directories.unshift(runtimeDirectory);
|
|
19597
|
-
}
|
|
19598
|
-
return { ...environment, [pathKey]: directories.join(delimiter) };
|
|
19599
|
-
}
|
|
19600
|
-
|
|
19601
|
-
// ../../harness-discovery/dist/resolve.js
|
|
19602
|
-
import os from "node:os";
|
|
19603
|
-
|
|
19604
|
-
// ../../harness-discovery/dist/version-managers.js
|
|
19605
|
-
function versionManagerBinaryDirectories(context) {
|
|
19606
|
-
const { platform, environment, home } = context;
|
|
19607
|
-
const list = context.subdirectories ?? subdirectoryNames;
|
|
19608
|
-
const pathFlavor = targetPath(platform);
|
|
19609
|
-
const value = (name) => environmentValue(environment, name);
|
|
19610
|
-
const directories = [];
|
|
19611
|
-
const versioned = (root, ...tail) => {
|
|
19612
|
-
for (const version2 of newestFirst(list(root))) {
|
|
19613
|
-
directories.push(pathFlavor.join(root, version2, ...tail));
|
|
19614
|
-
}
|
|
19615
|
-
};
|
|
19616
|
-
if (platform === "win32") {
|
|
19617
|
-
const appData = value("APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming");
|
|
19618
|
-
const localAppData = value("LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local");
|
|
19619
|
-
versioned(pathFlavor.join(appData, "nvm"));
|
|
19620
|
-
versioned(value("FNM_DIR") ?? pathFlavor.join(appData, "fnm", "node-versions"), "installation");
|
|
19621
|
-
directories.push(pathFlavor.join(localAppData, "Volta", "bin"));
|
|
19622
|
-
directories.push(pathFlavor.join(home, ".bun", "bin"));
|
|
19623
|
-
const pnpmHome2 = value("PNPM_HOME");
|
|
19624
|
-
if (pnpmHome2)
|
|
19625
|
-
directories.push(pnpmHome2);
|
|
19626
|
-
directories.push(pathFlavor.join(localAppData, "pnpm"));
|
|
19627
|
-
return directories;
|
|
19628
|
-
}
|
|
19629
|
-
versioned(pathFlavor.join(value("NVM_DIR") ?? pathFlavor.join(home, ".nvm"), "versions", "node"), "bin");
|
|
19630
|
-
const fnmRoots = [
|
|
19631
|
-
value("FNM_DIR"),
|
|
19632
|
-
pathFlavor.join(home, ".local", "share", "fnm"),
|
|
19633
|
-
pathFlavor.join(home, "Library", "Application Support", "fnm")
|
|
19634
|
-
].filter((root) => root !== void 0);
|
|
19635
|
-
for (const root of fnmRoots) {
|
|
19636
|
-
versioned(pathFlavor.join(root, "node-versions"), "installation", "bin");
|
|
19637
|
-
}
|
|
19638
|
-
const voltaHome = value("VOLTA_HOME") ?? pathFlavor.join(home, ".volta");
|
|
19639
|
-
versioned(pathFlavor.join(voltaHome, "tools", "image", "node"), "bin");
|
|
19640
|
-
directories.push(pathFlavor.join(voltaHome, "bin"));
|
|
19641
|
-
const asdfHome = value("ASDF_DATA_DIR") ?? pathFlavor.join(home, ".asdf");
|
|
19642
|
-
versioned(pathFlavor.join(asdfHome, "installs", "nodejs"), "bin");
|
|
19643
|
-
directories.push(pathFlavor.join(asdfHome, "shims"));
|
|
19644
|
-
const nodenvHome = value("NODENV_ROOT") ?? pathFlavor.join(home, ".nodenv");
|
|
19645
|
-
versioned(pathFlavor.join(nodenvHome, "versions"), "bin");
|
|
19646
|
-
directories.push(pathFlavor.join(nodenvHome, "shims"));
|
|
19647
|
-
versioned(pathFlavor.join(value("N_PREFIX") ?? "/usr/local", "n", "versions", "node"), "bin");
|
|
19648
|
-
directories.push(pathFlavor.join(home, ".bun", "bin"));
|
|
19649
|
-
const pnpmHome = value("PNPM_HOME");
|
|
19650
|
-
if (pnpmHome)
|
|
19651
|
-
directories.push(pnpmHome);
|
|
19652
|
-
directories.push(pathFlavor.join(home, "Library", "pnpm"));
|
|
19653
|
-
directories.push(pathFlavor.join(home, ".local", "share", "pnpm"));
|
|
19654
|
-
for (const prefix of ["/opt/homebrew/opt", "/usr/local/opt"]) {
|
|
19655
|
-
for (const formula of newestFirst(list(prefix).filter((name) => name.startsWith("node@")))) {
|
|
19656
|
-
directories.push(pathFlavor.join(prefix, formula, "bin"));
|
|
19657
|
-
}
|
|
19658
|
-
}
|
|
19659
|
-
return directories;
|
|
19660
|
-
}
|
|
19661
|
-
|
|
19662
|
-
// ../../harness-discovery/dist/resolve.js
|
|
19663
|
-
var VERSION_MANAGER_ROOTS = "<version-managers>";
|
|
19664
|
-
function installRootExtensions(platform) {
|
|
19665
|
-
return platform === "win32" ? [".exe", ".cmd"] : [""];
|
|
19666
|
-
}
|
|
19667
|
-
function resolveHomeDirectory(input) {
|
|
19668
|
-
return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
|
|
19669
|
-
}
|
|
19670
|
-
function templateVariables(environment, platform, home) {
|
|
19671
|
-
const pathFlavor = targetPath(platform);
|
|
19672
|
-
return {
|
|
19673
|
-
HOME: home,
|
|
19674
|
-
USERPROFILE: home,
|
|
19675
|
-
APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
|
|
19676
|
-
LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
|
|
19677
|
-
};
|
|
19678
|
-
}
|
|
19679
|
-
function joinTemplate(platform, value) {
|
|
19680
|
-
const pathFlavor = targetPath(platform);
|
|
19681
|
-
const segments = value.split("/");
|
|
19682
|
-
const head = segments[0] ?? "";
|
|
19683
|
-
const tail = segments.slice(1);
|
|
19684
|
-
if (head === "")
|
|
19685
|
-
return pathFlavor.join(pathFlavor.sep, ...tail);
|
|
19686
|
-
return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
|
|
19687
|
-
}
|
|
19688
|
-
function expandInstallRoot(template, environment, platform, home) {
|
|
19689
|
-
const variables = templateVariables(environment, platform, home);
|
|
19690
|
-
let unresolved = false;
|
|
19691
|
-
const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
|
|
19692
|
-
const value = variables[name] ?? environmentValue(environment, name);
|
|
19693
|
-
if (value === void 0 || value === "") {
|
|
19694
|
-
unresolved = true;
|
|
19695
|
-
return "";
|
|
19696
|
-
}
|
|
19697
|
-
return value;
|
|
19698
|
-
});
|
|
19699
|
-
return unresolved ? void 0 : joinTemplate(platform, substituted);
|
|
19700
|
-
}
|
|
19701
|
-
function installRootDirectories(spec, input, dependencies, platform, home) {
|
|
19702
|
-
const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
|
|
19703
|
-
const directories = [];
|
|
19704
|
-
for (const template of templates) {
|
|
19705
|
-
if (template === VERSION_MANAGER_ROOTS) {
|
|
19706
|
-
directories.push(...versionManagerBinaryDirectories({
|
|
19707
|
-
platform,
|
|
19708
|
-
environment: input.environment,
|
|
19709
|
-
home,
|
|
19710
|
-
...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
|
|
19711
|
-
}));
|
|
19712
|
-
continue;
|
|
19713
|
-
}
|
|
19714
|
-
const directory = expandInstallRoot(template, input.environment, platform, home);
|
|
19715
|
-
if (directory !== void 0)
|
|
19716
|
-
directories.push(directory);
|
|
19717
|
-
}
|
|
19718
|
-
return directories;
|
|
19719
|
-
}
|
|
19720
|
-
function harnessCandidates(spec, input, dependencies = {}) {
|
|
19721
|
-
const platform = input.platform ?? process.platform;
|
|
19722
|
-
const pathFlavor = targetPath(platform);
|
|
19723
|
-
const configured = input.command ?? (spec.commandEnvironmentVariable ? environmentValue(input.environment, spec.commandEnvironmentVariable) : void 0);
|
|
19724
|
-
const command = configured ?? spec.command;
|
|
19725
|
-
if (pathFlavor.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
|
|
19726
|
-
return [{ candidate: command, source: "configured" }];
|
|
19727
|
-
}
|
|
19728
|
-
const candidates = [];
|
|
19729
|
-
const extensions = executableExtensions(command, platform, input.environment);
|
|
19730
|
-
for (const directory of pathDirectories(input.environment, platform)) {
|
|
19731
|
-
for (const extension of extensions) {
|
|
19732
|
-
candidates.push({
|
|
19733
|
-
candidate: pathFlavor.join(directory, command + extension),
|
|
19734
|
-
source: "path"
|
|
19735
|
-
});
|
|
19736
|
-
}
|
|
19737
|
-
}
|
|
19738
|
-
if (configured !== void 0)
|
|
19739
|
-
return candidates;
|
|
19740
|
-
const home = resolveHomeDirectory(input);
|
|
19741
|
-
for (const directory of installRootDirectories(spec, input, dependencies, platform, home)) {
|
|
19742
|
-
for (const extension of installRootExtensions(platform)) {
|
|
19743
|
-
candidates.push({
|
|
19744
|
-
candidate: pathFlavor.join(directory, spec.command + extension),
|
|
19745
|
-
source: "install-root"
|
|
19746
|
-
});
|
|
19747
|
-
}
|
|
19977
|
+
};
|
|
19978
|
+
|
|
19979
|
+
// dist/copy-cleanup.js
|
|
19980
|
+
import { randomBytes } from "node:crypto";
|
|
19981
|
+
import { createInterface } from "node:readline";
|
|
19982
|
+
import { stripVTControlCharacters } from "node:util";
|
|
19983
|
+
import { Readable } from "node:stream";
|
|
19984
|
+
var CodeBuddyCopyCleanup = class {
|
|
19985
|
+
copyId;
|
|
19986
|
+
cwd;
|
|
19987
|
+
password = randomBytes(32).toString("base64url");
|
|
19988
|
+
arguments = [
|
|
19989
|
+
"--acp",
|
|
19990
|
+
"--serve",
|
|
19991
|
+
"--host",
|
|
19992
|
+
"127.0.0.1",
|
|
19993
|
+
"--port",
|
|
19994
|
+
"0",
|
|
19995
|
+
"--auth",
|
|
19996
|
+
"password"
|
|
19997
|
+
];
|
|
19998
|
+
#endpoint;
|
|
19999
|
+
constructor(copyId, cwd) {
|
|
20000
|
+
this.copyId = copyId;
|
|
20001
|
+
this.cwd = cwd;
|
|
19748
20002
|
}
|
|
19749
|
-
|
|
20003
|
+
environment(environment) {
|
|
20004
|
+
return {
|
|
20005
|
+
...environment,
|
|
20006
|
+
CODEBUDDY_GATEWAY_AUTH: "password",
|
|
20007
|
+
CODEBUDDY_GATEWAY_PASSWORD: this.password,
|
|
20008
|
+
CODEBUDDY_GATEWAY_BASE_PATH: ""
|
|
20009
|
+
};
|
|
20010
|
+
}
|
|
20011
|
+
/** Native --serve banners include its password; never pass them to the ACP parser/logs. */
|
|
20012
|
+
protocolOutput(stdout) {
|
|
20013
|
+
return Readable.from(this.#protocolLines(stdout));
|
|
20014
|
+
}
|
|
20015
|
+
async *#protocolLines(stdout) {
|
|
20016
|
+
for await (const line of createInterface({ input: stdout })) {
|
|
20017
|
+
const endpoint = /^\s*Endpoint\s+(http:\/\/127\.0\.0\.1:\d+)\s*$/u.exec(stripVTControlCharacters(line));
|
|
20018
|
+
if (endpoint)
|
|
20019
|
+
this.#endpoint = endpoint[1];
|
|
20020
|
+
if (line.trimStart().startsWith("{"))
|
|
20021
|
+
yield Buffer.from(`${line}
|
|
20022
|
+
`);
|
|
20023
|
+
}
|
|
20024
|
+
}
|
|
20025
|
+
async remove() {
|
|
20026
|
+
if (!this.#endpoint)
|
|
20027
|
+
throw new CodeBuddyError("nativeFailure", `Native cleanup endpoint was not reported; temporary Session ${this.copyId} remains`);
|
|
20028
|
+
const response = await fetch(`${this.#endpoint}/api/v1/sessions/${encodeURIComponent(this.copyId)}?cwd=${encodeURIComponent(this.cwd)}`, {
|
|
20029
|
+
method: "DELETE",
|
|
20030
|
+
headers: { Authorization: `Bearer ${this.password}`, "x-codebuddy-request": "true" },
|
|
20031
|
+
signal: AbortSignal.timeout(5e3),
|
|
20032
|
+
redirect: "error"
|
|
20033
|
+
}).catch(() => {
|
|
20034
|
+
throw new CodeBuddyError("nativeFailure", `Native cleanup request failed; temporary Session ${this.copyId} remains`);
|
|
20035
|
+
});
|
|
20036
|
+
await response.body?.cancel();
|
|
20037
|
+
if (response.status !== 204)
|
|
20038
|
+
throw new CodeBuddyError("nativeFailure", `Native cleanup failed (${response.status}); temporary Session ${this.copyId} remains`);
|
|
20039
|
+
}
|
|
20040
|
+
};
|
|
20041
|
+
|
|
20042
|
+
// ../../harness-discovery/dist/environment.js
|
|
20043
|
+
import fs from "node:fs";
|
|
20044
|
+
import path from "node:path";
|
|
20045
|
+
function targetPath(platform) {
|
|
20046
|
+
return platform === "win32" ? path.win32 : path.posix;
|
|
19750
20047
|
}
|
|
19751
|
-
function
|
|
19752
|
-
const
|
|
19753
|
-
const
|
|
19754
|
-
|
|
19755
|
-
|
|
19756
|
-
for (const { candidate, source } of harnessCandidates(spec, input, dependencies)) {
|
|
19757
|
-
const executable = runnable(candidate, context);
|
|
19758
|
-
if (executable !== void 0 && isExecutable(executable))
|
|
19759
|
-
return { executable, source };
|
|
20048
|
+
function environmentValue(environment, name) {
|
|
20049
|
+
const lowered = name.toLowerCase();
|
|
20050
|
+
for (const [key, value] of Object.entries(environment)) {
|
|
20051
|
+
if (key.toLowerCase() === lowered)
|
|
20052
|
+
return value;
|
|
19760
20053
|
}
|
|
19761
20054
|
return void 0;
|
|
19762
20055
|
}
|
|
19763
|
-
|
|
19764
|
-
|
|
19765
|
-
function invalidRequest(message) {
|
|
19766
|
-
return { code: "invalidRequest", message, retryable: false };
|
|
20056
|
+
function pathDelimiter(platform) {
|
|
20057
|
+
return platform === "win32" ? ";" : ":";
|
|
19767
20058
|
}
|
|
19768
|
-
function
|
|
19769
|
-
return
|
|
20059
|
+
function pathDirectories(environment, platform) {
|
|
20060
|
+
return (environmentValue(environment, "PATH") ?? "").split(pathDelimiter(platform)).map((directory) => directory.trim().replace(/^"|"$/gu, "")).filter(Boolean);
|
|
19770
20061
|
}
|
|
19771
|
-
|
|
19772
|
-
|
|
19773
|
-
|
|
19774
|
-
|
|
20062
|
+
function executableExtensions(command, platform, environment) {
|
|
20063
|
+
if (platform !== "win32")
|
|
20064
|
+
return [""];
|
|
20065
|
+
if (targetPath(platform).extname(command) !== "")
|
|
20066
|
+
return [""];
|
|
20067
|
+
return (environmentValue(environment, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter(Boolean);
|
|
19775
20068
|
}
|
|
19776
|
-
function
|
|
19777
|
-
|
|
19778
|
-
|
|
19779
|
-
return
|
|
19780
|
-
}
|
|
19781
|
-
|
|
19782
|
-
if (!questionIds.has(answerId)) {
|
|
19783
|
-
return invalidRequest2("Question Response contains an unknown Question ID");
|
|
19784
|
-
}
|
|
19785
|
-
}
|
|
19786
|
-
for (const question of interaction.questions) {
|
|
19787
|
-
const answers = response.answers[question.id] ?? [];
|
|
19788
|
-
if (!question.optional && answers.length === 0) {
|
|
19789
|
-
return invalidRequest2("Question Response omits a required answer");
|
|
19790
|
-
}
|
|
19791
|
-
if (question.type === "text") {
|
|
19792
|
-
if (answers.length > 1) {
|
|
19793
|
-
return invalidRequest2("Text Question accepts at most one answer");
|
|
19794
|
-
}
|
|
19795
|
-
continue;
|
|
19796
|
-
}
|
|
19797
|
-
if (!question.multiple && answers.length > 1) {
|
|
19798
|
-
return invalidRequest2("Single-choice Question accepts at most one answer");
|
|
19799
|
-
}
|
|
19800
|
-
const declared = new Set(question.options.map(({ value }) => value));
|
|
19801
|
-
if (!question.allowOther && answers.some((answer) => !declared.has(answer))) {
|
|
19802
|
-
return invalidRequest2("Question Response contains an undeclared choice");
|
|
19803
|
-
}
|
|
20069
|
+
function isExecutableFile(filePath, platform) {
|
|
20070
|
+
try {
|
|
20071
|
+
fs.accessSync(filePath, platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK);
|
|
20072
|
+
return fs.statSync(filePath).isFile();
|
|
20073
|
+
} catch {
|
|
20074
|
+
return false;
|
|
19804
20075
|
}
|
|
19805
|
-
return null;
|
|
19806
20076
|
}
|
|
19807
|
-
|
|
19808
|
-
|
|
19809
|
-
|
|
19810
|
-
|
|
20077
|
+
function subdirectoryNames(directory) {
|
|
20078
|
+
try {
|
|
20079
|
+
return fs.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
20080
|
+
} catch {
|
|
20081
|
+
return [];
|
|
20082
|
+
}
|
|
19811
20083
|
}
|
|
19812
|
-
function
|
|
19813
|
-
return
|
|
20084
|
+
function newestFirst(names) {
|
|
20085
|
+
return [...names].sort((left, right) => right.localeCompare(left, void 0, { numeric: true }));
|
|
19814
20086
|
}
|
|
19815
|
-
|
|
19816
|
-
|
|
19817
|
-
|
|
19818
|
-
|
|
19819
|
-
|
|
19820
|
-
|
|
20087
|
+
|
|
20088
|
+
// ../../harness-discovery/dist/invocation.js
|
|
20089
|
+
import path2 from "node:path";
|
|
20090
|
+
function commandInvocation(command, arguments_, environment, platform = process.platform) {
|
|
20091
|
+
const extension = path2.win32.extname(command).toLowerCase();
|
|
20092
|
+
if (platform !== "win32" || ![".cmd", ".bat"].includes(extension)) {
|
|
20093
|
+
return { command, arguments: [...arguments_], windowsVerbatimArguments: false };
|
|
19821
20094
|
}
|
|
19822
|
-
|
|
20095
|
+
const quote = (value) => `"${value.replaceAll("%", "%%").replaceAll('"', '""')}"`;
|
|
20096
|
+
const commandLine = [command, ...arguments_].map(quote).join(" ");
|
|
20097
|
+
return {
|
|
20098
|
+
command: environmentValue(environment, "ComSpec") ?? "cmd.exe",
|
|
20099
|
+
arguments: ["/d", "/v:off", "/s", "/c", `"${commandLine}"`],
|
|
20100
|
+
windowsVerbatimArguments: true
|
|
20101
|
+
};
|
|
19823
20102
|
}
|
|
19824
20103
|
|
|
19825
|
-
// ../../harness-
|
|
19826
|
-
|
|
19827
|
-
|
|
19828
|
-
|
|
19829
|
-
|
|
19830
|
-
|
|
19831
|
-
|
|
19832
|
-
|
|
19833
|
-
|
|
19834
|
-
|
|
19835
|
-
if (this.#consumerCreated) {
|
|
19836
|
-
throw new Error("Harness outputs allow only one consumer");
|
|
19837
|
-
}
|
|
19838
|
-
this.#consumerCreated = true;
|
|
19839
|
-
return {
|
|
19840
|
-
next: () => this.#next()
|
|
19841
|
-
};
|
|
19842
|
-
}
|
|
19843
|
-
};
|
|
19844
|
-
}
|
|
19845
|
-
emit(value) {
|
|
19846
|
-
if (this.#ended)
|
|
19847
|
-
return false;
|
|
19848
|
-
const resolve = this.#pending.shift();
|
|
19849
|
-
if (resolve)
|
|
19850
|
-
resolve({ done: false, value });
|
|
19851
|
-
else
|
|
19852
|
-
this.#values.push(value);
|
|
19853
|
-
return true;
|
|
19854
|
-
}
|
|
19855
|
-
end() {
|
|
19856
|
-
if (this.#ended)
|
|
19857
|
-
return;
|
|
19858
|
-
this.#ended = true;
|
|
19859
|
-
if (this.#values.length !== 0)
|
|
19860
|
-
return;
|
|
19861
|
-
for (const resolve of this.#pending.splice(0))
|
|
19862
|
-
resolve({ done: true, value: void 0 });
|
|
19863
|
-
}
|
|
19864
|
-
#next() {
|
|
19865
|
-
const value = this.#values.shift();
|
|
19866
|
-
if (value !== void 0)
|
|
19867
|
-
return Promise.resolve({ done: false, value });
|
|
19868
|
-
if (this.#ended)
|
|
19869
|
-
return Promise.resolve({ done: true, value: void 0 });
|
|
19870
|
-
return new Promise((resolve) => this.#pending.push(resolve));
|
|
20104
|
+
// ../../harness-discovery/dist/node-runtime.js
|
|
20105
|
+
import path3 from "node:path";
|
|
20106
|
+
function withNodeRuntimeOnPath(environment, runtimeExecutable = process.execPath, platform = process.platform) {
|
|
20107
|
+
const pathKey = Object.keys(environment).find((name) => name.toLowerCase() === "path") ?? "PATH";
|
|
20108
|
+
const delimiter = platform === "win32" ? ";" : ":";
|
|
20109
|
+
const runtimeDirectory = path3.dirname(runtimeExecutable);
|
|
20110
|
+
const directories = (environment[pathKey] ?? "").split(delimiter).filter(Boolean);
|
|
20111
|
+
const equal = platform === "win32" ? (value) => value.toLowerCase() : (value) => value;
|
|
20112
|
+
if (!directories.some((directory) => equal(directory) === equal(runtimeDirectory))) {
|
|
20113
|
+
directories.push(runtimeDirectory);
|
|
19871
20114
|
}
|
|
19872
|
-
};
|
|
19873
|
-
|
|
19874
|
-
// ../../harness-adapter/dist/diagnostics.js
|
|
19875
|
-
var DIAGNOSTIC_TAIL_MAX_LENGTH = 8e3;
|
|
19876
|
-
var SENSITIVE_VALUE_PATTERN = /(api[_-]?key|access[_-]?token|auth(?:orization)?|password|secret)(\s*[:=]\s*)([^\s,;]+)/giu;
|
|
19877
|
-
var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/giu;
|
|
19878
|
-
function sanitizeDiagnosticTail(value) {
|
|
19879
|
-
const redacted = value.replace(BEARER_PATTERN, "Bearer [redacted]").replace(SENSITIVE_VALUE_PATTERN, "$1$2[redacted]");
|
|
19880
|
-
return redacted.length <= DIAGNOSTIC_TAIL_MAX_LENGTH ? redacted : redacted.slice(-DIAGNOSTIC_TAIL_MAX_LENGTH);
|
|
20115
|
+
return { ...environment, [pathKey]: directories.join(delimiter) };
|
|
19881
20116
|
}
|
|
19882
20117
|
|
|
19883
|
-
// ../../harness-
|
|
19884
|
-
|
|
19885
|
-
|
|
19886
|
-
|
|
19887
|
-
|
|
19888
|
-
|
|
19889
|
-
|
|
19890
|
-
|
|
19891
|
-
|
|
19892
|
-
|
|
19893
|
-
|
|
19894
|
-
|
|
19895
|
-
|
|
19896
|
-
"planFiveHourResetsAtUnix",
|
|
19897
|
-
"planSevenDayResetsAtUnix"
|
|
19898
|
-
];
|
|
19899
|
-
var percentFields = [
|
|
19900
|
-
"cacheHitRatePercent",
|
|
19901
|
-
"planFiveHourUsedPercent",
|
|
19902
|
-
"planSevenDayUsedPercent"
|
|
19903
|
-
];
|
|
19904
|
-
var usageFields = /* @__PURE__ */ new Set([
|
|
19905
|
-
...tokenFields,
|
|
19906
|
-
...safeIntegerFields,
|
|
19907
|
-
...percentFields,
|
|
19908
|
-
"totalCostUsd",
|
|
19909
|
-
"totalCredits",
|
|
19910
|
-
"contextUsagePercent"
|
|
19911
|
-
]);
|
|
19912
|
-
function isRecord2(value) {
|
|
19913
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19914
|
-
}
|
|
19915
|
-
function parseHostUsage(value) {
|
|
19916
|
-
if (!isRecord2(value))
|
|
19917
|
-
throw new Error("Harness Usage must be an object");
|
|
19918
|
-
const keys = Object.keys(value);
|
|
19919
|
-
if (keys.length === 0)
|
|
19920
|
-
throw new Error("Harness Usage must contain a reliable field");
|
|
19921
|
-
for (const key of keys) {
|
|
19922
|
-
if (!usageFields.has(key)) {
|
|
19923
|
-
throw new Error(`Harness Usage contains unknown field '${key}'`);
|
|
20118
|
+
// ../../harness-discovery/dist/resolve.js
|
|
20119
|
+
import os from "node:os";
|
|
20120
|
+
|
|
20121
|
+
// ../../harness-discovery/dist/version-managers.js
|
|
20122
|
+
function versionManagerBinaryDirectories(context) {
|
|
20123
|
+
const { platform, environment, home } = context;
|
|
20124
|
+
const list = context.subdirectories ?? subdirectoryNames;
|
|
20125
|
+
const pathFlavor = targetPath(platform);
|
|
20126
|
+
const value = (name) => environmentValue(environment, name);
|
|
20127
|
+
const directories = [];
|
|
20128
|
+
const versioned = (root, ...tail) => {
|
|
20129
|
+
for (const version2 of newestFirst(list(root))) {
|
|
20130
|
+
directories.push(pathFlavor.join(root, version2, ...tail));
|
|
19924
20131
|
}
|
|
20132
|
+
};
|
|
20133
|
+
if (platform === "win32") {
|
|
20134
|
+
const appData = value("APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming");
|
|
20135
|
+
const localAppData = value("LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local");
|
|
20136
|
+
versioned(pathFlavor.join(appData, "nvm"));
|
|
20137
|
+
versioned(value("FNM_DIR") ?? pathFlavor.join(appData, "fnm", "node-versions"), "installation");
|
|
20138
|
+
directories.push(pathFlavor.join(localAppData, "Volta", "bin"));
|
|
20139
|
+
directories.push(pathFlavor.join(home, ".bun", "bin"));
|
|
20140
|
+
const pnpmHome2 = value("PNPM_HOME");
|
|
20141
|
+
if (pnpmHome2)
|
|
20142
|
+
directories.push(pnpmHome2);
|
|
20143
|
+
directories.push(pathFlavor.join(localAppData, "pnpm"));
|
|
20144
|
+
return directories;
|
|
19925
20145
|
}
|
|
19926
|
-
|
|
19927
|
-
|
|
19928
|
-
|
|
19929
|
-
|
|
19930
|
-
|
|
20146
|
+
versioned(pathFlavor.join(value("NVM_DIR") ?? pathFlavor.join(home, ".nvm"), "versions", "node"), "bin");
|
|
20147
|
+
const fnmRoots = [
|
|
20148
|
+
value("FNM_DIR"),
|
|
20149
|
+
pathFlavor.join(home, ".local", "share", "fnm"),
|
|
20150
|
+
pathFlavor.join(home, "Library", "Application Support", "fnm")
|
|
20151
|
+
].filter((root) => root !== void 0);
|
|
20152
|
+
for (const root of fnmRoots) {
|
|
20153
|
+
versioned(pathFlavor.join(root, "node-versions"), "installation", "bin");
|
|
19931
20154
|
}
|
|
19932
|
-
|
|
19933
|
-
|
|
19934
|
-
|
|
19935
|
-
|
|
20155
|
+
const voltaHome = value("VOLTA_HOME") ?? pathFlavor.join(home, ".volta");
|
|
20156
|
+
versioned(pathFlavor.join(voltaHome, "tools", "image", "node"), "bin");
|
|
20157
|
+
directories.push(pathFlavor.join(voltaHome, "bin"));
|
|
20158
|
+
const asdfHome = value("ASDF_DATA_DIR") ?? pathFlavor.join(home, ".asdf");
|
|
20159
|
+
versioned(pathFlavor.join(asdfHome, "installs", "nodejs"), "bin");
|
|
20160
|
+
directories.push(pathFlavor.join(asdfHome, "shims"));
|
|
20161
|
+
const nodenvHome = value("NODENV_ROOT") ?? pathFlavor.join(home, ".nodenv");
|
|
20162
|
+
versioned(pathFlavor.join(nodenvHome, "versions"), "bin");
|
|
20163
|
+
directories.push(pathFlavor.join(nodenvHome, "shims"));
|
|
20164
|
+
versioned(pathFlavor.join(value("N_PREFIX") ?? "/usr/local", "n", "versions", "node"), "bin");
|
|
20165
|
+
directories.push(pathFlavor.join(home, ".bun", "bin"));
|
|
20166
|
+
const pnpmHome = value("PNPM_HOME");
|
|
20167
|
+
if (pnpmHome)
|
|
20168
|
+
directories.push(pnpmHome);
|
|
20169
|
+
directories.push(pathFlavor.join(home, "Library", "pnpm"));
|
|
20170
|
+
directories.push(pathFlavor.join(home, ".local", "share", "pnpm"));
|
|
20171
|
+
for (const prefix of ["/opt/homebrew/opt", "/usr/local/opt"]) {
|
|
20172
|
+
for (const formula of newestFirst(list(prefix).filter((name) => name.startsWith("node@")))) {
|
|
20173
|
+
directories.push(pathFlavor.join(prefix, formula, "bin"));
|
|
19936
20174
|
}
|
|
19937
20175
|
}
|
|
19938
|
-
|
|
19939
|
-
|
|
19940
|
-
|
|
19941
|
-
|
|
20176
|
+
return directories;
|
|
20177
|
+
}
|
|
20178
|
+
|
|
20179
|
+
// ../../harness-discovery/dist/resolve.js
|
|
20180
|
+
var VERSION_MANAGER_ROOTS = "<version-managers>";
|
|
20181
|
+
function installRootExtensions(platform) {
|
|
20182
|
+
return platform === "win32" ? [".exe", ".cmd"] : [""];
|
|
20183
|
+
}
|
|
20184
|
+
function resolveHomeDirectory(input) {
|
|
20185
|
+
return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
|
|
20186
|
+
}
|
|
20187
|
+
function templateVariables(environment, platform, home) {
|
|
20188
|
+
const pathFlavor = targetPath(platform);
|
|
20189
|
+
return {
|
|
20190
|
+
HOME: home,
|
|
20191
|
+
USERPROFILE: home,
|
|
20192
|
+
APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
|
|
20193
|
+
LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
|
|
20194
|
+
};
|
|
20195
|
+
}
|
|
20196
|
+
function joinTemplate(platform, value) {
|
|
20197
|
+
const pathFlavor = targetPath(platform);
|
|
20198
|
+
const segments = value.split("/");
|
|
20199
|
+
const head = segments[0] ?? "";
|
|
20200
|
+
const tail = segments.slice(1);
|
|
20201
|
+
if (head === "")
|
|
20202
|
+
return pathFlavor.join(pathFlavor.sep, ...tail);
|
|
20203
|
+
return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
|
|
20204
|
+
}
|
|
20205
|
+
function expandInstallRoot(template, environment, platform, home) {
|
|
20206
|
+
const variables = templateVariables(environment, platform, home);
|
|
20207
|
+
let unresolved = false;
|
|
20208
|
+
const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
|
|
20209
|
+
const value = variables[name] ?? environmentValue(environment, name);
|
|
20210
|
+
if (value === void 0 || value === "") {
|
|
20211
|
+
unresolved = true;
|
|
20212
|
+
return "";
|
|
19942
20213
|
}
|
|
20214
|
+
return value;
|
|
20215
|
+
});
|
|
20216
|
+
return unresolved ? void 0 : joinTemplate(platform, substituted);
|
|
20217
|
+
}
|
|
20218
|
+
function installRootDirectories(spec, input, dependencies, platform, home) {
|
|
20219
|
+
const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
|
|
20220
|
+
const directories = [];
|
|
20221
|
+
for (const template of templates) {
|
|
20222
|
+
if (template === VERSION_MANAGER_ROOTS) {
|
|
20223
|
+
directories.push(...versionManagerBinaryDirectories({
|
|
20224
|
+
platform,
|
|
20225
|
+
environment: input.environment,
|
|
20226
|
+
home,
|
|
20227
|
+
...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
|
|
20228
|
+
}));
|
|
20229
|
+
continue;
|
|
20230
|
+
}
|
|
20231
|
+
const directory = expandInstallRoot(template, input.environment, platform, home);
|
|
20232
|
+
if (directory !== void 0)
|
|
20233
|
+
directories.push(directory);
|
|
19943
20234
|
}
|
|
19944
|
-
|
|
19945
|
-
|
|
19946
|
-
|
|
19947
|
-
|
|
19948
|
-
|
|
20235
|
+
return directories;
|
|
20236
|
+
}
|
|
20237
|
+
function harnessCandidates(spec, input, dependencies = {}) {
|
|
20238
|
+
const platform = input.platform ?? process.platform;
|
|
20239
|
+
const pathFlavor = targetPath(platform);
|
|
20240
|
+
const configured = input.command ?? (spec.commandEnvironmentVariable ? environmentValue(input.environment, spec.commandEnvironmentVariable) : void 0);
|
|
20241
|
+
const command = configured ?? spec.command;
|
|
20242
|
+
if (pathFlavor.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
|
|
20243
|
+
return [{ candidate: command, source: "configured" }];
|
|
19949
20244
|
}
|
|
19950
|
-
|
|
19951
|
-
|
|
19952
|
-
|
|
19953
|
-
|
|
20245
|
+
const candidates = [];
|
|
20246
|
+
const extensions = executableExtensions(command, platform, input.environment);
|
|
20247
|
+
for (const directory of pathDirectories(input.environment, platform)) {
|
|
20248
|
+
for (const extension of extensions) {
|
|
20249
|
+
candidates.push({
|
|
20250
|
+
candidate: pathFlavor.join(directory, command + extension),
|
|
20251
|
+
source: "path"
|
|
20252
|
+
});
|
|
19954
20253
|
}
|
|
19955
20254
|
}
|
|
19956
|
-
|
|
19957
|
-
|
|
19958
|
-
|
|
19959
|
-
|
|
20255
|
+
if (configured !== void 0)
|
|
20256
|
+
return candidates;
|
|
20257
|
+
const home = resolveHomeDirectory(input);
|
|
20258
|
+
for (const directory of installRootDirectories(spec, input, dependencies, platform, home)) {
|
|
20259
|
+
for (const extension of installRootExtensions(platform)) {
|
|
20260
|
+
candidates.push({
|
|
20261
|
+
candidate: pathFlavor.join(directory, spec.command + extension),
|
|
20262
|
+
source: "install-root"
|
|
20263
|
+
});
|
|
19960
20264
|
}
|
|
19961
20265
|
}
|
|
19962
|
-
|
|
19963
|
-
const hasContextWindow = value.contextWindowTokens !== void 0;
|
|
19964
|
-
if (hasContextUsed !== hasContextWindow) {
|
|
19965
|
-
throw new Error("Harness Usage context fields must be provided together");
|
|
19966
|
-
}
|
|
19967
|
-
if (hasContextWindow && value.contextWindowTokens === 0) {
|
|
19968
|
-
throw new Error("Harness Usage 'contextWindowTokens' must be greater than zero");
|
|
19969
|
-
}
|
|
19970
|
-
if (value.planFiveHourResetsAtUnix !== void 0 && value.planFiveHourUsedPercent === void 0) {
|
|
19971
|
-
throw new Error("Harness Usage 'planFiveHourResetsAtUnix' must be provided with 'planFiveHourUsedPercent'");
|
|
19972
|
-
}
|
|
19973
|
-
if (value.planSevenDayResetsAtUnix !== void 0 && value.planSevenDayUsedPercent === void 0) {
|
|
19974
|
-
throw new Error("Harness Usage 'planSevenDayResetsAtUnix' must be provided with 'planSevenDayUsedPercent'");
|
|
19975
|
-
}
|
|
19976
|
-
return { ...value };
|
|
19977
|
-
}
|
|
19978
|
-
|
|
19979
|
-
// dist/common.js
|
|
19980
|
-
var CODEBUDDY_ID = harnessIdSchema.parse("codebuddy");
|
|
19981
|
-
var OUTPUT_LIMIT = 64e3;
|
|
19982
|
-
var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
19983
|
-
var rows = (value) => Array.isArray(value) ? value.map(record2) : [];
|
|
19984
|
-
var text = (value) => typeof value === "string" ? value : "";
|
|
19985
|
-
var CodeBuddyError = class extends Error {
|
|
19986
|
-
code;
|
|
19987
|
-
constructor(code, message) {
|
|
19988
|
-
super(message);
|
|
19989
|
-
this.code = code;
|
|
19990
|
-
}
|
|
19991
|
-
};
|
|
19992
|
-
function nativeError(error51) {
|
|
19993
|
-
const diagnostic = sanitizeDiagnosticTail(error51 instanceof Error ? error51.message : String(error51));
|
|
19994
|
-
const nativeCode = record2(error51).code;
|
|
19995
|
-
const code = error51 instanceof CodeBuddyError ? error51.code : nativeCode === -32e3 || /authentication required|not logged in|unauthenticated/iu.test(diagnostic) ? "authenticationRequired" : nativeCode === "ENOENT" ? "notInstalled" : /session.*not found/iu.test(diagnostic) ? "sessionNotFound" : "nativeFailure";
|
|
19996
|
-
return {
|
|
19997
|
-
code,
|
|
19998
|
-
message: `CodeBuddy: ${diagnostic || "native operation failed"}`,
|
|
19999
|
-
retryable: ["sessionBusy", "unavailable"].includes(code)
|
|
20000
|
-
};
|
|
20001
|
-
}
|
|
20002
|
-
function failure(code, message) {
|
|
20003
|
-
return { ok: false, error: nativeError(new CodeBuddyError(code, message)) };
|
|
20266
|
+
return candidates;
|
|
20004
20267
|
}
|
|
20005
|
-
|
|
20006
|
-
|
|
20007
|
-
|
|
20008
|
-
|
|
20009
|
-
|
|
20010
|
-
|
|
20011
|
-
|
|
20012
|
-
|
|
20013
|
-
|
|
20014
|
-
onTimeout?.(error51);
|
|
20015
|
-
} finally {
|
|
20016
|
-
reject(error51);
|
|
20017
|
-
}
|
|
20018
|
-
}, milliseconds);
|
|
20019
|
-
})
|
|
20020
|
-
]);
|
|
20021
|
-
} finally {
|
|
20022
|
-
clearTimeout(timer);
|
|
20268
|
+
function resolveHarnessExecutable(spec, input, dependencies = {}) {
|
|
20269
|
+
const platform = input.platform ?? process.platform;
|
|
20270
|
+
const isExecutable = dependencies.isExecutable ?? ((candidate) => isExecutableFile(candidate, platform));
|
|
20271
|
+
const runnable = spec.runnableCandidate ?? ((candidate) => candidate);
|
|
20272
|
+
const context = { platform, isExecutable };
|
|
20273
|
+
for (const { candidate, source } of harnessCandidates(spec, input, dependencies)) {
|
|
20274
|
+
const executable = runnable(candidate, context);
|
|
20275
|
+
if (executable !== void 0 && isExecutable(executable))
|
|
20276
|
+
return { executable, source };
|
|
20023
20277
|
}
|
|
20278
|
+
return void 0;
|
|
20024
20279
|
}
|
|
20025
20280
|
|
|
20026
20281
|
// dist/command.js
|
|
@@ -20039,21 +20294,34 @@ var codeBuddyDiscoverySpec = {
|
|
|
20039
20294
|
]
|
|
20040
20295
|
}
|
|
20041
20296
|
};
|
|
20042
|
-
function codeBuddyInvocation(environment, ephemeral) {
|
|
20297
|
+
function codeBuddyInvocation(environment, ephemeral, argumentsOverride) {
|
|
20043
20298
|
const resolved = resolveHarnessExecutable(codeBuddyDiscoverySpec, { environment });
|
|
20044
20299
|
if (!resolved)
|
|
20045
20300
|
throw new CodeBuddyError("notInstalled", "CLI is not installed; run codebuddy and sign in first");
|
|
20046
20301
|
const env = withNodeRuntimeOnPath(environment);
|
|
20047
20302
|
return {
|
|
20048
|
-
...commandInvocation(resolved.executable,
|
|
20303
|
+
...commandInvocation(resolved.executable, argumentsOverride ?? [
|
|
20304
|
+
"--acp",
|
|
20305
|
+
...ephemeral ? ["--no-session-persistence"] : [],
|
|
20306
|
+
...!ephemeral && [
|
|
20307
|
+
"CODEXHOST_CLI_PATH",
|
|
20308
|
+
"CODEXHOST_RUNTIME_ENDPOINT",
|
|
20309
|
+
"CODEXHOST_RUNTIME_TOKEN",
|
|
20310
|
+
"CODEXHOST_THREAD_ID"
|
|
20311
|
+
].every((key) => environment[key]) ? ["--append-system-prompt", CODEBUDDY_DELEGATION_INSTRUCTIONS] : []
|
|
20312
|
+
], env),
|
|
20049
20313
|
environment: env
|
|
20050
20314
|
};
|
|
20051
20315
|
}
|
|
20316
|
+
var CODEBUDDY_DELEGATION_INSTRUCTIONS = `This Session runs inside codexhost.
|
|
20317
|
+
When the user requests cross-Harness agent delegation, use the executable at the CODEXHOST_CLI_PATH environment variable through your native shell tool. Start with its --help and harness list commands, then use delegate start and thread send/read/wait/cancel as documented by the CLI. Pass --format compact when reporting results. Keep the inherited CODEXHOST_RUNTIME_ENDPOINT, CODEXHOST_RUNTIME_TOKEN and CODEXHOST_THREAD_ID environment variables for all such calls; they identify this Runtime and parent Thread. Do not print or expose their values, replace the configured executable, or start delegation unless the user's request authorizes it. Native CodeBuddy Agent subagents remain available for CodeBuddy-only work.`;
|
|
20052
20318
|
|
|
20053
20319
|
// dist/acp-client.js
|
|
20054
20320
|
var CodeBuddyAcpClient = class {
|
|
20055
20321
|
options;
|
|
20056
20322
|
operationTimeoutMs;
|
|
20323
|
+
invocationFactory;
|
|
20324
|
+
#copyCleanup;
|
|
20057
20325
|
#child;
|
|
20058
20326
|
#connection;
|
|
20059
20327
|
#exited;
|
|
@@ -20065,12 +20333,14 @@ var CodeBuddyAcpClient = class {
|
|
|
20065
20333
|
#failed = new Promise((_, reject) => {
|
|
20066
20334
|
this.#rejectFailure = reject;
|
|
20067
20335
|
});
|
|
20068
|
-
constructor(options, operationTimeoutMs = 15e3) {
|
|
20336
|
+
constructor(options, operationTimeoutMs = 15e3, invocationFactory = codeBuddyInvocation) {
|
|
20069
20337
|
this.options = options;
|
|
20070
20338
|
this.operationTimeoutMs = operationTimeoutMs;
|
|
20339
|
+
this.invocationFactory = invocationFactory;
|
|
20071
20340
|
void this.#failed.catch(() => {
|
|
20072
20341
|
});
|
|
20073
|
-
|
|
20342
|
+
this.#copyCleanup = options.temporarySessionId ? new CodeBuddyCopyCleanup(options.temporarySessionId, options.cwd) : void 0;
|
|
20343
|
+
const invocation = invocationFactory(this.#copyCleanup?.environment(options.environment) ?? options.environment, options.ephemeral, this.#copyCleanup?.arguments);
|
|
20074
20344
|
this.#child = spawn(invocation.command, invocation.arguments, {
|
|
20075
20345
|
cwd: options.cwd,
|
|
20076
20346
|
env: invocation.environment,
|
|
@@ -20107,7 +20377,7 @@ var CodeBuddyAcpClient = class {
|
|
|
20107
20377
|
return { outcome: "cancelled" };
|
|
20108
20378
|
return options.handlers.question(params);
|
|
20109
20379
|
}
|
|
20110
|
-
}), ndJsonStream2(Writable.toWeb(this.#child.stdin),
|
|
20380
|
+
}), ndJsonStream2(Writable.toWeb(this.#child.stdin), Readable2.toWeb(this.#copyCleanup?.protocolOutput(this.#child.stdout) ?? this.#child.stdout)));
|
|
20111
20381
|
void this.#connection.closed.then(() => {
|
|
20112
20382
|
this.#fault(new CodeBuddyError("processExited", "ACP connection closed"));
|
|
20113
20383
|
}).catch((error51) => {
|
|
@@ -20157,13 +20427,27 @@ var CodeBuddyAcpClient = class {
|
|
|
20157
20427
|
async cancel(sessionId) {
|
|
20158
20428
|
await this.#request(() => this.#connection.cancel({ sessionId }), "ACP cancel");
|
|
20159
20429
|
}
|
|
20430
|
+
async removeCopy() {
|
|
20431
|
+
const cleanup = this.#copyCleanup;
|
|
20432
|
+
if (!cleanup)
|
|
20433
|
+
throw new CodeBuddyError("invalidState", "No temporary copy is owned by this process");
|
|
20434
|
+
await this.#request(() => cleanup.remove(), "Native temporary Session cleanup");
|
|
20435
|
+
}
|
|
20436
|
+
async rollback(sessionId, forkPointId) {
|
|
20437
|
+
return record2(await this.#request(() => this.#connection.extMethod("_codebuddy.ai/session/rollback", {
|
|
20438
|
+
sessionId,
|
|
20439
|
+
forkPointId,
|
|
20440
|
+
reason: "resend_edit",
|
|
20441
|
+
files: false
|
|
20442
|
+
}), "ACP history rewind"));
|
|
20443
|
+
}
|
|
20160
20444
|
async answer(sessionId, toolCallId, answers) {
|
|
20161
20445
|
const response = await this.#request(() => this.#connection.extMethod("_codebuddy.ai/resolveInterruption", {
|
|
20162
20446
|
sessionId,
|
|
20163
20447
|
toolCallId,
|
|
20164
20448
|
decision: answers === null ? "deny" : "allow",
|
|
20165
20449
|
...answers ? { answers } : {}
|
|
20166
|
-
}), "
|
|
20450
|
+
}), "ACP question response");
|
|
20167
20451
|
if (record2(response).resolved !== true)
|
|
20168
20452
|
throw new CodeBuddyError("protocolError", "Native question is no longer pending");
|
|
20169
20453
|
}
|
|
@@ -20205,19 +20489,25 @@ var CODEBUDDY_CAPABILITIES = {
|
|
|
20205
20489
|
selectPermissionMode: true,
|
|
20206
20490
|
permissionModeScope: "live"
|
|
20207
20491
|
},
|
|
20208
|
-
history: { fork:
|
|
20492
|
+
history: { fork: true, forkAcrossCwd: false, rollbackLastTurn: true },
|
|
20209
20493
|
subagents: { observe: true, readTranscript: true }
|
|
20210
20494
|
};
|
|
20495
|
+
function capabilitiesForProfile(profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20496
|
+
return {
|
|
20497
|
+
...CODEBUDDY_CAPABILITIES,
|
|
20498
|
+
history: profile.historyCapabilities ?? CODEBUDDY_CAPABILITIES.history
|
|
20499
|
+
};
|
|
20500
|
+
}
|
|
20211
20501
|
function modelRef(modelId) {
|
|
20212
20502
|
return harnessModelRefSchema.parse({ id: `cb.${Buffer.from(modelId).toString("base64url")}` });
|
|
20213
20503
|
}
|
|
20214
20504
|
function nativeModel(ref) {
|
|
20215
20505
|
const value = Buffer.from(ref.id.slice(3), "base64url").toString("utf8");
|
|
20216
20506
|
if (!value || !ref.id.startsWith("cb.") || modelRef(value).id !== ref.id)
|
|
20217
|
-
throw new CodeBuddyError("invalidRequest", "Invalid
|
|
20507
|
+
throw new CodeBuddyError("invalidRequest", "Invalid native Model Ref");
|
|
20218
20508
|
return value;
|
|
20219
20509
|
}
|
|
20220
|
-
function configuration(value) {
|
|
20510
|
+
function configuration(value, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20221
20511
|
const options = rows(value);
|
|
20222
20512
|
const get = (id) => options.find((option) => option.id === id) ?? {};
|
|
20223
20513
|
const model = get("model"), mode = get("mode"), thought = get("thought_level");
|
|
@@ -20227,7 +20517,12 @@ function configuration(value) {
|
|
|
20227
20517
|
ref: modelRef(text(option.value)),
|
|
20228
20518
|
label: text(option.name)
|
|
20229
20519
|
}));
|
|
20230
|
-
const
|
|
20520
|
+
const currentModelRef = modelRef(text(model.currentValue));
|
|
20521
|
+
let currentModel = models.find((item) => item.ref.id === currentModelRef.id);
|
|
20522
|
+
if (!currentModel && profile.allowUnlistedModelSelection) {
|
|
20523
|
+
currentModel = { ref: currentModelRef, label: text(model.currentValue) };
|
|
20524
|
+
models.push(currentModel);
|
|
20525
|
+
}
|
|
20231
20526
|
if (!currentModel)
|
|
20232
20527
|
throw new CodeBuddyError("protocolError", "ACP did not report a valid current Model");
|
|
20233
20528
|
const catalog = harnessModelCatalogSchema.parse({
|
|
@@ -20257,18 +20552,28 @@ function configuration(value) {
|
|
|
20257
20552
|
};
|
|
20258
20553
|
return { catalog, permissionModes, state, options };
|
|
20259
20554
|
}
|
|
20260
|
-
function confirmedConfiguration(response, id, value) {
|
|
20261
|
-
const result = configuration(record2(response).configOptions);
|
|
20555
|
+
function confirmedConfiguration(response, id, value, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20556
|
+
const result = configuration(record2(response).configOptions, profile);
|
|
20262
20557
|
if (result.options.find((option) => option.id === id)?.currentValue !== value) {
|
|
20263
20558
|
throw new CodeBuddyError("protocolError", `ACP did not confirm ${id}`);
|
|
20264
20559
|
}
|
|
20265
20560
|
return result;
|
|
20266
20561
|
}
|
|
20267
20562
|
|
|
20563
|
+
// dist/derivation.js
|
|
20564
|
+
import { randomUUID } from "node:crypto";
|
|
20565
|
+
import { execFile as execFile2, spawn as spawn2 } from "node:child_process";
|
|
20566
|
+
import { lstat, mkdir, readFile as readFile2, realpath as realpath4, unlink, writeFile } from "node:fs/promises";
|
|
20567
|
+
import path5 from "node:path";
|
|
20568
|
+
import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
|
|
20569
|
+
|
|
20268
20570
|
// dist/history.js
|
|
20571
|
+
import { createHash } from "node:crypto";
|
|
20572
|
+
import { realpathSync } from "node:fs";
|
|
20269
20573
|
import { access, readdir, realpath as realpath2 } from "node:fs/promises";
|
|
20270
20574
|
import { homedir } from "node:os";
|
|
20271
20575
|
import path4 from "node:path";
|
|
20576
|
+
import { isDeepStrictEqual } from "node:util";
|
|
20272
20577
|
|
|
20273
20578
|
// ../../../node_modules/diff/libesm/diff/base.js
|
|
20274
20579
|
var Diff = class {
|
|
@@ -20370,16 +20675,16 @@ var Diff = class {
|
|
|
20370
20675
|
}
|
|
20371
20676
|
}
|
|
20372
20677
|
}
|
|
20373
|
-
addToPath(
|
|
20374
|
-
const last =
|
|
20678
|
+
addToPath(path8, added, removed, oldPosInc, options) {
|
|
20679
|
+
const last = path8.lastComponent;
|
|
20375
20680
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
20376
20681
|
return {
|
|
20377
|
-
oldPos:
|
|
20682
|
+
oldPos: path8.oldPos + oldPosInc,
|
|
20378
20683
|
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
20379
20684
|
};
|
|
20380
20685
|
} else {
|
|
20381
20686
|
return {
|
|
20382
|
-
oldPos:
|
|
20687
|
+
oldPos: path8.oldPos + oldPosInc,
|
|
20383
20688
|
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
20384
20689
|
};
|
|
20385
20690
|
}
|
|
@@ -20717,28 +21022,31 @@ function toolOutput(value) {
|
|
|
20717
21022
|
...output.length > OUTPUT_LIMIT ? { truncated: true } : {}
|
|
20718
21023
|
};
|
|
20719
21024
|
}
|
|
20720
|
-
function toolOutcome(status) {
|
|
21025
|
+
function toolOutcome(status, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20721
21026
|
if (status === "completed")
|
|
20722
21027
|
return { status: "succeeded" };
|
|
20723
21028
|
if (status === "cancelled" || status === "interrupted")
|
|
20724
21029
|
return { status: "cancelled" };
|
|
20725
21030
|
return {
|
|
20726
21031
|
status: "failed",
|
|
20727
|
-
error: nativeError(new CodeBuddyError("nativeFailure", status === "failed" ? "Tool execution failed" : "Tool completion was not recorded"))
|
|
21032
|
+
error: nativeError(new CodeBuddyError("nativeFailure", status === "failed" ? "Tool execution failed" : "Tool completion was not recorded"), profile)
|
|
20728
21033
|
};
|
|
20729
21034
|
}
|
|
20730
21035
|
var CodeBuddyTurnOutput = class {
|
|
20731
21036
|
turnId;
|
|
20732
21037
|
cwd;
|
|
20733
21038
|
emit;
|
|
21039
|
+
profile;
|
|
20734
21040
|
#items = /* @__PURE__ */ new Map();
|
|
20735
21041
|
#finished = /* @__PURE__ */ new Set();
|
|
20736
21042
|
#tools = /* @__PURE__ */ new Map();
|
|
20737
21043
|
#diffs = /* @__PURE__ */ new Set();
|
|
20738
|
-
|
|
21044
|
+
#compactionOutcome;
|
|
21045
|
+
constructor(turnId, cwd, emit, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20739
21046
|
this.turnId = turnId;
|
|
20740
21047
|
this.cwd = cwd;
|
|
20741
21048
|
this.emit = emit;
|
|
21049
|
+
this.profile = profile;
|
|
20742
21050
|
}
|
|
20743
21051
|
#start(item) {
|
|
20744
21052
|
this.#items.set(item.itemId, { item, outcome: { status: "succeeded" } });
|
|
@@ -20755,11 +21063,33 @@ var CodeBuddyTurnOutput = class {
|
|
|
20755
21063
|
snapshot: structuredClone({ item, outcome })
|
|
20756
21064
|
});
|
|
20757
21065
|
}
|
|
21066
|
+
replayCommandResult(items) {
|
|
21067
|
+
if (this.#items.size)
|
|
21068
|
+
return;
|
|
21069
|
+
for (const snapshot of items) {
|
|
21070
|
+
const item = structuredClone(snapshot.item);
|
|
21071
|
+
this.#start(item);
|
|
21072
|
+
this.#finish(item, snapshot.outcome);
|
|
21073
|
+
}
|
|
21074
|
+
}
|
|
21075
|
+
confirmCompaction(items) {
|
|
21076
|
+
const persisted = items.find((snapshot) => snapshot.item.type === "contextCompaction");
|
|
21077
|
+
this.#compactionOutcome = persisted ? structuredClone(persisted.outcome) : void 0;
|
|
21078
|
+
}
|
|
21079
|
+
compact() {
|
|
21080
|
+
const itemId = hostItemIdSchema.parse(`compact-${this.turnId}`);
|
|
21081
|
+
if (!this.#items.has(itemId))
|
|
21082
|
+
this.#start({ type: "contextCompaction", itemId });
|
|
21083
|
+
}
|
|
20758
21084
|
update(value) {
|
|
20759
21085
|
const update = record2(value), meta3 = record2(update._meta);
|
|
20760
21086
|
if (meta3["codebuddy.ai/memberEvent"])
|
|
20761
21087
|
return;
|
|
20762
21088
|
const kind = update.sessionUpdate;
|
|
21089
|
+
if (nativeCommandsEnabled(this.profile) && meta3["codebuddy.ai/isCompactInternal"] === true) {
|
|
21090
|
+
this.compact();
|
|
21091
|
+
return;
|
|
21092
|
+
}
|
|
20763
21093
|
if (kind === "agent_message_chunk" || kind === "agent_thought_chunk") {
|
|
20764
21094
|
const delta = contentText(update.content);
|
|
20765
21095
|
if (!delta)
|
|
@@ -20799,7 +21129,7 @@ var CodeBuddyTurnOutput = class {
|
|
|
20799
21129
|
const terminal = update.status === "completed" || update.status === "failed";
|
|
20800
21130
|
if (!terminal && !record2(merged._meta)["codebuddy.ai/toolArgumentsComplete"])
|
|
20801
21131
|
return;
|
|
20802
|
-
const name = text(record2(merged._meta)["codebuddy.ai/toolName"]) || text(merged.title) ||
|
|
21132
|
+
const name = text(record2(merged._meta)["codebuddy.ai/toolName"]) || text(merged.title) || `${this.profile.displayName} tool`;
|
|
20803
21133
|
const id = `tool-${callId}`;
|
|
20804
21134
|
let item = this.#items.get(id)?.item;
|
|
20805
21135
|
if (!item) {
|
|
@@ -20830,7 +21160,7 @@ var CodeBuddyTurnOutput = class {
|
|
|
20830
21160
|
update: { type: "output.replace", output }
|
|
20831
21161
|
});
|
|
20832
21162
|
}
|
|
20833
|
-
this.#finish(item, toolOutcome(update.status));
|
|
21163
|
+
this.#finish(item, toolOutcome(update.status, this.profile));
|
|
20834
21164
|
if (update.status === "completed" && !this.#diffs.has(callId)) {
|
|
20835
21165
|
const changes = [];
|
|
20836
21166
|
for (const diff of rows(merged.content)) {
|
|
@@ -20859,9 +21189,13 @@ var CodeBuddyTurnOutput = class {
|
|
|
20859
21189
|
}
|
|
20860
21190
|
finish(status, error51) {
|
|
20861
21191
|
for (const { item } of this.#items.values()) {
|
|
20862
|
-
|
|
20863
|
-
|
|
20864
|
-
|
|
21192
|
+
if (item.type === "contextCompaction" && this.#compactionOutcome) {
|
|
21193
|
+
this.#finish(item, this.#compactionOutcome);
|
|
21194
|
+
continue;
|
|
21195
|
+
}
|
|
21196
|
+
const outcome = status === "failed" || item.type === "contextCompaction" && status === "succeeded" && !this.#compactionOutcome ? {
|
|
21197
|
+
status: "failed",
|
|
21198
|
+
error: error51 ?? nativeError(new CodeBuddyError("nativeFailure", item.type === "contextCompaction" ? "Native compaction completion was not confirmed" : "Turn failed"), this.profile)
|
|
20865
21199
|
} : { status };
|
|
20866
21200
|
this.#finish(item, outcome);
|
|
20867
21201
|
}
|
|
@@ -20878,7 +21212,7 @@ function codeBuddyChildId(value) {
|
|
|
20878
21212
|
const id = structured || /\[Agent ID: (agent-[a-zA-Z0-9_-]+)\]\s*$/u.exec(body)?.[1];
|
|
20879
21213
|
return id && validCodeBuddyChildId(id) ? id : void 0;
|
|
20880
21214
|
}
|
|
20881
|
-
function codeBuddyDelegation(callId, input, status, childId) {
|
|
21215
|
+
function codeBuddyDelegation(callId, input, status, childId, displayName = "CodeBuddy") {
|
|
20882
21216
|
const args = record2(input);
|
|
20883
21217
|
const resumed = text(args.resume);
|
|
20884
21218
|
const nativeId = childId ?? (validCodeBuddyChildId(resumed) ? resumed : void 0);
|
|
@@ -20891,7 +21225,7 @@ function codeBuddyDelegation(callId, input, status, childId) {
|
|
|
20891
21225
|
{
|
|
20892
21226
|
subagentId: nativeId ?? callId,
|
|
20893
21227
|
...nativeId ? { nativeSubagentId: nativeId } : {},
|
|
20894
|
-
description: text(args.description) ||
|
|
21228
|
+
description: text(args.description) || `${displayName} Subagent`,
|
|
20895
21229
|
...text(args.subagent_type) ? { role: text(args.subagent_type) } : {},
|
|
20896
21230
|
...text(args.model) ? { model: text(args.model) } : {},
|
|
20897
21231
|
background: args.run_in_background === true,
|
|
@@ -20925,9 +21259,55 @@ async function readCodeBuddyVersionedText(file2, maximumBytes, tooLargeMessage,
|
|
|
20925
21259
|
}
|
|
20926
21260
|
|
|
20927
21261
|
// dist/history.js
|
|
20928
|
-
function
|
|
20929
|
-
|
|
20930
|
-
|
|
21262
|
+
function codeBuddyProjectSlug(cwd, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21263
|
+
const canonical = codeBuddyCanonicalCwd(cwd);
|
|
21264
|
+
if (profile.projectDirectoryName)
|
|
21265
|
+
return profile.projectDirectoryName(canonical);
|
|
21266
|
+
return canonical.replace(/[^a-z0-9]/giu, "-").replace(/-+/gu, "-").replace(/^-|-$/gu, "").toLowerCase();
|
|
21267
|
+
}
|
|
21268
|
+
function codeBuddyCanonicalCwd(cwd) {
|
|
21269
|
+
try {
|
|
21270
|
+
return realpathSync.native(cwd);
|
|
21271
|
+
} catch {
|
|
21272
|
+
return path4.resolve(cwd);
|
|
21273
|
+
}
|
|
21274
|
+
}
|
|
21275
|
+
function codeBuddyConfigRoot(environment, profile) {
|
|
21276
|
+
const configuredRoot = profile.configDirectoryEnvironmentVariables.map((name) => environment[name]).find((value) => typeof value === "string" && value.trim().length > 0);
|
|
21277
|
+
return configuredRoot || path4.join(environment.HOME || environment.USERPROFILE || homedir(), profile.defaultConfigDirectoryName);
|
|
21278
|
+
}
|
|
21279
|
+
function codeBuddyPrimaryHistoryPath(cwd, ref, environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21280
|
+
return path4.join(codeBuddyConfigRoot(environment, profile), "projects", codeBuddyProjectSlug(cwd, profile), `${ref.nativeSessionId}.jsonl`);
|
|
21281
|
+
}
|
|
21282
|
+
function derivedLocator(ref) {
|
|
21283
|
+
const locator = record2(ref.locator);
|
|
21284
|
+
if (locator.codebuddyDerived !== 1)
|
|
21285
|
+
return void 0;
|
|
21286
|
+
const fields = [
|
|
21287
|
+
locator.boundCwd,
|
|
21288
|
+
locator.targetProjectSlug,
|
|
21289
|
+
locator.inheritedPrefixRows,
|
|
21290
|
+
locator.inheritedPrefixSha256,
|
|
21291
|
+
locator.bindingMarkerId
|
|
21292
|
+
];
|
|
21293
|
+
if (fields.every((value) => value === void 0))
|
|
21294
|
+
return void 0;
|
|
21295
|
+
if (typeof locator.boundCwd !== "string" || !locator.boundCwd || typeof locator.targetProjectSlug !== "string" || !locator.targetProjectSlug || !Number.isSafeInteger(locator.inheritedPrefixRows) || Number(locator.inheritedPrefixRows) < 0 || typeof locator.inheritedPrefixSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(locator.inheritedPrefixSha256) || typeof locator.bindingMarkerId !== "string" || !locator.bindingMarkerId)
|
|
21296
|
+
throw new CodeBuddyError("protocolError", "Derived Native Session locator is incomplete");
|
|
21297
|
+
return {
|
|
21298
|
+
boundCwd: locator.boundCwd,
|
|
21299
|
+
targetProjectSlug: locator.targetProjectSlug,
|
|
21300
|
+
inheritedPrefixRows: Number(locator.inheritedPrefixRows),
|
|
21301
|
+
inheritedPrefixSha256: locator.inheritedPrefixSha256,
|
|
21302
|
+
bindingMarkerId: locator.bindingMarkerId
|
|
21303
|
+
};
|
|
21304
|
+
}
|
|
21305
|
+
function nativeRowsDigest(rows2) {
|
|
21306
|
+
return createHash("sha256").update(JSON.stringify(rows2)).digest("hex");
|
|
21307
|
+
}
|
|
21308
|
+
function validateNativeRef(ref, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21309
|
+
if (ref.harnessId !== profile.harnessId || ref.formatVersion !== 1 || !/^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/u.test(ref.nativeSessionId)) {
|
|
21310
|
+
throw new CodeBuddyError("invalidRequest", `Invalid ${profile.displayName} Native Session identity`);
|
|
20931
21311
|
}
|
|
20932
21312
|
}
|
|
20933
21313
|
async function sameCwd(left, right) {
|
|
@@ -20939,18 +21319,37 @@ async function sameCwd(left, right) {
|
|
|
20939
21319
|
});
|
|
20940
21320
|
return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
20941
21321
|
}
|
|
20942
|
-
async function
|
|
20943
|
-
|
|
21322
|
+
async function matchesAnyHistoricalCwd(value, candidates) {
|
|
21323
|
+
const resolved = path4.resolve(value);
|
|
21324
|
+
for (const candidate of candidates) {
|
|
21325
|
+
const other = path4.resolve(candidate);
|
|
21326
|
+
if (process.platform === "win32" ? resolved.toLowerCase() === other.toLowerCase() : resolved === other)
|
|
21327
|
+
return true;
|
|
21328
|
+
try {
|
|
21329
|
+
if (await sameCwd(value, candidate))
|
|
21330
|
+
return true;
|
|
21331
|
+
} catch (error51) {
|
|
21332
|
+
if (!(error51 instanceof CodeBuddyError) && !["ENOENT", "ENOTDIR"].includes(text(record2(error51).code)))
|
|
21333
|
+
throw error51;
|
|
21334
|
+
}
|
|
21335
|
+
}
|
|
21336
|
+
return false;
|
|
21337
|
+
}
|
|
21338
|
+
async function codeBuddyNativeHistory(cwd, ref, environment, profileOrVerifiedSource = CODEBUDDY_RUNTIME_PROFILE, transaction) {
|
|
21339
|
+
const profile = typeof profileOrVerifiedSource === "string" ? CODEBUDDY_RUNTIME_PROFILE : profileOrVerifiedSource;
|
|
21340
|
+
const effectiveTransaction = typeof profileOrVerifiedSource === "string" ? { inheritedContents: profileOrVerifiedSource } : transaction;
|
|
21341
|
+
return codeBuddyHistory(cwd, ref, environment, false, profile, effectiveTransaction);
|
|
20944
21342
|
}
|
|
20945
|
-
async function codeBuddyLiveNativeHistory(cwd, ref, environment) {
|
|
20946
|
-
return codeBuddyHistory(cwd, ref, environment, true);
|
|
21343
|
+
async function codeBuddyLiveNativeHistory(cwd, ref, environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21344
|
+
return codeBuddyHistory(cwd, ref, environment, true, profile);
|
|
20947
21345
|
}
|
|
20948
|
-
async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail) {
|
|
20949
|
-
validateNativeRef(ref);
|
|
20950
|
-
const configRoot =
|
|
21346
|
+
async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail, profile, transaction) {
|
|
21347
|
+
validateNativeRef(ref, profile);
|
|
21348
|
+
const configRoot = codeBuddyConfigRoot(environment, profile);
|
|
20951
21349
|
const root = path4.join(configRoot, "projects");
|
|
20952
|
-
const slug =
|
|
21350
|
+
const slug = codeBuddyProjectSlug(cwd, profile);
|
|
20953
21351
|
const primary = path4.join(root, slug, `${ref.nativeSessionId}.jsonl`);
|
|
21352
|
+
const provenance = derivedLocator(ref);
|
|
20954
21353
|
let candidates = [];
|
|
20955
21354
|
try {
|
|
20956
21355
|
await access(primary);
|
|
@@ -20958,6 +21357,8 @@ async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail) {
|
|
|
20958
21357
|
} catch (error51) {
|
|
20959
21358
|
if (record2(error51).code !== "ENOENT")
|
|
20960
21359
|
throw error51;
|
|
21360
|
+
if (transaction?.requirePrimary || provenance)
|
|
21361
|
+
throw new CodeBuddyError("sessionNotFound", "Native Session history was not found");
|
|
20961
21362
|
const directories = await readdir(root, { withFileTypes: true }).catch((error52) => {
|
|
20962
21363
|
if (record2(error52).code === "ENOENT")
|
|
20963
21364
|
return [];
|
|
@@ -20981,15 +21382,63 @@ async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail) {
|
|
|
20981
21382
|
const file2 = candidates[0];
|
|
20982
21383
|
if (!file2)
|
|
20983
21384
|
throw new CodeBuddyError("sessionNotFound", "Native Session history was not found");
|
|
21385
|
+
if (profile.historyCapabilities?.fork && !transaction && path4.resolve(file2) !== path4.resolve(primary))
|
|
21386
|
+
throw new CodeBuddyError("invalidRequest", "Native Session is not stored in the requested working directory");
|
|
20984
21387
|
const source = await readCodeBuddyVersionedText(file2, 64e6, "Native history exceeds the supported 64 MB snapshot size"), parsed = parseJsonl(source.contents, tolerateIncompleteTail);
|
|
20985
21388
|
const checkedDirectories = /* @__PURE__ */ new Set();
|
|
20986
|
-
|
|
20987
|
-
|
|
20988
|
-
|
|
20989
|
-
|
|
20990
|
-
|
|
20991
|
-
|
|
20992
|
-
|
|
21389
|
+
const inheritedRows = /* @__PURE__ */ new Map();
|
|
21390
|
+
for (const row of transaction?.inheritedContents ? parseRows(transaction.inheritedContents) : []) {
|
|
21391
|
+
const id = text(row.id);
|
|
21392
|
+
const candidates2 = inheritedRows.get(id) ?? [];
|
|
21393
|
+
candidates2.push(row);
|
|
21394
|
+
inheritedRows.set(id, candidates2);
|
|
21395
|
+
}
|
|
21396
|
+
const inherited = (row) => inheritedRows.get(text(row.id))?.some((candidate) => isDeepStrictEqual(candidate, row)) === true;
|
|
21397
|
+
if (transaction) {
|
|
21398
|
+
for (const row of parsed.rows) {
|
|
21399
|
+
if (inherited(row)) {
|
|
21400
|
+
if (typeof row.cwd === "string")
|
|
21401
|
+
checkedDirectories.add(row.cwd);
|
|
21402
|
+
continue;
|
|
21403
|
+
}
|
|
21404
|
+
if (row.sessionId && row.sessionId !== ref.nativeSessionId)
|
|
21405
|
+
throw new CodeBuddyError("protocolError", "Native history has a different Session identity");
|
|
21406
|
+
if (typeof row.cwd === "string" && !checkedDirectories.has(row.cwd)) {
|
|
21407
|
+
const allowed = [cwd, ...transaction.allowedHistoricalCwds ?? []];
|
|
21408
|
+
if (!await matchesAnyHistoricalCwd(row.cwd, allowed))
|
|
21409
|
+
throw new CodeBuddyError("invalidRequest", "Native Session belongs to a different working directory");
|
|
21410
|
+
checkedDirectories.add(row.cwd);
|
|
21411
|
+
}
|
|
21412
|
+
}
|
|
21413
|
+
} else if (provenance) {
|
|
21414
|
+
if (!await sameCwd(provenance.boundCwd, cwd) || provenance.targetProjectSlug !== slug || path4.resolve(file2) !== path4.resolve(primary))
|
|
21415
|
+
throw new CodeBuddyError("invalidRequest", "Derived Native Session target binding changed");
|
|
21416
|
+
const active = nativeHistoryRows(parsed.contents);
|
|
21417
|
+
if (provenance.inheritedPrefixRows > active.length || nativeRowsDigest(active.slice(0, provenance.inheritedPrefixRows)) !== provenance.inheritedPrefixSha256)
|
|
21418
|
+
throw new CodeBuddyError("protocolError", "Derived Native Session prefix verification failed");
|
|
21419
|
+
const marker = parsed.rows.find((row) => text(row.id) === provenance.bindingMarkerId);
|
|
21420
|
+
if (!marker || marker.sessionId !== ref.nativeSessionId || typeof marker.cwd !== "string" || !await sameCwd(marker.cwd, cwd))
|
|
21421
|
+
throw new CodeBuddyError("protocolError", "Derived Native Session target marker is missing");
|
|
21422
|
+
checkedDirectories.add(cwd);
|
|
21423
|
+
const verifiedSuffixCwds = /* @__PURE__ */ new Set();
|
|
21424
|
+
for (const row of active.slice(provenance.inheritedPrefixRows)) {
|
|
21425
|
+
if (row.sessionId && row.sessionId !== ref.nativeSessionId)
|
|
21426
|
+
throw new CodeBuddyError("protocolError", "Derived Native Session appended foreign history");
|
|
21427
|
+
if (typeof row.cwd === "string" && !verifiedSuffixCwds.has(row.cwd)) {
|
|
21428
|
+
if (!await sameCwd(row.cwd, cwd))
|
|
21429
|
+
throw new CodeBuddyError("invalidRequest", "Derived Native Session left its target directory");
|
|
21430
|
+
verifiedSuffixCwds.add(row.cwd);
|
|
21431
|
+
}
|
|
21432
|
+
}
|
|
21433
|
+
} else {
|
|
21434
|
+
for (const row of parsed.rows) {
|
|
21435
|
+
if (row.sessionId && row.sessionId !== ref.nativeSessionId)
|
|
21436
|
+
throw new CodeBuddyError("protocolError", "Native history has a different Session identity");
|
|
21437
|
+
if (typeof row.cwd === "string" && !checkedDirectories.has(row.cwd)) {
|
|
21438
|
+
if (!await sameCwd(row.cwd, cwd))
|
|
21439
|
+
throw new CodeBuddyError("invalidRequest", "Native Session belongs to a different working directory");
|
|
21440
|
+
checkedDirectories.add(row.cwd);
|
|
21441
|
+
}
|
|
20993
21442
|
}
|
|
20994
21443
|
}
|
|
20995
21444
|
return {
|
|
@@ -20999,12 +21448,15 @@ async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail) {
|
|
|
20999
21448
|
reusableVersion: source.reusableVersion
|
|
21000
21449
|
};
|
|
21001
21450
|
}
|
|
21002
|
-
async function readNativeHistory(cwd, ref, environment) {
|
|
21003
|
-
return (await codeBuddyNativeHistory(cwd, ref, environment)).contents;
|
|
21451
|
+
async function readNativeHistory(cwd, ref, environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21452
|
+
return (await codeBuddyNativeHistory(cwd, ref, environment, profile)).contents;
|
|
21004
21453
|
}
|
|
21005
21454
|
function parseRows(contents, tolerateIncompleteTail = false) {
|
|
21006
21455
|
return parseJsonl(contents, tolerateIncompleteTail).rows;
|
|
21007
21456
|
}
|
|
21457
|
+
function nativeRawHistoryRows(contents) {
|
|
21458
|
+
return parseRows(contents);
|
|
21459
|
+
}
|
|
21008
21460
|
function parseJsonl(contents, tolerateIncompleteTail) {
|
|
21009
21461
|
const lines = contents.split(/\r?\n/u);
|
|
21010
21462
|
const completeLines = [], rows2 = [];
|
|
@@ -21025,11 +21477,25 @@ function parseJsonl(contents, tolerateIncompleteTail) {
|
|
|
21025
21477
|
contents: tolerateIncompleteTail ? completeLines.join("\n") : contents
|
|
21026
21478
|
};
|
|
21027
21479
|
}
|
|
21480
|
+
var NATIVE_MESSAGE_TYPES = /* @__PURE__ */ new Set([
|
|
21481
|
+
"message",
|
|
21482
|
+
"reasoning",
|
|
21483
|
+
"function_call",
|
|
21484
|
+
"function_call_result"
|
|
21485
|
+
]);
|
|
21486
|
+
function pendingNativeHistoryRewind(contents) {
|
|
21487
|
+
const last = parseRows(contents).findLast((row) => row.type === "resend-fork-notice" || NATIVE_MESSAGE_TYPES.has(text(row.type)));
|
|
21488
|
+
return last?.type === "resend-fork-notice" ? { forkPointId: text(last.parentId) || null } : void 0;
|
|
21489
|
+
}
|
|
21028
21490
|
function nativeHistoryRows(contents) {
|
|
21029
21491
|
const entries = /* @__PURE__ */ new Map();
|
|
21030
21492
|
let leaf = "";
|
|
21031
21493
|
for (const row of parseRows(contents)) {
|
|
21032
|
-
if (
|
|
21494
|
+
if (row.type === "resend-fork-notice") {
|
|
21495
|
+
leaf = text(row.parentId);
|
|
21496
|
+
continue;
|
|
21497
|
+
}
|
|
21498
|
+
if (!NATIVE_MESSAGE_TYPES.has(text(row.type)))
|
|
21033
21499
|
continue;
|
|
21034
21500
|
if (!text(row.id))
|
|
21035
21501
|
throw new CodeBuddyError("protocolError", "Native message is missing its stable ID");
|
|
@@ -21049,39 +21515,118 @@ function nativeHistoryRows(contents) {
|
|
|
21049
21515
|
}
|
|
21050
21516
|
return chain.reverse();
|
|
21051
21517
|
}
|
|
21052
|
-
function snapshotFromHistory(contents, ref, cwd) {
|
|
21518
|
+
function snapshotFromHistory(contents, ref, cwd, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21519
|
+
const supportsNativeCommands = nativeCommandsEnabled(profile);
|
|
21520
|
+
const supportsFork = capabilitiesForProfile(profile).history.fork;
|
|
21053
21521
|
const turns = [];
|
|
21054
21522
|
let current;
|
|
21055
21523
|
const tools = /* @__PURE__ */ new Map();
|
|
21056
|
-
|
|
21524
|
+
const earlyResults = /* @__PURE__ */ new Map();
|
|
21525
|
+
const applyResult = (snapshot, row) => {
|
|
21526
|
+
snapshot.outcome = toolOutcome(row.status, profile);
|
|
21527
|
+
if (snapshot.item.type === "subagentDelegation") {
|
|
21528
|
+
const childId = codeBuddyChildId(row);
|
|
21529
|
+
snapshot.item.subagents = snapshot.item.subagents.map((child) => ({
|
|
21530
|
+
...child,
|
|
21531
|
+
...childId ? { subagentId: childId, nativeSubagentId: childId } : {},
|
|
21532
|
+
status: snapshot.outcome.status === "failed" ? "failed" : child.background ? "interrupted" : "completed",
|
|
21533
|
+
resultSummary: child.background ? "Live background observation is unavailable after reload" : contentText(row.output).slice(0, 2e3)
|
|
21534
|
+
}));
|
|
21535
|
+
}
|
|
21536
|
+
if (snapshot.item.type === "toolExecution")
|
|
21537
|
+
snapshot.item.output = toolOutput(row.output);
|
|
21538
|
+
if (snapshot.item.type === "commandExecution") {
|
|
21539
|
+
const output = toolOutput(row.output);
|
|
21540
|
+
snapshot.item.output = contentText(output.content);
|
|
21541
|
+
snapshot.item.outputTruncated = Boolean(output.truncated);
|
|
21542
|
+
}
|
|
21543
|
+
};
|
|
21544
|
+
const history = nativeHistoryRows(contents);
|
|
21545
|
+
const manualCompactions = /* @__PURE__ */ new Set();
|
|
21546
|
+
let compactUser;
|
|
21547
|
+
if (supportsNativeCommands)
|
|
21548
|
+
for (const row of history) {
|
|
21549
|
+
const data = record2(row.providerData);
|
|
21550
|
+
if (row.type === "message" && row.role === "user")
|
|
21551
|
+
compactUser = data.agent === "compact" ? text(row.id) : void 0;
|
|
21552
|
+
if (compactUser && row.role === "assistant" && data.compactType === "user-command")
|
|
21553
|
+
manualCompactions.add(compactUser);
|
|
21554
|
+
}
|
|
21555
|
+
for (const row of history) {
|
|
21556
|
+
const data = record2(row.providerData);
|
|
21557
|
+
const body = contentText(row.content);
|
|
21558
|
+
const localCommand = supportsNativeCommands && data.skipRun === true ? /^<command-name>([^<]+)<\/command-name>(?:\s*<command-args>([\s\S]*)<\/command-args>)?$/u.exec(body) : null;
|
|
21559
|
+
const localOutput = supportsNativeCommands && data.skipRun === true ? /^<local-command-stdout>([\s\S]*)<\/local-command-stdout>$/u.exec(body) : null;
|
|
21560
|
+
if (localOutput) {
|
|
21561
|
+
if (current) {
|
|
21562
|
+
current.items.push({
|
|
21563
|
+
item: {
|
|
21564
|
+
type: "agentMessage",
|
|
21565
|
+
itemId: hostItemIdSchema.parse(`agentMessage-${text(row.id)}`),
|
|
21566
|
+
text: localOutput[1] ?? ""
|
|
21567
|
+
},
|
|
21568
|
+
outcome: { status: "succeeded" }
|
|
21569
|
+
});
|
|
21570
|
+
current.outcome = { status: "succeeded" };
|
|
21571
|
+
}
|
|
21572
|
+
continue;
|
|
21573
|
+
}
|
|
21574
|
+
if (supportsNativeCommands && data.skipRun === true && body.startsWith('<system-reminder data-role="command-caveat">'))
|
|
21575
|
+
continue;
|
|
21576
|
+
if (supportsNativeCommands && row.type === "message" && row.role === "user" && data.agent === "compact" && !manualCompactions.has(text(row.id)))
|
|
21577
|
+
continue;
|
|
21057
21578
|
if (row.type === "message" && row.role === "user") {
|
|
21058
21579
|
current = {
|
|
21059
21580
|
nativeTurnRef: nativeTurnRefSchema.parse({
|
|
21060
|
-
harnessId:
|
|
21581
|
+
harnessId: profile.harnessId,
|
|
21061
21582
|
nativeSessionId: ref.nativeSessionId,
|
|
21062
21583
|
nativeTurnKey: row.id,
|
|
21063
21584
|
formatVersion: 1
|
|
21064
21585
|
}),
|
|
21065
|
-
input: [
|
|
21586
|
+
input: [
|
|
21587
|
+
{
|
|
21588
|
+
type: "text",
|
|
21589
|
+
text: supportsNativeCommands && data.agent === "compact" ? "/compact" : localCommand ? `${localCommand[1]}${localCommand[2] ? ` ${localCommand[2]}` : ""}` : body
|
|
21590
|
+
}
|
|
21591
|
+
],
|
|
21066
21592
|
items: [],
|
|
21067
21593
|
outcome: { status: "unknown", reason: "Native terminal outcome was not recorded" },
|
|
21068
21594
|
...typeof row.timestamp === "number" ? { startedAtMs: row.timestamp } : {}
|
|
21069
21595
|
};
|
|
21070
21596
|
turns.push(current);
|
|
21071
21597
|
tools.clear();
|
|
21598
|
+
earlyResults.clear();
|
|
21072
21599
|
continue;
|
|
21073
21600
|
}
|
|
21074
21601
|
if (!current)
|
|
21075
21602
|
continue;
|
|
21603
|
+
if (supportsNativeCommands && (data.agent === "compact" || data.isCompactInternal === true)) {
|
|
21604
|
+
if (row.role === "assistant") {
|
|
21605
|
+
const outcome = row.status === "completed" && data.isCompacted === true ? { status: "succeeded" } : row.status === "cancelled" || row.status === "interrupted" ? { status: "cancelled" } : {
|
|
21606
|
+
status: "failed",
|
|
21607
|
+
error: nativeError(new CodeBuddyError("nativeFailure", "Native compaction did not complete"), profile)
|
|
21608
|
+
};
|
|
21609
|
+
current.items.push({
|
|
21610
|
+
item: {
|
|
21611
|
+
type: "contextCompaction",
|
|
21612
|
+
itemId: hostItemIdSchema.parse(`compact-${text(row.id)}`)
|
|
21613
|
+
},
|
|
21614
|
+
outcome
|
|
21615
|
+
});
|
|
21616
|
+
if (data.compactType === "user-command")
|
|
21617
|
+
current.outcome = outcome;
|
|
21618
|
+
}
|
|
21619
|
+
continue;
|
|
21620
|
+
}
|
|
21076
21621
|
const model = text(record2(row.providerData).model);
|
|
21077
21622
|
if (model)
|
|
21078
21623
|
current.model = modelRef(model);
|
|
21079
21624
|
if (row.type === "message" && row.role === "assistant" || row.type === "reasoning") {
|
|
21080
21625
|
const type = row.type === "reasoning" ? "reasoning" : "agentMessage";
|
|
21081
|
-
const
|
|
21082
|
-
if (
|
|
21626
|
+
const body2 = contentText(row.content) || contentText(row.rawContent);
|
|
21627
|
+
if (body2)
|
|
21083
21628
|
current.items.push({
|
|
21084
|
-
item: { type, itemId: hostItemIdSchema.parse(`${type}-${text(row.id)}`), text:
|
|
21629
|
+
item: { type, itemId: hostItemIdSchema.parse(`${type}-${text(row.id)}`), text: body2 },
|
|
21085
21630
|
outcome: { status: "succeeded" }
|
|
21086
21631
|
});
|
|
21087
21632
|
if (row.role === "assistant" && row.status === "completed") {
|
|
@@ -21098,36 +21643,36 @@ function snapshotFromHistory(contents, ref, cwd) {
|
|
|
21098
21643
|
throw new CodeBuddyError("protocolError", "Invalid native Tool arguments");
|
|
21099
21644
|
}
|
|
21100
21645
|
}
|
|
21646
|
+
const callId = text(row.callId);
|
|
21101
21647
|
const snapshot = {
|
|
21102
|
-
item: row.name === "Agent" ? codeBuddyDelegation(
|
|
21103
|
-
outcome: toolOutcome("unknown")
|
|
21648
|
+
item: row.name === "Agent" ? codeBuddyDelegation(callId, input, "running", void 0, profile.displayName) : toolItem(callId, text(row.name), input, typeof row.cwd === "string" ? row.cwd : cwd),
|
|
21649
|
+
outcome: toolOutcome("unknown", profile)
|
|
21104
21650
|
};
|
|
21105
|
-
tools.set(
|
|
21651
|
+
tools.set(callId, snapshot);
|
|
21106
21652
|
current.items.push(snapshot);
|
|
21107
21653
|
current.outcome = { status: "unknown", reason: "Native Tool has not completed" };
|
|
21108
|
-
|
|
21109
|
-
|
|
21110
|
-
|
|
21111
|
-
|
|
21112
|
-
snapshot.outcome = toolOutcome(row.status);
|
|
21113
|
-
if (snapshot.item.type === "subagentDelegation") {
|
|
21114
|
-
const childId = codeBuddyChildId(row);
|
|
21115
|
-
snapshot.item.subagents = snapshot.item.subagents.map((child) => ({
|
|
21116
|
-
...child,
|
|
21117
|
-
...childId ? { subagentId: childId, nativeSubagentId: childId } : {},
|
|
21118
|
-
status: snapshot.outcome.status === "failed" ? "failed" : child.background ? "interrupted" : "completed",
|
|
21119
|
-
resultSummary: child.background ? "Live background observation is unavailable after reload" : contentText(row.output).slice(0, 2e3)
|
|
21120
|
-
}));
|
|
21121
|
-
}
|
|
21122
|
-
if (snapshot.item.type === "toolExecution")
|
|
21123
|
-
snapshot.item.output = toolOutput(row.output);
|
|
21124
|
-
if (snapshot.item.type === "commandExecution") {
|
|
21125
|
-
const output = toolOutput(row.output);
|
|
21126
|
-
snapshot.item.output = contentText(output.content);
|
|
21127
|
-
snapshot.item.outputTruncated = Boolean(output.truncated);
|
|
21654
|
+
const early = earlyResults.get(callId);
|
|
21655
|
+
if (early) {
|
|
21656
|
+
earlyResults.delete(callId);
|
|
21657
|
+
applyResult(snapshot, early);
|
|
21128
21658
|
}
|
|
21659
|
+
} else if (row.type === "function_call_result") {
|
|
21660
|
+
const callId = text(row.callId);
|
|
21661
|
+
const snapshot = tools.get(callId);
|
|
21662
|
+
if (snapshot)
|
|
21663
|
+
applyResult(snapshot, row);
|
|
21664
|
+
else
|
|
21665
|
+
earlyResults.set(callId, row);
|
|
21129
21666
|
}
|
|
21130
21667
|
}
|
|
21668
|
+
if (supportsFork)
|
|
21669
|
+
for (const turn of turns)
|
|
21670
|
+
turn.checkpoint = nativeCheckpointRefSchema.parse({
|
|
21671
|
+
harnessId: profile.harnessId,
|
|
21672
|
+
nativeSessionId: ref.nativeSessionId,
|
|
21673
|
+
checkpointId: turn.nativeTurnRef.nativeTurnKey,
|
|
21674
|
+
formatVersion: 1
|
|
21675
|
+
});
|
|
21131
21676
|
return { turns };
|
|
21132
21677
|
}
|
|
21133
21678
|
function historyUsage(contents) {
|
|
@@ -21158,25 +21703,814 @@ function historyUsage(contents) {
|
|
|
21158
21703
|
return Object.keys(result).length ? result : null;
|
|
21159
21704
|
}
|
|
21160
21705
|
|
|
21706
|
+
// dist/child-provenance.js
|
|
21707
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
21708
|
+
import { realpath as realpath3 } from "node:fs/promises";
|
|
21709
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
21710
|
+
var CODEBUDDY_CHILD_MAX_BYTES = 8e6;
|
|
21711
|
+
var equalPath = (left, right) => process.platform === "win32" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
21712
|
+
function codeBuddyChildDigest(contents) {
|
|
21713
|
+
return createHash2("sha256").update(contents).digest("hex");
|
|
21714
|
+
}
|
|
21715
|
+
function parseCodeBuddyChild(contents, tolerateIncompleteTail) {
|
|
21716
|
+
const lines = contents.split(/\r?\n/u);
|
|
21717
|
+
if (tolerateIncompleteTail && lines.at(-1)?.trim()) {
|
|
21718
|
+
try {
|
|
21719
|
+
JSON.parse(lines.at(-1) ?? "");
|
|
21720
|
+
} catch {
|
|
21721
|
+
lines.pop();
|
|
21722
|
+
}
|
|
21723
|
+
}
|
|
21724
|
+
const entries = lines.filter((line) => line.trim()).map((line) => record2(JSON.parse(line)));
|
|
21725
|
+
return { contents: lines.join("\n"), entries };
|
|
21726
|
+
}
|
|
21727
|
+
function inheritedChildren(parent) {
|
|
21728
|
+
const value = record2(parent.locator).codebuddyInheritedChildren;
|
|
21729
|
+
if (value === void 0)
|
|
21730
|
+
return [];
|
|
21731
|
+
if (!Array.isArray(value) || value.length > 256)
|
|
21732
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is invalid");
|
|
21733
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21734
|
+
return value.map((candidate) => {
|
|
21735
|
+
const child = record2(candidate);
|
|
21736
|
+
const historicalCwds = child.historicalCwds;
|
|
21737
|
+
const recordedCwds = child.recordedCwds;
|
|
21738
|
+
const workspaceBindings = child.workspaceBindings;
|
|
21739
|
+
if (!validCodeBuddyChildId(text(child.childId)) || !/^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/u.test(text(child.nativeSessionId)) || !Number.isSafeInteger(child.inheritedBytes) || Number(child.inheritedBytes) < 0 || Number(child.inheritedBytes) > CODEBUDDY_CHILD_MAX_BYTES || !Number.isSafeInteger(child.inheritedRows) || Number(child.inheritedRows) < 0 || typeof child.inheritedSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(child.inheritedSha256) || !Array.isArray(historicalCwds) || historicalCwds.length > 256 || historicalCwds.some((cwd) => typeof cwd !== "string" || !cwd) || !Array.isArray(recordedCwds) || recordedCwds.length > 256 || recordedCwds.some((cwd) => typeof cwd !== "string" || !cwd) || !Array.isArray(workspaceBindings) || workspaceBindings.length > 256)
|
|
21740
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is invalid");
|
|
21741
|
+
const bindings = workspaceBindings.map((candidate2) => {
|
|
21742
|
+
const binding = record2(candidate2);
|
|
21743
|
+
if (typeof binding.recordedCwd !== "string" || !binding.recordedCwd || typeof binding.canonicalCwd !== "string" || !binding.canonicalCwd)
|
|
21744
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is invalid");
|
|
21745
|
+
return {
|
|
21746
|
+
recordedCwd: binding.recordedCwd,
|
|
21747
|
+
canonicalCwd: binding.canonicalCwd
|
|
21748
|
+
};
|
|
21749
|
+
});
|
|
21750
|
+
const boundRecorded = new Set(bindings.map((binding) => binding.recordedCwd));
|
|
21751
|
+
const boundCanonical = new Set(bindings.map((binding) => binding.canonicalCwd));
|
|
21752
|
+
if (boundRecorded.size !== bindings.length || new Set(recordedCwds).size !== recordedCwds.length || boundRecorded.size !== new Set(recordedCwds).size || recordedCwds.some((cwd) => !boundRecorded.has(cwd)) || new Set(historicalCwds).size !== historicalCwds.length || boundCanonical.size !== new Set(historicalCwds).size || historicalCwds.some((cwd) => !boundCanonical.has(cwd)))
|
|
21753
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is inconsistent");
|
|
21754
|
+
const childId = text(child.childId);
|
|
21755
|
+
if (seen.has(childId))
|
|
21756
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is ambiguous");
|
|
21757
|
+
seen.add(childId);
|
|
21758
|
+
return {
|
|
21759
|
+
childId,
|
|
21760
|
+
nativeSessionId: text(child.nativeSessionId),
|
|
21761
|
+
inheritedBytes: Number(child.inheritedBytes),
|
|
21762
|
+
inheritedRows: Number(child.inheritedRows),
|
|
21763
|
+
inheritedSha256: child.inheritedSha256,
|
|
21764
|
+
recordedCwds: [...recordedCwds],
|
|
21765
|
+
historicalCwds: [...historicalCwds],
|
|
21766
|
+
workspaceBindings: bindings
|
|
21767
|
+
};
|
|
21768
|
+
});
|
|
21769
|
+
}
|
|
21770
|
+
function codeBuddyInheritedChild(parent, childId) {
|
|
21771
|
+
return inheritedChildren(parent).find((child) => child.childId === childId);
|
|
21772
|
+
}
|
|
21773
|
+
async function canonicalCwds(cwds) {
|
|
21774
|
+
const result = /* @__PURE__ */ new Map();
|
|
21775
|
+
for (const cwd of new Set(cwds)) {
|
|
21776
|
+
const canonical = await realpath3(cwd).catch((error51) => {
|
|
21777
|
+
if (["ENOENT", "ENOTDIR"].includes(String(record2(error51).code)))
|
|
21778
|
+
throw new CodeBuddyError("invalidRequest", "Subagent historical working directory is unavailable; ownership cannot be verified");
|
|
21779
|
+
throw error51;
|
|
21780
|
+
});
|
|
21781
|
+
result.set(cwd, canonical);
|
|
21782
|
+
}
|
|
21783
|
+
return result;
|
|
21784
|
+
}
|
|
21785
|
+
async function validateCodeBuddyChildContents(contents, parent, childId, cwd, tolerateIncompleteTail) {
|
|
21786
|
+
if (!validCodeBuddyChildId(childId))
|
|
21787
|
+
throw new CodeBuddyError("invalidRequest", "Invalid native Subagent ID");
|
|
21788
|
+
const parsed = parseCodeBuddyChild(contents, tolerateIncompleteTail);
|
|
21789
|
+
const sessions = new Set(parsed.entries.map((row) => text(row.sessionId)).filter(Boolean));
|
|
21790
|
+
if (sessions.size !== 1)
|
|
21791
|
+
throw new CodeBuddyError("protocolError", "Subagent transcript identity is missing or mixed");
|
|
21792
|
+
const nativeSessionId = [...sessions][0];
|
|
21793
|
+
if (!nativeSessionId || !/^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/u.test(nativeSessionId))
|
|
21794
|
+
throw new CodeBuddyError("protocolError", "Missing or invalid native child Session");
|
|
21795
|
+
const inherited = codeBuddyInheritedChild(parent, childId);
|
|
21796
|
+
let inheritedEntries = [];
|
|
21797
|
+
if (inherited) {
|
|
21798
|
+
const bytes = Buffer.from(contents, "utf8");
|
|
21799
|
+
if (inherited.inheritedBytes > bytes.length)
|
|
21800
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent prefix is incomplete");
|
|
21801
|
+
const prefix = bytes.subarray(0, inherited.inheritedBytes);
|
|
21802
|
+
const prefixText = prefix.toString("utf8");
|
|
21803
|
+
if (!isDeepStrictEqual2(Buffer.from(prefixText, "utf8"), prefix) || codeBuddyChildDigest(prefix) !== inherited.inheritedSha256)
|
|
21804
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent prefix verification failed");
|
|
21805
|
+
let prefixParsed;
|
|
21806
|
+
try {
|
|
21807
|
+
prefixParsed = parseCodeBuddyChild(prefixText, false);
|
|
21808
|
+
} catch {
|
|
21809
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent prefix is malformed");
|
|
21810
|
+
}
|
|
21811
|
+
if (prefixParsed.entries.length !== inherited.inheritedRows || parsed.entries.length < inherited.inheritedRows || !isDeepStrictEqual2(prefixParsed.entries, parsed.entries.slice(0, inherited.inheritedRows)) || nativeSessionId !== inherited.nativeSessionId)
|
|
21812
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent identity changed");
|
|
21813
|
+
inheritedEntries = prefixParsed.entries;
|
|
21814
|
+
}
|
|
21815
|
+
const target = await realpath3(cwd);
|
|
21816
|
+
const inheritedCwds = inheritedEntries.flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []);
|
|
21817
|
+
const suffixCwds = parsed.entries.slice(inheritedEntries.length).flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []);
|
|
21818
|
+
const canonical = await canonicalCwds(suffixCwds);
|
|
21819
|
+
if (inherited) {
|
|
21820
|
+
const allowed = new Set(inherited.recordedCwds);
|
|
21821
|
+
const observed = new Set(inheritedCwds);
|
|
21822
|
+
if (allowed.size !== observed.size || [...allowed].some((value) => !observed.has(value)) || inheritedCwds.some((value) => !allowed.has(value)))
|
|
21823
|
+
throw new CodeBuddyError("invalidRequest", "Inherited Subagent workspace changed");
|
|
21824
|
+
}
|
|
21825
|
+
for (const value of suffixCwds) {
|
|
21826
|
+
const actual = canonical.get(value);
|
|
21827
|
+
if (!actual || !equalPath(actual, target))
|
|
21828
|
+
throw new CodeBuddyError("invalidRequest", "Subagent workspace differs from parent");
|
|
21829
|
+
}
|
|
21830
|
+
const bindings = new Map((inherited?.workspaceBindings ?? []).map((binding) => [
|
|
21831
|
+
binding.recordedCwd,
|
|
21832
|
+
binding.canonicalCwd
|
|
21833
|
+
]));
|
|
21834
|
+
for (const value of new Set(suffixCwds)) {
|
|
21835
|
+
const resolved = canonical.get(value);
|
|
21836
|
+
if (!resolved)
|
|
21837
|
+
throw new CodeBuddyError("invalidRequest", "Subagent workspace is unavailable");
|
|
21838
|
+
const existing = bindings.get(value);
|
|
21839
|
+
if (existing && !equalPath(existing, resolved))
|
|
21840
|
+
throw new CodeBuddyError("invalidRequest", "Subagent workspace binding changed");
|
|
21841
|
+
bindings.set(value, resolved);
|
|
21842
|
+
}
|
|
21843
|
+
return {
|
|
21844
|
+
...parsed,
|
|
21845
|
+
nativeSessionId,
|
|
21846
|
+
recordedCwds: [...bindings.keys()],
|
|
21847
|
+
historicalCwds: [...new Set(bindings.values())],
|
|
21848
|
+
workspaceBindings: [...bindings].map(([recordedCwd, canonicalCwd]) => ({
|
|
21849
|
+
recordedCwd,
|
|
21850
|
+
canonicalCwd
|
|
21851
|
+
}))
|
|
21852
|
+
};
|
|
21853
|
+
}
|
|
21854
|
+
function codeBuddyInheritedChildDescriptor(childId, contents, child) {
|
|
21855
|
+
if (child.recordedCwds.length > 256 || child.historicalCwds.length > 256)
|
|
21856
|
+
throw new CodeBuddyError("unsupported", "Too many Subagent historical workspaces");
|
|
21857
|
+
return {
|
|
21858
|
+
childId,
|
|
21859
|
+
nativeSessionId: child.nativeSessionId,
|
|
21860
|
+
inheritedBytes: Buffer.byteLength(contents, "utf8"),
|
|
21861
|
+
inheritedRows: child.entries.length,
|
|
21862
|
+
inheritedSha256: codeBuddyChildDigest(contents),
|
|
21863
|
+
recordedCwds: child.recordedCwds,
|
|
21864
|
+
historicalCwds: child.historicalCwds,
|
|
21865
|
+
workspaceBindings: child.workspaceBindings
|
|
21866
|
+
};
|
|
21867
|
+
}
|
|
21868
|
+
async function codeBuddyChildPrefixThrough(contents, lastId, child) {
|
|
21869
|
+
let cursor = 0;
|
|
21870
|
+
let rowIndex = 0;
|
|
21871
|
+
let match = -1;
|
|
21872
|
+
let end = -1;
|
|
21873
|
+
while (cursor < contents.length) {
|
|
21874
|
+
const newline2 = contents.indexOf("\n", cursor);
|
|
21875
|
+
const next = newline2 < 0 ? contents.length : newline2 + 1;
|
|
21876
|
+
const physicalLine = contents.slice(cursor, next);
|
|
21877
|
+
const line = physicalLine.replace(/\r?\n$/u, "");
|
|
21878
|
+
if (line.trim()) {
|
|
21879
|
+
const row = child.entries[rowIndex++];
|
|
21880
|
+
if (!row)
|
|
21881
|
+
throw new CodeBuddyError("protocolError", "Subagent transcript rows changed");
|
|
21882
|
+
if (text(row.id) === lastId) {
|
|
21883
|
+
if (match >= 0)
|
|
21884
|
+
throw new CodeBuddyError("protocolError", "Agent result has an ambiguous child range");
|
|
21885
|
+
match = rowIndex - 1;
|
|
21886
|
+
end = next;
|
|
21887
|
+
}
|
|
21888
|
+
}
|
|
21889
|
+
cursor = next;
|
|
21890
|
+
}
|
|
21891
|
+
if (rowIndex !== child.entries.length || match < 0 || end < 0)
|
|
21892
|
+
throw new CodeBuddyError("protocolError", "Agent result child range was not found");
|
|
21893
|
+
const entries = child.entries.slice(0, match + 1);
|
|
21894
|
+
const cwdValues = entries.flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []);
|
|
21895
|
+
const inheritedBindings = new Map(child.workspaceBindings.map((binding) => [binding.recordedCwd, binding.canonicalCwd]));
|
|
21896
|
+
const bindings = [...new Set(cwdValues)].map((recordedCwd) => {
|
|
21897
|
+
const canonicalCwd = inheritedBindings.get(recordedCwd);
|
|
21898
|
+
if (!canonicalCwd)
|
|
21899
|
+
throw new CodeBuddyError("protocolError", "Subagent workspace binding is missing");
|
|
21900
|
+
return { recordedCwd, canonicalCwd };
|
|
21901
|
+
});
|
|
21902
|
+
return {
|
|
21903
|
+
contents: contents.slice(0, end),
|
|
21904
|
+
child: {
|
|
21905
|
+
contents: contents.slice(0, end),
|
|
21906
|
+
entries,
|
|
21907
|
+
nativeSessionId: child.nativeSessionId,
|
|
21908
|
+
recordedCwds: bindings.map((binding) => binding.recordedCwd),
|
|
21909
|
+
historicalCwds: [...new Set(bindings.map((binding) => binding.canonicalCwd))],
|
|
21910
|
+
workspaceBindings: bindings
|
|
21911
|
+
}
|
|
21912
|
+
};
|
|
21913
|
+
}
|
|
21914
|
+
|
|
21915
|
+
// dist/derivation.js
|
|
21916
|
+
async function copyCodeBuddySession(cwd, sourceId, targetId, environment, signal, invocationFactory = codeBuddyInvocation) {
|
|
21917
|
+
if (signal.aborted)
|
|
21918
|
+
throw new CodeBuddyError("invalidState", "Adapter closed before history copy");
|
|
21919
|
+
const invocation = invocationFactory(environment, false, [
|
|
21920
|
+
"--resume",
|
|
21921
|
+
sourceId,
|
|
21922
|
+
"--fork-session",
|
|
21923
|
+
"--session-id",
|
|
21924
|
+
targetId,
|
|
21925
|
+
"--print",
|
|
21926
|
+
"--input-format",
|
|
21927
|
+
"stream-json",
|
|
21928
|
+
"--output-format",
|
|
21929
|
+
"stream-json"
|
|
21930
|
+
]);
|
|
21931
|
+
await new Promise((resolve, reject) => {
|
|
21932
|
+
const child = spawn2(invocation.command, invocation.arguments, {
|
|
21933
|
+
cwd,
|
|
21934
|
+
env: invocation.environment,
|
|
21935
|
+
stdio: "pipe",
|
|
21936
|
+
windowsHide: true,
|
|
21937
|
+
windowsVerbatimArguments: invocation.windowsVerbatimArguments,
|
|
21938
|
+
detached: process.platform !== "win32"
|
|
21939
|
+
});
|
|
21940
|
+
let output = "", bytes = 0, failed = false;
|
|
21941
|
+
let termination = Promise.resolve();
|
|
21942
|
+
const stop = () => {
|
|
21943
|
+
if (failed)
|
|
21944
|
+
return;
|
|
21945
|
+
failed = true;
|
|
21946
|
+
if (child.exitCode !== null || child.signalCode !== null) {
|
|
21947
|
+
child.stdout.destroy();
|
|
21948
|
+
child.stderr.destroy();
|
|
21949
|
+
} else if (process.platform === "win32" && child.pid) {
|
|
21950
|
+
termination = new Promise((done) => {
|
|
21951
|
+
execFile2("taskkill", ["/PID", String(child.pid), "/T", "/F"], { windowsHide: true, timeout: 3e3 }, () => {
|
|
21952
|
+
child.kill();
|
|
21953
|
+
done();
|
|
21954
|
+
});
|
|
21955
|
+
});
|
|
21956
|
+
} else if (child.pid) {
|
|
21957
|
+
try {
|
|
21958
|
+
process.kill(-child.pid, "SIGKILL");
|
|
21959
|
+
} catch {
|
|
21960
|
+
child.kill("SIGKILL");
|
|
21961
|
+
}
|
|
21962
|
+
} else
|
|
21963
|
+
child.kill("SIGKILL");
|
|
21964
|
+
};
|
|
21965
|
+
const timer = setTimeout(stop, 3e4);
|
|
21966
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
21967
|
+
child.stdout.on("data", (data) => {
|
|
21968
|
+
bytes += data.length;
|
|
21969
|
+
if (bytes > 64e6) {
|
|
21970
|
+
stop();
|
|
21971
|
+
return;
|
|
21972
|
+
}
|
|
21973
|
+
output += data.toString();
|
|
21974
|
+
});
|
|
21975
|
+
child.stderr.resume();
|
|
21976
|
+
child.stdin.on("error", () => {
|
|
21977
|
+
});
|
|
21978
|
+
child.once("error", reject);
|
|
21979
|
+
child.once("close", async (code) => {
|
|
21980
|
+
await termination;
|
|
21981
|
+
clearTimeout(timer);
|
|
21982
|
+
signal.removeEventListener("abort", stop);
|
|
21983
|
+
if (failed || signal.aborted || code !== 0) {
|
|
21984
|
+
reject(new CodeBuddyError("nativeFailure", "Native history copy failed or was interrupted"));
|
|
21985
|
+
return;
|
|
21986
|
+
}
|
|
21987
|
+
try {
|
|
21988
|
+
const rows2 = output.trim().split(/\r?\n/u).filter(Boolean).map((line) => record2(JSON.parse(line)));
|
|
21989
|
+
const init = rows2.find((row) => row.type === "system" && row.subtype === "init");
|
|
21990
|
+
const result = rows2.findLast((row) => row.type === "result");
|
|
21991
|
+
if (init?.session_id !== targetId || result?.session_id !== targetId || result?.is_error !== false || result?.duration_api_ms !== 0)
|
|
21992
|
+
throw new CodeBuddyError("unsupported", "Native CLI did not confirm a model-free history copy");
|
|
21993
|
+
resolve();
|
|
21994
|
+
} catch (error51) {
|
|
21995
|
+
reject(error51);
|
|
21996
|
+
}
|
|
21997
|
+
});
|
|
21998
|
+
if (signal.aborted)
|
|
21999
|
+
stop();
|
|
22000
|
+
child.stdin.end();
|
|
22001
|
+
});
|
|
22002
|
+
}
|
|
22003
|
+
function withoutIdentity(row) {
|
|
22004
|
+
const result = { ...row };
|
|
22005
|
+
delete result.id;
|
|
22006
|
+
delete result.parentId;
|
|
22007
|
+
delete result.logicalParentId;
|
|
22008
|
+
delete result.sessionId;
|
|
22009
|
+
return result;
|
|
22010
|
+
}
|
|
22011
|
+
function assertCopiedPrefix(source, copied) {
|
|
22012
|
+
if (copied.length < source.length)
|
|
22013
|
+
throw new CodeBuddyError("unsupported", "Native Fork omitted history");
|
|
22014
|
+
const ids = new Map(source.map((row, index) => [text(row.id), text(copied[index]?.id)]));
|
|
22015
|
+
for (const [index, row] of source.entries()) {
|
|
22016
|
+
const clone2 = copied[index];
|
|
22017
|
+
if (!clone2)
|
|
22018
|
+
throw new CodeBuddyError("unsupported", "Native Fork omitted history");
|
|
22019
|
+
if (!isDeepStrictEqual3(withoutIdentity(row), withoutIdentity(clone2)) || ["parentId", "logicalParentId"].some((key) => text(clone2[key]) !== (ids.get(text(row[key])) ?? "")))
|
|
22020
|
+
throw new CodeBuddyError("unsupported", "Native Fork did not preserve the exact history prefix");
|
|
22021
|
+
}
|
|
22022
|
+
}
|
|
22023
|
+
function commandCaveat(row) {
|
|
22024
|
+
return record2(row?.providerData).skipRun === true && JSON.stringify(row?.content).includes('data-role=\\"command-caveat\\"');
|
|
22025
|
+
}
|
|
22026
|
+
function retainedRowCount(input, contents, sourceCwd = input.cwd, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
22027
|
+
const rows2 = nativeHistoryRows(contents);
|
|
22028
|
+
const turns = snapshotFromHistory(contents, input.sourceRef, sourceCwd, profile).turns;
|
|
22029
|
+
let excluded2;
|
|
22030
|
+
if (input.kind === "rollbackLastTurn") {
|
|
22031
|
+
if (!turns.length)
|
|
22032
|
+
throw new CodeBuddyError("invalidState", "Native Session has no Turn to revise");
|
|
22033
|
+
excluded2 = turns.at(-1)?.nativeTurnRef.nativeTurnKey;
|
|
22034
|
+
} else {
|
|
22035
|
+
const checkpoint = input.checkpoint;
|
|
22036
|
+
const index = turns.findIndex((turn) => turn.nativeTurnRef.nativeTurnKey === checkpoint.checkpointId);
|
|
22037
|
+
if (checkpoint.harnessId !== profile.harnessId || checkpoint.nativeSessionId !== input.sourceRef.nativeSessionId || checkpoint.formatVersion !== 1 || index < 0)
|
|
22038
|
+
throw new CodeBuddyError("checkpointNotFound", "Native Fork checkpoint was not found");
|
|
22039
|
+
excluded2 = turns[index + 1]?.nativeTurnRef.nativeTurnKey;
|
|
22040
|
+
}
|
|
22041
|
+
let count = excluded2 ? rows2.findIndex((row) => row.id === excluded2) : rows2.length;
|
|
22042
|
+
if (count < 0)
|
|
22043
|
+
throw new CodeBuddyError("protocolError", "Native Turn boundary is missing");
|
|
22044
|
+
if (excluded2)
|
|
22045
|
+
while (count > 0 && commandCaveat(rows2[count - 1]))
|
|
22046
|
+
count--;
|
|
22047
|
+
return count;
|
|
22048
|
+
}
|
|
22049
|
+
function sameResolvedPath(left, right) {
|
|
22050
|
+
const a = codeBuddyCanonicalCwd(left), b = codeBuddyCanonicalCwd(right);
|
|
22051
|
+
return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
22052
|
+
}
|
|
22053
|
+
async function bridgeCopyToTarget(sourceCwd, targetCwd, ref, contents, environment, profile) {
|
|
22054
|
+
const sourceFile = codeBuddyPrimaryHistoryPath(sourceCwd, ref, environment, profile);
|
|
22055
|
+
const targetFile = codeBuddyPrimaryHistoryPath(targetCwd, ref, environment, profile);
|
|
22056
|
+
if (sameResolvedPath(sourceFile, targetFile))
|
|
22057
|
+
return void 0;
|
|
22058
|
+
const targetDirectory = path5.dirname(targetFile);
|
|
22059
|
+
const projectsDirectory = path5.dirname(targetDirectory);
|
|
22060
|
+
await mkdir(targetDirectory, { recursive: true });
|
|
22061
|
+
const [realProjects, realTargetDirectory] = await Promise.all([
|
|
22062
|
+
realpath4(projectsDirectory),
|
|
22063
|
+
realpath4(targetDirectory)
|
|
22064
|
+
]);
|
|
22065
|
+
if (!sameResolvedPath(realTargetDirectory, path5.join(realProjects, codeBuddyProjectSlug(targetCwd, profile))))
|
|
22066
|
+
throw new CodeBuddyError("invalidRequest", "Cross-directory history bridge target escaped the native projects root");
|
|
22067
|
+
const expected = Buffer.from(contents, "utf8");
|
|
22068
|
+
await writeFile(targetFile, expected, { flag: "wx", mode: 384 });
|
|
22069
|
+
const bridge = { file: targetFile, expected };
|
|
22070
|
+
try {
|
|
22071
|
+
const persisted = await readFile2(targetFile);
|
|
22072
|
+
if (!isDeepStrictEqual3(persisted, expected))
|
|
22073
|
+
throw new CodeBuddyError("nativeFailure", "Cross-directory history bridge changed native bytes");
|
|
22074
|
+
return bridge;
|
|
22075
|
+
} catch (error51) {
|
|
22076
|
+
return failAfterBridgeCleanup(error51, bridge);
|
|
22077
|
+
}
|
|
22078
|
+
}
|
|
22079
|
+
async function cleanupBridge(bridge) {
|
|
22080
|
+
if (!bridge)
|
|
22081
|
+
return;
|
|
22082
|
+
try {
|
|
22083
|
+
const info = await lstat(bridge.file);
|
|
22084
|
+
if (!info.isFile() || process.platform !== "win32" && (info.mode & 63) !== 0)
|
|
22085
|
+
return;
|
|
22086
|
+
if (!isDeepStrictEqual3(await readFile2(bridge.file), bridge.expected))
|
|
22087
|
+
return;
|
|
22088
|
+
await unlink(bridge.file);
|
|
22089
|
+
} catch (error51) {
|
|
22090
|
+
if (record2(error51).code !== "ENOENT")
|
|
22091
|
+
throw error51;
|
|
22092
|
+
}
|
|
22093
|
+
}
|
|
22094
|
+
async function failAfterBridgeCleanup(failure2, bridge) {
|
|
22095
|
+
try {
|
|
22096
|
+
await cleanupBridge(bridge);
|
|
22097
|
+
} catch (cleanupFailure) {
|
|
22098
|
+
throw new AggregateError([failure2, cleanupFailure], "Native derivation and bridge cleanup both failed");
|
|
22099
|
+
}
|
|
22100
|
+
throw failure2;
|
|
22101
|
+
}
|
|
22102
|
+
function argumentsRecord(value) {
|
|
22103
|
+
if (typeof value !== "string")
|
|
22104
|
+
return record2(value);
|
|
22105
|
+
try {
|
|
22106
|
+
return record2(JSON.parse(value));
|
|
22107
|
+
} catch {
|
|
22108
|
+
return {};
|
|
22109
|
+
}
|
|
22110
|
+
}
|
|
22111
|
+
function referencedChildren(rows2) {
|
|
22112
|
+
const calls = /* @__PURE__ */ new Map();
|
|
22113
|
+
const children = /* @__PURE__ */ new Map();
|
|
22114
|
+
for (const row of rows2) {
|
|
22115
|
+
if (row.type === "function_call" && row.name === "Agent") {
|
|
22116
|
+
const callId2 = text(row.callId);
|
|
22117
|
+
if (!callId2 || calls.has(callId2))
|
|
22118
|
+
throw new CodeBuddyError("protocolError", "Agent delegation identity is ambiguous");
|
|
22119
|
+
const resumed2 = text(argumentsRecord(row.arguments).resume);
|
|
22120
|
+
if (resumed2 && !validCodeBuddyChildId(resumed2))
|
|
22121
|
+
throw new CodeBuddyError("protocolError", "Agent delegation has an invalid child identity");
|
|
22122
|
+
calls.set(callId2, resumed2 || void 0);
|
|
22123
|
+
continue;
|
|
22124
|
+
}
|
|
22125
|
+
if (row.type !== "function_call_result")
|
|
22126
|
+
continue;
|
|
22127
|
+
const callId = text(row.callId);
|
|
22128
|
+
if (!calls.has(callId))
|
|
22129
|
+
continue;
|
|
22130
|
+
const subagent = record2(record2(record2(row.providerData).toolResult).subAgent);
|
|
22131
|
+
const childId = text(subagent.sessionId);
|
|
22132
|
+
if (!validCodeBuddyChildId(childId))
|
|
22133
|
+
throw new CodeBuddyError("unsupported", "Retained Agent result has no verified native child identity");
|
|
22134
|
+
const resumed = calls.get(callId);
|
|
22135
|
+
if (resumed && resumed !== childId)
|
|
22136
|
+
throw new CodeBuddyError("protocolError", "Agent result changed its child identity");
|
|
22137
|
+
const lastId = text(subagent.lastId);
|
|
22138
|
+
const afterId = text(subagent.afterId);
|
|
22139
|
+
if (!lastId)
|
|
22140
|
+
throw new CodeBuddyError("unsupported", "Retained Agent result has no bounded child transcript range");
|
|
22141
|
+
const child = children.get(childId) ?? { childId, ranges: [] };
|
|
22142
|
+
child.ranges.push({ ...afterId ? { afterId } : {}, lastId });
|
|
22143
|
+
children.set(childId, child);
|
|
22144
|
+
if (children.size > 256)
|
|
22145
|
+
throw new CodeBuddyError("unsupported", "Too many retained Subagent transcripts");
|
|
22146
|
+
calls.delete(callId);
|
|
22147
|
+
}
|
|
22148
|
+
if (calls.size)
|
|
22149
|
+
throw new CodeBuddyError("unsupported", "Retained Agent delegation is incomplete");
|
|
22150
|
+
return [...children.values()];
|
|
22151
|
+
}
|
|
22152
|
+
function assertChildRanges(rows2, child) {
|
|
22153
|
+
const positions = /* @__PURE__ */ new Map();
|
|
22154
|
+
for (const [index, row] of rows2.entries()) {
|
|
22155
|
+
const id = text(row.id);
|
|
22156
|
+
if (!id)
|
|
22157
|
+
continue;
|
|
22158
|
+
const matches = positions.get(id) ?? [];
|
|
22159
|
+
matches.push(index);
|
|
22160
|
+
positions.set(id, matches);
|
|
22161
|
+
}
|
|
22162
|
+
let previous = -1;
|
|
22163
|
+
for (const range of child.ranges) {
|
|
22164
|
+
const last = positions.get(range.lastId);
|
|
22165
|
+
const after = range.afterId ? positions.get(range.afterId) : void 0;
|
|
22166
|
+
if (last?.length !== 1 || after && after.length !== 1 || range.afterId && !after || after && (after[0] ?? -1) >= (last[0] ?? -1) || (last[0] ?? -1) < previous)
|
|
22167
|
+
throw new CodeBuddyError("protocolError", "Agent result child range is inconsistent");
|
|
22168
|
+
previous = last[0] ?? -1;
|
|
22169
|
+
}
|
|
22170
|
+
}
|
|
22171
|
+
async function plainDirectory(parent, name) {
|
|
22172
|
+
const directory = path5.join(parent, name);
|
|
22173
|
+
await mkdir(directory, { mode: 448 }).catch((error51) => {
|
|
22174
|
+
if (record2(error51).code !== "EEXIST")
|
|
22175
|
+
throw error51;
|
|
22176
|
+
});
|
|
22177
|
+
const info = await lstat(directory);
|
|
22178
|
+
if (!info.isDirectory() || info.isSymbolicLink() || process.platform !== "win32" && (info.mode & 18) !== 0)
|
|
22179
|
+
throw new CodeBuddyError("invalidRequest", "Redirected native Subagent directory");
|
|
22180
|
+
const actual = await realpath4(directory);
|
|
22181
|
+
if (!sameResolvedPath(actual, directory))
|
|
22182
|
+
throw new CodeBuddyError("invalidRequest", "Redirected native Subagent directory");
|
|
22183
|
+
return directory;
|
|
22184
|
+
}
|
|
22185
|
+
async function verifiedChildFile(file2, expected) {
|
|
22186
|
+
const info = await lstat(file2);
|
|
22187
|
+
if (!info.isFile() || info.isSymbolicLink() || process.platform !== "win32" && (info.mode & 63) !== 0)
|
|
22188
|
+
throw new CodeBuddyError("invalidRequest", "Unsafe derived Subagent transcript");
|
|
22189
|
+
if (!sameResolvedPath(await realpath4(file2), file2))
|
|
22190
|
+
throw new CodeBuddyError("invalidRequest", "Redirected derived Subagent transcript");
|
|
22191
|
+
const before = await codeBuddyFileVersion(file2);
|
|
22192
|
+
const actual = await readCodeBuddyVersionedText(file2, CODEBUDDY_CHILD_MAX_BYTES, "Subagent transcript exceeds 8 MB", before);
|
|
22193
|
+
if (!actual.reusableVersion || !sameCodeBuddyFileVersion(before, actual.reusableVersion) || !isDeepStrictEqual3(Buffer.from(actual.contents, "utf8"), expected))
|
|
22194
|
+
throw new CodeBuddyError("nativeFailure", "Native Fork produced a different Subagent transcript");
|
|
22195
|
+
}
|
|
22196
|
+
async function persistChildCopy(file2, expected) {
|
|
22197
|
+
try {
|
|
22198
|
+
await writeFile(file2, expected, { flag: "wx", mode: 384 });
|
|
22199
|
+
} catch (error51) {
|
|
22200
|
+
if (record2(error51).code !== "EEXIST")
|
|
22201
|
+
throw error51;
|
|
22202
|
+
await verifiedChildFile(file2, expected);
|
|
22203
|
+
return void 0;
|
|
22204
|
+
}
|
|
22205
|
+
const copy = { file: file2, expected };
|
|
22206
|
+
try {
|
|
22207
|
+
await verifiedChildFile(file2, expected);
|
|
22208
|
+
return copy;
|
|
22209
|
+
} catch (error51) {
|
|
22210
|
+
return failAfterBridgeCleanup(error51, copy);
|
|
22211
|
+
}
|
|
22212
|
+
}
|
|
22213
|
+
async function copyInheritedChildren(options) {
|
|
22214
|
+
const { references } = options;
|
|
22215
|
+
if (!references.length)
|
|
22216
|
+
return { descriptors: [], created: [] };
|
|
22217
|
+
const sourceHistoryFile = await realpath4(options.sourceHistoryFile);
|
|
22218
|
+
const sourceProject = path5.dirname(sourceHistoryFile);
|
|
22219
|
+
if (!sameResolvedPath(sourceHistoryFile, path5.join(sourceProject, `${options.sourceRef.nativeSessionId}.jsonl`)))
|
|
22220
|
+
throw new CodeBuddyError("invalidRequest", "Unexpected source history location");
|
|
22221
|
+
const sourceDirectory = path5.join(sourceProject, options.sourceRef.nativeSessionId, "subagents");
|
|
22222
|
+
const sourceDirectoryInfo = await lstat(sourceDirectory);
|
|
22223
|
+
if (!sourceDirectoryInfo.isDirectory() || sourceDirectoryInfo.isSymbolicLink())
|
|
22224
|
+
throw new CodeBuddyError("invalidRequest", "Redirected source Subagent directory");
|
|
22225
|
+
if (!sameResolvedPath(await realpath4(sourceDirectory), sourceDirectory))
|
|
22226
|
+
throw new CodeBuddyError("invalidRequest", "Redirected source Subagent directory");
|
|
22227
|
+
const targetHistoryFile = await realpath4(options.targetHistoryFile);
|
|
22228
|
+
const targetProject = path5.dirname(targetHistoryFile);
|
|
22229
|
+
if (!sameResolvedPath(targetHistoryFile, path5.join(targetProject, `${options.targetRef.nativeSessionId}.jsonl`)))
|
|
22230
|
+
throw new CodeBuddyError("invalidRequest", "Unexpected target history location");
|
|
22231
|
+
const targetSessionDirectory = await plainDirectory(targetProject, options.targetRef.nativeSessionId);
|
|
22232
|
+
const targetDirectory = await plainDirectory(targetSessionDirectory, "subagents");
|
|
22233
|
+
const descriptors = [];
|
|
22234
|
+
const created = [];
|
|
22235
|
+
try {
|
|
22236
|
+
for (const reference of references) {
|
|
22237
|
+
const sourceFile = path5.join(sourceDirectory, `${reference.childId}.jsonl`);
|
|
22238
|
+
const sourceInfo = await lstat(sourceFile);
|
|
22239
|
+
if (!sourceInfo.isFile() || sourceInfo.isSymbolicLink())
|
|
22240
|
+
throw new CodeBuddyError("invalidRequest", "Redirected source Subagent transcript");
|
|
22241
|
+
const before = await codeBuddyFileVersion(sourceFile);
|
|
22242
|
+
if (!sameResolvedPath(before.realFile, sourceFile))
|
|
22243
|
+
throw new CodeBuddyError("invalidRequest", "Redirected source Subagent transcript");
|
|
22244
|
+
if (before.size > CODEBUDDY_CHILD_MAX_BYTES)
|
|
22245
|
+
throw new CodeBuddyError("unsupported", "Subagent transcript exceeds 8 MB");
|
|
22246
|
+
const source = await readCodeBuddyVersionedText(sourceFile, CODEBUDDY_CHILD_MAX_BYTES, "Subagent transcript exceeds 8 MB", before);
|
|
22247
|
+
if (!source.reusableVersion)
|
|
22248
|
+
throw new CodeBuddyError("sessionBusy", "Source Subagent changed during Fork");
|
|
22249
|
+
const validated = await validateCodeBuddyChildContents(source.contents, options.sourceRef, reference.childId, options.sourceCwd, false);
|
|
22250
|
+
assertChildRanges(validated.entries, reference);
|
|
22251
|
+
const last = reference.ranges.at(-1)?.lastId;
|
|
22252
|
+
if (!last)
|
|
22253
|
+
throw new CodeBuddyError("protocolError", "Missing Agent result child range");
|
|
22254
|
+
const prefix = await codeBuddyChildPrefixThrough(source.contents, last, validated);
|
|
22255
|
+
const expected = Buffer.from(prefix.contents, "utf8");
|
|
22256
|
+
const targetFile = path5.join(targetDirectory, `${reference.childId}.jsonl`);
|
|
22257
|
+
const copy = await persistChildCopy(targetFile, expected);
|
|
22258
|
+
if (copy)
|
|
22259
|
+
created.push(copy);
|
|
22260
|
+
const after = await readCodeBuddyVersionedText(sourceFile, CODEBUDDY_CHILD_MAX_BYTES, "Subagent transcript exceeds 8 MB", before);
|
|
22261
|
+
if (!after.reusableVersion || !sameCodeBuddyFileVersion(before, after.reusableVersion) || after.contents !== source.contents)
|
|
22262
|
+
throw new CodeBuddyError("sessionBusy", "Source Subagent changed during Fork");
|
|
22263
|
+
descriptors.push(codeBuddyInheritedChildDescriptor(reference.childId, prefix.contents, prefix.child));
|
|
22264
|
+
}
|
|
22265
|
+
return { descriptors, created };
|
|
22266
|
+
} catch (failure2) {
|
|
22267
|
+
const cleanupFailures = [];
|
|
22268
|
+
for (const copy of created.toReversed()) {
|
|
22269
|
+
try {
|
|
22270
|
+
await cleanupBridge(copy);
|
|
22271
|
+
} catch (error51) {
|
|
22272
|
+
cleanupFailures.push(error51);
|
|
22273
|
+
}
|
|
22274
|
+
}
|
|
22275
|
+
if (cleanupFailures.length)
|
|
22276
|
+
throw new AggregateError([failure2, ...cleanupFailures], "Subagent copy and cleanup both failed");
|
|
22277
|
+
throw failure2;
|
|
22278
|
+
}
|
|
22279
|
+
}
|
|
22280
|
+
async function deriveCodeBuddySession(options) {
|
|
22281
|
+
const { input, environment, factory, signal } = options;
|
|
22282
|
+
const sourceCwd = options.sourceCwd ?? input.cwd;
|
|
22283
|
+
const profile = options.profile ?? CODEBUDDY_RUNTIME_PROFILE;
|
|
22284
|
+
const strictHistoryBinding = profile.historyCapabilities?.forkAcrossCwd === true;
|
|
22285
|
+
validateNativeRef(input.sourceRef, profile);
|
|
22286
|
+
const source = await codeBuddyNativeHistory(sourceCwd, input.sourceRef, environment, profile);
|
|
22287
|
+
const retained = retainedRowCount(input, source.contents, sourceCwd, profile);
|
|
22288
|
+
const sourceRows = nativeHistoryRows(source.contents);
|
|
22289
|
+
const childReferences = referencedChildren(sourceRows.slice(0, retained));
|
|
22290
|
+
const temporary = nativeSessionRefSchema.parse({
|
|
22291
|
+
harnessId: profile.harnessId,
|
|
22292
|
+
nativeSessionId: randomUUID(),
|
|
22293
|
+
formatVersion: 1
|
|
22294
|
+
});
|
|
22295
|
+
await (options.copy ?? copyCodeBuddySession)(sourceCwd, input.sourceRef.nativeSessionId, temporary.nativeSessionId, environment, signal, options.invocationFactory ?? codeBuddyInvocation);
|
|
22296
|
+
const nativeCopy = await codeBuddyNativeHistory(sourceCwd, temporary, environment, profile, {
|
|
22297
|
+
...strictHistoryBinding ? { requirePrimary: true } : {},
|
|
22298
|
+
inheritedContents: source.contents
|
|
22299
|
+
});
|
|
22300
|
+
if (!isDeepStrictEqual3(nativeHistoryRows(nativeCopy.contents), sourceRows))
|
|
22301
|
+
throw new CodeBuddyError("unsupported", "Native history copy changed the source prefix");
|
|
22302
|
+
const bridge = strictHistoryBinding ? await bridgeCopyToTarget(sourceCwd, input.cwd, temporary, nativeCopy.contents, environment, profile) : void 0;
|
|
22303
|
+
if (strictHistoryBinding) {
|
|
22304
|
+
let targetCopy;
|
|
22305
|
+
try {
|
|
22306
|
+
targetCopy = await codeBuddyNativeHistory(input.cwd, temporary, environment, profile, {
|
|
22307
|
+
requirePrimary: true,
|
|
22308
|
+
inheritedContents: nativeCopy.contents
|
|
22309
|
+
});
|
|
22310
|
+
} catch (error51) {
|
|
22311
|
+
return failAfterBridgeCleanup(error51, bridge);
|
|
22312
|
+
}
|
|
22313
|
+
if (targetCopy.contents !== nativeCopy.contents) {
|
|
22314
|
+
return failAfterBridgeCleanup(new CodeBuddyError("nativeFailure", "Cross-directory history bridge changed native bytes"), bridge);
|
|
22315
|
+
}
|
|
22316
|
+
}
|
|
22317
|
+
let derivedId;
|
|
22318
|
+
let failure2;
|
|
22319
|
+
let inheritedChildCopies = [];
|
|
22320
|
+
let derivationSucceeded = false;
|
|
22321
|
+
let receiveCommands;
|
|
22322
|
+
const commands = new Promise((resolve) => {
|
|
22323
|
+
receiveCommands = resolve;
|
|
22324
|
+
});
|
|
22325
|
+
let client2;
|
|
22326
|
+
try {
|
|
22327
|
+
client2 = factory({
|
|
22328
|
+
cwd: input.cwd,
|
|
22329
|
+
environment,
|
|
22330
|
+
ephemeral: false,
|
|
22331
|
+
temporarySessionId: temporary.nativeSessionId,
|
|
22332
|
+
handlers: {
|
|
22333
|
+
permission: async () => ({ outcome: { outcome: "cancelled" } }),
|
|
22334
|
+
question: async () => ({ outcome: "cancelled" }),
|
|
22335
|
+
fault: (error51) => {
|
|
22336
|
+
failure2 = error51;
|
|
22337
|
+
},
|
|
22338
|
+
update: ({ sessionId, update }) => {
|
|
22339
|
+
if (record2(update).sessionUpdate === "available_commands_update")
|
|
22340
|
+
receiveCommands(record2(update).availableCommands);
|
|
22341
|
+
const meta3 = record2(record2(update)._meta);
|
|
22342
|
+
if (meta3["codebuddy.ai/sessionReset"] === true && meta3["codebuddy.ai/newSessionId"] === sessionId)
|
|
22343
|
+
derivedId = sessionId;
|
|
22344
|
+
}
|
|
22345
|
+
}
|
|
22346
|
+
});
|
|
22347
|
+
} catch (error51) {
|
|
22348
|
+
return failAfterBridgeCleanup(error51, bridge);
|
|
22349
|
+
}
|
|
22350
|
+
const abort = () => {
|
|
22351
|
+
void client2.close();
|
|
22352
|
+
};
|
|
22353
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
22354
|
+
let primaryFailure;
|
|
22355
|
+
try {
|
|
22356
|
+
if (!client2.removeCopy)
|
|
22357
|
+
throw new CodeBuddyError("unsupported", "Native temporary Session cleanup is unavailable");
|
|
22358
|
+
if (signal.aborted)
|
|
22359
|
+
throw new CodeBuddyError("invalidState", "Adapter closed during Fork");
|
|
22360
|
+
await client2.initialize();
|
|
22361
|
+
const opened = await client2.open(input.cwd, temporary.nativeSessionId);
|
|
22362
|
+
if (opened.sessionId && opened.sessionId !== temporary.nativeSessionId)
|
|
22363
|
+
throw new CodeBuddyError("protocolError", "ACP loaded a different temporary Session");
|
|
22364
|
+
const nativeState = configuration(opened.configOptions, profile).state;
|
|
22365
|
+
const available = await bounded(commands, 5e3, "Native command discovery", abort);
|
|
22366
|
+
if (!Array.isArray(available) || !available.some((entry) => record2(entry).name === "fork"))
|
|
22367
|
+
throw new CodeBuddyError("unsupported", "Native Session does not advertise /fork");
|
|
22368
|
+
const result = await bounded(client2.prompt(temporary.nativeSessionId, "/fork"), 2e4, "Native Fork", abort);
|
|
22369
|
+
if (failure2)
|
|
22370
|
+
throw failure2;
|
|
22371
|
+
if (result.stopReason !== "end_turn" || !derivedId || [input.sourceRef.nativeSessionId, temporary.nativeSessionId].includes(derivedId))
|
|
22372
|
+
throw new CodeBuddyError("unsupported", "Native Fork did not report a separate Session");
|
|
22373
|
+
const preliminaryRef = nativeSessionRefSchema.parse({
|
|
22374
|
+
harnessId: profile.harnessId,
|
|
22375
|
+
nativeSessionId: derivedId,
|
|
22376
|
+
formatVersion: 1
|
|
22377
|
+
});
|
|
22378
|
+
const historicalCwds = [
|
|
22379
|
+
.../* @__PURE__ */ new Set([
|
|
22380
|
+
...sourceRows.flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []),
|
|
22381
|
+
...source.historicalCwds,
|
|
22382
|
+
sourceCwd,
|
|
22383
|
+
input.cwd
|
|
22384
|
+
])
|
|
22385
|
+
];
|
|
22386
|
+
const historyTransaction = strictHistoryBinding ? { requirePrimary: true, allowedHistoricalCwds: historicalCwds } : void 0;
|
|
22387
|
+
const forked = await codeBuddyNativeHistory(input.cwd, preliminaryRef, environment, profile, historyTransaction);
|
|
22388
|
+
const forkRows = nativeHistoryRows(forked.contents);
|
|
22389
|
+
assertCopiedPrefix(sourceRows, forkRows);
|
|
22390
|
+
const marker = strictHistoryBinding ? nativeRawHistoryRows(forked.contents).findLast((row) => Boolean(text(row.id)) && row.sessionId === derivedId && typeof row.cwd === "string" && sameResolvedPath(row.cwd, input.cwd)) : void 0;
|
|
22391
|
+
if (strictHistoryBinding && !marker)
|
|
22392
|
+
throw new CodeBuddyError("unsupported", "Native Fork did not persist a target binding marker");
|
|
22393
|
+
if (!client2.rollback)
|
|
22394
|
+
throw new CodeBuddyError("unsupported", "Native history rewind is unavailable");
|
|
22395
|
+
const point = retained ? text(forkRows[retained - 1]?.id) : null;
|
|
22396
|
+
const rewound = await client2.rollback(derivedId, point);
|
|
22397
|
+
if (rewound.applied !== true || (rewound.actualForkPointId ?? null) !== point)
|
|
22398
|
+
throw new CodeBuddyError("nativeFailure", "Native history rewind was not confirmed");
|
|
22399
|
+
const verified = await codeBuddyNativeHistory(input.cwd, preliminaryRef, environment, profile, historyTransaction);
|
|
22400
|
+
const finalRows = nativeHistoryRows(verified.contents);
|
|
22401
|
+
if (!isDeepStrictEqual3(finalRows, forkRows.slice(0, retained)))
|
|
22402
|
+
throw new CodeBuddyError("nativeFailure", "Native history rewind did not persist the exact prefix");
|
|
22403
|
+
const inheritedChildren2 = await copyInheritedChildren({
|
|
22404
|
+
references: childReferences,
|
|
22405
|
+
sourceRef: input.sourceRef,
|
|
22406
|
+
sourceCwd,
|
|
22407
|
+
sourceHistoryFile: source.file,
|
|
22408
|
+
targetRef: preliminaryRef,
|
|
22409
|
+
targetHistoryFile: verified.file
|
|
22410
|
+
});
|
|
22411
|
+
inheritedChildCopies = inheritedChildren2.created;
|
|
22412
|
+
const inheritedChildLocator = inheritedChildren2.descriptors.length ? { codebuddyInheritedChildren: inheritedChildren2.descriptors } : {};
|
|
22413
|
+
const ref = nativeSessionRefSchema.parse({
|
|
22414
|
+
...preliminaryRef,
|
|
22415
|
+
locator: strictHistoryBinding ? {
|
|
22416
|
+
codebuddyDerived: 1,
|
|
22417
|
+
boundCwd: codeBuddyCanonicalCwd(input.cwd),
|
|
22418
|
+
targetProjectSlug: codeBuddyProjectSlug(input.cwd, profile),
|
|
22419
|
+
inheritedPrefixRows: finalRows.length,
|
|
22420
|
+
inheritedPrefixSha256: nativeRowsDigest(finalRows),
|
|
22421
|
+
bindingMarkerId: text(marker?.id),
|
|
22422
|
+
...inheritedChildLocator
|
|
22423
|
+
} : { codebuddyDerived: 1, ...inheritedChildLocator }
|
|
22424
|
+
});
|
|
22425
|
+
await codeBuddyNativeHistory(input.cwd, ref, environment, profile);
|
|
22426
|
+
const after = await codeBuddyNativeHistory(sourceCwd, input.sourceRef, environment, profile);
|
|
22427
|
+
if (after.contents !== source.contents)
|
|
22428
|
+
throw new CodeBuddyError("sessionBusy", "Source history changed during Fork");
|
|
22429
|
+
if (signal.aborted)
|
|
22430
|
+
throw new CodeBuddyError("invalidState", "Adapter closed during Fork");
|
|
22431
|
+
const saved = record2(record2(input.sourceRef.locator).configuration);
|
|
22432
|
+
const state = options.state ?? {
|
|
22433
|
+
...nativeState,
|
|
22434
|
+
...text(saved.model) ? { effectiveModel: modelRef(text(saved.model)) } : {}
|
|
22435
|
+
};
|
|
22436
|
+
const model = input.kind === "rollbackLastTurn" && input.model ? input.model : state.effectiveModel;
|
|
22437
|
+
const thinking = input.kind === "rollbackLastTurn" && input.thinkingOptionId ? input.thinkingOptionId : options.state?.effectiveThinkingOptionId ?? (text(saved.thinking) ? harnessThinkingOptionIdSchema.parse(saved.thinking) : state.effectiveThinkingOptionId);
|
|
22438
|
+
const mode = input.kind === "rollbackLastTurn" && input.permissionModeId ? input.permissionModeId : options.state?.effectivePermissionModeId ?? (text(saved.mode) ? harnessPermissionModeIdSchema.parse(saved.mode) : state.effectivePermissionModeId);
|
|
22439
|
+
const resume = {
|
|
22440
|
+
kind: "resume",
|
|
22441
|
+
nativeRef: ref,
|
|
22442
|
+
cwd: input.cwd,
|
|
22443
|
+
...input.environment ? { environment: input.environment } : {},
|
|
22444
|
+
...model ? { model } : {},
|
|
22445
|
+
...thinking ? { thinkingOptionId: thinking } : {},
|
|
22446
|
+
...mode ? { permissionModeId: mode } : {}
|
|
22447
|
+
};
|
|
22448
|
+
derivationSucceeded = true;
|
|
22449
|
+
return resume;
|
|
22450
|
+
} catch (error51) {
|
|
22451
|
+
primaryFailure = error51;
|
|
22452
|
+
throw error51;
|
|
22453
|
+
} finally {
|
|
22454
|
+
signal.removeEventListener("abort", abort);
|
|
22455
|
+
const cleanupFailures = [];
|
|
22456
|
+
let temporaryCleanupFailed = false;
|
|
22457
|
+
try {
|
|
22458
|
+
if (client2.removeCopy)
|
|
22459
|
+
await client2.removeCopy();
|
|
22460
|
+
} catch (error51) {
|
|
22461
|
+
temporaryCleanupFailed = true;
|
|
22462
|
+
cleanupFailures.push(error51);
|
|
22463
|
+
}
|
|
22464
|
+
try {
|
|
22465
|
+
await client2.close();
|
|
22466
|
+
} catch (error51) {
|
|
22467
|
+
cleanupFailures.push(error51);
|
|
22468
|
+
}
|
|
22469
|
+
try {
|
|
22470
|
+
await cleanupBridge(bridge);
|
|
22471
|
+
} catch (error51) {
|
|
22472
|
+
cleanupFailures.push(error51);
|
|
22473
|
+
}
|
|
22474
|
+
if (!derivationSucceeded || cleanupFailures.length) {
|
|
22475
|
+
for (const copy of inheritedChildCopies.toReversed()) {
|
|
22476
|
+
try {
|
|
22477
|
+
await cleanupBridge(copy);
|
|
22478
|
+
} catch (error51) {
|
|
22479
|
+
cleanupFailures.push(error51);
|
|
22480
|
+
}
|
|
22481
|
+
}
|
|
22482
|
+
}
|
|
22483
|
+
if (cleanupFailures.length) {
|
|
22484
|
+
if (primaryFailure)
|
|
22485
|
+
throw new AggregateError([primaryFailure, ...cleanupFailures], `${primaryFailure instanceof Error ? primaryFailure.message : "Native derivation failed"}; ${temporaryCleanupFailed ? `temporary Session ${temporary.nativeSessionId} could not be removed` : "native derivation cleanup also failed"}`);
|
|
22486
|
+
if (cleanupFailures.length === 1)
|
|
22487
|
+
throw cleanupFailures[0];
|
|
22488
|
+
throw new AggregateError(cleanupFailures, "Native derivation cleanup failed");
|
|
22489
|
+
}
|
|
22490
|
+
}
|
|
22491
|
+
}
|
|
22492
|
+
|
|
21161
22493
|
// dist/interactions.js
|
|
21162
22494
|
var CodeBuddyInteractions = class {
|
|
21163
22495
|
emit;
|
|
21164
22496
|
client;
|
|
22497
|
+
profile;
|
|
21165
22498
|
#pending = /* @__PURE__ */ new Map();
|
|
21166
22499
|
#sequence = 0;
|
|
21167
|
-
constructor(emit, client2) {
|
|
22500
|
+
constructor(emit, client2, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21168
22501
|
this.emit = emit;
|
|
21169
22502
|
this.client = client2;
|
|
22503
|
+
this.profile = profile;
|
|
21170
22504
|
}
|
|
21171
22505
|
#question(turnId, input) {
|
|
21172
22506
|
const questions = rows(record2(input).questions);
|
|
21173
22507
|
if (!questions.length || questions.length > 4)
|
|
21174
|
-
throw new CodeBuddyError("protocolError",
|
|
22508
|
+
throw new CodeBuddyError("protocolError", `Invalid ${this.profile.displayName} question count`);
|
|
21175
22509
|
return {
|
|
21176
22510
|
type: "question",
|
|
21177
|
-
interactionId: hostInteractionIdSchema.parse(
|
|
22511
|
+
interactionId: hostInteractionIdSchema.parse(`${this.profile.interactionIdPrefix}-question-${++this.#sequence}`),
|
|
21178
22512
|
turnId,
|
|
21179
|
-
title:
|
|
22513
|
+
title: this.profile.displayName,
|
|
21180
22514
|
questions: questions.map((question, index) => {
|
|
21181
22515
|
const options = rows(question.options).map((option) => ({
|
|
21182
22516
|
value: text(option.label),
|
|
@@ -21184,7 +22518,7 @@ var CodeBuddyInteractions = class {
|
|
|
21184
22518
|
...option.description ? { description: text(option.description) } : {}
|
|
21185
22519
|
}));
|
|
21186
22520
|
if (!text(question.question) || !options.length || options.some((option) => !option.value))
|
|
21187
|
-
throw new CodeBuddyError("protocolError",
|
|
22521
|
+
throw new CodeBuddyError("protocolError", `Malformed ${this.profile.displayName} question`);
|
|
21188
22522
|
return {
|
|
21189
22523
|
id: text(question.id) || `q_${index}`,
|
|
21190
22524
|
type: "choice",
|
|
@@ -21217,16 +22551,16 @@ var CodeBuddyInteractions = class {
|
|
|
21217
22551
|
});
|
|
21218
22552
|
}
|
|
21219
22553
|
const actions = request.options.flatMap((option) => {
|
|
21220
|
-
const effect = option.kind === "allow_once" ? "allowOnce" : option.kind === "allow_always" ? "
|
|
22554
|
+
const effect = option.kind === "allow_once" ? "allowOnce" : option.kind === "allow_always" ? "allowForSession" : option.kind === "reject_once" || option.kind === "reject_always" ? "deny" : void 0;
|
|
21221
22555
|
return effect ? [{ id: option.optionId, label: option.name, effect }] : [];
|
|
21222
22556
|
});
|
|
21223
22557
|
if (!actions.some((action) => action.effect === "deny"))
|
|
21224
22558
|
throw new CodeBuddyError("unsupported", "ACP approval does not provide a reject action");
|
|
21225
22559
|
const interaction = {
|
|
21226
22560
|
type: "approval",
|
|
21227
|
-
interactionId: hostInteractionIdSchema.parse(
|
|
22561
|
+
interactionId: hostInteractionIdSchema.parse(`${this.profile.interactionIdPrefix}-approval-${++this.#sequence}`),
|
|
21228
22562
|
turnId,
|
|
21229
|
-
title: name || request.toolCall.title ||
|
|
22563
|
+
title: name || request.toolCall.title || `${this.profile.displayName} tool approval`,
|
|
21230
22564
|
subject: { type: "nativeAction" },
|
|
21231
22565
|
actions,
|
|
21232
22566
|
description: JSON.stringify(request.toolCall.rawInput ?? {}).slice(0, 16e3)
|
|
@@ -21262,7 +22596,7 @@ var CodeBuddyInteractions = class {
|
|
|
21262
22596
|
async respond(command) {
|
|
21263
22597
|
const pending = this.#pending.get(command.interactionId);
|
|
21264
22598
|
if (!pending || pending.responding)
|
|
21265
|
-
return failure("invalidRequest", "Interaction is not awaiting a response");
|
|
22599
|
+
return failure("invalidRequest", "Interaction is not awaiting a response", this.profile);
|
|
21266
22600
|
const validation = validateHostInteractionResponse(pending.interaction, command.response);
|
|
21267
22601
|
if (validation)
|
|
21268
22602
|
return { ok: false, error: validation };
|
|
@@ -21273,7 +22607,7 @@ var CodeBuddyInteractions = class {
|
|
|
21273
22607
|
return { ok: true, value: { accepted: true } };
|
|
21274
22608
|
} catch (error51) {
|
|
21275
22609
|
pending.responding = false;
|
|
21276
|
-
return { ok: false, error: nativeError(error51) };
|
|
22610
|
+
return { ok: false, error: nativeError(error51, this.profile) };
|
|
21277
22611
|
}
|
|
21278
22612
|
}
|
|
21279
22613
|
#finish(pending, reason) {
|
|
@@ -21298,33 +22632,23 @@ var CodeBuddyInteractions = class {
|
|
|
21298
22632
|
};
|
|
21299
22633
|
|
|
21300
22634
|
// dist/subagent-history.js
|
|
21301
|
-
import { readdir as readdir2, realpath as
|
|
21302
|
-
import
|
|
21303
|
-
var
|
|
22635
|
+
import { readdir as readdir2, realpath as realpath5 } from "node:fs/promises";
|
|
22636
|
+
import path6 from "node:path";
|
|
22637
|
+
var equalPath2 = (a, b) => process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
21304
22638
|
var MAX_CACHED_CHILDREN = 16;
|
|
21305
|
-
function childContents(contents) {
|
|
21306
|
-
const lines = contents.split(/\r?\n/u);
|
|
21307
|
-
if (lines.at(-1)?.trim()) {
|
|
21308
|
-
try {
|
|
21309
|
-
JSON.parse(lines.at(-1) ?? "");
|
|
21310
|
-
} catch {
|
|
21311
|
-
lines.pop();
|
|
21312
|
-
}
|
|
21313
|
-
}
|
|
21314
|
-
const entries = lines.filter((line) => line.trim()).map((line) => record2(JSON.parse(line)));
|
|
21315
|
-
return { contents: lines.join("\n"), entries };
|
|
21316
|
-
}
|
|
21317
22639
|
var CodeBuddyChildObserver = class {
|
|
21318
22640
|
parent;
|
|
21319
22641
|
cwd;
|
|
21320
22642
|
environment;
|
|
22643
|
+
profile;
|
|
21321
22644
|
#children = /* @__PURE__ */ new Map();
|
|
21322
22645
|
#parent;
|
|
21323
22646
|
#closed = false;
|
|
21324
|
-
constructor(parent, cwd, environment) {
|
|
22647
|
+
constructor(parent, cwd, environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21325
22648
|
this.parent = parent;
|
|
21326
22649
|
this.cwd = cwd;
|
|
21327
22650
|
this.environment = environment;
|
|
22651
|
+
this.profile = profile;
|
|
21328
22652
|
}
|
|
21329
22653
|
close() {
|
|
21330
22654
|
this.#closed = true;
|
|
@@ -21335,16 +22659,16 @@ var CodeBuddyChildObserver = class {
|
|
|
21335
22659
|
if (this.#closed)
|
|
21336
22660
|
throw new CodeBuddyError("invalidRequest", "Subagent observer is closed");
|
|
21337
22661
|
}
|
|
21338
|
-
async #validateWorkspaces(cwds
|
|
21339
|
-
const expected = await
|
|
22662
|
+
async #validateWorkspaces(cwds) {
|
|
22663
|
+
const expected = await realpath5(this.cwd);
|
|
21340
22664
|
for (const cwd of new Set(cwds)) {
|
|
21341
|
-
const actual = await
|
|
21342
|
-
if (
|
|
22665
|
+
const actual = await realpath5(cwd).catch((error51) => {
|
|
22666
|
+
if (["ENOENT", "ENOTDIR"].includes(String(record2(error51).code)))
|
|
21343
22667
|
throw new CodeBuddyError("invalidRequest", "Native Session historical working directory is unavailable; ownership cannot be verified");
|
|
21344
22668
|
throw error51;
|
|
21345
22669
|
});
|
|
21346
|
-
if (!
|
|
21347
|
-
throw new CodeBuddyError("invalidRequest",
|
|
22670
|
+
if (!equalPath2(actual, expected))
|
|
22671
|
+
throw new CodeBuddyError("invalidRequest", "Native Session belongs to a different working directory");
|
|
21348
22672
|
}
|
|
21349
22673
|
}
|
|
21350
22674
|
async #parentHistory() {
|
|
@@ -21361,7 +22685,7 @@ var CodeBuddyChildObserver = class {
|
|
|
21361
22685
|
return this.#parent;
|
|
21362
22686
|
}
|
|
21363
22687
|
}
|
|
21364
|
-
const history = await codeBuddyLiveNativeHistory(this.cwd, this.parent, this.environment);
|
|
22688
|
+
const history = await codeBuddyLiveNativeHistory(this.cwd, this.parent, this.environment, this.profile);
|
|
21365
22689
|
this.#assertOpen();
|
|
21366
22690
|
this.#parent = {
|
|
21367
22691
|
file: history.file,
|
|
@@ -21373,31 +22697,34 @@ var CodeBuddyChildObserver = class {
|
|
|
21373
22697
|
}
|
|
21374
22698
|
async #directory() {
|
|
21375
22699
|
const history = await this.#parentHistory();
|
|
21376
|
-
const project =
|
|
21377
|
-
const expected =
|
|
21378
|
-
const actual = await
|
|
22700
|
+
const project = path6.dirname(await realpath5(history.file));
|
|
22701
|
+
const expected = path6.join(project, this.parent.nativeSessionId, "subagents");
|
|
22702
|
+
const actual = await realpath5(expected);
|
|
21379
22703
|
this.#assertOpen();
|
|
21380
|
-
if (!
|
|
21381
|
-
throw new CodeBuddyError("invalidRequest",
|
|
22704
|
+
if (!equalPath2(actual, expected))
|
|
22705
|
+
throw new CodeBuddyError("invalidRequest", `Redirected ${this.profile.displayName} Subagent directory`);
|
|
21382
22706
|
return actual;
|
|
21383
22707
|
}
|
|
21384
22708
|
async #child(directory, childId) {
|
|
21385
22709
|
if (!validCodeBuddyChildId(childId))
|
|
21386
22710
|
throw new CodeBuddyError("invalidRequest", "Invalid native Subagent ID");
|
|
21387
|
-
const file2 =
|
|
22711
|
+
const file2 = path6.join(directory, `${childId}.jsonl`);
|
|
21388
22712
|
const before = await codeBuddyFileVersion(file2);
|
|
21389
|
-
if (!
|
|
22713
|
+
if (!equalPath2(before.realFile, file2))
|
|
21390
22714
|
throw new CodeBuddyError("invalidRequest", "Redirected Subagent transcript");
|
|
21391
22715
|
this.#assertOpen();
|
|
21392
|
-
if (before.size >
|
|
22716
|
+
if (before.size > CODEBUDDY_CHILD_MAX_BYTES)
|
|
21393
22717
|
throw new CodeBuddyError("unsupported", "Subagent transcript exceeds 8 MB");
|
|
21394
22718
|
const cached2 = this.#children.get(childId);
|
|
21395
|
-
if (cached2 && sameCodeBuddyFileVersion(cached2.version, before))
|
|
22719
|
+
if (cached2 && sameCodeBuddyFileVersion(cached2.version, before)) {
|
|
22720
|
+
await validateCodeBuddyChildContents(cached2.rawContents, this.parent, childId, this.cwd, true);
|
|
21396
22721
|
return cached2;
|
|
21397
|
-
|
|
22722
|
+
}
|
|
22723
|
+
const source = await readCodeBuddyVersionedText(file2, CODEBUDDY_CHILD_MAX_BYTES, "Subagent transcript exceeds 8 MB", before), data = await validateCodeBuddyChildContents(source.contents, this.parent, childId, this.cwd, true);
|
|
21398
22724
|
this.#assertOpen();
|
|
21399
22725
|
const next = {
|
|
21400
22726
|
...data,
|
|
22727
|
+
rawContents: source.contents,
|
|
21401
22728
|
version: source.reusableVersion
|
|
21402
22729
|
};
|
|
21403
22730
|
this.#children.delete(childId);
|
|
@@ -21433,26 +22760,19 @@ var CodeBuddyChildObserver = class {
|
|
|
21433
22760
|
async read(childId, status) {
|
|
21434
22761
|
if (!status) {
|
|
21435
22762
|
const source = await this.#parentHistory();
|
|
21436
|
-
const states = snapshotFromHistory(source.contents, this.parent, this.cwd).turns.flatMap((turn) => turn.items.flatMap(({ item }) => item.type === "subagentDelegation" ? item.subagents : []));
|
|
22763
|
+
const states = snapshotFromHistory(source.contents, this.parent, this.cwd, this.profile).turns.flatMap((turn) => turn.items.flatMap(({ item }) => item.type === "subagentDelegation" ? item.subagents : []));
|
|
21437
22764
|
status = states.findLast((child) => child.nativeSubagentId === childId)?.status;
|
|
21438
22765
|
}
|
|
21439
22766
|
const data = await this.#child(await this.#directory(), childId);
|
|
21440
|
-
const sessions = new Set(data.entries.map((row) => text(row.sessionId)).filter(Boolean));
|
|
21441
|
-
if (sessions.size !== 1)
|
|
21442
|
-
throw new CodeBuddyError("protocolError", "Subagent transcript identity is missing or mixed");
|
|
21443
|
-
await this.#validateWorkspaces(data.entries.flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []), true);
|
|
21444
22767
|
this.#assertOpen();
|
|
21445
|
-
|
|
21446
|
-
if (!childSessionId)
|
|
21447
|
-
throw new CodeBuddyError("protocolError", "Missing native child Session");
|
|
21448
|
-
data.snapshot ??= snapshotFromHistory(data.contents, { ...this.parent, nativeSessionId: childSessionId }, this.cwd);
|
|
22768
|
+
data.snapshot ??= snapshotFromHistory(data.contents, { ...this.parent, nativeSessionId: data.nativeSessionId }, this.cwd, this.profile);
|
|
21449
22769
|
const snapshot = structuredClone(data.snapshot);
|
|
21450
22770
|
projectChildSnapshot(snapshot, this.parent, childId, status);
|
|
21451
22771
|
return snapshot;
|
|
21452
22772
|
}
|
|
21453
22773
|
};
|
|
21454
|
-
async function readCodeBuddyChild(parent, childId, cwd, environment, status) {
|
|
21455
|
-
const observer = new CodeBuddyChildObserver(parent, cwd, environment);
|
|
22774
|
+
async function readCodeBuddyChild(parent, childId, cwd, environment, status, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
22775
|
+
const observer = new CodeBuddyChildObserver(parent, cwd, environment, profile);
|
|
21456
22776
|
try {
|
|
21457
22777
|
return await observer.read(childId, status);
|
|
21458
22778
|
} finally {
|
|
@@ -21466,6 +22786,7 @@ function projectChildSnapshot(snapshot, parent, childId, status) {
|
|
|
21466
22786
|
nativeSessionId: parent.nativeSessionId,
|
|
21467
22787
|
nativeTurnKey: `${childId}:${turn.nativeTurnRef.nativeTurnKey}`
|
|
21468
22788
|
};
|
|
22789
|
+
delete turn.checkpoint;
|
|
21469
22790
|
turn.items = turn.items.filter(({ outcome }) => !(outcome.status === "failed" && outcome.error.message.includes("Tool completion was not recorded")));
|
|
21470
22791
|
if (!status || status === "running" || status === "pending")
|
|
21471
22792
|
turn.outcome = { status: "unknown", reason: "Subagent completion has not been confirmed" };
|
|
@@ -21491,6 +22812,9 @@ var CodeBuddySubagents = class {
|
|
|
21491
22812
|
constructor(options) {
|
|
21492
22813
|
this.options = options;
|
|
21493
22814
|
}
|
|
22815
|
+
get profile() {
|
|
22816
|
+
return this.options.profile ?? CODEBUDDY_RUNTIME_PROFILE;
|
|
22817
|
+
}
|
|
21494
22818
|
begin(turnId) {
|
|
21495
22819
|
this.#turnId = turnId;
|
|
21496
22820
|
}
|
|
@@ -21531,7 +22855,7 @@ var CodeBuddySubagents = class {
|
|
|
21531
22855
|
return true;
|
|
21532
22856
|
call = {
|
|
21533
22857
|
turnId: this.#turnId,
|
|
21534
|
-
item: codeBuddyDelegation(callId, update.rawInput, "running"),
|
|
22858
|
+
item: codeBuddyDelegation(callId, update.rawInput, "running", void 0, this.profile.displayName),
|
|
21535
22859
|
itemCompleted: false,
|
|
21536
22860
|
observationDone: false
|
|
21537
22861
|
};
|
|
@@ -21562,7 +22886,7 @@ var CodeBuddySubagents = class {
|
|
|
21562
22886
|
status: "failed",
|
|
21563
22887
|
error: {
|
|
21564
22888
|
code: "nativeFailure",
|
|
21565
|
-
message:
|
|
22889
|
+
message: `${this.profile.displayName} Subagent invocation failed`,
|
|
21566
22890
|
retryable: false
|
|
21567
22891
|
}
|
|
21568
22892
|
} : { status: "succeeded" }
|
|
@@ -21613,19 +22937,19 @@ var CodeBuddySubagents = class {
|
|
|
21613
22937
|
const parent = this.options.parent();
|
|
21614
22938
|
if (!parent)
|
|
21615
22939
|
return;
|
|
21616
|
-
this.#observer ??= new CodeBuddyChildObserver(parent, this.options.cwd, this.options.environment);
|
|
22940
|
+
this.#observer ??= new CodeBuddyChildObserver(parent, this.options.cwd, this.options.environment, this.profile);
|
|
21617
22941
|
this.#refreshing = true;
|
|
21618
22942
|
try {
|
|
21619
22943
|
for (const call of this.#calls.values()) {
|
|
21620
22944
|
if (call.observationDone)
|
|
21621
22945
|
continue;
|
|
21622
22946
|
try {
|
|
21623
|
-
const id = call.item.subagents[0]?.nativeSubagentId ?? (call.requestId ? await (this.options.locate ? this.options.locate(parent, this.options.cwd, this.options.environment, call.requestId) : this.#observer.locate(call.requestId)) : void 0);
|
|
22947
|
+
const id = call.item.subagents[0]?.nativeSubagentId ?? (call.requestId ? await (this.options.locate ? this.options.locate(parent, this.options.cwd, this.options.environment, call.requestId, this.profile) : this.#observer.locate(call.requestId)) : void 0);
|
|
21624
22948
|
if (!id || this.#closed || call.observationDone)
|
|
21625
22949
|
continue;
|
|
21626
22950
|
if (!call.item.subagents[0]?.nativeSubagentId)
|
|
21627
22951
|
this.#update(call, { nativeSubagentId: id, subagentId: id });
|
|
21628
|
-
const snapshot = await (this.options.read ? this.options.read(parent, id, this.options.cwd, this.options.environment, "running") : this.#observer.read(id, "running"));
|
|
22952
|
+
const snapshot = await (this.options.read ? this.options.read(parent, id, this.options.cwd, this.options.environment, "running", this.profile) : this.#observer.read(id, "running"));
|
|
21629
22953
|
if (this.#closed || call.observationDone)
|
|
21630
22954
|
continue;
|
|
21631
22955
|
const observedModel = snapshot.turns.at(-1)?.model;
|
|
@@ -21681,8 +23005,11 @@ var CodeBuddySession = class {
|
|
|
21681
23005
|
factory;
|
|
21682
23006
|
readHistory;
|
|
21683
23007
|
onClose;
|
|
21684
|
-
|
|
21685
|
-
|
|
23008
|
+
profile;
|
|
23009
|
+
harnessId;
|
|
23010
|
+
#commands = { commands: [] };
|
|
23011
|
+
commands;
|
|
23012
|
+
capabilities;
|
|
21686
23013
|
initialState = {};
|
|
21687
23014
|
initialUsage = null;
|
|
21688
23015
|
#channel = new HarnessOutputChannel();
|
|
@@ -21704,19 +23031,29 @@ var CodeBuddySession = class {
|
|
|
21704
23031
|
#usage = null;
|
|
21705
23032
|
#context = {};
|
|
21706
23033
|
constructor(input, environment, factory, readHistory = readNativeHistory, onClose = () => {
|
|
21707
|
-
}) {
|
|
23034
|
+
}, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21708
23035
|
this.input = input;
|
|
21709
23036
|
this.environment = environment;
|
|
21710
23037
|
this.factory = factory;
|
|
21711
23038
|
this.readHistory = readHistory;
|
|
21712
23039
|
this.onClose = onClose;
|
|
23040
|
+
this.profile = profile;
|
|
23041
|
+
this.harnessId = profile.harnessId;
|
|
23042
|
+
this.capabilities = capabilitiesForProfile(profile);
|
|
23043
|
+
this.#commands = structuredClone(profile.staticCommandCatalog ?? { commands: [] });
|
|
23044
|
+
if (nativeCommandsEnabled(profile))
|
|
23045
|
+
this.commands = {
|
|
23046
|
+
list: async () => this.#closed || this.#fault ? failure("invalidState", "Session is closed or faulted", this.profile) : { ok: true, value: structuredClone(this.#commands) },
|
|
23047
|
+
execute: (command) => this.#executeCommand(command)
|
|
23048
|
+
};
|
|
21713
23049
|
this.subagents = new CodeBuddySubagents({
|
|
21714
23050
|
parent: () => this.#ref,
|
|
21715
23051
|
cwd: input.cwd,
|
|
21716
23052
|
environment,
|
|
21717
|
-
emit: (event) => this.#emit(event)
|
|
23053
|
+
emit: (event) => this.#emit(event),
|
|
23054
|
+
profile
|
|
21718
23055
|
});
|
|
21719
|
-
this.#interactions = new CodeBuddyInteractions((output) => this.#channel.emit(output), () => this.#client);
|
|
23056
|
+
this.#interactions = new CodeBuddyInteractions((output) => this.#channel.emit(output), () => this.#client, profile);
|
|
21720
23057
|
this.#client = this.#createClient();
|
|
21721
23058
|
}
|
|
21722
23059
|
#createClient() {
|
|
@@ -21731,16 +23068,23 @@ var CodeBuddySession = class {
|
|
|
21731
23068
|
this.#onFault(error51);
|
|
21732
23069
|
},
|
|
21733
23070
|
update: (notification) => {
|
|
21734
|
-
if (generation !== this.#generation || this.#
|
|
23071
|
+
if (generation !== this.#generation || this.#closed)
|
|
21735
23072
|
return;
|
|
21736
23073
|
if (this.#ref && notification.sessionId !== this.#ref.nativeSessionId)
|
|
21737
23074
|
return;
|
|
21738
23075
|
try {
|
|
21739
23076
|
const update = record2(notification.update);
|
|
23077
|
+
if (nativeCommandsEnabled(this.profile) && update.sessionUpdate === "available_commands_update") {
|
|
23078
|
+
if (!this.profile.staticCommandCatalog)
|
|
23079
|
+
this.#commands = commandCatalog(update.availableCommands, this.profile);
|
|
23080
|
+
return;
|
|
23081
|
+
}
|
|
23082
|
+
if (this.#replaying)
|
|
23083
|
+
return;
|
|
21740
23084
|
if (this.subagents.update(update))
|
|
21741
23085
|
return;
|
|
21742
23086
|
if (update.sessionUpdate === "config_option_update" && this.#config)
|
|
21743
|
-
this.#apply(configuration(update.configOptions));
|
|
23087
|
+
this.#apply(configuration(update.configOptions, this.profile));
|
|
21744
23088
|
if (update.sessionUpdate === "usage_update" && typeof update.used === "number" && typeof update.size === "number" && update.size > 0) {
|
|
21745
23089
|
this.#context = {
|
|
21746
23090
|
contextUsedTokens: update.used,
|
|
@@ -21762,32 +23106,54 @@ var CodeBuddySession = class {
|
|
|
21762
23106
|
}
|
|
21763
23107
|
});
|
|
21764
23108
|
}
|
|
21765
|
-
|
|
21766
|
-
|
|
21767
|
-
|
|
21768
|
-
|
|
21769
|
-
|
|
23109
|
+
/** Every fresh process must restore an unanchored rewind before it can accept prompts. */
|
|
23110
|
+
async #openClient() {
|
|
23111
|
+
let rewind;
|
|
23112
|
+
if (this.#ref) {
|
|
23113
|
+
const history = await this.readHistory(this.input.cwd, this.#ref, this.environment, this.profile);
|
|
23114
|
+
this.#hasTurn = snapshotFromHistory(history, this.#ref, this.input.cwd, this.profile).turns.length > 0;
|
|
21770
23115
|
this.#usage = historyUsage(history);
|
|
23116
|
+
rewind = pendingNativeHistoryRewind(history);
|
|
21771
23117
|
}
|
|
21772
23118
|
await this.#client.initialize();
|
|
21773
23119
|
const opened = await this.#client.open(this.input.cwd, this.#ref?.nativeSessionId);
|
|
21774
23120
|
const sessionId = this.#ref?.nativeSessionId ?? text(opened.sessionId);
|
|
21775
23121
|
if (!sessionId || opened.sessionId && opened.sessionId !== sessionId)
|
|
21776
23122
|
throw new CodeBuddyError("protocolError", "ACP returned a different Native Session identity");
|
|
23123
|
+
if (rewind) {
|
|
23124
|
+
if (!this.#client.rollback)
|
|
23125
|
+
throw new CodeBuddyError("unsupported", "Native history rewind is unavailable");
|
|
23126
|
+
const result = await this.#client.rollback(sessionId, rewind.forkPointId);
|
|
23127
|
+
if (result.applied !== true || (result.actualForkPointId ?? null) !== rewind.forkPointId)
|
|
23128
|
+
throw new CodeBuddyError("nativeFailure", "Native history rewind was not confirmed");
|
|
23129
|
+
}
|
|
23130
|
+
return { ...opened, sessionId };
|
|
23131
|
+
}
|
|
23132
|
+
async initialize() {
|
|
23133
|
+
const saved = this.input.kind === "resume" && record2(this.input.nativeRef.locator).codebuddyDerived === 1 ? record2(record2(this.input.nativeRef.locator).configuration) : {};
|
|
23134
|
+
if (this.input.kind === "resume")
|
|
23135
|
+
this.#ref = this.input.nativeRef;
|
|
23136
|
+
const opened = await this.#openClient();
|
|
21777
23137
|
this.#ref = nativeSessionRefSchema.parse({
|
|
21778
|
-
harnessId:
|
|
21779
|
-
nativeSessionId: sessionId,
|
|
21780
|
-
formatVersion: 1
|
|
23138
|
+
harnessId: this.profile.harnessId,
|
|
23139
|
+
nativeSessionId: opened.sessionId,
|
|
23140
|
+
formatVersion: 1,
|
|
23141
|
+
...this.#ref?.locator || this.capabilities.history.fork ? {
|
|
23142
|
+
locator: {
|
|
23143
|
+
...record2(this.#ref?.locator),
|
|
23144
|
+
...this.capabilities.history.fork ? { boundCwd: codeBuddyCanonicalCwd(this.input.cwd) } : {}
|
|
23145
|
+
}
|
|
23146
|
+
} : {}
|
|
21781
23147
|
});
|
|
21782
|
-
this.#apply(configuration(opened.configOptions), false);
|
|
23148
|
+
this.#apply(configuration(opened.configOptions, this.profile), false);
|
|
21783
23149
|
if (this.input.kind === "create" && this.input.executionPolicy === "unattended-full-access") {
|
|
21784
23150
|
await this.#configure("mode", "fullAccess");
|
|
21785
|
-
} else if (this.input.permissionModeId)
|
|
21786
|
-
await this.#configure("mode", this.input.permissionModeId);
|
|
21787
|
-
if (this.input.model)
|
|
21788
|
-
await this.#configure("model", nativeModel(this.input.model));
|
|
21789
|
-
if (this.input.thinkingOptionId)
|
|
21790
|
-
await this.#configure("thought_level", this.input.thinkingOptionId);
|
|
23151
|
+
} else if (this.input.permissionModeId || text(saved.mode))
|
|
23152
|
+
await this.#configure("mode", this.input.permissionModeId ?? text(saved.mode));
|
|
23153
|
+
if (this.input.model || text(saved.model))
|
|
23154
|
+
await this.#configure("model", this.input.model ? nativeModel(this.input.model) : text(saved.model));
|
|
23155
|
+
if (this.input.thinkingOptionId || text(saved.thinking))
|
|
23156
|
+
await this.#configure("thought_level", this.input.thinkingOptionId ?? text(saved.thinking));
|
|
21791
23157
|
if (this.#fault || this.#closed)
|
|
21792
23158
|
throw new CodeBuddyError("invalidState", "Native Session failed while opening");
|
|
21793
23159
|
this.initialState = { ...this.#state };
|
|
@@ -21798,29 +23164,43 @@ var CodeBuddySession = class {
|
|
|
21798
23164
|
}
|
|
21799
23165
|
#apply(config2, emit = true) {
|
|
21800
23166
|
this.#config = config2;
|
|
23167
|
+
if (this.#ref && record2(this.#ref.locator).codebuddyDerived === 1)
|
|
23168
|
+
this.#ref = nativeSessionRefSchema.parse({
|
|
23169
|
+
...this.#ref,
|
|
23170
|
+
locator: {
|
|
23171
|
+
...record2(this.#ref.locator),
|
|
23172
|
+
configuration: {
|
|
23173
|
+
model: config2.state.effectiveModel ? nativeModel(config2.state.effectiveModel) : "",
|
|
23174
|
+
mode: config2.state.effectivePermissionModeId ?? "",
|
|
23175
|
+
thinking: config2.state.effectiveThinkingOptionId ?? ""
|
|
23176
|
+
}
|
|
23177
|
+
}
|
|
23178
|
+
});
|
|
21801
23179
|
this.#state = { ...config2.state, ...this.#ref ? { nativeRef: this.#ref } : {} };
|
|
21802
23180
|
if (emit)
|
|
21803
23181
|
this.#emit({ type: "session.state.changed", state: this.#state });
|
|
21804
23182
|
}
|
|
21805
23183
|
async #configure(id, value) {
|
|
21806
23184
|
const option = this.#config?.options.find((option2) => option2.id === id);
|
|
21807
|
-
|
|
21808
|
-
|
|
23185
|
+
const listed = Array.isArray(option?.options) && option.options.some((option2) => record2(option2).value === value);
|
|
23186
|
+
const allowedProductModel = id === "model" && this.profile.allowUnlistedModelSelection;
|
|
23187
|
+
if (!listed && !allowedProductModel)
|
|
23188
|
+
throw new CodeBuddyError("invalidRequest", `Unavailable ${this.profile.displayName} ${id} selection`);
|
|
21809
23189
|
if (!this.#ref)
|
|
21810
23190
|
throw new CodeBuddyError("invalidState", "Session is not open");
|
|
21811
23191
|
const result = await this.#client.configure(this.#ref.nativeSessionId, id, value);
|
|
21812
23192
|
if (this.#closed || this.#fault)
|
|
21813
23193
|
throw new CodeBuddyError("invalidState", "Session closed during configuration");
|
|
21814
|
-
this.#apply(confirmedConfiguration(result, id, value));
|
|
23194
|
+
this.#apply(confirmedConfiguration(result, id, value, this.profile));
|
|
21815
23195
|
}
|
|
21816
23196
|
async #snapshot() {
|
|
21817
23197
|
if (!this.#ref)
|
|
21818
23198
|
throw new CodeBuddyError("invalidState", "Session is not open");
|
|
21819
23199
|
try {
|
|
21820
|
-
const history = await this.readHistory(this.input.cwd, this.#ref, this.environment);
|
|
23200
|
+
const history = await this.readHistory(this.input.cwd, this.#ref, this.environment, this.profile);
|
|
21821
23201
|
this.#usage = historyUsage(history);
|
|
21822
23202
|
return {
|
|
21823
|
-
...this.subagents.project(snapshotFromHistory(history, this.#ref, this.input.cwd)),
|
|
23203
|
+
...this.subagents.project(snapshotFromHistory(history, this.#ref, this.input.cwd, this.profile)),
|
|
21824
23204
|
state: this.#state
|
|
21825
23205
|
};
|
|
21826
23206
|
} catch (error51) {
|
|
@@ -21831,62 +23211,80 @@ var CodeBuddySession = class {
|
|
|
21831
23211
|
}
|
|
21832
23212
|
async readSnapshot() {
|
|
21833
23213
|
if (this.#closed || this.#fault)
|
|
21834
|
-
return failure("invalidState", "Session is closed or faulted");
|
|
23214
|
+
return failure("invalidState", "Session is closed or faulted", this.profile);
|
|
21835
23215
|
if (this.#busy || this.#active)
|
|
21836
|
-
return failure("sessionBusy", "Session is executing an operation");
|
|
23216
|
+
return failure("sessionBusy", "Session is executing an operation", this.profile);
|
|
21837
23217
|
this.#busy = true;
|
|
21838
23218
|
try {
|
|
21839
23219
|
return { ok: true, value: await this.#snapshot() };
|
|
21840
23220
|
} catch (error51) {
|
|
21841
|
-
return { ok: false, error: nativeError(error51) };
|
|
23221
|
+
return { ok: false, error: nativeError(error51, this.profile) };
|
|
21842
23222
|
} finally {
|
|
21843
23223
|
this.#busy = false;
|
|
21844
23224
|
}
|
|
21845
23225
|
}
|
|
23226
|
+
async #executeCommand(command) {
|
|
23227
|
+
const parsed = commandPrompt(command, this.#commands, this.profile);
|
|
23228
|
+
if (!parsed.ok)
|
|
23229
|
+
return parsed;
|
|
23230
|
+
const result = await this.#execute({ type: "turn.start", turnId: command.turnId, input: [{ type: "text", text: parsed.value }] }, true);
|
|
23231
|
+
return result.ok ? { ok: true, value: { turnId: command.turnId } } : result;
|
|
23232
|
+
}
|
|
21846
23233
|
async execute(command) {
|
|
23234
|
+
const invocation = command.type === "turn.start" ? command.input.filter((item) => item.type === "text").map((item) => item.text).join("\n").trim().split(/\s/u)[0] : void 0;
|
|
23235
|
+
if (nativeCommandsEnabled(this.profile) && isExcludedInvocation(invocation))
|
|
23236
|
+
return failure("unsupported", "Command is not available in this Session", this.profile);
|
|
23237
|
+
return this.#execute(command, nativeCommandsEnabled(this.profile) && this.#commands.commands.some((entry) => entry.invocation === invocation));
|
|
23238
|
+
}
|
|
23239
|
+
async #execute(command, nativeCommand = false) {
|
|
21847
23240
|
if (this.#closed || this.#fault)
|
|
21848
|
-
return failure("invalidState", "Session is closed or faulted");
|
|
23241
|
+
return failure("invalidState", "Session is closed or faulted", this.profile);
|
|
21849
23242
|
if (command.type === "interaction.respond")
|
|
21850
23243
|
return this.#interactions.respond(command);
|
|
21851
23244
|
if (command.type === "turn.cancel") {
|
|
21852
23245
|
const active = this.#active;
|
|
21853
23246
|
if (!active || active.command.turnId !== command.turnId || !this.#ref)
|
|
21854
|
-
return failure("invalidRequest", "Turn is not active");
|
|
23247
|
+
return failure("invalidRequest", "Turn is not active", this.profile);
|
|
21855
23248
|
if (!active.cancelled) {
|
|
21856
23249
|
active.cancelled = true;
|
|
21857
23250
|
try {
|
|
21858
23251
|
await this.#client.cancel(this.#ref.nativeSessionId);
|
|
21859
23252
|
} catch (error51) {
|
|
21860
23253
|
this.#onFault(error51);
|
|
21861
|
-
return { ok: false, error: nativeError(error51) };
|
|
23254
|
+
return { ok: false, error: nativeError(error51, this.profile) };
|
|
21862
23255
|
}
|
|
21863
23256
|
this.#interactions.close();
|
|
21864
23257
|
void bounded(active.completion, 3e4, "ACP cancel acknowledgement").catch((error51) => this.#onFault(error51));
|
|
21865
23258
|
}
|
|
21866
23259
|
return { ok: true, value: { cancellationRequested: true } };
|
|
21867
23260
|
}
|
|
21868
|
-
if (this.#busy || this.#active)
|
|
21869
|
-
return failure("sessionBusy", "Session is executing an operation");
|
|
23261
|
+
if (this.#busy || this.#active && command.type !== "model.select" && command.type !== "thinking.select")
|
|
23262
|
+
return failure("sessionBusy", "Session is executing an operation", this.profile);
|
|
21870
23263
|
this.#busy = true;
|
|
21871
23264
|
try {
|
|
21872
23265
|
if (command.type === "turn.start") {
|
|
21873
23266
|
const prompt = command.input.filter((item) => item.type === "text").map((item) => item.text).join("");
|
|
21874
23267
|
if (!command.turnId.trim() || !command.input.length || command.input.some((item) => item.type !== "text") || !prompt.trim())
|
|
21875
|
-
return failure("invalidRequest", "A nonempty text prompt is required");
|
|
21876
|
-
const
|
|
23268
|
+
return failure("invalidRequest", "A nonempty text prompt is required", this.profile);
|
|
23269
|
+
const snapshot = await this.#snapshot();
|
|
23270
|
+
const before = new Set(snapshot.turns.map((turn) => turn.nativeTurnRef.nativeTurnKey));
|
|
23271
|
+
const beforeItems = new Set(snapshot.turns.flatMap((turn) => turn.items.map((snapshot2) => snapshot2.item.itemId)));
|
|
21877
23272
|
if (this.#closed || this.#fault)
|
|
21878
|
-
return failure("invalidState", "Session closed before Turn start");
|
|
23273
|
+
return failure("invalidState", "Session closed before Turn start", this.profile);
|
|
21879
23274
|
const active = {
|
|
21880
23275
|
command,
|
|
21881
23276
|
before,
|
|
21882
|
-
|
|
23277
|
+
beforeItems,
|
|
23278
|
+
output: new CodeBuddyTurnOutput(command.turnId, this.input.cwd, (event) => this.#emit(event), this.profile),
|
|
23279
|
+
nativeCommand,
|
|
21883
23280
|
cancelled: false,
|
|
21884
23281
|
done: false,
|
|
21885
23282
|
completion: Promise.resolve()
|
|
21886
23283
|
};
|
|
21887
23284
|
this.#active = active;
|
|
21888
23285
|
this.subagents.begin(command.turnId);
|
|
21889
|
-
|
|
23286
|
+
if (!nativeCommand)
|
|
23287
|
+
this.#hasTurn = true;
|
|
21890
23288
|
this.#emit({ type: "turn.started", turnId: command.turnId });
|
|
21891
23289
|
active.completion = this.#run(active);
|
|
21892
23290
|
return { ok: true, value: { turnId: command.turnId } };
|
|
@@ -21894,7 +23292,7 @@ var CodeBuddySession = class {
|
|
|
21894
23292
|
await this.#configure(command.type === "model.select" ? "model" : command.type === "thinking.select" ? "thought_level" : "mode", command.type === "model.select" ? nativeModel(command.model) : command.type === "thinking.select" ? command.thinkingOptionId : command.permissionModeId);
|
|
21895
23293
|
return { ok: true, value: { completed: true } };
|
|
21896
23294
|
} catch (error51) {
|
|
21897
|
-
return { ok: false, error: nativeError(error51) };
|
|
23295
|
+
return { ok: false, error: nativeError(error51, this.profile) };
|
|
21898
23296
|
} finally {
|
|
21899
23297
|
this.#busy = false;
|
|
21900
23298
|
}
|
|
@@ -21911,23 +23309,36 @@ var CodeBuddySession = class {
|
|
|
21911
23309
|
// Those remain visible on individual Items; they do not fail the completed Turn.
|
|
21912
23310
|
(!meta3["codebuddy.ai/outcome"] || meta3["codebuddy.ai/outcome"] === "SUCCESS" || meta3["codebuddy.ai/outcome"] === "PARTIAL_SUCCESS") ? { status: "succeeded" } : {
|
|
21913
23311
|
status: "failed",
|
|
21914
|
-
error: nativeError(new CodeBuddyError("nativeFailure", `Native Turn stopped: ${text(stop) || "unknown"} (${text(meta3["codebuddy.ai/outcome"]) || "no native outcome"})`))
|
|
23312
|
+
error: nativeError(new CodeBuddyError("nativeFailure", `Native Turn stopped: ${text(stop) || "unknown"} (${text(meta3["codebuddy.ai/outcome"]) || "no native outcome"})`), this.profile)
|
|
21915
23313
|
};
|
|
21916
23314
|
const snapshot = await this.#snapshot();
|
|
21917
23315
|
const added = snapshot.turns.filter((turn) => !active.before.has(turn.nativeTurnRef.nativeTurnKey));
|
|
21918
|
-
if (added.length > 1 || outcome.status === "succeeded" && added.length !== 1)
|
|
23316
|
+
if (added.length > 1 || !active.nativeCommand && outcome.status === "succeeded" && added.length !== 1)
|
|
21919
23317
|
throw new CodeBuddyError("protocolError", "Could not identify exactly one persisted Native Turn");
|
|
23318
|
+
active.output.confirmCompaction(snapshot.turns.flatMap((turn) => turn.items).filter((snapshot2) => !active.beforeItems.has(snapshot2.item.itemId)));
|
|
23319
|
+
if (active.nativeCommand)
|
|
23320
|
+
active.output.replayCommandResult(added[0]?.items ?? []);
|
|
21920
23321
|
const nativeTurnRef = added[0]?.nativeTurnRef;
|
|
23322
|
+
if (nativeTurnRef)
|
|
23323
|
+
this.#hasTurn = true;
|
|
21921
23324
|
if (response.userMessageId && nativeTurnRef?.nativeTurnKey !== response.userMessageId)
|
|
21922
23325
|
throw new CodeBuddyError("protocolError", "ACP terminal and native history disagree on Turn identity");
|
|
21923
23326
|
if (outcome.status === "cancelled")
|
|
21924
23327
|
await this.#resumeAfterCancel();
|
|
21925
|
-
|
|
23328
|
+
const compactCommand = active.nativeCommand && /^\/compact(?:\s|$)/u.test(active.command.input.filter((item) => item.type === "text").map((item) => item.text).join("\n").trim());
|
|
23329
|
+
const persisted = compactCommand ? added[0]?.outcome : void 0;
|
|
23330
|
+
if (compactCommand && (!persisted || persisted.status === "unknown"))
|
|
23331
|
+
throw new CodeBuddyError("protocolError", "Native compaction terminal outcome was not persisted");
|
|
23332
|
+
const terminalOutcome = persisted && persisted.status !== "unknown" ? persisted : outcome;
|
|
23333
|
+
this.#finish(active, {
|
|
23334
|
+
...terminalOutcome,
|
|
23335
|
+
...added[0]?.checkpoint ? { checkpoint: added[0].checkpoint } : {}
|
|
23336
|
+
}, nativeTurnRef);
|
|
21926
23337
|
if (this.#usage)
|
|
21927
23338
|
this.#emit({ type: "session.usage.changed", usage: { ...this.#usage, ...this.#context } });
|
|
21928
23339
|
} catch (error51) {
|
|
21929
23340
|
if (!active.done)
|
|
21930
|
-
this.#finish(active, { status: "failed", error: nativeError(error51) });
|
|
23341
|
+
this.#finish(active, { status: "failed", error: nativeError(error51, this.profile) });
|
|
21931
23342
|
}
|
|
21932
23343
|
}
|
|
21933
23344
|
async #resumeAfterCancel() {
|
|
@@ -21942,11 +23353,8 @@ var CodeBuddySession = class {
|
|
|
21942
23353
|
if (this.#closed)
|
|
21943
23354
|
return;
|
|
21944
23355
|
this.#client = this.#createClient();
|
|
21945
|
-
await this.#
|
|
21946
|
-
|
|
21947
|
-
if (loaded.sessionId && loaded.sessionId !== this.#ref.nativeSessionId)
|
|
21948
|
-
throw new CodeBuddyError("protocolError", "Cancellation recovery changed Native Session identity");
|
|
21949
|
-
this.#apply(configuration(loaded.configOptions));
|
|
23356
|
+
const loaded = await this.#openClient();
|
|
23357
|
+
this.#apply(configuration(loaded.configOptions, this.profile));
|
|
21950
23358
|
if (saved.effectiveModel)
|
|
21951
23359
|
await this.#configure("model", nativeModel(saved.effectiveModel));
|
|
21952
23360
|
if (saved.effectiveThinkingOptionId)
|
|
@@ -21979,7 +23387,7 @@ var CodeBuddySession = class {
|
|
|
21979
23387
|
#onFault(error51) {
|
|
21980
23388
|
if (this.#fault || this.#closed)
|
|
21981
23389
|
return;
|
|
21982
|
-
this.#fault = nativeError(error51);
|
|
23390
|
+
this.#fault = nativeError(error51, this.profile);
|
|
21983
23391
|
if (this.#active)
|
|
21984
23392
|
this.#finish(this.#active, { status: "failed", error: this.#fault });
|
|
21985
23393
|
this.#interactions.close();
|
|
@@ -22010,30 +23418,43 @@ var CodeBuddySession = class {
|
|
|
22010
23418
|
// dist/codebuddy-adapter.js
|
|
22011
23419
|
var CodeBuddyAdapter = class {
|
|
22012
23420
|
options;
|
|
22013
|
-
harnessId
|
|
23421
|
+
harnessId;
|
|
23422
|
+
commandCatalog;
|
|
22014
23423
|
subagents = {
|
|
22015
23424
|
readSnapshot: async ({ parent, nativeSubagentId, cwd }) => {
|
|
22016
23425
|
try {
|
|
22017
23426
|
if (this.#closed)
|
|
22018
|
-
return failure("invalidState", "Adapter is closed");
|
|
23427
|
+
return failure("invalidState", "Adapter is closed", this.#profile);
|
|
22019
23428
|
const session = [...this.#sessions].find((s) => s.initialState.nativeRef?.nativeSessionId === parent.nativeSessionId);
|
|
22020
|
-
const snapshot = await readCodeBuddyChild(parent, nativeSubagentId, cwd, session?.environment ?? this.#environment, session?.subagents.state(nativeSubagentId)?.status);
|
|
23429
|
+
const snapshot = await readCodeBuddyChild(parent, nativeSubagentId, cwd, session?.environment ?? this.#environment, session?.subagents.state(nativeSubagentId)?.status, this.#profile);
|
|
22021
23430
|
return { ok: true, value: snapshot };
|
|
22022
23431
|
} catch (error51) {
|
|
22023
|
-
return { ok: false, error: nativeError(error51) };
|
|
23432
|
+
return { ok: false, error: nativeError(error51, this.#profile) };
|
|
22024
23433
|
}
|
|
22025
23434
|
}
|
|
22026
23435
|
};
|
|
22027
23436
|
#environment;
|
|
23437
|
+
#profile;
|
|
22028
23438
|
#factory;
|
|
23439
|
+
#invocation;
|
|
22029
23440
|
#sessions = /* @__PURE__ */ new Set();
|
|
22030
23441
|
#inspections = /* @__PURE__ */ new Set();
|
|
22031
23442
|
#cache = /* @__PURE__ */ new Map();
|
|
22032
23443
|
#closed = false;
|
|
23444
|
+
#abort = new AbortController();
|
|
23445
|
+
#derivations = /* @__PURE__ */ new Set();
|
|
22033
23446
|
constructor(options = {}) {
|
|
22034
23447
|
this.options = options;
|
|
23448
|
+
this.#profile = options.profile ?? CODEBUDDY_RUNTIME_PROFILE;
|
|
23449
|
+
this.harnessId = this.#profile.harnessId;
|
|
23450
|
+
if (nativeCommandsEnabled(this.#profile)) {
|
|
23451
|
+
const commandCatalog2 = this.#profile.staticCommandCatalog ?? (this.#profile.harnessId === CODEBUDDY_RUNTIME_PROFILE.harnessId ? CODEBUDDY_COMMAND_CATALOG : void 0);
|
|
23452
|
+
if (commandCatalog2)
|
|
23453
|
+
this.commandCatalog = commandCatalog2;
|
|
23454
|
+
}
|
|
22035
23455
|
this.#environment = { ...options.environment ?? process.env };
|
|
22036
|
-
this.#
|
|
23456
|
+
this.#invocation = options.invocationFactory ?? codeBuddyInvocation;
|
|
23457
|
+
this.#factory = options.clientFactory ?? ((clientOptions) => new CodeBuddyAcpClient(clientOptions, void 0, this.#invocation));
|
|
22037
23458
|
}
|
|
22038
23459
|
inspect(input = {}) {
|
|
22039
23460
|
const cwd = input.cwd ?? process.cwd();
|
|
@@ -22069,15 +23490,15 @@ var CodeBuddyAdapter = class {
|
|
|
22069
23490
|
this.#inspections.add(client2);
|
|
22070
23491
|
await client2.initialize();
|
|
22071
23492
|
const opened = await client2.open(cwd);
|
|
22072
|
-
const config2 = configuration(opened.configOptions);
|
|
23493
|
+
const config2 = configuration(opened.configOptions, this.#profile);
|
|
22073
23494
|
return harnessInspectionSchema.parse({
|
|
22074
23495
|
status: "ready",
|
|
22075
23496
|
catalog: config2.catalog,
|
|
22076
23497
|
permissionModes: config2.permissionModes,
|
|
22077
|
-
capabilities:
|
|
23498
|
+
capabilities: capabilitiesForProfile(this.#profile)
|
|
22078
23499
|
});
|
|
22079
23500
|
} catch (error51) {
|
|
22080
|
-
const issue2 = nativeError(error51);
|
|
23501
|
+
const issue2 = nativeError(error51, this.#profile);
|
|
22081
23502
|
return {
|
|
22082
23503
|
status: issue2.code === "notInstalled" ? "notInstalled" : "unavailable",
|
|
22083
23504
|
error: issue2
|
|
@@ -22092,19 +23513,56 @@ var CodeBuddyAdapter = class {
|
|
|
22092
23513
|
}
|
|
22093
23514
|
async open(input) {
|
|
22094
23515
|
if (this.#closed)
|
|
22095
|
-
return failure("invalidState", "Adapter is closed");
|
|
22096
|
-
if (input.kind === "
|
|
22097
|
-
return failure("
|
|
23516
|
+
return failure("invalidState", "Adapter is closed", this.#profile);
|
|
23517
|
+
if (input.kind === "create" && input.executionPolicy === "unattended-full-access" && input.permissionModeId && input.permissionModeId !== "fullAccess")
|
|
23518
|
+
return failure("invalidRequest", "Unattended execution requires native fullAccess permissions", this.#profile);
|
|
22098
23519
|
let session;
|
|
22099
23520
|
try {
|
|
22100
23521
|
if (!(await stat2(input.cwd)).isDirectory())
|
|
22101
23522
|
throw new CodeBuddyError("invalidRequest", "Working directory is not a directory");
|
|
23523
|
+
if (this.#closed)
|
|
23524
|
+
throw new CodeBuddyError("invalidState", "Adapter closed while opening Session");
|
|
22102
23525
|
if (input.kind === "resume")
|
|
22103
|
-
validateNativeRef(input.nativeRef);
|
|
23526
|
+
validateNativeRef(input.nativeRef, this.#profile);
|
|
23527
|
+
if (input.kind === "fork" || input.kind === "rollbackLastTurn") {
|
|
23528
|
+
const capabilities = capabilitiesForProfile(this.#profile).history;
|
|
23529
|
+
if (input.kind === "fork" && !capabilities.fork || input.kind === "rollbackLastTurn" && !capabilities.rollbackLastTurn)
|
|
23530
|
+
throw new CodeBuddyError("unsupported", `${this.#profile.displayName} does not expose this verified history operation`);
|
|
23531
|
+
const sourceRef = input.sourceRef;
|
|
23532
|
+
validateNativeRef(sourceRef, this.#profile);
|
|
23533
|
+
const source = [...this.#sessions].find((candidate) => candidate.initialState.nativeRef?.nativeSessionId === sourceRef.nativeSessionId);
|
|
23534
|
+
const snapshot = await source?.readSnapshot();
|
|
23535
|
+
if (this.#closed)
|
|
23536
|
+
throw new CodeBuddyError("invalidState", "Adapter closed while reading source Session");
|
|
23537
|
+
if (snapshot && !snapshot.ok)
|
|
23538
|
+
return snapshot;
|
|
23539
|
+
const boundCwd = text(record2(sourceRef.locator).boundCwd);
|
|
23540
|
+
const sourceCwd = (source?.input.cwd ?? boundCwd) || input.cwd;
|
|
23541
|
+
if (input.kind === "fork" && !capabilities.forkAcrossCwd && codeBuddyCanonicalCwd(sourceCwd) !== codeBuddyCanonicalCwd(input.cwd))
|
|
23542
|
+
throw new CodeBuddyError("unsupported", `${this.#profile.displayName} does not support cross-directory Fork`);
|
|
23543
|
+
const derivation = deriveCodeBuddySession({
|
|
23544
|
+
input,
|
|
23545
|
+
sourceCwd,
|
|
23546
|
+
environment: { ...this.#environment, ...input.environment },
|
|
23547
|
+
factory: this.#factory,
|
|
23548
|
+
invocationFactory: this.#invocation,
|
|
23549
|
+
profile: this.#profile,
|
|
23550
|
+
signal: this.#abort.signal,
|
|
23551
|
+
...snapshot?.ok && snapshot.value.state ? { state: snapshot.value.state } : {}
|
|
23552
|
+
});
|
|
23553
|
+
this.#derivations.add(derivation);
|
|
23554
|
+
try {
|
|
23555
|
+
input = await derivation;
|
|
23556
|
+
} finally {
|
|
23557
|
+
this.#derivations.delete(derivation);
|
|
23558
|
+
}
|
|
23559
|
+
}
|
|
23560
|
+
if (this.#closed)
|
|
23561
|
+
throw new CodeBuddyError("invalidState", "Adapter closed while opening Session");
|
|
22104
23562
|
session = new CodeBuddySession(input, { ...this.#environment, ...input.environment }, this.#factory, this.options.readHistory, () => {
|
|
22105
23563
|
if (session)
|
|
22106
23564
|
this.#sessions.delete(session);
|
|
22107
|
-
});
|
|
23565
|
+
}, this.#profile);
|
|
22108
23566
|
this.#sessions.add(session);
|
|
22109
23567
|
await session.initialize();
|
|
22110
23568
|
if (this.#closed)
|
|
@@ -22117,24 +23575,26 @@ var CodeBuddyAdapter = class {
|
|
|
22117
23575
|
this.#sessions.delete(session);
|
|
22118
23576
|
}
|
|
22119
23577
|
const issue2 = record2(error51).code === "ENOENT" ? new CodeBuddyError("invalidRequest", "Working directory does not exist") : error51;
|
|
22120
|
-
return { ok: false, error: nativeError(issue2) };
|
|
23578
|
+
return { ok: false, error: nativeError(issue2, this.#profile) };
|
|
22121
23579
|
}
|
|
22122
23580
|
}
|
|
22123
23581
|
async close() {
|
|
22124
23582
|
this.#closed = true;
|
|
23583
|
+
this.#abort.abort();
|
|
23584
|
+
await Promise.allSettled([...this.#derivations]);
|
|
22125
23585
|
const results = await Promise.allSettled([...this.#sessions, ...this.#inspections].map((resource) => resource.close()));
|
|
22126
23586
|
this.#sessions.clear();
|
|
22127
23587
|
this.#inspections.clear();
|
|
22128
23588
|
this.#cache.clear();
|
|
22129
23589
|
const errors = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
22130
23590
|
if (errors.length)
|
|
22131
|
-
throw new AggregateError(errors,
|
|
23591
|
+
throw new AggregateError(errors, `${this.#profile.displayName} process cleanup failed`);
|
|
22132
23592
|
}
|
|
22133
23593
|
};
|
|
22134
23594
|
|
|
22135
23595
|
// ../../harness-broker/dist/client.js
|
|
22136
|
-
import { randomUUID } from "node:crypto";
|
|
22137
|
-
import { lstat, readFile as
|
|
23596
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
23597
|
+
import { lstat as lstat2, readFile as readFile3 } from "node:fs/promises";
|
|
22138
23598
|
import net, {} from "node:net";
|
|
22139
23599
|
|
|
22140
23600
|
// ../../harness-broker/dist/protocol.js
|
|
@@ -22252,18 +23712,18 @@ function consumeBrokerFrames(socket, onFrame, onError) {
|
|
|
22252
23712
|
|
|
22253
23713
|
// ../../harness-broker/dist/paths.js
|
|
22254
23714
|
import os2 from "node:os";
|
|
22255
|
-
import
|
|
23715
|
+
import path7 from "node:path";
|
|
22256
23716
|
var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
|
|
22257
23717
|
var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
|
|
22258
23718
|
function defaultHarnessBrokerDirectory(environment = process.env) {
|
|
22259
23719
|
const home = environment.HOME || os2.homedir();
|
|
22260
|
-
return
|
|
23720
|
+
return path7.join(home, ".codexhost", "harness-broker");
|
|
22261
23721
|
}
|
|
22262
23722
|
function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
|
|
22263
23723
|
harnessPluginIdSchema.parse(harnessId);
|
|
22264
23724
|
if (harnessId !== "claude-code")
|
|
22265
|
-
return
|
|
22266
|
-
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ??
|
|
23725
|
+
return path7.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
|
|
23726
|
+
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path7.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
|
|
22267
23727
|
}
|
|
22268
23728
|
|
|
22269
23729
|
// ../../harness-broker/dist/validation.js
|
|
@@ -22561,7 +24021,7 @@ function parseSessionMetadata(value) {
|
|
|
22561
24021
|
};
|
|
22562
24022
|
}
|
|
22563
24023
|
async function readDescriptor(descriptorPath) {
|
|
22564
|
-
const metadata = await
|
|
24024
|
+
const metadata = await lstat2(descriptorPath);
|
|
22565
24025
|
if (metadata.isSymbolicLink())
|
|
22566
24026
|
throw new Error("Aqua Harness broker descriptor must not be a symlink");
|
|
22567
24027
|
if (!metadata.isFile())
|
|
@@ -22573,12 +24033,12 @@ async function readDescriptor(descriptorPath) {
|
|
|
22573
24033
|
throw new Error("Aqua Harness broker descriptor belongs to another user");
|
|
22574
24034
|
}
|
|
22575
24035
|
}
|
|
22576
|
-
const descriptor = harnessBrokerDescriptorSchema.parse(JSON.parse(await
|
|
24036
|
+
const descriptor = harnessBrokerDescriptorSchema.parse(JSON.parse(await readFile3(descriptorPath, "utf8")));
|
|
22577
24037
|
if (process.platform === "darwin" && Buffer.byteLength(descriptor.socketPath) > 103) {
|
|
22578
24038
|
throw new Error("Aqua Harness broker socket path is too long for macOS");
|
|
22579
24039
|
}
|
|
22580
24040
|
if (process.platform !== "win32") {
|
|
22581
|
-
const socket = await
|
|
24041
|
+
const socket = await lstat2(descriptor.socketPath);
|
|
22582
24042
|
if (socket.isSymbolicLink() || !socket.isSocket()) {
|
|
22583
24043
|
throw new Error("Aqua Harness broker endpoint is not a Unix socket");
|
|
22584
24044
|
}
|
|
@@ -22675,7 +24135,7 @@ var BrokerConnection = class _BrokerConnection {
|
|
|
22675
24135
|
throw new Error("Aqua Harness broker request limit exceeded");
|
|
22676
24136
|
}
|
|
22677
24137
|
this.#inputSequence += 1;
|
|
22678
|
-
const id =
|
|
24138
|
+
const id = randomUUID2();
|
|
22679
24139
|
const response = new Promise((resolve, reject) => {
|
|
22680
24140
|
const timeout = setTimeout(() => {
|
|
22681
24141
|
this.#pending.delete(id);
|
|
@@ -23150,6 +24610,7 @@ function createHarnessAdapter(context) {
|
|
|
23150
24610
|
return new BrokeredHarnessAdapter({
|
|
23151
24611
|
harnessId: "codebuddy",
|
|
23152
24612
|
forwardDelegationEnvironment: true,
|
|
24613
|
+
commandCatalog: CODEBUDDY_COMMAND_CATALOG,
|
|
23153
24614
|
environment: { ...context.environment }
|
|
23154
24615
|
});
|
|
23155
24616
|
return new CodeBuddyAdapter({ environment: { ...context.environment } });
|