@codexhost/cli-darwin-x64 0.9.1-test.2 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +256 -179
- package/app/host-runtime.mjs +594 -298
- package/app/plugins/antigravity/plugin.mjs +123 -1
- package/app/plugins/claude-code/plugin.mjs +248 -42
- package/app/plugins/codebuddy/plugin.mjs +2166 -758
- package/app/plugins/cursor-cli/plugin.mjs +35942 -10942
- package/app/plugins/deepseek-harness/plugin.mjs +70 -0
- package/app/plugins/enabled.json +1 -0
- package/app/plugins/grok/plugin.mjs +193 -82
- package/app/plugins/hermes/plugin.mjs +2444 -94
- package/app/plugins/kiro-cli/plugin.mjs +70 -0
- package/app/plugins/omp/plugin.mjs +106 -8
- package/app/plugins/opencode/plugin.mjs +70 -0
- package/app/plugins/pi/plugin.mjs +1933 -767
- package/app/plugins/qoder/plugin.mjs +71 -9
- package/app/plugins/qoder-cn/plugin.mjs +71 -9
- package/app/plugins/workbuddy/assets/icon.svg +29 -0
- package/app/plugins/workbuddy/manifest.json +14 -0
- package/app/plugins/workbuddy/plugin.mjs +24873 -0
- package/app/renderer-extension.js +5290 -3642
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- 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,6 +14519,61 @@ 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
|
|
|
@@ -15050,6 +15102,8 @@ var pluginPresentationShape = {
|
|
|
15050
15102
|
id: harnessPluginIdSchema,
|
|
15051
15103
|
name: external_exports.string().trim().min(1).max(128),
|
|
15052
15104
|
version: external_exports.string().min(1).max(128),
|
|
15105
|
+
/** The factory accepts a persisted local entrypoint through its construction context. */
|
|
15106
|
+
launchCommand: external_exports.literal(true).optional(),
|
|
15053
15107
|
links: external_exports.object({
|
|
15054
15108
|
documentation: documentationUrlSchema.optional(),
|
|
15055
15109
|
installation: documentationUrlSchema.optional()
|
|
@@ -15087,6 +15141,19 @@ var harnessPluginRouteSchema = external_exports.object({
|
|
|
15087
15141
|
permissionModeId: harnessPermissionModeIdSchema.optional()
|
|
15088
15142
|
}).strict();
|
|
15089
15143
|
|
|
15144
|
+
// ../../shared-contracts/dist/harness-launch-settings.js
|
|
15145
|
+
var harnessLaunchPathSchema = external_exports.string().trim().min(1).max(4096).refine((value) => !/[\u0000\r\n]/u.test(value), "Invalid entrypoint path");
|
|
15146
|
+
var harnessLaunchSettingsGetSchema = external_exports.object({
|
|
15147
|
+
harnessId: harnessPluginIdSchema
|
|
15148
|
+
}).strict();
|
|
15149
|
+
var harnessLaunchSettingsSetSchema = harnessLaunchSettingsGetSchema.extend({
|
|
15150
|
+
path: harnessLaunchPathSchema.nullable()
|
|
15151
|
+
});
|
|
15152
|
+
var harnessLaunchSettingsSchema = external_exports.object({
|
|
15153
|
+
path: harnessLaunchPathSchema.nullable(),
|
|
15154
|
+
restartRequired: external_exports.boolean()
|
|
15155
|
+
}).strict();
|
|
15156
|
+
|
|
15090
15157
|
// ../../shared-contracts/dist/codex-accounts.js
|
|
15091
15158
|
var accountIdSchema = external_exports.string().min(1).max(256).regex(/^[A-Za-z0-9._~-]+$/u);
|
|
15092
15159
|
var nonBlankTextSchema3 = external_exports.string().trim().min(1);
|
|
@@ -15374,203 +15441,544 @@ var updateStatusResultSchema = external_exports.strictObject({
|
|
|
15374
15441
|
// ../../shared-contracts/dist/index.js
|
|
15375
15442
|
var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
|
|
15376
15443
|
|
|
15377
|
-
// dist/
|
|
15378
|
-
|
|
15379
|
-
|
|
15380
|
-
|
|
15381
|
-
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
|
|
15382
|
-
var AGENT_METHODS = {
|
|
15383
|
-
initialize: "initialize",
|
|
15384
|
-
authenticate: "authenticate",
|
|
15385
|
-
providers_list: "providers/list",
|
|
15386
|
-
providers_set: "providers/set",
|
|
15387
|
-
providers_disable: "providers/disable",
|
|
15388
|
-
session_new: "session/new",
|
|
15389
|
-
session_load: "session/load",
|
|
15390
|
-
session_set_mode: "session/set_mode",
|
|
15391
|
-
session_set_config_option: "session/set_config_option",
|
|
15392
|
-
session_prompt: "session/prompt",
|
|
15393
|
-
session_cancel: "session/cancel",
|
|
15394
|
-
mcp_message: "mcp/message",
|
|
15395
|
-
session_list: "session/list",
|
|
15396
|
-
session_delete: "session/delete",
|
|
15397
|
-
session_fork: "session/fork",
|
|
15398
|
-
session_resume: "session/resume",
|
|
15399
|
-
session_close: "session/close",
|
|
15400
|
-
logout: "logout",
|
|
15401
|
-
nes_start: "nes/start",
|
|
15402
|
-
nes_suggest: "nes/suggest",
|
|
15403
|
-
nes_accept: "nes/accept",
|
|
15404
|
-
nes_reject: "nes/reject",
|
|
15405
|
-
nes_close: "nes/close",
|
|
15406
|
-
document_did_open: "document/didOpen",
|
|
15407
|
-
document_did_change: "document/didChange",
|
|
15408
|
-
document_did_close: "document/didClose",
|
|
15409
|
-
document_did_save: "document/didSave",
|
|
15410
|
-
document_did_focus: "document/didFocus"
|
|
15411
|
-
};
|
|
15412
|
-
var CLIENT_METHODS = {
|
|
15413
|
-
session_request_permission: "session/request_permission",
|
|
15414
|
-
session_update: "session/update",
|
|
15415
|
-
fs_write_text_file: "fs/write_text_file",
|
|
15416
|
-
fs_read_text_file: "fs/read_text_file",
|
|
15417
|
-
terminal_create: "terminal/create",
|
|
15418
|
-
terminal_output: "terminal/output",
|
|
15419
|
-
terminal_release: "terminal/release",
|
|
15420
|
-
terminal_wait_for_exit: "terminal/wait_for_exit",
|
|
15421
|
-
terminal_kill: "terminal/kill",
|
|
15422
|
-
mcp_connect: "mcp/connect",
|
|
15423
|
-
mcp_message: "mcp/message",
|
|
15424
|
-
mcp_disconnect: "mcp/disconnect",
|
|
15425
|
-
elicitation_create: "elicitation/create",
|
|
15426
|
-
elicitation_complete: "elicitation/complete"
|
|
15427
|
-
};
|
|
15428
|
-
var PROTOCOL_METHODS = {
|
|
15429
|
-
cancel_request: "$/cancel_request"
|
|
15430
|
-
};
|
|
15431
|
-
|
|
15432
|
-
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema-deserialize.js
|
|
15433
|
-
var skippedItem = /* @__PURE__ */ Symbol("skippedItem");
|
|
15434
|
-
function defaultOnError(schema, fallback) {
|
|
15435
|
-
return schema.catch(fallback);
|
|
15444
|
+
// ../../harness-adapter/dist/approval.js
|
|
15445
|
+
function invalidRequest(message) {
|
|
15446
|
+
return { code: "invalidRequest", message, retryable: false };
|
|
15436
15447
|
}
|
|
15437
|
-
function
|
|
15438
|
-
|
|
15439
|
-
return external_exports.unknown().transform((value, context) => {
|
|
15440
|
-
if (value !== void 0)
|
|
15441
|
-
return schemaWithCatch.parse(value);
|
|
15442
|
-
context.addIssue({
|
|
15443
|
-
code: "custom",
|
|
15444
|
-
message: "Required value is missing"
|
|
15445
|
-
});
|
|
15446
|
-
return external_exports.NEVER;
|
|
15447
|
-
});
|
|
15448
|
+
function validateHostApprovalResponse(interaction, response) {
|
|
15449
|
+
return interaction.actions.some(({ id }) => id === response.actionId) ? null : invalidRequest("Approval Response contains an undeclared action ID");
|
|
15448
15450
|
}
|
|
15449
|
-
|
|
15450
|
-
|
|
15451
|
-
|
|
15452
|
-
}
|
|
15453
|
-
const tag = value[key];
|
|
15454
|
-
return typeof tag === "string" ? tag : void 0;
|
|
15451
|
+
|
|
15452
|
+
// ../../harness-adapter/dist/question.js
|
|
15453
|
+
function invalidRequest2(message) {
|
|
15454
|
+
return { code: "invalidRequest", message, retryable: false };
|
|
15455
15455
|
}
|
|
15456
|
-
function
|
|
15457
|
-
|
|
15458
|
-
|
|
15459
|
-
|
|
15460
|
-
|
|
15461
|
-
|
|
15462
|
-
|
|
15463
|
-
|
|
15464
|
-
});
|
|
15456
|
+
function validateHostQuestionResponse(interaction, response) {
|
|
15457
|
+
const questionIds = new Set(interaction.questions.map(({ id }) => id));
|
|
15458
|
+
if (response.cancelled) {
|
|
15459
|
+
return Object.keys(response.answers).length === 0 ? null : invalidRequest2("Cancelled Question Response must not contain answers");
|
|
15460
|
+
}
|
|
15461
|
+
for (const answerId of Object.keys(response.answers)) {
|
|
15462
|
+
if (!questionIds.has(answerId)) {
|
|
15463
|
+
return invalidRequest2("Question Response contains an unknown Question ID");
|
|
15465
15464
|
}
|
|
15466
|
-
}
|
|
15467
|
-
|
|
15468
|
-
|
|
15469
|
-
|
|
15470
|
-
|
|
15471
|
-
if (!result.success) {
|
|
15472
|
-
for (const issue2 of result.error.issues) {
|
|
15473
|
-
context.addIssue({ ...issue2, input: value });
|
|
15474
|
-
}
|
|
15475
|
-
return external_exports.NEVER;
|
|
15465
|
+
}
|
|
15466
|
+
for (const question of interaction.questions) {
|
|
15467
|
+
const answers = response.answers[question.id] ?? [];
|
|
15468
|
+
if (!question.optional && answers.length === 0) {
|
|
15469
|
+
return invalidRequest2("Question Response omits a required answer");
|
|
15476
15470
|
}
|
|
15477
|
-
|
|
15478
|
-
|
|
15479
|
-
|
|
15480
|
-
const raw = value;
|
|
15481
|
-
for (const [property, rawValue] of Object.entries(raw)) {
|
|
15482
|
-
if (property === "__proto__")
|
|
15483
|
-
continue;
|
|
15484
|
-
if (!Object.hasOwn(output, property))
|
|
15485
|
-
output[property] = rawValue;
|
|
15471
|
+
if (question.type === "text") {
|
|
15472
|
+
if (answers.length > 1) {
|
|
15473
|
+
return invalidRequest2("Text Question accepts at most one answer");
|
|
15486
15474
|
}
|
|
15475
|
+
continue;
|
|
15487
15476
|
}
|
|
15488
|
-
|
|
15489
|
-
|
|
15477
|
+
if (!question.multiple && answers.length > 1) {
|
|
15478
|
+
return invalidRequest2("Single-choice Question accepts at most one answer");
|
|
15479
|
+
}
|
|
15480
|
+
const declared = new Set(question.options.map(({ value }) => value));
|
|
15481
|
+
if (!question.allowOther && answers.some((answer) => !declared.has(answer))) {
|
|
15482
|
+
return invalidRequest2("Question Response contains an undeclared choice");
|
|
15483
|
+
}
|
|
15484
|
+
}
|
|
15485
|
+
return null;
|
|
15490
15486
|
}
|
|
15491
|
-
|
|
15492
|
-
|
|
15487
|
+
|
|
15488
|
+
// ../../harness-adapter/dist/interaction.js
|
|
15489
|
+
function invalidRequest3(message) {
|
|
15490
|
+
return { code: "invalidRequest", message, retryable: false };
|
|
15491
|
+
}
|
|
15492
|
+
function invalidState(message) {
|
|
15493
|
+
return { code: "invalidState", message, retryable: false };
|
|
15494
|
+
}
|
|
15495
|
+
function validateHostInteractionResponse(interaction, response) {
|
|
15496
|
+
if (!interaction) {
|
|
15497
|
+
return invalidState("Interaction Response must reference a pending Interaction");
|
|
15498
|
+
}
|
|
15499
|
+
if (interaction.type === "question") {
|
|
15500
|
+
return response.type === "question" ? validateHostQuestionResponse(interaction, response) : invalidRequest3("Interaction Response type does not match the pending Interaction");
|
|
15501
|
+
}
|
|
15502
|
+
return response.type === "approval" ? validateHostApprovalResponse(interaction, response) : invalidRequest3("Interaction Response type does not match the pending Interaction");
|
|
15493
15503
|
}
|
|
15494
15504
|
|
|
15495
|
-
//
|
|
15496
|
-
var
|
|
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
|
-
|
|
15531
|
-
|
|
15532
|
-
|
|
15533
|
-
|
|
15534
|
-
|
|
15535
|
-
|
|
15536
|
-
|
|
15537
|
-
|
|
15538
|
-
|
|
15539
|
-
|
|
15540
|
-
|
|
15541
|
-
|
|
15542
|
-
|
|
15543
|
-
|
|
15544
|
-
|
|
15545
|
-
|
|
15546
|
-
var
|
|
15547
|
-
|
|
15548
|
-
|
|
15549
|
-
|
|
15550
|
-
|
|
15551
|
-
|
|
15552
|
-
|
|
15553
|
-
|
|
15554
|
-
|
|
15555
|
-
|
|
15556
|
-
|
|
15557
|
-
|
|
15558
|
-
|
|
15559
|
-
|
|
15560
|
-
|
|
15561
|
-
|
|
15562
|
-
|
|
15563
|
-
|
|
15564
|
-
|
|
15565
|
-
|
|
15566
|
-
|
|
15567
|
-
|
|
15568
|
-
|
|
15569
|
-
var
|
|
15570
|
-
|
|
15571
|
-
|
|
15572
|
-
|
|
15573
|
-
|
|
15505
|
+
// ../../harness-adapter/dist/output-channel.js
|
|
15506
|
+
var HarnessOutputChannel = class {
|
|
15507
|
+
outputs;
|
|
15508
|
+
#consumerCreated = false;
|
|
15509
|
+
#ended = false;
|
|
15510
|
+
#pending = [];
|
|
15511
|
+
#values = [];
|
|
15512
|
+
constructor() {
|
|
15513
|
+
this.outputs = {
|
|
15514
|
+
[Symbol.asyncIterator]: () => {
|
|
15515
|
+
if (this.#consumerCreated) {
|
|
15516
|
+
throw new Error("Harness outputs allow only one consumer");
|
|
15517
|
+
}
|
|
15518
|
+
this.#consumerCreated = true;
|
|
15519
|
+
return {
|
|
15520
|
+
next: () => this.#next()
|
|
15521
|
+
};
|
|
15522
|
+
}
|
|
15523
|
+
};
|
|
15524
|
+
}
|
|
15525
|
+
emit(value) {
|
|
15526
|
+
if (this.#ended)
|
|
15527
|
+
return false;
|
|
15528
|
+
const resolve = this.#pending.shift();
|
|
15529
|
+
if (resolve)
|
|
15530
|
+
resolve({ done: false, value });
|
|
15531
|
+
else
|
|
15532
|
+
this.#values.push(value);
|
|
15533
|
+
return true;
|
|
15534
|
+
}
|
|
15535
|
+
end() {
|
|
15536
|
+
if (this.#ended)
|
|
15537
|
+
return;
|
|
15538
|
+
this.#ended = true;
|
|
15539
|
+
if (this.#values.length !== 0)
|
|
15540
|
+
return;
|
|
15541
|
+
for (const resolve of this.#pending.splice(0))
|
|
15542
|
+
resolve({ done: true, value: void 0 });
|
|
15543
|
+
}
|
|
15544
|
+
#next() {
|
|
15545
|
+
const value = this.#values.shift();
|
|
15546
|
+
if (value !== void 0)
|
|
15547
|
+
return Promise.resolve({ done: false, value });
|
|
15548
|
+
if (this.#ended)
|
|
15549
|
+
return Promise.resolve({ done: true, value: void 0 });
|
|
15550
|
+
return new Promise((resolve) => this.#pending.push(resolve));
|
|
15551
|
+
}
|
|
15552
|
+
};
|
|
15553
|
+
|
|
15554
|
+
// ../../harness-adapter/dist/diagnostics.js
|
|
15555
|
+
var DIAGNOSTIC_TAIL_MAX_LENGTH = 8e3;
|
|
15556
|
+
var SENSITIVE_VALUE_PATTERN = /(api[_-]?key|access[_-]?token|auth(?:orization)?|password|secret)(\s*[:=]\s*)([^\s,;]+)/giu;
|
|
15557
|
+
var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/giu;
|
|
15558
|
+
function sanitizeDiagnosticTail(value) {
|
|
15559
|
+
const redacted = value.replace(BEARER_PATTERN, "Bearer [redacted]").replace(SENSITIVE_VALUE_PATTERN, "$1$2[redacted]");
|
|
15560
|
+
return redacted.length <= DIAGNOSTIC_TAIL_MAX_LENGTH ? redacted : redacted.slice(-DIAGNOSTIC_TAIL_MAX_LENGTH);
|
|
15561
|
+
}
|
|
15562
|
+
|
|
15563
|
+
// ../../harness-adapter/dist/usage.js
|
|
15564
|
+
var tokenFields = [
|
|
15565
|
+
"inputTokens",
|
|
15566
|
+
"cachedInputTokens",
|
|
15567
|
+
"cacheWriteInputTokens",
|
|
15568
|
+
"outputTokens",
|
|
15569
|
+
"outputTokensPerSecond",
|
|
15570
|
+
"reasoningOutputTokens",
|
|
15571
|
+
"totalTokens",
|
|
15572
|
+
"contextWindowTokens",
|
|
15573
|
+
"contextUsedTokens"
|
|
15574
|
+
];
|
|
15575
|
+
var safeIntegerFields = [
|
|
15576
|
+
"planFiveHourResetsAtUnix",
|
|
15577
|
+
"planSevenDayResetsAtUnix"
|
|
15578
|
+
];
|
|
15579
|
+
var percentFields = [
|
|
15580
|
+
"cacheHitRatePercent",
|
|
15581
|
+
"planFiveHourUsedPercent",
|
|
15582
|
+
"planSevenDayUsedPercent"
|
|
15583
|
+
];
|
|
15584
|
+
var usageFields = /* @__PURE__ */ new Set([
|
|
15585
|
+
...tokenFields,
|
|
15586
|
+
...safeIntegerFields,
|
|
15587
|
+
...percentFields,
|
|
15588
|
+
"totalCostUsd",
|
|
15589
|
+
"totalCredits",
|
|
15590
|
+
"contextUsagePercent"
|
|
15591
|
+
]);
|
|
15592
|
+
function isRecord(value) {
|
|
15593
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15594
|
+
}
|
|
15595
|
+
function parseHostUsage(value) {
|
|
15596
|
+
if (!isRecord(value))
|
|
15597
|
+
throw new Error("Harness Usage must be an object");
|
|
15598
|
+
const keys = Object.keys(value);
|
|
15599
|
+
if (keys.length === 0)
|
|
15600
|
+
throw new Error("Harness Usage must contain a reliable field");
|
|
15601
|
+
for (const key of keys) {
|
|
15602
|
+
if (!usageFields.has(key)) {
|
|
15603
|
+
throw new Error(`Harness Usage contains unknown field '${key}'`);
|
|
15604
|
+
}
|
|
15605
|
+
}
|
|
15606
|
+
for (const field of ["totalCredits", "contextUsagePercent"]) {
|
|
15607
|
+
const candidate = value[field];
|
|
15608
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)) {
|
|
15609
|
+
throw new Error(`Harness Usage '${field}' must be a finite non-negative number`);
|
|
15610
|
+
}
|
|
15611
|
+
}
|
|
15612
|
+
for (const field of tokenFields) {
|
|
15613
|
+
const candidate = value[field];
|
|
15614
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
15615
|
+
throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
|
|
15616
|
+
}
|
|
15617
|
+
}
|
|
15618
|
+
for (const field of safeIntegerFields) {
|
|
15619
|
+
const candidate = value[field];
|
|
15620
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
15621
|
+
throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
|
|
15622
|
+
}
|
|
15623
|
+
}
|
|
15624
|
+
if (value.outputTokensPerSecond !== void 0 && (typeof value.outputTokensPerSecond !== "number" || !Number.isFinite(value.outputTokensPerSecond) || value.outputTokensPerSecond < 0)) {
|
|
15625
|
+
throw new Error("Harness Usage 'outputTokensPerSecond' must be a finite non-negative number");
|
|
15626
|
+
}
|
|
15627
|
+
if (value.totalCostUsd !== void 0 && (typeof value.totalCostUsd !== "number" || !Number.isFinite(value.totalCostUsd) || value.totalCostUsd < 0)) {
|
|
15628
|
+
throw new Error("Harness Usage 'totalCostUsd' must be a finite non-negative number");
|
|
15629
|
+
}
|
|
15630
|
+
for (const field of percentFields) {
|
|
15631
|
+
const candidate = value[field];
|
|
15632
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0 || candidate > 100)) {
|
|
15633
|
+
throw new Error(`Harness Usage '${field}' must be between 0 and 100`);
|
|
15634
|
+
}
|
|
15635
|
+
}
|
|
15636
|
+
const hasContextUsed = value.contextUsedTokens !== void 0;
|
|
15637
|
+
const hasContextWindow = value.contextWindowTokens !== void 0;
|
|
15638
|
+
if (hasContextUsed !== hasContextWindow) {
|
|
15639
|
+
throw new Error("Harness Usage context fields must be provided together");
|
|
15640
|
+
}
|
|
15641
|
+
if (hasContextWindow && value.contextWindowTokens === 0) {
|
|
15642
|
+
throw new Error("Harness Usage 'contextWindowTokens' must be greater than zero");
|
|
15643
|
+
}
|
|
15644
|
+
if (value.planFiveHourResetsAtUnix !== void 0 && value.planFiveHourUsedPercent === void 0) {
|
|
15645
|
+
throw new Error("Harness Usage 'planFiveHourResetsAtUnix' must be provided with 'planFiveHourUsedPercent'");
|
|
15646
|
+
}
|
|
15647
|
+
if (value.planSevenDayResetsAtUnix !== void 0 && value.planSevenDayUsedPercent === void 0) {
|
|
15648
|
+
throw new Error("Harness Usage 'planSevenDayResetsAtUnix' must be provided with 'planSevenDayUsedPercent'");
|
|
15649
|
+
}
|
|
15650
|
+
return { ...value };
|
|
15651
|
+
}
|
|
15652
|
+
|
|
15653
|
+
// dist/common.js
|
|
15654
|
+
var CODEBUDDY_ID = harnessIdSchema.parse("codebuddy");
|
|
15655
|
+
var CODEBUDDY_RUNTIME_PROFILE = {
|
|
15656
|
+
harnessId: CODEBUDDY_ID,
|
|
15657
|
+
displayName: "CodeBuddy",
|
|
15658
|
+
interactionIdPrefix: "codebuddy",
|
|
15659
|
+
configDirectoryEnvironmentVariables: ["CODEBUDDY_CONFIG_DIR"],
|
|
15660
|
+
defaultConfigDirectoryName: ".codebuddy"
|
|
15661
|
+
};
|
|
15662
|
+
var OUTPUT_LIMIT = 64e3;
|
|
15663
|
+
var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
15664
|
+
var rows = (value) => Array.isArray(value) ? value.map(record2) : [];
|
|
15665
|
+
var text = (value) => typeof value === "string" ? value : "";
|
|
15666
|
+
var CodeBuddyError = class extends Error {
|
|
15667
|
+
code;
|
|
15668
|
+
constructor(code, message) {
|
|
15669
|
+
super(message);
|
|
15670
|
+
this.code = code;
|
|
15671
|
+
}
|
|
15672
|
+
};
|
|
15673
|
+
function nativeError(error51, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15674
|
+
const diagnostic = sanitizeDiagnosticTail(error51 instanceof Error ? error51.message : String(error51));
|
|
15675
|
+
const nativeCode = record2(error51).code;
|
|
15676
|
+
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";
|
|
15677
|
+
return {
|
|
15678
|
+
code,
|
|
15679
|
+
message: `${profile.displayName}: ${diagnostic || "native operation failed"}`,
|
|
15680
|
+
retryable: ["sessionBusy", "unavailable"].includes(code)
|
|
15681
|
+
};
|
|
15682
|
+
}
|
|
15683
|
+
function failure(code, message, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15684
|
+
return { ok: false, error: nativeError(new CodeBuddyError(code, message), profile) };
|
|
15685
|
+
}
|
|
15686
|
+
async function bounded(operation, milliseconds, label, onTimeout) {
|
|
15687
|
+
let timer;
|
|
15688
|
+
try {
|
|
15689
|
+
return await Promise.race([
|
|
15690
|
+
operation,
|
|
15691
|
+
new Promise((_, reject) => {
|
|
15692
|
+
timer = setTimeout(() => {
|
|
15693
|
+
const error51 = new CodeBuddyError("unavailable", `${label} timed out`);
|
|
15694
|
+
try {
|
|
15695
|
+
onTimeout?.(error51);
|
|
15696
|
+
} finally {
|
|
15697
|
+
reject(error51);
|
|
15698
|
+
}
|
|
15699
|
+
}, milliseconds);
|
|
15700
|
+
})
|
|
15701
|
+
]);
|
|
15702
|
+
} finally {
|
|
15703
|
+
clearTimeout(timer);
|
|
15704
|
+
}
|
|
15705
|
+
}
|
|
15706
|
+
|
|
15707
|
+
// dist/slash-commands.js
|
|
15708
|
+
var excluded = /* @__PURE__ */ new Set([
|
|
15709
|
+
"background",
|
|
15710
|
+
"bg",
|
|
15711
|
+
"branch",
|
|
15712
|
+
"fork",
|
|
15713
|
+
"fork-bg",
|
|
15714
|
+
"clear",
|
|
15715
|
+
"resume",
|
|
15716
|
+
"exit",
|
|
15717
|
+
"rewind",
|
|
15718
|
+
"multitask",
|
|
15719
|
+
"agent-mode",
|
|
15720
|
+
"btw",
|
|
15721
|
+
"loop",
|
|
15722
|
+
"goal",
|
|
15723
|
+
"login",
|
|
15724
|
+
"logout",
|
|
15725
|
+
"feedback",
|
|
15726
|
+
"keybindings",
|
|
15727
|
+
"copy",
|
|
15728
|
+
"statusline",
|
|
15729
|
+
"gateway",
|
|
15730
|
+
"remote-control",
|
|
15731
|
+
"_compact"
|
|
15732
|
+
]);
|
|
15733
|
+
function isExcludedInvocation(invocation) {
|
|
15734
|
+
return invocation?.startsWith("/") === true && excluded.has(invocation.slice(1));
|
|
15735
|
+
}
|
|
15736
|
+
function nativeCommandsEnabled(profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15737
|
+
return profile.nativeCommands ?? profile.harnessId === CODEBUDDY_RUNTIME_PROFILE.harnessId;
|
|
15738
|
+
}
|
|
15739
|
+
function commandCatalog(value, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15740
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15741
|
+
return {
|
|
15742
|
+
commands: rows(value).flatMap((entry) => {
|
|
15743
|
+
const name = text(entry.name).replace(/^\//u, "");
|
|
15744
|
+
if (excluded.has(name) || seen.has(name))
|
|
15745
|
+
return [];
|
|
15746
|
+
const parsed = harnessCommandCatalogSchema.safeParse({
|
|
15747
|
+
commands: [
|
|
15748
|
+
{
|
|
15749
|
+
id: `${profile.harnessId}.${name}`,
|
|
15750
|
+
invocation: `/${name}`,
|
|
15751
|
+
label: name,
|
|
15752
|
+
...text(entry.description).trim() ? { description: text(entry.description).trim().slice(0, 512) } : {},
|
|
15753
|
+
argumentMode: name === "compact" || record2(entry.input).hint || record2(entry._meta).type === "skill" ? "text" : "none"
|
|
15754
|
+
}
|
|
15755
|
+
]
|
|
15756
|
+
});
|
|
15757
|
+
if (!parsed.success)
|
|
15758
|
+
return [];
|
|
15759
|
+
seen.add(name);
|
|
15760
|
+
return parsed.data.commands;
|
|
15761
|
+
})
|
|
15762
|
+
};
|
|
15763
|
+
}
|
|
15764
|
+
var CODEBUDDY_COMMAND_CATALOG = commandCatalog([
|
|
15765
|
+
{
|
|
15766
|
+
name: "compact",
|
|
15767
|
+
description: "Summarize conversation context with optional focus instructions"
|
|
15768
|
+
},
|
|
15769
|
+
{ name: "cost", description: "Show current Session usage and cost" }
|
|
15770
|
+
]);
|
|
15771
|
+
function commandPrompt(command, catalog, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15772
|
+
const descriptor = catalog.commands.find((entry) => entry.id === command.commandId);
|
|
15773
|
+
if (!descriptor)
|
|
15774
|
+
return failure("unsupported", "Command is not available in this Session", profile);
|
|
15775
|
+
const args = command.arguments;
|
|
15776
|
+
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))
|
|
15777
|
+
return failure("invalidRequest", "Command arguments must match the native command", profile);
|
|
15778
|
+
const argument = typeof args?.text === "string" ? args.text.trim() : "";
|
|
15779
|
+
return { ok: true, value: `${descriptor.invocation}${argument ? ` ${argument}` : ""}` };
|
|
15780
|
+
}
|
|
15781
|
+
|
|
15782
|
+
// dist/codebuddy-adapter.js
|
|
15783
|
+
import { stat as stat2 } from "node:fs/promises";
|
|
15784
|
+
|
|
15785
|
+
// dist/acp-client.js
|
|
15786
|
+
import { execFile, spawn } from "node:child_process";
|
|
15787
|
+
import { Readable as Readable2, Writable } from "node:stream";
|
|
15788
|
+
|
|
15789
|
+
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
|
|
15790
|
+
var AGENT_METHODS = {
|
|
15791
|
+
initialize: "initialize",
|
|
15792
|
+
authenticate: "authenticate",
|
|
15793
|
+
providers_list: "providers/list",
|
|
15794
|
+
providers_set: "providers/set",
|
|
15795
|
+
providers_disable: "providers/disable",
|
|
15796
|
+
session_new: "session/new",
|
|
15797
|
+
session_load: "session/load",
|
|
15798
|
+
session_set_mode: "session/set_mode",
|
|
15799
|
+
session_set_config_option: "session/set_config_option",
|
|
15800
|
+
session_prompt: "session/prompt",
|
|
15801
|
+
session_cancel: "session/cancel",
|
|
15802
|
+
mcp_message: "mcp/message",
|
|
15803
|
+
session_list: "session/list",
|
|
15804
|
+
session_delete: "session/delete",
|
|
15805
|
+
session_fork: "session/fork",
|
|
15806
|
+
session_resume: "session/resume",
|
|
15807
|
+
session_close: "session/close",
|
|
15808
|
+
logout: "logout",
|
|
15809
|
+
nes_start: "nes/start",
|
|
15810
|
+
nes_suggest: "nes/suggest",
|
|
15811
|
+
nes_accept: "nes/accept",
|
|
15812
|
+
nes_reject: "nes/reject",
|
|
15813
|
+
nes_close: "nes/close",
|
|
15814
|
+
document_did_open: "document/didOpen",
|
|
15815
|
+
document_did_change: "document/didChange",
|
|
15816
|
+
document_did_close: "document/didClose",
|
|
15817
|
+
document_did_save: "document/didSave",
|
|
15818
|
+
document_did_focus: "document/didFocus"
|
|
15819
|
+
};
|
|
15820
|
+
var CLIENT_METHODS = {
|
|
15821
|
+
session_request_permission: "session/request_permission",
|
|
15822
|
+
session_update: "session/update",
|
|
15823
|
+
fs_write_text_file: "fs/write_text_file",
|
|
15824
|
+
fs_read_text_file: "fs/read_text_file",
|
|
15825
|
+
terminal_create: "terminal/create",
|
|
15826
|
+
terminal_output: "terminal/output",
|
|
15827
|
+
terminal_release: "terminal/release",
|
|
15828
|
+
terminal_wait_for_exit: "terminal/wait_for_exit",
|
|
15829
|
+
terminal_kill: "terminal/kill",
|
|
15830
|
+
mcp_connect: "mcp/connect",
|
|
15831
|
+
mcp_message: "mcp/message",
|
|
15832
|
+
mcp_disconnect: "mcp/disconnect",
|
|
15833
|
+
elicitation_create: "elicitation/create",
|
|
15834
|
+
elicitation_complete: "elicitation/complete"
|
|
15835
|
+
};
|
|
15836
|
+
var PROTOCOL_METHODS = {
|
|
15837
|
+
cancel_request: "$/cancel_request"
|
|
15838
|
+
};
|
|
15839
|
+
|
|
15840
|
+
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema-deserialize.js
|
|
15841
|
+
var skippedItem = /* @__PURE__ */ Symbol("skippedItem");
|
|
15842
|
+
function defaultOnError(schema, fallback) {
|
|
15843
|
+
return schema.catch(fallback);
|
|
15844
|
+
}
|
|
15845
|
+
function requiredDefaultOnError(schema, fallback) {
|
|
15846
|
+
const schemaWithCatch = schema.catch(fallback);
|
|
15847
|
+
return external_exports.unknown().transform((value, context) => {
|
|
15848
|
+
if (value !== void 0)
|
|
15849
|
+
return schemaWithCatch.parse(value);
|
|
15850
|
+
context.addIssue({
|
|
15851
|
+
code: "custom",
|
|
15852
|
+
message: "Required value is missing"
|
|
15853
|
+
});
|
|
15854
|
+
return external_exports.NEVER;
|
|
15855
|
+
});
|
|
15856
|
+
}
|
|
15857
|
+
function stringTag(value, key) {
|
|
15858
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
15859
|
+
return void 0;
|
|
15860
|
+
}
|
|
15861
|
+
const tag = value[key];
|
|
15862
|
+
return typeof tag === "string" ? tag : void 0;
|
|
15863
|
+
}
|
|
15864
|
+
function excludeKnownTags(schema, key, knownTags) {
|
|
15865
|
+
return schema.superRefine((value, context) => {
|
|
15866
|
+
const tag = stringTag(value, key);
|
|
15867
|
+
if (tag !== void 0 && knownTags.includes(tag)) {
|
|
15868
|
+
context.addIssue({
|
|
15869
|
+
code: "custom",
|
|
15870
|
+
path: [key],
|
|
15871
|
+
message: `${key} ${JSON.stringify(tag)} is reserved by a known variant, but the value does not match that variant's schema`
|
|
15872
|
+
});
|
|
15873
|
+
}
|
|
15874
|
+
});
|
|
15875
|
+
}
|
|
15876
|
+
function preserveCustomPayload(schema, key, knownTags) {
|
|
15877
|
+
return external_exports.unknown().transform((value, context) => {
|
|
15878
|
+
const result = schema.safeParse(value);
|
|
15879
|
+
if (!result.success) {
|
|
15880
|
+
for (const issue2 of result.error.issues) {
|
|
15881
|
+
context.addIssue({ ...issue2, input: value });
|
|
15882
|
+
}
|
|
15883
|
+
return external_exports.NEVER;
|
|
15884
|
+
}
|
|
15885
|
+
const output = result.data;
|
|
15886
|
+
const tag = stringTag(value, key);
|
|
15887
|
+
if (tag !== void 0 && !knownTags.includes(tag)) {
|
|
15888
|
+
const raw = value;
|
|
15889
|
+
for (const [property, rawValue] of Object.entries(raw)) {
|
|
15890
|
+
if (property === "__proto__")
|
|
15891
|
+
continue;
|
|
15892
|
+
if (!Object.hasOwn(output, property))
|
|
15893
|
+
output[property] = rawValue;
|
|
15894
|
+
}
|
|
15895
|
+
}
|
|
15896
|
+
return output;
|
|
15897
|
+
});
|
|
15898
|
+
}
|
|
15899
|
+
function vecSkipError(itemSchema) {
|
|
15900
|
+
return external_exports.array(itemSchema.catch(skippedItem)).transform((items) => items.filter((item) => item !== skippedItem));
|
|
15901
|
+
}
|
|
15902
|
+
|
|
15903
|
+
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema/zod.gen.js
|
|
15904
|
+
var zRequestId = union([number2(), string2()]).nullable();
|
|
15905
|
+
var zSessionId = string2();
|
|
15906
|
+
var zWriteTextFileRequest = object({
|
|
15907
|
+
sessionId: zSessionId,
|
|
15908
|
+
path: string2(),
|
|
15909
|
+
content: string2(),
|
|
15910
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15911
|
+
});
|
|
15912
|
+
var zReadTextFileRequest = object({
|
|
15913
|
+
sessionId: zSessionId,
|
|
15914
|
+
path: string2(),
|
|
15915
|
+
line: defaultOnError(int().gte(0).max(4294967295, {
|
|
15916
|
+
error: "Invalid value: Expected uint32 to be <= 4294967295"
|
|
15917
|
+
}).nullish(), () => void 0),
|
|
15918
|
+
limit: defaultOnError(int().gte(0).max(4294967295, {
|
|
15919
|
+
error: "Invalid value: Expected uint32 to be <= 4294967295"
|
|
15920
|
+
}).nullish(), () => void 0),
|
|
15921
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15922
|
+
});
|
|
15923
|
+
var zToolCallId = string2();
|
|
15924
|
+
var zToolKind = union([
|
|
15925
|
+
literal("read"),
|
|
15926
|
+
literal("edit"),
|
|
15927
|
+
literal("delete"),
|
|
15928
|
+
literal("move"),
|
|
15929
|
+
literal("search"),
|
|
15930
|
+
literal("execute"),
|
|
15931
|
+
literal("think"),
|
|
15932
|
+
literal("fetch"),
|
|
15933
|
+
literal("switch_mode"),
|
|
15934
|
+
literal("other")
|
|
15935
|
+
]);
|
|
15936
|
+
var zToolCallStatus = union([
|
|
15937
|
+
literal("pending"),
|
|
15938
|
+
literal("in_progress"),
|
|
15939
|
+
literal("completed"),
|
|
15940
|
+
literal("failed")
|
|
15941
|
+
]);
|
|
15942
|
+
var zRole = union([literal("assistant"), literal("user")]);
|
|
15943
|
+
var zAnnotations = object({
|
|
15944
|
+
audience: defaultOnError(vecSkipError(zRole).nullish(), () => void 0),
|
|
15945
|
+
lastModified: defaultOnError(string2().nullish(), () => void 0),
|
|
15946
|
+
priority: defaultOnError(number2().nullish(), () => void 0),
|
|
15947
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15948
|
+
});
|
|
15949
|
+
var zTextContent = object({
|
|
15950
|
+
annotations: defaultOnError(zAnnotations.nullish(), () => void 0),
|
|
15951
|
+
text: string2(),
|
|
15952
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15953
|
+
});
|
|
15954
|
+
var zImageContent = object({
|
|
15955
|
+
annotations: defaultOnError(zAnnotations.nullish(), () => void 0),
|
|
15956
|
+
data: string2(),
|
|
15957
|
+
mimeType: string2(),
|
|
15958
|
+
uri: defaultOnError(string2().nullish(), () => void 0),
|
|
15959
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15960
|
+
});
|
|
15961
|
+
var zAudioContent = object({
|
|
15962
|
+
annotations: defaultOnError(zAnnotations.nullish(), () => void 0),
|
|
15963
|
+
data: string2(),
|
|
15964
|
+
mimeType: string2(),
|
|
15965
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15966
|
+
});
|
|
15967
|
+
var zResourceLink = object({
|
|
15968
|
+
annotations: defaultOnError(zAnnotations.nullish(), () => void 0),
|
|
15969
|
+
description: defaultOnError(string2().nullish(), () => void 0),
|
|
15970
|
+
mimeType: defaultOnError(string2().nullish(), () => void 0),
|
|
15971
|
+
name: string2(),
|
|
15972
|
+
size: defaultOnError(number2().nullish(), () => void 0),
|
|
15973
|
+
title: defaultOnError(string2().nullish(), () => void 0),
|
|
15974
|
+
uri: string2(),
|
|
15975
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15976
|
+
});
|
|
15977
|
+
var zTextResourceContents = object({
|
|
15978
|
+
mimeType: defaultOnError(string2().nullish(), () => void 0),
|
|
15979
|
+
text: string2(),
|
|
15980
|
+
uri: string2(),
|
|
15981
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15574
15982
|
});
|
|
15575
15983
|
var zBlobResourceContents = object({
|
|
15576
15984
|
blob: string2(),
|
|
@@ -17112,17 +17520,17 @@ function isResponseMessage(value) {
|
|
|
17112
17520
|
function isNotificationMessage(value) {
|
|
17113
17521
|
return isJsonRpcEnvelope(value) && !("id" in value) && typeof value["method"] === "string";
|
|
17114
17522
|
}
|
|
17115
|
-
function
|
|
17523
|
+
function isRecord2(value) {
|
|
17116
17524
|
return typeof value === "object" && value !== null;
|
|
17117
17525
|
}
|
|
17118
17526
|
function isJsonRpcEnvelope(value) {
|
|
17119
|
-
return
|
|
17527
|
+
return isRecord2(value) && value["jsonrpc"] === "2.0";
|
|
17120
17528
|
}
|
|
17121
17529
|
function isJsonRpcId(value) {
|
|
17122
17530
|
return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
17123
17531
|
}
|
|
17124
17532
|
function isResponseShapedMessage(value) {
|
|
17125
|
-
return
|
|
17533
|
+
return isRecord2(value) && !("method" in value) && ("id" in value || "result" in value || "error" in value);
|
|
17126
17534
|
}
|
|
17127
17535
|
function isResponseBatch(batch) {
|
|
17128
17536
|
let hasValidCall = false;
|
|
@@ -17132,7 +17540,7 @@ function isResponseBatch(batch) {
|
|
|
17132
17540
|
for (const entry of batch) {
|
|
17133
17541
|
hasValidCall ||= isRequestMessage(entry) || isNotificationMessage(entry);
|
|
17134
17542
|
hasValidResponse ||= isResponseMessage(entry);
|
|
17135
|
-
if (!
|
|
17543
|
+
if (!isRecord2(entry)) {
|
|
17136
17544
|
continue;
|
|
17137
17545
|
}
|
|
17138
17546
|
hasCallShape ||= "method" in entry;
|
|
@@ -17147,13 +17555,13 @@ function isResponseBatch(batch) {
|
|
|
17147
17555
|
return hasResponseShape && !hasCallShape;
|
|
17148
17556
|
}
|
|
17149
17557
|
function cancelRequestId(params) {
|
|
17150
|
-
if (!
|
|
17558
|
+
if (!isRecord2(params) || !isJsonRpcId(params["requestId"])) {
|
|
17151
17559
|
return void 0;
|
|
17152
17560
|
}
|
|
17153
17561
|
return params["requestId"];
|
|
17154
17562
|
}
|
|
17155
17563
|
function isErrorResponse(value) {
|
|
17156
|
-
return
|
|
17564
|
+
return isRecord2(value) && typeof value["code"] === "number" && Number.isInteger(value["code"]) && typeof value["message"] === "string";
|
|
17157
17565
|
}
|
|
17158
17566
|
var Handled = {
|
|
17159
17567
|
/**
|
|
@@ -17644,7 +18052,7 @@ var Connection = class {
|
|
|
17644
18052
|
this.receiveBatch(message);
|
|
17645
18053
|
return;
|
|
17646
18054
|
}
|
|
17647
|
-
if (!
|
|
18055
|
+
if (!isRecord2(message)) {
|
|
17648
18056
|
console.error("Invalid message", { message });
|
|
17649
18057
|
return;
|
|
17650
18058
|
}
|
|
@@ -17707,7 +18115,7 @@ var Connection = class {
|
|
|
17707
18115
|
if (this.abortController.signal.aborted) {
|
|
17708
18116
|
return Promise.resolve();
|
|
17709
18117
|
}
|
|
17710
|
-
if (!
|
|
18118
|
+
if (!isRecord2(message)) {
|
|
17711
18119
|
console.error("Invalid message", { message });
|
|
17712
18120
|
return Promise.resolve();
|
|
17713
18121
|
}
|
|
@@ -18077,7 +18485,7 @@ function ndJsonStream(output, input) {
|
|
|
18077
18485
|
if (trimmedLine) {
|
|
18078
18486
|
try {
|
|
18079
18487
|
const message = JSON.parse(trimmedLine);
|
|
18080
|
-
if (
|
|
18488
|
+
if (isRecord2(message) || Array.isArray(message)) {
|
|
18081
18489
|
controller.enqueue(message);
|
|
18082
18490
|
} else {
|
|
18083
18491
|
console.warn("Skipping JSON line that is not an object:", trimmedLine);
|
|
@@ -19538,6 +19946,69 @@ var ClientSideConnection = class {
|
|
|
19538
19946
|
}
|
|
19539
19947
|
};
|
|
19540
19948
|
|
|
19949
|
+
// dist/copy-cleanup.js
|
|
19950
|
+
import { randomBytes } from "node:crypto";
|
|
19951
|
+
import { createInterface } from "node:readline";
|
|
19952
|
+
import { stripVTControlCharacters } from "node:util";
|
|
19953
|
+
import { Readable } from "node:stream";
|
|
19954
|
+
var CodeBuddyCopyCleanup = class {
|
|
19955
|
+
copyId;
|
|
19956
|
+
cwd;
|
|
19957
|
+
password = randomBytes(32).toString("base64url");
|
|
19958
|
+
arguments = [
|
|
19959
|
+
"--acp",
|
|
19960
|
+
"--serve",
|
|
19961
|
+
"--host",
|
|
19962
|
+
"127.0.0.1",
|
|
19963
|
+
"--port",
|
|
19964
|
+
"0",
|
|
19965
|
+
"--auth",
|
|
19966
|
+
"password"
|
|
19967
|
+
];
|
|
19968
|
+
#endpoint;
|
|
19969
|
+
constructor(copyId, cwd) {
|
|
19970
|
+
this.copyId = copyId;
|
|
19971
|
+
this.cwd = cwd;
|
|
19972
|
+
}
|
|
19973
|
+
environment(environment) {
|
|
19974
|
+
return {
|
|
19975
|
+
...environment,
|
|
19976
|
+
CODEBUDDY_GATEWAY_AUTH: "password",
|
|
19977
|
+
CODEBUDDY_GATEWAY_PASSWORD: this.password,
|
|
19978
|
+
CODEBUDDY_GATEWAY_BASE_PATH: ""
|
|
19979
|
+
};
|
|
19980
|
+
}
|
|
19981
|
+
/** Native --serve banners include its password; never pass them to the ACP parser/logs. */
|
|
19982
|
+
protocolOutput(stdout) {
|
|
19983
|
+
return Readable.from(this.#protocolLines(stdout));
|
|
19984
|
+
}
|
|
19985
|
+
async *#protocolLines(stdout) {
|
|
19986
|
+
for await (const line of createInterface({ input: stdout })) {
|
|
19987
|
+
const endpoint = /^\s*Endpoint\s+(http:\/\/127\.0\.0\.1:\d+)\s*$/u.exec(stripVTControlCharacters(line));
|
|
19988
|
+
if (endpoint)
|
|
19989
|
+
this.#endpoint = endpoint[1];
|
|
19990
|
+
if (line.trimStart().startsWith("{"))
|
|
19991
|
+
yield Buffer.from(`${line}
|
|
19992
|
+
`);
|
|
19993
|
+
}
|
|
19994
|
+
}
|
|
19995
|
+
async remove() {
|
|
19996
|
+
if (!this.#endpoint)
|
|
19997
|
+
throw new CodeBuddyError("nativeFailure", `Native cleanup endpoint was not reported; temporary Session ${this.copyId} remains`);
|
|
19998
|
+
const response = await fetch(`${this.#endpoint}/api/v1/sessions/${encodeURIComponent(this.copyId)}?cwd=${encodeURIComponent(this.cwd)}`, {
|
|
19999
|
+
method: "DELETE",
|
|
20000
|
+
headers: { Authorization: `Bearer ${this.password}`, "x-codebuddy-request": "true" },
|
|
20001
|
+
signal: AbortSignal.timeout(5e3),
|
|
20002
|
+
redirect: "error"
|
|
20003
|
+
}).catch(() => {
|
|
20004
|
+
throw new CodeBuddyError("nativeFailure", `Native cleanup request failed; temporary Session ${this.copyId} remains`);
|
|
20005
|
+
});
|
|
20006
|
+
await response.body?.cancel();
|
|
20007
|
+
if (response.status !== 204)
|
|
20008
|
+
throw new CodeBuddyError("nativeFailure", `Native cleanup failed (${response.status}); temporary Session ${this.copyId} remains`);
|
|
20009
|
+
}
|
|
20010
|
+
};
|
|
20011
|
+
|
|
19541
20012
|
// ../../harness-discovery/dist/environment.js
|
|
19542
20013
|
import fs from "node:fs";
|
|
19543
20014
|
import path from "node:path";
|
|
@@ -19609,7 +20080,7 @@ function withNodeRuntimeOnPath(environment, runtimeExecutable = process.execPath
|
|
|
19609
20080
|
const directories = (environment[pathKey] ?? "").split(delimiter).filter(Boolean);
|
|
19610
20081
|
const equal = platform === "win32" ? (value) => value.toLowerCase() : (value) => value;
|
|
19611
20082
|
if (!directories.some((directory) => equal(directory) === equal(runtimeDirectory))) {
|
|
19612
|
-
directories.
|
|
20083
|
+
directories.push(runtimeDirectory);
|
|
19613
20084
|
}
|
|
19614
20085
|
return { ...environment, [pathKey]: directories.join(delimiter) };
|
|
19615
20086
|
}
|
|
@@ -19672,365 +20143,109 @@ function versionManagerBinaryDirectories(context) {
|
|
|
19672
20143
|
directories.push(pathFlavor.join(prefix, formula, "bin"));
|
|
19673
20144
|
}
|
|
19674
20145
|
}
|
|
19675
|
-
return directories;
|
|
19676
|
-
}
|
|
19677
|
-
|
|
19678
|
-
// ../../harness-discovery/dist/resolve.js
|
|
19679
|
-
var VERSION_MANAGER_ROOTS = "<version-managers>";
|
|
19680
|
-
function installRootExtensions(platform) {
|
|
19681
|
-
return platform === "win32" ? [".exe", ".cmd"] : [""];
|
|
19682
|
-
}
|
|
19683
|
-
function resolveHomeDirectory(input) {
|
|
19684
|
-
return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
|
|
19685
|
-
}
|
|
19686
|
-
function templateVariables(environment, platform, home) {
|
|
19687
|
-
const pathFlavor = targetPath(platform);
|
|
19688
|
-
return {
|
|
19689
|
-
HOME: home,
|
|
19690
|
-
USERPROFILE: home,
|
|
19691
|
-
APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
|
|
19692
|
-
LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
|
|
19693
|
-
};
|
|
19694
|
-
}
|
|
19695
|
-
function joinTemplate(platform, value) {
|
|
19696
|
-
const pathFlavor = targetPath(platform);
|
|
19697
|
-
const segments = value.split("/");
|
|
19698
|
-
const head = segments[0] ?? "";
|
|
19699
|
-
const tail = segments.slice(1);
|
|
19700
|
-
if (head === "")
|
|
19701
|
-
return pathFlavor.join(pathFlavor.sep, ...tail);
|
|
19702
|
-
return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
|
|
19703
|
-
}
|
|
19704
|
-
function expandInstallRoot(template, environment, platform, home) {
|
|
19705
|
-
const variables = templateVariables(environment, platform, home);
|
|
19706
|
-
let unresolved = false;
|
|
19707
|
-
const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
|
|
19708
|
-
const value = variables[name] ?? environmentValue(environment, name);
|
|
19709
|
-
if (value === void 0 || value === "") {
|
|
19710
|
-
unresolved = true;
|
|
19711
|
-
return "";
|
|
19712
|
-
}
|
|
19713
|
-
return value;
|
|
19714
|
-
});
|
|
19715
|
-
return unresolved ? void 0 : joinTemplate(platform, substituted);
|
|
19716
|
-
}
|
|
19717
|
-
function installRootDirectories(spec, input, dependencies, platform, home) {
|
|
19718
|
-
const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
|
|
19719
|
-
const directories = [];
|
|
19720
|
-
for (const template of templates) {
|
|
19721
|
-
if (template === VERSION_MANAGER_ROOTS) {
|
|
19722
|
-
directories.push(...versionManagerBinaryDirectories({
|
|
19723
|
-
platform,
|
|
19724
|
-
environment: input.environment,
|
|
19725
|
-
home,
|
|
19726
|
-
...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
|
|
19727
|
-
}));
|
|
19728
|
-
continue;
|
|
19729
|
-
}
|
|
19730
|
-
const directory = expandInstallRoot(template, input.environment, platform, home);
|
|
19731
|
-
if (directory !== void 0)
|
|
19732
|
-
directories.push(directory);
|
|
19733
|
-
}
|
|
19734
|
-
return directories;
|
|
19735
|
-
}
|
|
19736
|
-
function harnessCandidates(spec, input, dependencies = {}) {
|
|
19737
|
-
const platform = input.platform ?? process.platform;
|
|
19738
|
-
const pathFlavor = targetPath(platform);
|
|
19739
|
-
const configured = input.command ?? (spec.commandEnvironmentVariable ? environmentValue(input.environment, spec.commandEnvironmentVariable) : void 0);
|
|
19740
|
-
const command = configured ?? spec.command;
|
|
19741
|
-
if (pathFlavor.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
|
|
19742
|
-
return [{ candidate: command, source: "configured" }];
|
|
19743
|
-
}
|
|
19744
|
-
const candidates = [];
|
|
19745
|
-
const extensions = executableExtensions(command, platform, input.environment);
|
|
19746
|
-
for (const directory of pathDirectories(input.environment, platform)) {
|
|
19747
|
-
for (const extension of extensions) {
|
|
19748
|
-
candidates.push({
|
|
19749
|
-
candidate: pathFlavor.join(directory, command + extension),
|
|
19750
|
-
source: "path"
|
|
19751
|
-
});
|
|
19752
|
-
}
|
|
19753
|
-
}
|
|
19754
|
-
if (configured !== void 0)
|
|
19755
|
-
return candidates;
|
|
19756
|
-
const home = resolveHomeDirectory(input);
|
|
19757
|
-
for (const directory of installRootDirectories(spec, input, dependencies, platform, home)) {
|
|
19758
|
-
for (const extension of installRootExtensions(platform)) {
|
|
19759
|
-
candidates.push({
|
|
19760
|
-
candidate: pathFlavor.join(directory, spec.command + extension),
|
|
19761
|
-
source: "install-root"
|
|
19762
|
-
});
|
|
19763
|
-
}
|
|
19764
|
-
}
|
|
19765
|
-
return candidates;
|
|
19766
|
-
}
|
|
19767
|
-
function resolveHarnessExecutable(spec, input, dependencies = {}) {
|
|
19768
|
-
const platform = input.platform ?? process.platform;
|
|
19769
|
-
const isExecutable = dependencies.isExecutable ?? ((candidate) => isExecutableFile(candidate, platform));
|
|
19770
|
-
const runnable = spec.runnableCandidate ?? ((candidate) => candidate);
|
|
19771
|
-
const context = { platform, isExecutable };
|
|
19772
|
-
for (const { candidate, source } of harnessCandidates(spec, input, dependencies)) {
|
|
19773
|
-
const executable = runnable(candidate, context);
|
|
19774
|
-
if (executable !== void 0 && isExecutable(executable))
|
|
19775
|
-
return { executable, source };
|
|
19776
|
-
}
|
|
19777
|
-
return void 0;
|
|
19778
|
-
}
|
|
19779
|
-
|
|
19780
|
-
// ../../harness-adapter/dist/approval.js
|
|
19781
|
-
function invalidRequest(message) {
|
|
19782
|
-
return { code: "invalidRequest", message, retryable: false };
|
|
19783
|
-
}
|
|
19784
|
-
function validateHostApprovalResponse(interaction, response) {
|
|
19785
|
-
return interaction.actions.some(({ id }) => id === response.actionId) ? null : invalidRequest("Approval Response contains an undeclared action ID");
|
|
19786
|
-
}
|
|
19787
|
-
|
|
19788
|
-
// ../../harness-adapter/dist/question.js
|
|
19789
|
-
function invalidRequest2(message) {
|
|
19790
|
-
return { code: "invalidRequest", message, retryable: false };
|
|
19791
|
-
}
|
|
19792
|
-
function validateHostQuestionResponse(interaction, response) {
|
|
19793
|
-
const questionIds = new Set(interaction.questions.map(({ id }) => id));
|
|
19794
|
-
if (response.cancelled) {
|
|
19795
|
-
return Object.keys(response.answers).length === 0 ? null : invalidRequest2("Cancelled Question Response must not contain answers");
|
|
19796
|
-
}
|
|
19797
|
-
for (const answerId of Object.keys(response.answers)) {
|
|
19798
|
-
if (!questionIds.has(answerId)) {
|
|
19799
|
-
return invalidRequest2("Question Response contains an unknown Question ID");
|
|
19800
|
-
}
|
|
19801
|
-
}
|
|
19802
|
-
for (const question of interaction.questions) {
|
|
19803
|
-
const answers = response.answers[question.id] ?? [];
|
|
19804
|
-
if (!question.optional && answers.length === 0) {
|
|
19805
|
-
return invalidRequest2("Question Response omits a required answer");
|
|
19806
|
-
}
|
|
19807
|
-
if (question.type === "text") {
|
|
19808
|
-
if (answers.length > 1) {
|
|
19809
|
-
return invalidRequest2("Text Question accepts at most one answer");
|
|
19810
|
-
}
|
|
19811
|
-
continue;
|
|
19812
|
-
}
|
|
19813
|
-
if (!question.multiple && answers.length > 1) {
|
|
19814
|
-
return invalidRequest2("Single-choice Question accepts at most one answer");
|
|
19815
|
-
}
|
|
19816
|
-
const declared = new Set(question.options.map(({ value }) => value));
|
|
19817
|
-
if (!question.allowOther && answers.some((answer) => !declared.has(answer))) {
|
|
19818
|
-
return invalidRequest2("Question Response contains an undeclared choice");
|
|
19819
|
-
}
|
|
19820
|
-
}
|
|
19821
|
-
return null;
|
|
19822
|
-
}
|
|
19823
|
-
|
|
19824
|
-
// ../../harness-adapter/dist/interaction.js
|
|
19825
|
-
function invalidRequest3(message) {
|
|
19826
|
-
return { code: "invalidRequest", message, retryable: false };
|
|
19827
|
-
}
|
|
19828
|
-
function invalidState(message) {
|
|
19829
|
-
return { code: "invalidState", message, retryable: false };
|
|
19830
|
-
}
|
|
19831
|
-
function validateHostInteractionResponse(interaction, response) {
|
|
19832
|
-
if (!interaction) {
|
|
19833
|
-
return invalidState("Interaction Response must reference a pending Interaction");
|
|
19834
|
-
}
|
|
19835
|
-
if (interaction.type === "question") {
|
|
19836
|
-
return response.type === "question" ? validateHostQuestionResponse(interaction, response) : invalidRequest3("Interaction Response type does not match the pending Interaction");
|
|
19837
|
-
}
|
|
19838
|
-
return response.type === "approval" ? validateHostApprovalResponse(interaction, response) : invalidRequest3("Interaction Response type does not match the pending Interaction");
|
|
19839
|
-
}
|
|
19840
|
-
|
|
19841
|
-
// ../../harness-adapter/dist/output-channel.js
|
|
19842
|
-
var HarnessOutputChannel = class {
|
|
19843
|
-
outputs;
|
|
19844
|
-
#consumerCreated = false;
|
|
19845
|
-
#ended = false;
|
|
19846
|
-
#pending = [];
|
|
19847
|
-
#values = [];
|
|
19848
|
-
constructor() {
|
|
19849
|
-
this.outputs = {
|
|
19850
|
-
[Symbol.asyncIterator]: () => {
|
|
19851
|
-
if (this.#consumerCreated) {
|
|
19852
|
-
throw new Error("Harness outputs allow only one consumer");
|
|
19853
|
-
}
|
|
19854
|
-
this.#consumerCreated = true;
|
|
19855
|
-
return {
|
|
19856
|
-
next: () => this.#next()
|
|
19857
|
-
};
|
|
19858
|
-
}
|
|
19859
|
-
};
|
|
19860
|
-
}
|
|
19861
|
-
emit(value) {
|
|
19862
|
-
if (this.#ended)
|
|
19863
|
-
return false;
|
|
19864
|
-
const resolve = this.#pending.shift();
|
|
19865
|
-
if (resolve)
|
|
19866
|
-
resolve({ done: false, value });
|
|
19867
|
-
else
|
|
19868
|
-
this.#values.push(value);
|
|
19869
|
-
return true;
|
|
19870
|
-
}
|
|
19871
|
-
end() {
|
|
19872
|
-
if (this.#ended)
|
|
19873
|
-
return;
|
|
19874
|
-
this.#ended = true;
|
|
19875
|
-
if (this.#values.length !== 0)
|
|
19876
|
-
return;
|
|
19877
|
-
for (const resolve of this.#pending.splice(0))
|
|
19878
|
-
resolve({ done: true, value: void 0 });
|
|
19879
|
-
}
|
|
19880
|
-
#next() {
|
|
19881
|
-
const value = this.#values.shift();
|
|
19882
|
-
if (value !== void 0)
|
|
19883
|
-
return Promise.resolve({ done: false, value });
|
|
19884
|
-
if (this.#ended)
|
|
19885
|
-
return Promise.resolve({ done: true, value: void 0 });
|
|
19886
|
-
return new Promise((resolve) => this.#pending.push(resolve));
|
|
19887
|
-
}
|
|
19888
|
-
};
|
|
19889
|
-
|
|
19890
|
-
// ../../harness-adapter/dist/diagnostics.js
|
|
19891
|
-
var DIAGNOSTIC_TAIL_MAX_LENGTH = 8e3;
|
|
19892
|
-
var SENSITIVE_VALUE_PATTERN = /(api[_-]?key|access[_-]?token|auth(?:orization)?|password|secret)(\s*[:=]\s*)([^\s,;]+)/giu;
|
|
19893
|
-
var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/giu;
|
|
19894
|
-
function sanitizeDiagnosticTail(value) {
|
|
19895
|
-
const redacted = value.replace(BEARER_PATTERN, "Bearer [redacted]").replace(SENSITIVE_VALUE_PATTERN, "$1$2[redacted]");
|
|
19896
|
-
return redacted.length <= DIAGNOSTIC_TAIL_MAX_LENGTH ? redacted : redacted.slice(-DIAGNOSTIC_TAIL_MAX_LENGTH);
|
|
20146
|
+
return directories;
|
|
19897
20147
|
}
|
|
19898
20148
|
|
|
19899
|
-
// ../../harness-
|
|
19900
|
-
var
|
|
19901
|
-
|
|
19902
|
-
"
|
|
19903
|
-
"cacheWriteInputTokens",
|
|
19904
|
-
"outputTokens",
|
|
19905
|
-
"outputTokensPerSecond",
|
|
19906
|
-
"reasoningOutputTokens",
|
|
19907
|
-
"totalTokens",
|
|
19908
|
-
"contextWindowTokens",
|
|
19909
|
-
"contextUsedTokens"
|
|
19910
|
-
];
|
|
19911
|
-
var safeIntegerFields = [
|
|
19912
|
-
"planFiveHourResetsAtUnix",
|
|
19913
|
-
"planSevenDayResetsAtUnix"
|
|
19914
|
-
];
|
|
19915
|
-
var percentFields = [
|
|
19916
|
-
"cacheHitRatePercent",
|
|
19917
|
-
"planFiveHourUsedPercent",
|
|
19918
|
-
"planSevenDayUsedPercent"
|
|
19919
|
-
];
|
|
19920
|
-
var usageFields = /* @__PURE__ */ new Set([
|
|
19921
|
-
...tokenFields,
|
|
19922
|
-
...safeIntegerFields,
|
|
19923
|
-
...percentFields,
|
|
19924
|
-
"totalCostUsd",
|
|
19925
|
-
"totalCredits",
|
|
19926
|
-
"contextUsagePercent"
|
|
19927
|
-
]);
|
|
19928
|
-
function isRecord2(value) {
|
|
19929
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20149
|
+
// ../../harness-discovery/dist/resolve.js
|
|
20150
|
+
var VERSION_MANAGER_ROOTS = "<version-managers>";
|
|
20151
|
+
function installRootExtensions(platform) {
|
|
20152
|
+
return platform === "win32" ? [".exe", ".cmd"] : [""];
|
|
19930
20153
|
}
|
|
19931
|
-
function
|
|
19932
|
-
|
|
19933
|
-
|
|
19934
|
-
|
|
19935
|
-
|
|
19936
|
-
|
|
19937
|
-
|
|
19938
|
-
|
|
19939
|
-
|
|
20154
|
+
function resolveHomeDirectory(input) {
|
|
20155
|
+
return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
|
|
20156
|
+
}
|
|
20157
|
+
function templateVariables(environment, platform, home) {
|
|
20158
|
+
const pathFlavor = targetPath(platform);
|
|
20159
|
+
return {
|
|
20160
|
+
HOME: home,
|
|
20161
|
+
USERPROFILE: home,
|
|
20162
|
+
APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
|
|
20163
|
+
LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
|
|
20164
|
+
};
|
|
20165
|
+
}
|
|
20166
|
+
function joinTemplate(platform, value) {
|
|
20167
|
+
const pathFlavor = targetPath(platform);
|
|
20168
|
+
const segments = value.split("/");
|
|
20169
|
+
const head = segments[0] ?? "";
|
|
20170
|
+
const tail = segments.slice(1);
|
|
20171
|
+
if (head === "")
|
|
20172
|
+
return pathFlavor.join(pathFlavor.sep, ...tail);
|
|
20173
|
+
return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
|
|
20174
|
+
}
|
|
20175
|
+
function expandInstallRoot(template, environment, platform, home) {
|
|
20176
|
+
const variables = templateVariables(environment, platform, home);
|
|
20177
|
+
let unresolved = false;
|
|
20178
|
+
const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
|
|
20179
|
+
const value = variables[name] ?? environmentValue(environment, name);
|
|
20180
|
+
if (value === void 0 || value === "") {
|
|
20181
|
+
unresolved = true;
|
|
20182
|
+
return "";
|
|
19940
20183
|
}
|
|
19941
|
-
|
|
19942
|
-
|
|
19943
|
-
|
|
19944
|
-
|
|
19945
|
-
|
|
20184
|
+
return value;
|
|
20185
|
+
});
|
|
20186
|
+
return unresolved ? void 0 : joinTemplate(platform, substituted);
|
|
20187
|
+
}
|
|
20188
|
+
function installRootDirectories(spec, input, dependencies, platform, home) {
|
|
20189
|
+
const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
|
|
20190
|
+
const directories = [];
|
|
20191
|
+
for (const template of templates) {
|
|
20192
|
+
if (template === VERSION_MANAGER_ROOTS) {
|
|
20193
|
+
directories.push(...versionManagerBinaryDirectories({
|
|
20194
|
+
platform,
|
|
20195
|
+
environment: input.environment,
|
|
20196
|
+
home,
|
|
20197
|
+
...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
|
|
20198
|
+
}));
|
|
20199
|
+
continue;
|
|
19946
20200
|
}
|
|
20201
|
+
const directory = expandInstallRoot(template, input.environment, platform, home);
|
|
20202
|
+
if (directory !== void 0)
|
|
20203
|
+
directories.push(directory);
|
|
19947
20204
|
}
|
|
19948
|
-
|
|
19949
|
-
|
|
19950
|
-
|
|
19951
|
-
|
|
19952
|
-
|
|
20205
|
+
return directories;
|
|
20206
|
+
}
|
|
20207
|
+
function harnessCandidates(spec, input, dependencies = {}) {
|
|
20208
|
+
const platform = input.platform ?? process.platform;
|
|
20209
|
+
const pathFlavor = targetPath(platform);
|
|
20210
|
+
const configured = input.command ?? (spec.commandEnvironmentVariable ? environmentValue(input.environment, spec.commandEnvironmentVariable) : void 0);
|
|
20211
|
+
const command = configured ?? spec.command;
|
|
20212
|
+
if (pathFlavor.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
|
|
20213
|
+
return [{ candidate: command, source: "configured" }];
|
|
19953
20214
|
}
|
|
19954
|
-
|
|
19955
|
-
|
|
19956
|
-
|
|
19957
|
-
|
|
20215
|
+
const candidates = [];
|
|
20216
|
+
const extensions = executableExtensions(command, platform, input.environment);
|
|
20217
|
+
for (const directory of pathDirectories(input.environment, platform)) {
|
|
20218
|
+
for (const extension of extensions) {
|
|
20219
|
+
candidates.push({
|
|
20220
|
+
candidate: pathFlavor.join(directory, command + extension),
|
|
20221
|
+
source: "path"
|
|
20222
|
+
});
|
|
19958
20223
|
}
|
|
19959
20224
|
}
|
|
19960
|
-
if (
|
|
19961
|
-
|
|
19962
|
-
|
|
19963
|
-
|
|
19964
|
-
|
|
19965
|
-
|
|
19966
|
-
|
|
19967
|
-
|
|
19968
|
-
|
|
19969
|
-
throw new Error(`Harness Usage '${field}' must be between 0 and 100`);
|
|
20225
|
+
if (configured !== void 0)
|
|
20226
|
+
return candidates;
|
|
20227
|
+
const home = resolveHomeDirectory(input);
|
|
20228
|
+
for (const directory of installRootDirectories(spec, input, dependencies, platform, home)) {
|
|
20229
|
+
for (const extension of installRootExtensions(platform)) {
|
|
20230
|
+
candidates.push({
|
|
20231
|
+
candidate: pathFlavor.join(directory, spec.command + extension),
|
|
20232
|
+
source: "install-root"
|
|
20233
|
+
});
|
|
19970
20234
|
}
|
|
19971
20235
|
}
|
|
19972
|
-
|
|
19973
|
-
const hasContextWindow = value.contextWindowTokens !== void 0;
|
|
19974
|
-
if (hasContextUsed !== hasContextWindow) {
|
|
19975
|
-
throw new Error("Harness Usage context fields must be provided together");
|
|
19976
|
-
}
|
|
19977
|
-
if (hasContextWindow && value.contextWindowTokens === 0) {
|
|
19978
|
-
throw new Error("Harness Usage 'contextWindowTokens' must be greater than zero");
|
|
19979
|
-
}
|
|
19980
|
-
if (value.planFiveHourResetsAtUnix !== void 0 && value.planFiveHourUsedPercent === void 0) {
|
|
19981
|
-
throw new Error("Harness Usage 'planFiveHourResetsAtUnix' must be provided with 'planFiveHourUsedPercent'");
|
|
19982
|
-
}
|
|
19983
|
-
if (value.planSevenDayResetsAtUnix !== void 0 && value.planSevenDayUsedPercent === void 0) {
|
|
19984
|
-
throw new Error("Harness Usage 'planSevenDayResetsAtUnix' must be provided with 'planSevenDayUsedPercent'");
|
|
19985
|
-
}
|
|
19986
|
-
return { ...value };
|
|
19987
|
-
}
|
|
19988
|
-
|
|
19989
|
-
// dist/common.js
|
|
19990
|
-
var CODEBUDDY_ID = harnessIdSchema.parse("codebuddy");
|
|
19991
|
-
var OUTPUT_LIMIT = 64e3;
|
|
19992
|
-
var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
19993
|
-
var rows = (value) => Array.isArray(value) ? value.map(record2) : [];
|
|
19994
|
-
var text = (value) => typeof value === "string" ? value : "";
|
|
19995
|
-
var CodeBuddyError = class extends Error {
|
|
19996
|
-
code;
|
|
19997
|
-
constructor(code, message) {
|
|
19998
|
-
super(message);
|
|
19999
|
-
this.code = code;
|
|
20000
|
-
}
|
|
20001
|
-
};
|
|
20002
|
-
function nativeError(error51) {
|
|
20003
|
-
const diagnostic = sanitizeDiagnosticTail(error51 instanceof Error ? error51.message : String(error51));
|
|
20004
|
-
const nativeCode = record2(error51).code;
|
|
20005
|
-
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";
|
|
20006
|
-
return {
|
|
20007
|
-
code,
|
|
20008
|
-
message: `CodeBuddy: ${diagnostic || "native operation failed"}`,
|
|
20009
|
-
retryable: ["sessionBusy", "unavailable"].includes(code)
|
|
20010
|
-
};
|
|
20011
|
-
}
|
|
20012
|
-
function failure(code, message) {
|
|
20013
|
-
return { ok: false, error: nativeError(new CodeBuddyError(code, message)) };
|
|
20236
|
+
return candidates;
|
|
20014
20237
|
}
|
|
20015
|
-
|
|
20016
|
-
|
|
20017
|
-
|
|
20018
|
-
|
|
20019
|
-
|
|
20020
|
-
|
|
20021
|
-
|
|
20022
|
-
|
|
20023
|
-
|
|
20024
|
-
onTimeout?.(error51);
|
|
20025
|
-
} finally {
|
|
20026
|
-
reject(error51);
|
|
20027
|
-
}
|
|
20028
|
-
}, milliseconds);
|
|
20029
|
-
})
|
|
20030
|
-
]);
|
|
20031
|
-
} finally {
|
|
20032
|
-
clearTimeout(timer);
|
|
20238
|
+
function resolveHarnessExecutable(spec, input, dependencies = {}) {
|
|
20239
|
+
const platform = input.platform ?? process.platform;
|
|
20240
|
+
const isExecutable = dependencies.isExecutable ?? ((candidate) => isExecutableFile(candidate, platform));
|
|
20241
|
+
const runnable = spec.runnableCandidate ?? ((candidate) => candidate);
|
|
20242
|
+
const context = { platform, isExecutable };
|
|
20243
|
+
for (const { candidate, source } of harnessCandidates(spec, input, dependencies)) {
|
|
20244
|
+
const executable = runnable(candidate, context);
|
|
20245
|
+
if (executable !== void 0 && isExecutable(executable))
|
|
20246
|
+
return { executable, source };
|
|
20033
20247
|
}
|
|
20248
|
+
return void 0;
|
|
20034
20249
|
}
|
|
20035
20250
|
|
|
20036
20251
|
// dist/command.js
|
|
@@ -20049,21 +20264,34 @@ var codeBuddyDiscoverySpec = {
|
|
|
20049
20264
|
]
|
|
20050
20265
|
}
|
|
20051
20266
|
};
|
|
20052
|
-
function codeBuddyInvocation(environment, ephemeral) {
|
|
20267
|
+
function codeBuddyInvocation(environment, ephemeral, argumentsOverride) {
|
|
20053
20268
|
const resolved = resolveHarnessExecutable(codeBuddyDiscoverySpec, { environment });
|
|
20054
20269
|
if (!resolved)
|
|
20055
20270
|
throw new CodeBuddyError("notInstalled", "CLI is not installed; run codebuddy and sign in first");
|
|
20056
20271
|
const env = withNodeRuntimeOnPath(environment);
|
|
20057
20272
|
return {
|
|
20058
|
-
...commandInvocation(resolved.executable,
|
|
20273
|
+
...commandInvocation(resolved.executable, argumentsOverride ?? [
|
|
20274
|
+
"--acp",
|
|
20275
|
+
...ephemeral ? ["--no-session-persistence"] : [],
|
|
20276
|
+
...!ephemeral && [
|
|
20277
|
+
"CODEXHOST_CLI_PATH",
|
|
20278
|
+
"CODEXHOST_RUNTIME_ENDPOINT",
|
|
20279
|
+
"CODEXHOST_RUNTIME_TOKEN",
|
|
20280
|
+
"CODEXHOST_THREAD_ID"
|
|
20281
|
+
].every((key) => environment[key]) ? ["--append-system-prompt", CODEBUDDY_DELEGATION_INSTRUCTIONS] : []
|
|
20282
|
+
], env),
|
|
20059
20283
|
environment: env
|
|
20060
20284
|
};
|
|
20061
20285
|
}
|
|
20286
|
+
var CODEBUDDY_DELEGATION_INSTRUCTIONS = `This Session runs inside codexhost.
|
|
20287
|
+
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.`;
|
|
20062
20288
|
|
|
20063
20289
|
// dist/acp-client.js
|
|
20064
20290
|
var CodeBuddyAcpClient = class {
|
|
20065
20291
|
options;
|
|
20066
20292
|
operationTimeoutMs;
|
|
20293
|
+
invocationFactory;
|
|
20294
|
+
#copyCleanup;
|
|
20067
20295
|
#child;
|
|
20068
20296
|
#connection;
|
|
20069
20297
|
#exited;
|
|
@@ -20075,12 +20303,14 @@ var CodeBuddyAcpClient = class {
|
|
|
20075
20303
|
#failed = new Promise((_, reject) => {
|
|
20076
20304
|
this.#rejectFailure = reject;
|
|
20077
20305
|
});
|
|
20078
|
-
constructor(options, operationTimeoutMs = 15e3) {
|
|
20306
|
+
constructor(options, operationTimeoutMs = 15e3, invocationFactory = codeBuddyInvocation) {
|
|
20079
20307
|
this.options = options;
|
|
20080
20308
|
this.operationTimeoutMs = operationTimeoutMs;
|
|
20309
|
+
this.invocationFactory = invocationFactory;
|
|
20081
20310
|
void this.#failed.catch(() => {
|
|
20082
20311
|
});
|
|
20083
|
-
|
|
20312
|
+
this.#copyCleanup = options.temporarySessionId ? new CodeBuddyCopyCleanup(options.temporarySessionId, options.cwd) : void 0;
|
|
20313
|
+
const invocation = invocationFactory(this.#copyCleanup?.environment(options.environment) ?? options.environment, options.ephemeral, this.#copyCleanup?.arguments);
|
|
20084
20314
|
this.#child = spawn(invocation.command, invocation.arguments, {
|
|
20085
20315
|
cwd: options.cwd,
|
|
20086
20316
|
env: invocation.environment,
|
|
@@ -20117,7 +20347,7 @@ var CodeBuddyAcpClient = class {
|
|
|
20117
20347
|
return { outcome: "cancelled" };
|
|
20118
20348
|
return options.handlers.question(params);
|
|
20119
20349
|
}
|
|
20120
|
-
}), ndJsonStream2(Writable.toWeb(this.#child.stdin),
|
|
20350
|
+
}), ndJsonStream2(Writable.toWeb(this.#child.stdin), Readable2.toWeb(this.#copyCleanup?.protocolOutput(this.#child.stdout) ?? this.#child.stdout)));
|
|
20121
20351
|
void this.#connection.closed.then(() => {
|
|
20122
20352
|
this.#fault(new CodeBuddyError("processExited", "ACP connection closed"));
|
|
20123
20353
|
}).catch((error51) => {
|
|
@@ -20167,13 +20397,27 @@ var CodeBuddyAcpClient = class {
|
|
|
20167
20397
|
async cancel(sessionId) {
|
|
20168
20398
|
await this.#request(() => this.#connection.cancel({ sessionId }), "ACP cancel");
|
|
20169
20399
|
}
|
|
20400
|
+
async removeCopy() {
|
|
20401
|
+
const cleanup = this.#copyCleanup;
|
|
20402
|
+
if (!cleanup)
|
|
20403
|
+
throw new CodeBuddyError("invalidState", "No temporary copy is owned by this process");
|
|
20404
|
+
await this.#request(() => cleanup.remove(), "Native temporary Session cleanup");
|
|
20405
|
+
}
|
|
20406
|
+
async rollback(sessionId, forkPointId) {
|
|
20407
|
+
return record2(await this.#request(() => this.#connection.extMethod("_codebuddy.ai/session/rollback", {
|
|
20408
|
+
sessionId,
|
|
20409
|
+
forkPointId,
|
|
20410
|
+
reason: "resend_edit",
|
|
20411
|
+
files: false
|
|
20412
|
+
}), "ACP history rewind"));
|
|
20413
|
+
}
|
|
20170
20414
|
async answer(sessionId, toolCallId, answers) {
|
|
20171
20415
|
const response = await this.#request(() => this.#connection.extMethod("_codebuddy.ai/resolveInterruption", {
|
|
20172
20416
|
sessionId,
|
|
20173
20417
|
toolCallId,
|
|
20174
20418
|
decision: answers === null ? "deny" : "allow",
|
|
20175
20419
|
...answers ? { answers } : {}
|
|
20176
|
-
}), "
|
|
20420
|
+
}), "ACP question response");
|
|
20177
20421
|
if (record2(response).resolved !== true)
|
|
20178
20422
|
throw new CodeBuddyError("protocolError", "Native question is no longer pending");
|
|
20179
20423
|
}
|
|
@@ -20215,19 +20459,25 @@ var CODEBUDDY_CAPABILITIES = {
|
|
|
20215
20459
|
selectPermissionMode: true,
|
|
20216
20460
|
permissionModeScope: "live"
|
|
20217
20461
|
},
|
|
20218
|
-
history: { fork:
|
|
20462
|
+
history: { fork: true, forkAcrossCwd: false, rollbackLastTurn: true },
|
|
20219
20463
|
subagents: { observe: true, readTranscript: true }
|
|
20220
20464
|
};
|
|
20465
|
+
function capabilitiesForProfile(profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20466
|
+
return {
|
|
20467
|
+
...CODEBUDDY_CAPABILITIES,
|
|
20468
|
+
history: profile.historyCapabilities ?? CODEBUDDY_CAPABILITIES.history
|
|
20469
|
+
};
|
|
20470
|
+
}
|
|
20221
20471
|
function modelRef(modelId) {
|
|
20222
20472
|
return harnessModelRefSchema.parse({ id: `cb.${Buffer.from(modelId).toString("base64url")}` });
|
|
20223
20473
|
}
|
|
20224
20474
|
function nativeModel(ref) {
|
|
20225
20475
|
const value = Buffer.from(ref.id.slice(3), "base64url").toString("utf8");
|
|
20226
20476
|
if (!value || !ref.id.startsWith("cb.") || modelRef(value).id !== ref.id)
|
|
20227
|
-
throw new CodeBuddyError("invalidRequest", "Invalid
|
|
20477
|
+
throw new CodeBuddyError("invalidRequest", "Invalid native Model Ref");
|
|
20228
20478
|
return value;
|
|
20229
20479
|
}
|
|
20230
|
-
function configuration(value) {
|
|
20480
|
+
function configuration(value, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20231
20481
|
const options = rows(value);
|
|
20232
20482
|
const get = (id) => options.find((option) => option.id === id) ?? {};
|
|
20233
20483
|
const model = get("model"), mode = get("mode"), thought = get("thought_level");
|
|
@@ -20237,7 +20487,12 @@ function configuration(value) {
|
|
|
20237
20487
|
ref: modelRef(text(option.value)),
|
|
20238
20488
|
label: text(option.name)
|
|
20239
20489
|
}));
|
|
20240
|
-
const
|
|
20490
|
+
const currentModelRef = modelRef(text(model.currentValue));
|
|
20491
|
+
let currentModel = models.find((item) => item.ref.id === currentModelRef.id);
|
|
20492
|
+
if (!currentModel && profile.allowUnlistedModelSelection) {
|
|
20493
|
+
currentModel = { ref: currentModelRef, label: text(model.currentValue) };
|
|
20494
|
+
models.push(currentModel);
|
|
20495
|
+
}
|
|
20241
20496
|
if (!currentModel)
|
|
20242
20497
|
throw new CodeBuddyError("protocolError", "ACP did not report a valid current Model");
|
|
20243
20498
|
const catalog = harnessModelCatalogSchema.parse({
|
|
@@ -20267,18 +20522,28 @@ function configuration(value) {
|
|
|
20267
20522
|
};
|
|
20268
20523
|
return { catalog, permissionModes, state, options };
|
|
20269
20524
|
}
|
|
20270
|
-
function confirmedConfiguration(response, id, value) {
|
|
20271
|
-
const result = configuration(record2(response).configOptions);
|
|
20525
|
+
function confirmedConfiguration(response, id, value, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20526
|
+
const result = configuration(record2(response).configOptions, profile);
|
|
20272
20527
|
if (result.options.find((option) => option.id === id)?.currentValue !== value) {
|
|
20273
20528
|
throw new CodeBuddyError("protocolError", `ACP did not confirm ${id}`);
|
|
20274
20529
|
}
|
|
20275
20530
|
return result;
|
|
20276
20531
|
}
|
|
20277
20532
|
|
|
20533
|
+
// dist/derivation.js
|
|
20534
|
+
import { randomUUID } from "node:crypto";
|
|
20535
|
+
import { execFile as execFile2, spawn as spawn2 } from "node:child_process";
|
|
20536
|
+
import { lstat, mkdir, readFile as readFile2, realpath as realpath4, unlink, writeFile } from "node:fs/promises";
|
|
20537
|
+
import path5 from "node:path";
|
|
20538
|
+
import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
|
|
20539
|
+
|
|
20278
20540
|
// dist/history.js
|
|
20541
|
+
import { createHash } from "node:crypto";
|
|
20542
|
+
import { realpathSync } from "node:fs";
|
|
20279
20543
|
import { access, readdir, realpath as realpath2 } from "node:fs/promises";
|
|
20280
20544
|
import { homedir } from "node:os";
|
|
20281
20545
|
import path4 from "node:path";
|
|
20546
|
+
import { isDeepStrictEqual } from "node:util";
|
|
20282
20547
|
|
|
20283
20548
|
// ../../../node_modules/diff/libesm/diff/base.js
|
|
20284
20549
|
var Diff = class {
|
|
@@ -20380,16 +20645,16 @@ var Diff = class {
|
|
|
20380
20645
|
}
|
|
20381
20646
|
}
|
|
20382
20647
|
}
|
|
20383
|
-
addToPath(
|
|
20384
|
-
const last =
|
|
20648
|
+
addToPath(path8, added, removed, oldPosInc, options) {
|
|
20649
|
+
const last = path8.lastComponent;
|
|
20385
20650
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
20386
20651
|
return {
|
|
20387
|
-
oldPos:
|
|
20652
|
+
oldPos: path8.oldPos + oldPosInc,
|
|
20388
20653
|
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
20389
20654
|
};
|
|
20390
20655
|
} else {
|
|
20391
20656
|
return {
|
|
20392
|
-
oldPos:
|
|
20657
|
+
oldPos: path8.oldPos + oldPosInc,
|
|
20393
20658
|
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
20394
20659
|
};
|
|
20395
20660
|
}
|
|
@@ -20727,28 +20992,31 @@ function toolOutput(value) {
|
|
|
20727
20992
|
...output.length > OUTPUT_LIMIT ? { truncated: true } : {}
|
|
20728
20993
|
};
|
|
20729
20994
|
}
|
|
20730
|
-
function toolOutcome(status) {
|
|
20995
|
+
function toolOutcome(status, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20731
20996
|
if (status === "completed")
|
|
20732
20997
|
return { status: "succeeded" };
|
|
20733
20998
|
if (status === "cancelled" || status === "interrupted")
|
|
20734
20999
|
return { status: "cancelled" };
|
|
20735
21000
|
return {
|
|
20736
21001
|
status: "failed",
|
|
20737
|
-
error: nativeError(new CodeBuddyError("nativeFailure", status === "failed" ? "Tool execution failed" : "Tool completion was not recorded"))
|
|
21002
|
+
error: nativeError(new CodeBuddyError("nativeFailure", status === "failed" ? "Tool execution failed" : "Tool completion was not recorded"), profile)
|
|
20738
21003
|
};
|
|
20739
21004
|
}
|
|
20740
21005
|
var CodeBuddyTurnOutput = class {
|
|
20741
21006
|
turnId;
|
|
20742
21007
|
cwd;
|
|
20743
21008
|
emit;
|
|
21009
|
+
profile;
|
|
20744
21010
|
#items = /* @__PURE__ */ new Map();
|
|
20745
21011
|
#finished = /* @__PURE__ */ new Set();
|
|
20746
21012
|
#tools = /* @__PURE__ */ new Map();
|
|
20747
21013
|
#diffs = /* @__PURE__ */ new Set();
|
|
20748
|
-
|
|
21014
|
+
#compactionOutcome;
|
|
21015
|
+
constructor(turnId, cwd, emit, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20749
21016
|
this.turnId = turnId;
|
|
20750
21017
|
this.cwd = cwd;
|
|
20751
21018
|
this.emit = emit;
|
|
21019
|
+
this.profile = profile;
|
|
20752
21020
|
}
|
|
20753
21021
|
#start(item) {
|
|
20754
21022
|
this.#items.set(item.itemId, { item, outcome: { status: "succeeded" } });
|
|
@@ -20765,11 +21033,33 @@ var CodeBuddyTurnOutput = class {
|
|
|
20765
21033
|
snapshot: structuredClone({ item, outcome })
|
|
20766
21034
|
});
|
|
20767
21035
|
}
|
|
21036
|
+
replayCommandResult(items) {
|
|
21037
|
+
if (this.#items.size)
|
|
21038
|
+
return;
|
|
21039
|
+
for (const snapshot of items) {
|
|
21040
|
+
const item = structuredClone(snapshot.item);
|
|
21041
|
+
this.#start(item);
|
|
21042
|
+
this.#finish(item, snapshot.outcome);
|
|
21043
|
+
}
|
|
21044
|
+
}
|
|
21045
|
+
confirmCompaction(items) {
|
|
21046
|
+
const persisted = items.find((snapshot) => snapshot.item.type === "contextCompaction");
|
|
21047
|
+
this.#compactionOutcome = persisted ? structuredClone(persisted.outcome) : void 0;
|
|
21048
|
+
}
|
|
21049
|
+
compact() {
|
|
21050
|
+
const itemId = hostItemIdSchema.parse(`compact-${this.turnId}`);
|
|
21051
|
+
if (!this.#items.has(itemId))
|
|
21052
|
+
this.#start({ type: "contextCompaction", itemId });
|
|
21053
|
+
}
|
|
20768
21054
|
update(value) {
|
|
20769
21055
|
const update = record2(value), meta3 = record2(update._meta);
|
|
20770
21056
|
if (meta3["codebuddy.ai/memberEvent"])
|
|
20771
21057
|
return;
|
|
20772
21058
|
const kind = update.sessionUpdate;
|
|
21059
|
+
if (nativeCommandsEnabled(this.profile) && meta3["codebuddy.ai/isCompactInternal"] === true) {
|
|
21060
|
+
this.compact();
|
|
21061
|
+
return;
|
|
21062
|
+
}
|
|
20773
21063
|
if (kind === "agent_message_chunk" || kind === "agent_thought_chunk") {
|
|
20774
21064
|
const delta = contentText(update.content);
|
|
20775
21065
|
if (!delta)
|
|
@@ -20809,7 +21099,7 @@ var CodeBuddyTurnOutput = class {
|
|
|
20809
21099
|
const terminal = update.status === "completed" || update.status === "failed";
|
|
20810
21100
|
if (!terminal && !record2(merged._meta)["codebuddy.ai/toolArgumentsComplete"])
|
|
20811
21101
|
return;
|
|
20812
|
-
const name = text(record2(merged._meta)["codebuddy.ai/toolName"]) || text(merged.title) ||
|
|
21102
|
+
const name = text(record2(merged._meta)["codebuddy.ai/toolName"]) || text(merged.title) || `${this.profile.displayName} tool`;
|
|
20813
21103
|
const id = `tool-${callId}`;
|
|
20814
21104
|
let item = this.#items.get(id)?.item;
|
|
20815
21105
|
if (!item) {
|
|
@@ -20840,7 +21130,7 @@ var CodeBuddyTurnOutput = class {
|
|
|
20840
21130
|
update: { type: "output.replace", output }
|
|
20841
21131
|
});
|
|
20842
21132
|
}
|
|
20843
|
-
this.#finish(item, toolOutcome(update.status));
|
|
21133
|
+
this.#finish(item, toolOutcome(update.status, this.profile));
|
|
20844
21134
|
if (update.status === "completed" && !this.#diffs.has(callId)) {
|
|
20845
21135
|
const changes = [];
|
|
20846
21136
|
for (const diff of rows(merged.content)) {
|
|
@@ -20869,9 +21159,13 @@ var CodeBuddyTurnOutput = class {
|
|
|
20869
21159
|
}
|
|
20870
21160
|
finish(status, error51) {
|
|
20871
21161
|
for (const { item } of this.#items.values()) {
|
|
20872
|
-
|
|
20873
|
-
|
|
20874
|
-
|
|
21162
|
+
if (item.type === "contextCompaction" && this.#compactionOutcome) {
|
|
21163
|
+
this.#finish(item, this.#compactionOutcome);
|
|
21164
|
+
continue;
|
|
21165
|
+
}
|
|
21166
|
+
const outcome = status === "failed" || item.type === "contextCompaction" && status === "succeeded" && !this.#compactionOutcome ? {
|
|
21167
|
+
status: "failed",
|
|
21168
|
+
error: error51 ?? nativeError(new CodeBuddyError("nativeFailure", item.type === "contextCompaction" ? "Native compaction completion was not confirmed" : "Turn failed"), this.profile)
|
|
20875
21169
|
} : { status };
|
|
20876
21170
|
this.#finish(item, outcome);
|
|
20877
21171
|
}
|
|
@@ -20888,7 +21182,7 @@ function codeBuddyChildId(value) {
|
|
|
20888
21182
|
const id = structured || /\[Agent ID: (agent-[a-zA-Z0-9_-]+)\]\s*$/u.exec(body)?.[1];
|
|
20889
21183
|
return id && validCodeBuddyChildId(id) ? id : void 0;
|
|
20890
21184
|
}
|
|
20891
|
-
function codeBuddyDelegation(callId, input, status, childId) {
|
|
21185
|
+
function codeBuddyDelegation(callId, input, status, childId, displayName = "CodeBuddy") {
|
|
20892
21186
|
const args = record2(input);
|
|
20893
21187
|
const resumed = text(args.resume);
|
|
20894
21188
|
const nativeId = childId ?? (validCodeBuddyChildId(resumed) ? resumed : void 0);
|
|
@@ -20901,7 +21195,7 @@ function codeBuddyDelegation(callId, input, status, childId) {
|
|
|
20901
21195
|
{
|
|
20902
21196
|
subagentId: nativeId ?? callId,
|
|
20903
21197
|
...nativeId ? { nativeSubagentId: nativeId } : {},
|
|
20904
|
-
description: text(args.description) ||
|
|
21198
|
+
description: text(args.description) || `${displayName} Subagent`,
|
|
20905
21199
|
...text(args.subagent_type) ? { role: text(args.subagent_type) } : {},
|
|
20906
21200
|
...text(args.model) ? { model: text(args.model) } : {},
|
|
20907
21201
|
background: args.run_in_background === true,
|
|
@@ -20935,9 +21229,55 @@ async function readCodeBuddyVersionedText(file2, maximumBytes, tooLargeMessage,
|
|
|
20935
21229
|
}
|
|
20936
21230
|
|
|
20937
21231
|
// dist/history.js
|
|
20938
|
-
function
|
|
20939
|
-
|
|
20940
|
-
|
|
21232
|
+
function codeBuddyProjectSlug(cwd, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21233
|
+
const canonical = codeBuddyCanonicalCwd(cwd);
|
|
21234
|
+
if (profile.projectDirectoryName)
|
|
21235
|
+
return profile.projectDirectoryName(canonical);
|
|
21236
|
+
return canonical.replace(/[^a-z0-9]/giu, "-").replace(/-+/gu, "-").replace(/^-|-$/gu, "").toLowerCase();
|
|
21237
|
+
}
|
|
21238
|
+
function codeBuddyCanonicalCwd(cwd) {
|
|
21239
|
+
try {
|
|
21240
|
+
return realpathSync.native(cwd);
|
|
21241
|
+
} catch {
|
|
21242
|
+
return path4.resolve(cwd);
|
|
21243
|
+
}
|
|
21244
|
+
}
|
|
21245
|
+
function codeBuddyConfigRoot(environment, profile) {
|
|
21246
|
+
const configuredRoot = profile.configDirectoryEnvironmentVariables.map((name) => environment[name]).find((value) => typeof value === "string" && value.trim().length > 0);
|
|
21247
|
+
return configuredRoot || path4.join(environment.HOME || environment.USERPROFILE || homedir(), profile.defaultConfigDirectoryName);
|
|
21248
|
+
}
|
|
21249
|
+
function codeBuddyPrimaryHistoryPath(cwd, ref, environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21250
|
+
return path4.join(codeBuddyConfigRoot(environment, profile), "projects", codeBuddyProjectSlug(cwd, profile), `${ref.nativeSessionId}.jsonl`);
|
|
21251
|
+
}
|
|
21252
|
+
function derivedLocator(ref) {
|
|
21253
|
+
const locator = record2(ref.locator);
|
|
21254
|
+
if (locator.codebuddyDerived !== 1)
|
|
21255
|
+
return void 0;
|
|
21256
|
+
const fields = [
|
|
21257
|
+
locator.boundCwd,
|
|
21258
|
+
locator.targetProjectSlug,
|
|
21259
|
+
locator.inheritedPrefixRows,
|
|
21260
|
+
locator.inheritedPrefixSha256,
|
|
21261
|
+
locator.bindingMarkerId
|
|
21262
|
+
];
|
|
21263
|
+
if (fields.every((value) => value === void 0))
|
|
21264
|
+
return void 0;
|
|
21265
|
+
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)
|
|
21266
|
+
throw new CodeBuddyError("protocolError", "Derived Native Session locator is incomplete");
|
|
21267
|
+
return {
|
|
21268
|
+
boundCwd: locator.boundCwd,
|
|
21269
|
+
targetProjectSlug: locator.targetProjectSlug,
|
|
21270
|
+
inheritedPrefixRows: Number(locator.inheritedPrefixRows),
|
|
21271
|
+
inheritedPrefixSha256: locator.inheritedPrefixSha256,
|
|
21272
|
+
bindingMarkerId: locator.bindingMarkerId
|
|
21273
|
+
};
|
|
21274
|
+
}
|
|
21275
|
+
function nativeRowsDigest(rows2) {
|
|
21276
|
+
return createHash("sha256").update(JSON.stringify(rows2)).digest("hex");
|
|
21277
|
+
}
|
|
21278
|
+
function validateNativeRef(ref, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21279
|
+
if (ref.harnessId !== profile.harnessId || ref.formatVersion !== 1 || !/^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/u.test(ref.nativeSessionId)) {
|
|
21280
|
+
throw new CodeBuddyError("invalidRequest", `Invalid ${profile.displayName} Native Session identity`);
|
|
20941
21281
|
}
|
|
20942
21282
|
}
|
|
20943
21283
|
async function sameCwd(left, right) {
|
|
@@ -20949,18 +21289,37 @@ async function sameCwd(left, right) {
|
|
|
20949
21289
|
});
|
|
20950
21290
|
return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
20951
21291
|
}
|
|
20952
|
-
async function
|
|
20953
|
-
|
|
21292
|
+
async function matchesAnyHistoricalCwd(value, candidates) {
|
|
21293
|
+
const resolved = path4.resolve(value);
|
|
21294
|
+
for (const candidate of candidates) {
|
|
21295
|
+
const other = path4.resolve(candidate);
|
|
21296
|
+
if (process.platform === "win32" ? resolved.toLowerCase() === other.toLowerCase() : resolved === other)
|
|
21297
|
+
return true;
|
|
21298
|
+
try {
|
|
21299
|
+
if (await sameCwd(value, candidate))
|
|
21300
|
+
return true;
|
|
21301
|
+
} catch (error51) {
|
|
21302
|
+
if (!(error51 instanceof CodeBuddyError) && !["ENOENT", "ENOTDIR"].includes(text(record2(error51).code)))
|
|
21303
|
+
throw error51;
|
|
21304
|
+
}
|
|
21305
|
+
}
|
|
21306
|
+
return false;
|
|
21307
|
+
}
|
|
21308
|
+
async function codeBuddyNativeHistory(cwd, ref, environment, profileOrVerifiedSource = CODEBUDDY_RUNTIME_PROFILE, transaction) {
|
|
21309
|
+
const profile = typeof profileOrVerifiedSource === "string" ? CODEBUDDY_RUNTIME_PROFILE : profileOrVerifiedSource;
|
|
21310
|
+
const effectiveTransaction = typeof profileOrVerifiedSource === "string" ? { inheritedContents: profileOrVerifiedSource } : transaction;
|
|
21311
|
+
return codeBuddyHistory(cwd, ref, environment, false, profile, effectiveTransaction);
|
|
20954
21312
|
}
|
|
20955
|
-
async function codeBuddyLiveNativeHistory(cwd, ref, environment) {
|
|
20956
|
-
return codeBuddyHistory(cwd, ref, environment, true);
|
|
21313
|
+
async function codeBuddyLiveNativeHistory(cwd, ref, environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21314
|
+
return codeBuddyHistory(cwd, ref, environment, true, profile);
|
|
20957
21315
|
}
|
|
20958
|
-
async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail) {
|
|
20959
|
-
validateNativeRef(ref);
|
|
20960
|
-
const configRoot =
|
|
21316
|
+
async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail, profile, transaction) {
|
|
21317
|
+
validateNativeRef(ref, profile);
|
|
21318
|
+
const configRoot = codeBuddyConfigRoot(environment, profile);
|
|
20961
21319
|
const root = path4.join(configRoot, "projects");
|
|
20962
|
-
const slug =
|
|
21320
|
+
const slug = codeBuddyProjectSlug(cwd, profile);
|
|
20963
21321
|
const primary = path4.join(root, slug, `${ref.nativeSessionId}.jsonl`);
|
|
21322
|
+
const provenance = derivedLocator(ref);
|
|
20964
21323
|
let candidates = [];
|
|
20965
21324
|
try {
|
|
20966
21325
|
await access(primary);
|
|
@@ -20968,6 +21327,8 @@ async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail) {
|
|
|
20968
21327
|
} catch (error51) {
|
|
20969
21328
|
if (record2(error51).code !== "ENOENT")
|
|
20970
21329
|
throw error51;
|
|
21330
|
+
if (transaction?.requirePrimary || provenance)
|
|
21331
|
+
throw new CodeBuddyError("sessionNotFound", "Native Session history was not found");
|
|
20971
21332
|
const directories = await readdir(root, { withFileTypes: true }).catch((error52) => {
|
|
20972
21333
|
if (record2(error52).code === "ENOENT")
|
|
20973
21334
|
return [];
|
|
@@ -20991,15 +21352,63 @@ async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail) {
|
|
|
20991
21352
|
const file2 = candidates[0];
|
|
20992
21353
|
if (!file2)
|
|
20993
21354
|
throw new CodeBuddyError("sessionNotFound", "Native Session history was not found");
|
|
21355
|
+
if (profile.historyCapabilities?.fork && !transaction && path4.resolve(file2) !== path4.resolve(primary))
|
|
21356
|
+
throw new CodeBuddyError("invalidRequest", "Native Session is not stored in the requested working directory");
|
|
20994
21357
|
const source = await readCodeBuddyVersionedText(file2, 64e6, "Native history exceeds the supported 64 MB snapshot size"), parsed = parseJsonl(source.contents, tolerateIncompleteTail);
|
|
20995
21358
|
const checkedDirectories = /* @__PURE__ */ new Set();
|
|
20996
|
-
|
|
20997
|
-
|
|
20998
|
-
|
|
20999
|
-
|
|
21000
|
-
|
|
21001
|
-
|
|
21002
|
-
|
|
21359
|
+
const inheritedRows = /* @__PURE__ */ new Map();
|
|
21360
|
+
for (const row of transaction?.inheritedContents ? parseRows(transaction.inheritedContents) : []) {
|
|
21361
|
+
const id = text(row.id);
|
|
21362
|
+
const candidates2 = inheritedRows.get(id) ?? [];
|
|
21363
|
+
candidates2.push(row);
|
|
21364
|
+
inheritedRows.set(id, candidates2);
|
|
21365
|
+
}
|
|
21366
|
+
const inherited = (row) => inheritedRows.get(text(row.id))?.some((candidate) => isDeepStrictEqual(candidate, row)) === true;
|
|
21367
|
+
if (transaction) {
|
|
21368
|
+
for (const row of parsed.rows) {
|
|
21369
|
+
if (inherited(row)) {
|
|
21370
|
+
if (typeof row.cwd === "string")
|
|
21371
|
+
checkedDirectories.add(row.cwd);
|
|
21372
|
+
continue;
|
|
21373
|
+
}
|
|
21374
|
+
if (row.sessionId && row.sessionId !== ref.nativeSessionId)
|
|
21375
|
+
throw new CodeBuddyError("protocolError", "Native history has a different Session identity");
|
|
21376
|
+
if (typeof row.cwd === "string" && !checkedDirectories.has(row.cwd)) {
|
|
21377
|
+
const allowed = [cwd, ...transaction.allowedHistoricalCwds ?? []];
|
|
21378
|
+
if (!await matchesAnyHistoricalCwd(row.cwd, allowed))
|
|
21379
|
+
throw new CodeBuddyError("invalidRequest", "Native Session belongs to a different working directory");
|
|
21380
|
+
checkedDirectories.add(row.cwd);
|
|
21381
|
+
}
|
|
21382
|
+
}
|
|
21383
|
+
} else if (provenance) {
|
|
21384
|
+
if (!await sameCwd(provenance.boundCwd, cwd) || provenance.targetProjectSlug !== slug || path4.resolve(file2) !== path4.resolve(primary))
|
|
21385
|
+
throw new CodeBuddyError("invalidRequest", "Derived Native Session target binding changed");
|
|
21386
|
+
const active = nativeHistoryRows(parsed.contents);
|
|
21387
|
+
if (provenance.inheritedPrefixRows > active.length || nativeRowsDigest(active.slice(0, provenance.inheritedPrefixRows)) !== provenance.inheritedPrefixSha256)
|
|
21388
|
+
throw new CodeBuddyError("protocolError", "Derived Native Session prefix verification failed");
|
|
21389
|
+
const marker = parsed.rows.find((row) => text(row.id) === provenance.bindingMarkerId);
|
|
21390
|
+
if (!marker || marker.sessionId !== ref.nativeSessionId || typeof marker.cwd !== "string" || !await sameCwd(marker.cwd, cwd))
|
|
21391
|
+
throw new CodeBuddyError("protocolError", "Derived Native Session target marker is missing");
|
|
21392
|
+
checkedDirectories.add(cwd);
|
|
21393
|
+
const verifiedSuffixCwds = /* @__PURE__ */ new Set();
|
|
21394
|
+
for (const row of active.slice(provenance.inheritedPrefixRows)) {
|
|
21395
|
+
if (row.sessionId && row.sessionId !== ref.nativeSessionId)
|
|
21396
|
+
throw new CodeBuddyError("protocolError", "Derived Native Session appended foreign history");
|
|
21397
|
+
if (typeof row.cwd === "string" && !verifiedSuffixCwds.has(row.cwd)) {
|
|
21398
|
+
if (!await sameCwd(row.cwd, cwd))
|
|
21399
|
+
throw new CodeBuddyError("invalidRequest", "Derived Native Session left its target directory");
|
|
21400
|
+
verifiedSuffixCwds.add(row.cwd);
|
|
21401
|
+
}
|
|
21402
|
+
}
|
|
21403
|
+
} else {
|
|
21404
|
+
for (const row of parsed.rows) {
|
|
21405
|
+
if (row.sessionId && row.sessionId !== ref.nativeSessionId)
|
|
21406
|
+
throw new CodeBuddyError("protocolError", "Native history has a different Session identity");
|
|
21407
|
+
if (typeof row.cwd === "string" && !checkedDirectories.has(row.cwd)) {
|
|
21408
|
+
if (!await sameCwd(row.cwd, cwd))
|
|
21409
|
+
throw new CodeBuddyError("invalidRequest", "Native Session belongs to a different working directory");
|
|
21410
|
+
checkedDirectories.add(row.cwd);
|
|
21411
|
+
}
|
|
21003
21412
|
}
|
|
21004
21413
|
}
|
|
21005
21414
|
return {
|
|
@@ -21009,12 +21418,15 @@ async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail) {
|
|
|
21009
21418
|
reusableVersion: source.reusableVersion
|
|
21010
21419
|
};
|
|
21011
21420
|
}
|
|
21012
|
-
async function readNativeHistory(cwd, ref, environment) {
|
|
21013
|
-
return (await codeBuddyNativeHistory(cwd, ref, environment)).contents;
|
|
21421
|
+
async function readNativeHistory(cwd, ref, environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21422
|
+
return (await codeBuddyNativeHistory(cwd, ref, environment, profile)).contents;
|
|
21014
21423
|
}
|
|
21015
21424
|
function parseRows(contents, tolerateIncompleteTail = false) {
|
|
21016
21425
|
return parseJsonl(contents, tolerateIncompleteTail).rows;
|
|
21017
21426
|
}
|
|
21427
|
+
function nativeRawHistoryRows(contents) {
|
|
21428
|
+
return parseRows(contents);
|
|
21429
|
+
}
|
|
21018
21430
|
function parseJsonl(contents, tolerateIncompleteTail) {
|
|
21019
21431
|
const lines = contents.split(/\r?\n/u);
|
|
21020
21432
|
const completeLines = [], rows2 = [];
|
|
@@ -21035,11 +21447,25 @@ function parseJsonl(contents, tolerateIncompleteTail) {
|
|
|
21035
21447
|
contents: tolerateIncompleteTail ? completeLines.join("\n") : contents
|
|
21036
21448
|
};
|
|
21037
21449
|
}
|
|
21450
|
+
var NATIVE_MESSAGE_TYPES = /* @__PURE__ */ new Set([
|
|
21451
|
+
"message",
|
|
21452
|
+
"reasoning",
|
|
21453
|
+
"function_call",
|
|
21454
|
+
"function_call_result"
|
|
21455
|
+
]);
|
|
21456
|
+
function pendingNativeHistoryRewind(contents) {
|
|
21457
|
+
const last = parseRows(contents).findLast((row) => row.type === "resend-fork-notice" || NATIVE_MESSAGE_TYPES.has(text(row.type)));
|
|
21458
|
+
return last?.type === "resend-fork-notice" ? { forkPointId: text(last.parentId) || null } : void 0;
|
|
21459
|
+
}
|
|
21038
21460
|
function nativeHistoryRows(contents) {
|
|
21039
21461
|
const entries = /* @__PURE__ */ new Map();
|
|
21040
21462
|
let leaf = "";
|
|
21041
21463
|
for (const row of parseRows(contents)) {
|
|
21042
|
-
if (
|
|
21464
|
+
if (row.type === "resend-fork-notice") {
|
|
21465
|
+
leaf = text(row.parentId);
|
|
21466
|
+
continue;
|
|
21467
|
+
}
|
|
21468
|
+
if (!NATIVE_MESSAGE_TYPES.has(text(row.type)))
|
|
21043
21469
|
continue;
|
|
21044
21470
|
if (!text(row.id))
|
|
21045
21471
|
throw new CodeBuddyError("protocolError", "Native message is missing its stable ID");
|
|
@@ -21059,13 +21485,15 @@ function nativeHistoryRows(contents) {
|
|
|
21059
21485
|
}
|
|
21060
21486
|
return chain.reverse();
|
|
21061
21487
|
}
|
|
21062
|
-
function snapshotFromHistory(contents, ref, cwd) {
|
|
21488
|
+
function snapshotFromHistory(contents, ref, cwd, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21489
|
+
const supportsNativeCommands = nativeCommandsEnabled(profile);
|
|
21490
|
+
const supportsFork = capabilitiesForProfile(profile).history.fork;
|
|
21063
21491
|
const turns = [];
|
|
21064
21492
|
let current;
|
|
21065
21493
|
const tools = /* @__PURE__ */ new Map();
|
|
21066
21494
|
const earlyResults = /* @__PURE__ */ new Map();
|
|
21067
21495
|
const applyResult = (snapshot, row) => {
|
|
21068
|
-
snapshot.outcome = toolOutcome(row.status);
|
|
21496
|
+
snapshot.outcome = toolOutcome(row.status, profile);
|
|
21069
21497
|
if (snapshot.item.type === "subagentDelegation") {
|
|
21070
21498
|
const childId = codeBuddyChildId(row);
|
|
21071
21499
|
snapshot.item.subagents = snapshot.item.subagents.map((child) => ({
|
|
@@ -21083,16 +21511,54 @@ function snapshotFromHistory(contents, ref, cwd) {
|
|
|
21083
21511
|
snapshot.item.outputTruncated = Boolean(output.truncated);
|
|
21084
21512
|
}
|
|
21085
21513
|
};
|
|
21086
|
-
|
|
21514
|
+
const history = nativeHistoryRows(contents);
|
|
21515
|
+
const manualCompactions = /* @__PURE__ */ new Set();
|
|
21516
|
+
let compactUser;
|
|
21517
|
+
if (supportsNativeCommands)
|
|
21518
|
+
for (const row of history) {
|
|
21519
|
+
const data = record2(row.providerData);
|
|
21520
|
+
if (row.type === "message" && row.role === "user")
|
|
21521
|
+
compactUser = data.agent === "compact" ? text(row.id) : void 0;
|
|
21522
|
+
if (compactUser && row.role === "assistant" && data.compactType === "user-command")
|
|
21523
|
+
manualCompactions.add(compactUser);
|
|
21524
|
+
}
|
|
21525
|
+
for (const row of history) {
|
|
21526
|
+
const data = record2(row.providerData);
|
|
21527
|
+
const body = contentText(row.content);
|
|
21528
|
+
const localCommand = supportsNativeCommands && data.skipRun === true ? /^<command-name>([^<]+)<\/command-name>(?:\s*<command-args>([\s\S]*)<\/command-args>)?$/u.exec(body) : null;
|
|
21529
|
+
const localOutput = supportsNativeCommands && data.skipRun === true ? /^<local-command-stdout>([\s\S]*)<\/local-command-stdout>$/u.exec(body) : null;
|
|
21530
|
+
if (localOutput) {
|
|
21531
|
+
if (current) {
|
|
21532
|
+
current.items.push({
|
|
21533
|
+
item: {
|
|
21534
|
+
type: "agentMessage",
|
|
21535
|
+
itemId: hostItemIdSchema.parse(`agentMessage-${text(row.id)}`),
|
|
21536
|
+
text: localOutput[1] ?? ""
|
|
21537
|
+
},
|
|
21538
|
+
outcome: { status: "succeeded" }
|
|
21539
|
+
});
|
|
21540
|
+
current.outcome = { status: "succeeded" };
|
|
21541
|
+
}
|
|
21542
|
+
continue;
|
|
21543
|
+
}
|
|
21544
|
+
if (supportsNativeCommands && data.skipRun === true && body.startsWith('<system-reminder data-role="command-caveat">'))
|
|
21545
|
+
continue;
|
|
21546
|
+
if (supportsNativeCommands && row.type === "message" && row.role === "user" && data.agent === "compact" && !manualCompactions.has(text(row.id)))
|
|
21547
|
+
continue;
|
|
21087
21548
|
if (row.type === "message" && row.role === "user") {
|
|
21088
21549
|
current = {
|
|
21089
21550
|
nativeTurnRef: nativeTurnRefSchema.parse({
|
|
21090
|
-
harnessId:
|
|
21551
|
+
harnessId: profile.harnessId,
|
|
21091
21552
|
nativeSessionId: ref.nativeSessionId,
|
|
21092
21553
|
nativeTurnKey: row.id,
|
|
21093
21554
|
formatVersion: 1
|
|
21094
21555
|
}),
|
|
21095
|
-
input: [
|
|
21556
|
+
input: [
|
|
21557
|
+
{
|
|
21558
|
+
type: "text",
|
|
21559
|
+
text: supportsNativeCommands && data.agent === "compact" ? "/compact" : localCommand ? `${localCommand[1]}${localCommand[2] ? ` ${localCommand[2]}` : ""}` : body
|
|
21560
|
+
}
|
|
21561
|
+
],
|
|
21096
21562
|
items: [],
|
|
21097
21563
|
outcome: { status: "unknown", reason: "Native terminal outcome was not recorded" },
|
|
21098
21564
|
...typeof row.timestamp === "number" ? { startedAtMs: row.timestamp } : {}
|
|
@@ -21104,15 +21570,33 @@ function snapshotFromHistory(contents, ref, cwd) {
|
|
|
21104
21570
|
}
|
|
21105
21571
|
if (!current)
|
|
21106
21572
|
continue;
|
|
21573
|
+
if (supportsNativeCommands && (data.agent === "compact" || data.isCompactInternal === true)) {
|
|
21574
|
+
if (row.role === "assistant") {
|
|
21575
|
+
const outcome = row.status === "completed" && data.isCompacted === true ? { status: "succeeded" } : row.status === "cancelled" || row.status === "interrupted" ? { status: "cancelled" } : {
|
|
21576
|
+
status: "failed",
|
|
21577
|
+
error: nativeError(new CodeBuddyError("nativeFailure", "Native compaction did not complete"), profile)
|
|
21578
|
+
};
|
|
21579
|
+
current.items.push({
|
|
21580
|
+
item: {
|
|
21581
|
+
type: "contextCompaction",
|
|
21582
|
+
itemId: hostItemIdSchema.parse(`compact-${text(row.id)}`)
|
|
21583
|
+
},
|
|
21584
|
+
outcome
|
|
21585
|
+
});
|
|
21586
|
+
if (data.compactType === "user-command")
|
|
21587
|
+
current.outcome = outcome;
|
|
21588
|
+
}
|
|
21589
|
+
continue;
|
|
21590
|
+
}
|
|
21107
21591
|
const model = text(record2(row.providerData).model);
|
|
21108
21592
|
if (model)
|
|
21109
21593
|
current.model = modelRef(model);
|
|
21110
21594
|
if (row.type === "message" && row.role === "assistant" || row.type === "reasoning") {
|
|
21111
21595
|
const type = row.type === "reasoning" ? "reasoning" : "agentMessage";
|
|
21112
|
-
const
|
|
21113
|
-
if (
|
|
21596
|
+
const body2 = contentText(row.content) || contentText(row.rawContent);
|
|
21597
|
+
if (body2)
|
|
21114
21598
|
current.items.push({
|
|
21115
|
-
item: { type, itemId: hostItemIdSchema.parse(`${type}-${text(row.id)}`), text:
|
|
21599
|
+
item: { type, itemId: hostItemIdSchema.parse(`${type}-${text(row.id)}`), text: body2 },
|
|
21116
21600
|
outcome: { status: "succeeded" }
|
|
21117
21601
|
});
|
|
21118
21602
|
if (row.role === "assistant" && row.status === "completed") {
|
|
@@ -21131,8 +21615,8 @@ function snapshotFromHistory(contents, ref, cwd) {
|
|
|
21131
21615
|
}
|
|
21132
21616
|
const callId = text(row.callId);
|
|
21133
21617
|
const snapshot = {
|
|
21134
|
-
item: row.name === "Agent" ? codeBuddyDelegation(callId, input, "running") : toolItem(callId, text(row.name), input, cwd),
|
|
21135
|
-
outcome: toolOutcome("unknown")
|
|
21618
|
+
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),
|
|
21619
|
+
outcome: toolOutcome("unknown", profile)
|
|
21136
21620
|
};
|
|
21137
21621
|
tools.set(callId, snapshot);
|
|
21138
21622
|
current.items.push(snapshot);
|
|
@@ -21151,6 +21635,14 @@ function snapshotFromHistory(contents, ref, cwd) {
|
|
|
21151
21635
|
earlyResults.set(callId, row);
|
|
21152
21636
|
}
|
|
21153
21637
|
}
|
|
21638
|
+
if (supportsFork)
|
|
21639
|
+
for (const turn of turns)
|
|
21640
|
+
turn.checkpoint = nativeCheckpointRefSchema.parse({
|
|
21641
|
+
harnessId: profile.harnessId,
|
|
21642
|
+
nativeSessionId: ref.nativeSessionId,
|
|
21643
|
+
checkpointId: turn.nativeTurnRef.nativeTurnKey,
|
|
21644
|
+
formatVersion: 1
|
|
21645
|
+
});
|
|
21154
21646
|
return { turns };
|
|
21155
21647
|
}
|
|
21156
21648
|
function historyUsage(contents) {
|
|
@@ -21181,25 +21673,814 @@ function historyUsage(contents) {
|
|
|
21181
21673
|
return Object.keys(result).length ? result : null;
|
|
21182
21674
|
}
|
|
21183
21675
|
|
|
21676
|
+
// dist/child-provenance.js
|
|
21677
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
21678
|
+
import { realpath as realpath3 } from "node:fs/promises";
|
|
21679
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
21680
|
+
var CODEBUDDY_CHILD_MAX_BYTES = 8e6;
|
|
21681
|
+
var equalPath = (left, right) => process.platform === "win32" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
21682
|
+
function codeBuddyChildDigest(contents) {
|
|
21683
|
+
return createHash2("sha256").update(contents).digest("hex");
|
|
21684
|
+
}
|
|
21685
|
+
function parseCodeBuddyChild(contents, tolerateIncompleteTail) {
|
|
21686
|
+
const lines = contents.split(/\r?\n/u);
|
|
21687
|
+
if (tolerateIncompleteTail && lines.at(-1)?.trim()) {
|
|
21688
|
+
try {
|
|
21689
|
+
JSON.parse(lines.at(-1) ?? "");
|
|
21690
|
+
} catch {
|
|
21691
|
+
lines.pop();
|
|
21692
|
+
}
|
|
21693
|
+
}
|
|
21694
|
+
const entries = lines.filter((line) => line.trim()).map((line) => record2(JSON.parse(line)));
|
|
21695
|
+
return { contents: lines.join("\n"), entries };
|
|
21696
|
+
}
|
|
21697
|
+
function inheritedChildren(parent) {
|
|
21698
|
+
const value = record2(parent.locator).codebuddyInheritedChildren;
|
|
21699
|
+
if (value === void 0)
|
|
21700
|
+
return [];
|
|
21701
|
+
if (!Array.isArray(value) || value.length > 256)
|
|
21702
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is invalid");
|
|
21703
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21704
|
+
return value.map((candidate) => {
|
|
21705
|
+
const child = record2(candidate);
|
|
21706
|
+
const historicalCwds = child.historicalCwds;
|
|
21707
|
+
const recordedCwds = child.recordedCwds;
|
|
21708
|
+
const workspaceBindings = child.workspaceBindings;
|
|
21709
|
+
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)
|
|
21710
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is invalid");
|
|
21711
|
+
const bindings = workspaceBindings.map((candidate2) => {
|
|
21712
|
+
const binding = record2(candidate2);
|
|
21713
|
+
if (typeof binding.recordedCwd !== "string" || !binding.recordedCwd || typeof binding.canonicalCwd !== "string" || !binding.canonicalCwd)
|
|
21714
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is invalid");
|
|
21715
|
+
return {
|
|
21716
|
+
recordedCwd: binding.recordedCwd,
|
|
21717
|
+
canonicalCwd: binding.canonicalCwd
|
|
21718
|
+
};
|
|
21719
|
+
});
|
|
21720
|
+
const boundRecorded = new Set(bindings.map((binding) => binding.recordedCwd));
|
|
21721
|
+
const boundCanonical = new Set(bindings.map((binding) => binding.canonicalCwd));
|
|
21722
|
+
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)))
|
|
21723
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is inconsistent");
|
|
21724
|
+
const childId = text(child.childId);
|
|
21725
|
+
if (seen.has(childId))
|
|
21726
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is ambiguous");
|
|
21727
|
+
seen.add(childId);
|
|
21728
|
+
return {
|
|
21729
|
+
childId,
|
|
21730
|
+
nativeSessionId: text(child.nativeSessionId),
|
|
21731
|
+
inheritedBytes: Number(child.inheritedBytes),
|
|
21732
|
+
inheritedRows: Number(child.inheritedRows),
|
|
21733
|
+
inheritedSha256: child.inheritedSha256,
|
|
21734
|
+
recordedCwds: [...recordedCwds],
|
|
21735
|
+
historicalCwds: [...historicalCwds],
|
|
21736
|
+
workspaceBindings: bindings
|
|
21737
|
+
};
|
|
21738
|
+
});
|
|
21739
|
+
}
|
|
21740
|
+
function codeBuddyInheritedChild(parent, childId) {
|
|
21741
|
+
return inheritedChildren(parent).find((child) => child.childId === childId);
|
|
21742
|
+
}
|
|
21743
|
+
async function canonicalCwds(cwds) {
|
|
21744
|
+
const result = /* @__PURE__ */ new Map();
|
|
21745
|
+
for (const cwd of new Set(cwds)) {
|
|
21746
|
+
const canonical = await realpath3(cwd).catch((error51) => {
|
|
21747
|
+
if (["ENOENT", "ENOTDIR"].includes(String(record2(error51).code)))
|
|
21748
|
+
throw new CodeBuddyError("invalidRequest", "Subagent historical working directory is unavailable; ownership cannot be verified");
|
|
21749
|
+
throw error51;
|
|
21750
|
+
});
|
|
21751
|
+
result.set(cwd, canonical);
|
|
21752
|
+
}
|
|
21753
|
+
return result;
|
|
21754
|
+
}
|
|
21755
|
+
async function validateCodeBuddyChildContents(contents, parent, childId, cwd, tolerateIncompleteTail) {
|
|
21756
|
+
if (!validCodeBuddyChildId(childId))
|
|
21757
|
+
throw new CodeBuddyError("invalidRequest", "Invalid native Subagent ID");
|
|
21758
|
+
const parsed = parseCodeBuddyChild(contents, tolerateIncompleteTail);
|
|
21759
|
+
const sessions = new Set(parsed.entries.map((row) => text(row.sessionId)).filter(Boolean));
|
|
21760
|
+
if (sessions.size !== 1)
|
|
21761
|
+
throw new CodeBuddyError("protocolError", "Subagent transcript identity is missing or mixed");
|
|
21762
|
+
const nativeSessionId = [...sessions][0];
|
|
21763
|
+
if (!nativeSessionId || !/^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/u.test(nativeSessionId))
|
|
21764
|
+
throw new CodeBuddyError("protocolError", "Missing or invalid native child Session");
|
|
21765
|
+
const inherited = codeBuddyInheritedChild(parent, childId);
|
|
21766
|
+
let inheritedEntries = [];
|
|
21767
|
+
if (inherited) {
|
|
21768
|
+
const bytes = Buffer.from(contents, "utf8");
|
|
21769
|
+
if (inherited.inheritedBytes > bytes.length)
|
|
21770
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent prefix is incomplete");
|
|
21771
|
+
const prefix = bytes.subarray(0, inherited.inheritedBytes);
|
|
21772
|
+
const prefixText = prefix.toString("utf8");
|
|
21773
|
+
if (!isDeepStrictEqual2(Buffer.from(prefixText, "utf8"), prefix) || codeBuddyChildDigest(prefix) !== inherited.inheritedSha256)
|
|
21774
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent prefix verification failed");
|
|
21775
|
+
let prefixParsed;
|
|
21776
|
+
try {
|
|
21777
|
+
prefixParsed = parseCodeBuddyChild(prefixText, false);
|
|
21778
|
+
} catch {
|
|
21779
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent prefix is malformed");
|
|
21780
|
+
}
|
|
21781
|
+
if (prefixParsed.entries.length !== inherited.inheritedRows || parsed.entries.length < inherited.inheritedRows || !isDeepStrictEqual2(prefixParsed.entries, parsed.entries.slice(0, inherited.inheritedRows)) || nativeSessionId !== inherited.nativeSessionId)
|
|
21782
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent identity changed");
|
|
21783
|
+
inheritedEntries = prefixParsed.entries;
|
|
21784
|
+
}
|
|
21785
|
+
const target = await realpath3(cwd);
|
|
21786
|
+
const inheritedCwds = inheritedEntries.flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []);
|
|
21787
|
+
const suffixCwds = parsed.entries.slice(inheritedEntries.length).flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []);
|
|
21788
|
+
const canonical = await canonicalCwds(suffixCwds);
|
|
21789
|
+
if (inherited) {
|
|
21790
|
+
const allowed = new Set(inherited.recordedCwds);
|
|
21791
|
+
const observed = new Set(inheritedCwds);
|
|
21792
|
+
if (allowed.size !== observed.size || [...allowed].some((value) => !observed.has(value)) || inheritedCwds.some((value) => !allowed.has(value)))
|
|
21793
|
+
throw new CodeBuddyError("invalidRequest", "Inherited Subagent workspace changed");
|
|
21794
|
+
}
|
|
21795
|
+
for (const value of suffixCwds) {
|
|
21796
|
+
const actual = canonical.get(value);
|
|
21797
|
+
if (!actual || !equalPath(actual, target))
|
|
21798
|
+
throw new CodeBuddyError("invalidRequest", "Subagent workspace differs from parent");
|
|
21799
|
+
}
|
|
21800
|
+
const bindings = new Map((inherited?.workspaceBindings ?? []).map((binding) => [
|
|
21801
|
+
binding.recordedCwd,
|
|
21802
|
+
binding.canonicalCwd
|
|
21803
|
+
]));
|
|
21804
|
+
for (const value of new Set(suffixCwds)) {
|
|
21805
|
+
const resolved = canonical.get(value);
|
|
21806
|
+
if (!resolved)
|
|
21807
|
+
throw new CodeBuddyError("invalidRequest", "Subagent workspace is unavailable");
|
|
21808
|
+
const existing = bindings.get(value);
|
|
21809
|
+
if (existing && !equalPath(existing, resolved))
|
|
21810
|
+
throw new CodeBuddyError("invalidRequest", "Subagent workspace binding changed");
|
|
21811
|
+
bindings.set(value, resolved);
|
|
21812
|
+
}
|
|
21813
|
+
return {
|
|
21814
|
+
...parsed,
|
|
21815
|
+
nativeSessionId,
|
|
21816
|
+
recordedCwds: [...bindings.keys()],
|
|
21817
|
+
historicalCwds: [...new Set(bindings.values())],
|
|
21818
|
+
workspaceBindings: [...bindings].map(([recordedCwd, canonicalCwd]) => ({
|
|
21819
|
+
recordedCwd,
|
|
21820
|
+
canonicalCwd
|
|
21821
|
+
}))
|
|
21822
|
+
};
|
|
21823
|
+
}
|
|
21824
|
+
function codeBuddyInheritedChildDescriptor(childId, contents, child) {
|
|
21825
|
+
if (child.recordedCwds.length > 256 || child.historicalCwds.length > 256)
|
|
21826
|
+
throw new CodeBuddyError("unsupported", "Too many Subagent historical workspaces");
|
|
21827
|
+
return {
|
|
21828
|
+
childId,
|
|
21829
|
+
nativeSessionId: child.nativeSessionId,
|
|
21830
|
+
inheritedBytes: Buffer.byteLength(contents, "utf8"),
|
|
21831
|
+
inheritedRows: child.entries.length,
|
|
21832
|
+
inheritedSha256: codeBuddyChildDigest(contents),
|
|
21833
|
+
recordedCwds: child.recordedCwds,
|
|
21834
|
+
historicalCwds: child.historicalCwds,
|
|
21835
|
+
workspaceBindings: child.workspaceBindings
|
|
21836
|
+
};
|
|
21837
|
+
}
|
|
21838
|
+
async function codeBuddyChildPrefixThrough(contents, lastId, child) {
|
|
21839
|
+
let cursor = 0;
|
|
21840
|
+
let rowIndex = 0;
|
|
21841
|
+
let match = -1;
|
|
21842
|
+
let end = -1;
|
|
21843
|
+
while (cursor < contents.length) {
|
|
21844
|
+
const newline2 = contents.indexOf("\n", cursor);
|
|
21845
|
+
const next = newline2 < 0 ? contents.length : newline2 + 1;
|
|
21846
|
+
const physicalLine = contents.slice(cursor, next);
|
|
21847
|
+
const line = physicalLine.replace(/\r?\n$/u, "");
|
|
21848
|
+
if (line.trim()) {
|
|
21849
|
+
const row = child.entries[rowIndex++];
|
|
21850
|
+
if (!row)
|
|
21851
|
+
throw new CodeBuddyError("protocolError", "Subagent transcript rows changed");
|
|
21852
|
+
if (text(row.id) === lastId) {
|
|
21853
|
+
if (match >= 0)
|
|
21854
|
+
throw new CodeBuddyError("protocolError", "Agent result has an ambiguous child range");
|
|
21855
|
+
match = rowIndex - 1;
|
|
21856
|
+
end = next;
|
|
21857
|
+
}
|
|
21858
|
+
}
|
|
21859
|
+
cursor = next;
|
|
21860
|
+
}
|
|
21861
|
+
if (rowIndex !== child.entries.length || match < 0 || end < 0)
|
|
21862
|
+
throw new CodeBuddyError("protocolError", "Agent result child range was not found");
|
|
21863
|
+
const entries = child.entries.slice(0, match + 1);
|
|
21864
|
+
const cwdValues = entries.flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []);
|
|
21865
|
+
const inheritedBindings = new Map(child.workspaceBindings.map((binding) => [binding.recordedCwd, binding.canonicalCwd]));
|
|
21866
|
+
const bindings = [...new Set(cwdValues)].map((recordedCwd) => {
|
|
21867
|
+
const canonicalCwd = inheritedBindings.get(recordedCwd);
|
|
21868
|
+
if (!canonicalCwd)
|
|
21869
|
+
throw new CodeBuddyError("protocolError", "Subagent workspace binding is missing");
|
|
21870
|
+
return { recordedCwd, canonicalCwd };
|
|
21871
|
+
});
|
|
21872
|
+
return {
|
|
21873
|
+
contents: contents.slice(0, end),
|
|
21874
|
+
child: {
|
|
21875
|
+
contents: contents.slice(0, end),
|
|
21876
|
+
entries,
|
|
21877
|
+
nativeSessionId: child.nativeSessionId,
|
|
21878
|
+
recordedCwds: bindings.map((binding) => binding.recordedCwd),
|
|
21879
|
+
historicalCwds: [...new Set(bindings.map((binding) => binding.canonicalCwd))],
|
|
21880
|
+
workspaceBindings: bindings
|
|
21881
|
+
}
|
|
21882
|
+
};
|
|
21883
|
+
}
|
|
21884
|
+
|
|
21885
|
+
// dist/derivation.js
|
|
21886
|
+
async function copyCodeBuddySession(cwd, sourceId, targetId, environment, signal, invocationFactory = codeBuddyInvocation) {
|
|
21887
|
+
if (signal.aborted)
|
|
21888
|
+
throw new CodeBuddyError("invalidState", "Adapter closed before history copy");
|
|
21889
|
+
const invocation = invocationFactory(environment, false, [
|
|
21890
|
+
"--resume",
|
|
21891
|
+
sourceId,
|
|
21892
|
+
"--fork-session",
|
|
21893
|
+
"--session-id",
|
|
21894
|
+
targetId,
|
|
21895
|
+
"--print",
|
|
21896
|
+
"--input-format",
|
|
21897
|
+
"stream-json",
|
|
21898
|
+
"--output-format",
|
|
21899
|
+
"stream-json"
|
|
21900
|
+
]);
|
|
21901
|
+
await new Promise((resolve, reject) => {
|
|
21902
|
+
const child = spawn2(invocation.command, invocation.arguments, {
|
|
21903
|
+
cwd,
|
|
21904
|
+
env: invocation.environment,
|
|
21905
|
+
stdio: "pipe",
|
|
21906
|
+
windowsHide: true,
|
|
21907
|
+
windowsVerbatimArguments: invocation.windowsVerbatimArguments,
|
|
21908
|
+
detached: process.platform !== "win32"
|
|
21909
|
+
});
|
|
21910
|
+
let output = "", bytes = 0, failed = false;
|
|
21911
|
+
let termination = Promise.resolve();
|
|
21912
|
+
const stop = () => {
|
|
21913
|
+
if (failed)
|
|
21914
|
+
return;
|
|
21915
|
+
failed = true;
|
|
21916
|
+
if (child.exitCode !== null || child.signalCode !== null) {
|
|
21917
|
+
child.stdout.destroy();
|
|
21918
|
+
child.stderr.destroy();
|
|
21919
|
+
} else if (process.platform === "win32" && child.pid) {
|
|
21920
|
+
termination = new Promise((done) => {
|
|
21921
|
+
execFile2("taskkill", ["/PID", String(child.pid), "/T", "/F"], { windowsHide: true, timeout: 3e3 }, () => {
|
|
21922
|
+
child.kill();
|
|
21923
|
+
done();
|
|
21924
|
+
});
|
|
21925
|
+
});
|
|
21926
|
+
} else if (child.pid) {
|
|
21927
|
+
try {
|
|
21928
|
+
process.kill(-child.pid, "SIGKILL");
|
|
21929
|
+
} catch {
|
|
21930
|
+
child.kill("SIGKILL");
|
|
21931
|
+
}
|
|
21932
|
+
} else
|
|
21933
|
+
child.kill("SIGKILL");
|
|
21934
|
+
};
|
|
21935
|
+
const timer = setTimeout(stop, 3e4);
|
|
21936
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
21937
|
+
child.stdout.on("data", (data) => {
|
|
21938
|
+
bytes += data.length;
|
|
21939
|
+
if (bytes > 64e6) {
|
|
21940
|
+
stop();
|
|
21941
|
+
return;
|
|
21942
|
+
}
|
|
21943
|
+
output += data.toString();
|
|
21944
|
+
});
|
|
21945
|
+
child.stderr.resume();
|
|
21946
|
+
child.stdin.on("error", () => {
|
|
21947
|
+
});
|
|
21948
|
+
child.once("error", reject);
|
|
21949
|
+
child.once("close", async (code) => {
|
|
21950
|
+
await termination;
|
|
21951
|
+
clearTimeout(timer);
|
|
21952
|
+
signal.removeEventListener("abort", stop);
|
|
21953
|
+
if (failed || signal.aborted || code !== 0) {
|
|
21954
|
+
reject(new CodeBuddyError("nativeFailure", "Native history copy failed or was interrupted"));
|
|
21955
|
+
return;
|
|
21956
|
+
}
|
|
21957
|
+
try {
|
|
21958
|
+
const rows2 = output.trim().split(/\r?\n/u).filter(Boolean).map((line) => record2(JSON.parse(line)));
|
|
21959
|
+
const init = rows2.find((row) => row.type === "system" && row.subtype === "init");
|
|
21960
|
+
const result = rows2.findLast((row) => row.type === "result");
|
|
21961
|
+
if (init?.session_id !== targetId || result?.session_id !== targetId || result?.is_error !== false || result?.duration_api_ms !== 0)
|
|
21962
|
+
throw new CodeBuddyError("unsupported", "Native CLI did not confirm a model-free history copy");
|
|
21963
|
+
resolve();
|
|
21964
|
+
} catch (error51) {
|
|
21965
|
+
reject(error51);
|
|
21966
|
+
}
|
|
21967
|
+
});
|
|
21968
|
+
if (signal.aborted)
|
|
21969
|
+
stop();
|
|
21970
|
+
child.stdin.end();
|
|
21971
|
+
});
|
|
21972
|
+
}
|
|
21973
|
+
function withoutIdentity(row) {
|
|
21974
|
+
const result = { ...row };
|
|
21975
|
+
delete result.id;
|
|
21976
|
+
delete result.parentId;
|
|
21977
|
+
delete result.logicalParentId;
|
|
21978
|
+
delete result.sessionId;
|
|
21979
|
+
return result;
|
|
21980
|
+
}
|
|
21981
|
+
function assertCopiedPrefix(source, copied) {
|
|
21982
|
+
if (copied.length < source.length)
|
|
21983
|
+
throw new CodeBuddyError("unsupported", "Native Fork omitted history");
|
|
21984
|
+
const ids = new Map(source.map((row, index) => [text(row.id), text(copied[index]?.id)]));
|
|
21985
|
+
for (const [index, row] of source.entries()) {
|
|
21986
|
+
const clone2 = copied[index];
|
|
21987
|
+
if (!clone2)
|
|
21988
|
+
throw new CodeBuddyError("unsupported", "Native Fork omitted history");
|
|
21989
|
+
if (!isDeepStrictEqual3(withoutIdentity(row), withoutIdentity(clone2)) || ["parentId", "logicalParentId"].some((key) => text(clone2[key]) !== (ids.get(text(row[key])) ?? "")))
|
|
21990
|
+
throw new CodeBuddyError("unsupported", "Native Fork did not preserve the exact history prefix");
|
|
21991
|
+
}
|
|
21992
|
+
}
|
|
21993
|
+
function commandCaveat(row) {
|
|
21994
|
+
return record2(row?.providerData).skipRun === true && JSON.stringify(row?.content).includes('data-role=\\"command-caveat\\"');
|
|
21995
|
+
}
|
|
21996
|
+
function retainedRowCount(input, contents, sourceCwd = input.cwd, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21997
|
+
const rows2 = nativeHistoryRows(contents);
|
|
21998
|
+
const turns = snapshotFromHistory(contents, input.sourceRef, sourceCwd, profile).turns;
|
|
21999
|
+
let excluded2;
|
|
22000
|
+
if (input.kind === "rollbackLastTurn") {
|
|
22001
|
+
if (!turns.length)
|
|
22002
|
+
throw new CodeBuddyError("invalidState", "Native Session has no Turn to revise");
|
|
22003
|
+
excluded2 = turns.at(-1)?.nativeTurnRef.nativeTurnKey;
|
|
22004
|
+
} else {
|
|
22005
|
+
const checkpoint = input.checkpoint;
|
|
22006
|
+
const index = turns.findIndex((turn) => turn.nativeTurnRef.nativeTurnKey === checkpoint.checkpointId);
|
|
22007
|
+
if (checkpoint.harnessId !== profile.harnessId || checkpoint.nativeSessionId !== input.sourceRef.nativeSessionId || checkpoint.formatVersion !== 1 || index < 0)
|
|
22008
|
+
throw new CodeBuddyError("checkpointNotFound", "Native Fork checkpoint was not found");
|
|
22009
|
+
excluded2 = turns[index + 1]?.nativeTurnRef.nativeTurnKey;
|
|
22010
|
+
}
|
|
22011
|
+
let count = excluded2 ? rows2.findIndex((row) => row.id === excluded2) : rows2.length;
|
|
22012
|
+
if (count < 0)
|
|
22013
|
+
throw new CodeBuddyError("protocolError", "Native Turn boundary is missing");
|
|
22014
|
+
if (excluded2)
|
|
22015
|
+
while (count > 0 && commandCaveat(rows2[count - 1]))
|
|
22016
|
+
count--;
|
|
22017
|
+
return count;
|
|
22018
|
+
}
|
|
22019
|
+
function sameResolvedPath(left, right) {
|
|
22020
|
+
const a = codeBuddyCanonicalCwd(left), b = codeBuddyCanonicalCwd(right);
|
|
22021
|
+
return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
22022
|
+
}
|
|
22023
|
+
async function bridgeCopyToTarget(sourceCwd, targetCwd, ref, contents, environment, profile) {
|
|
22024
|
+
const sourceFile = codeBuddyPrimaryHistoryPath(sourceCwd, ref, environment, profile);
|
|
22025
|
+
const targetFile = codeBuddyPrimaryHistoryPath(targetCwd, ref, environment, profile);
|
|
22026
|
+
if (sameResolvedPath(sourceFile, targetFile))
|
|
22027
|
+
return void 0;
|
|
22028
|
+
const targetDirectory = path5.dirname(targetFile);
|
|
22029
|
+
const projectsDirectory = path5.dirname(targetDirectory);
|
|
22030
|
+
await mkdir(targetDirectory, { recursive: true });
|
|
22031
|
+
const [realProjects, realTargetDirectory] = await Promise.all([
|
|
22032
|
+
realpath4(projectsDirectory),
|
|
22033
|
+
realpath4(targetDirectory)
|
|
22034
|
+
]);
|
|
22035
|
+
if (!sameResolvedPath(realTargetDirectory, path5.join(realProjects, codeBuddyProjectSlug(targetCwd, profile))))
|
|
22036
|
+
throw new CodeBuddyError("invalidRequest", "Cross-directory history bridge target escaped the native projects root");
|
|
22037
|
+
const expected = Buffer.from(contents, "utf8");
|
|
22038
|
+
await writeFile(targetFile, expected, { flag: "wx", mode: 384 });
|
|
22039
|
+
const bridge = { file: targetFile, expected };
|
|
22040
|
+
try {
|
|
22041
|
+
const persisted = await readFile2(targetFile);
|
|
22042
|
+
if (!isDeepStrictEqual3(persisted, expected))
|
|
22043
|
+
throw new CodeBuddyError("nativeFailure", "Cross-directory history bridge changed native bytes");
|
|
22044
|
+
return bridge;
|
|
22045
|
+
} catch (error51) {
|
|
22046
|
+
return failAfterBridgeCleanup(error51, bridge);
|
|
22047
|
+
}
|
|
22048
|
+
}
|
|
22049
|
+
async function cleanupBridge(bridge) {
|
|
22050
|
+
if (!bridge)
|
|
22051
|
+
return;
|
|
22052
|
+
try {
|
|
22053
|
+
const info = await lstat(bridge.file);
|
|
22054
|
+
if (!info.isFile() || process.platform !== "win32" && (info.mode & 63) !== 0)
|
|
22055
|
+
return;
|
|
22056
|
+
if (!isDeepStrictEqual3(await readFile2(bridge.file), bridge.expected))
|
|
22057
|
+
return;
|
|
22058
|
+
await unlink(bridge.file);
|
|
22059
|
+
} catch (error51) {
|
|
22060
|
+
if (record2(error51).code !== "ENOENT")
|
|
22061
|
+
throw error51;
|
|
22062
|
+
}
|
|
22063
|
+
}
|
|
22064
|
+
async function failAfterBridgeCleanup(failure2, bridge) {
|
|
22065
|
+
try {
|
|
22066
|
+
await cleanupBridge(bridge);
|
|
22067
|
+
} catch (cleanupFailure) {
|
|
22068
|
+
throw new AggregateError([failure2, cleanupFailure], "Native derivation and bridge cleanup both failed");
|
|
22069
|
+
}
|
|
22070
|
+
throw failure2;
|
|
22071
|
+
}
|
|
22072
|
+
function argumentsRecord(value) {
|
|
22073
|
+
if (typeof value !== "string")
|
|
22074
|
+
return record2(value);
|
|
22075
|
+
try {
|
|
22076
|
+
return record2(JSON.parse(value));
|
|
22077
|
+
} catch {
|
|
22078
|
+
return {};
|
|
22079
|
+
}
|
|
22080
|
+
}
|
|
22081
|
+
function referencedChildren(rows2) {
|
|
22082
|
+
const calls = /* @__PURE__ */ new Map();
|
|
22083
|
+
const children = /* @__PURE__ */ new Map();
|
|
22084
|
+
for (const row of rows2) {
|
|
22085
|
+
if (row.type === "function_call" && row.name === "Agent") {
|
|
22086
|
+
const callId2 = text(row.callId);
|
|
22087
|
+
if (!callId2 || calls.has(callId2))
|
|
22088
|
+
throw new CodeBuddyError("protocolError", "Agent delegation identity is ambiguous");
|
|
22089
|
+
const resumed2 = text(argumentsRecord(row.arguments).resume);
|
|
22090
|
+
if (resumed2 && !validCodeBuddyChildId(resumed2))
|
|
22091
|
+
throw new CodeBuddyError("protocolError", "Agent delegation has an invalid child identity");
|
|
22092
|
+
calls.set(callId2, resumed2 || void 0);
|
|
22093
|
+
continue;
|
|
22094
|
+
}
|
|
22095
|
+
if (row.type !== "function_call_result")
|
|
22096
|
+
continue;
|
|
22097
|
+
const callId = text(row.callId);
|
|
22098
|
+
if (!calls.has(callId))
|
|
22099
|
+
continue;
|
|
22100
|
+
const subagent = record2(record2(record2(row.providerData).toolResult).subAgent);
|
|
22101
|
+
const childId = text(subagent.sessionId);
|
|
22102
|
+
if (!validCodeBuddyChildId(childId))
|
|
22103
|
+
throw new CodeBuddyError("unsupported", "Retained Agent result has no verified native child identity");
|
|
22104
|
+
const resumed = calls.get(callId);
|
|
22105
|
+
if (resumed && resumed !== childId)
|
|
22106
|
+
throw new CodeBuddyError("protocolError", "Agent result changed its child identity");
|
|
22107
|
+
const lastId = text(subagent.lastId);
|
|
22108
|
+
const afterId = text(subagent.afterId);
|
|
22109
|
+
if (!lastId)
|
|
22110
|
+
throw new CodeBuddyError("unsupported", "Retained Agent result has no bounded child transcript range");
|
|
22111
|
+
const child = children.get(childId) ?? { childId, ranges: [] };
|
|
22112
|
+
child.ranges.push({ ...afterId ? { afterId } : {}, lastId });
|
|
22113
|
+
children.set(childId, child);
|
|
22114
|
+
if (children.size > 256)
|
|
22115
|
+
throw new CodeBuddyError("unsupported", "Too many retained Subagent transcripts");
|
|
22116
|
+
calls.delete(callId);
|
|
22117
|
+
}
|
|
22118
|
+
if (calls.size)
|
|
22119
|
+
throw new CodeBuddyError("unsupported", "Retained Agent delegation is incomplete");
|
|
22120
|
+
return [...children.values()];
|
|
22121
|
+
}
|
|
22122
|
+
function assertChildRanges(rows2, child) {
|
|
22123
|
+
const positions = /* @__PURE__ */ new Map();
|
|
22124
|
+
for (const [index, row] of rows2.entries()) {
|
|
22125
|
+
const id = text(row.id);
|
|
22126
|
+
if (!id)
|
|
22127
|
+
continue;
|
|
22128
|
+
const matches = positions.get(id) ?? [];
|
|
22129
|
+
matches.push(index);
|
|
22130
|
+
positions.set(id, matches);
|
|
22131
|
+
}
|
|
22132
|
+
let previous = -1;
|
|
22133
|
+
for (const range of child.ranges) {
|
|
22134
|
+
const last = positions.get(range.lastId);
|
|
22135
|
+
const after = range.afterId ? positions.get(range.afterId) : void 0;
|
|
22136
|
+
if (last?.length !== 1 || after && after.length !== 1 || range.afterId && !after || after && (after[0] ?? -1) >= (last[0] ?? -1) || (last[0] ?? -1) < previous)
|
|
22137
|
+
throw new CodeBuddyError("protocolError", "Agent result child range is inconsistent");
|
|
22138
|
+
previous = last[0] ?? -1;
|
|
22139
|
+
}
|
|
22140
|
+
}
|
|
22141
|
+
async function plainDirectory(parent, name) {
|
|
22142
|
+
const directory = path5.join(parent, name);
|
|
22143
|
+
await mkdir(directory, { mode: 448 }).catch((error51) => {
|
|
22144
|
+
if (record2(error51).code !== "EEXIST")
|
|
22145
|
+
throw error51;
|
|
22146
|
+
});
|
|
22147
|
+
const info = await lstat(directory);
|
|
22148
|
+
if (!info.isDirectory() || info.isSymbolicLink() || process.platform !== "win32" && (info.mode & 18) !== 0)
|
|
22149
|
+
throw new CodeBuddyError("invalidRequest", "Redirected native Subagent directory");
|
|
22150
|
+
const actual = await realpath4(directory);
|
|
22151
|
+
if (!sameResolvedPath(actual, directory))
|
|
22152
|
+
throw new CodeBuddyError("invalidRequest", "Redirected native Subagent directory");
|
|
22153
|
+
return directory;
|
|
22154
|
+
}
|
|
22155
|
+
async function verifiedChildFile(file2, expected) {
|
|
22156
|
+
const info = await lstat(file2);
|
|
22157
|
+
if (!info.isFile() || info.isSymbolicLink() || process.platform !== "win32" && (info.mode & 63) !== 0)
|
|
22158
|
+
throw new CodeBuddyError("invalidRequest", "Unsafe derived Subagent transcript");
|
|
22159
|
+
if (!sameResolvedPath(await realpath4(file2), file2))
|
|
22160
|
+
throw new CodeBuddyError("invalidRequest", "Redirected derived Subagent transcript");
|
|
22161
|
+
const before = await codeBuddyFileVersion(file2);
|
|
22162
|
+
const actual = await readCodeBuddyVersionedText(file2, CODEBUDDY_CHILD_MAX_BYTES, "Subagent transcript exceeds 8 MB", before);
|
|
22163
|
+
if (!actual.reusableVersion || !sameCodeBuddyFileVersion(before, actual.reusableVersion) || !isDeepStrictEqual3(Buffer.from(actual.contents, "utf8"), expected))
|
|
22164
|
+
throw new CodeBuddyError("nativeFailure", "Native Fork produced a different Subagent transcript");
|
|
22165
|
+
}
|
|
22166
|
+
async function persistChildCopy(file2, expected) {
|
|
22167
|
+
try {
|
|
22168
|
+
await writeFile(file2, expected, { flag: "wx", mode: 384 });
|
|
22169
|
+
} catch (error51) {
|
|
22170
|
+
if (record2(error51).code !== "EEXIST")
|
|
22171
|
+
throw error51;
|
|
22172
|
+
await verifiedChildFile(file2, expected);
|
|
22173
|
+
return void 0;
|
|
22174
|
+
}
|
|
22175
|
+
const copy = { file: file2, expected };
|
|
22176
|
+
try {
|
|
22177
|
+
await verifiedChildFile(file2, expected);
|
|
22178
|
+
return copy;
|
|
22179
|
+
} catch (error51) {
|
|
22180
|
+
return failAfterBridgeCleanup(error51, copy);
|
|
22181
|
+
}
|
|
22182
|
+
}
|
|
22183
|
+
async function copyInheritedChildren(options) {
|
|
22184
|
+
const { references } = options;
|
|
22185
|
+
if (!references.length)
|
|
22186
|
+
return { descriptors: [], created: [] };
|
|
22187
|
+
const sourceHistoryFile = await realpath4(options.sourceHistoryFile);
|
|
22188
|
+
const sourceProject = path5.dirname(sourceHistoryFile);
|
|
22189
|
+
if (!sameResolvedPath(sourceHistoryFile, path5.join(sourceProject, `${options.sourceRef.nativeSessionId}.jsonl`)))
|
|
22190
|
+
throw new CodeBuddyError("invalidRequest", "Unexpected source history location");
|
|
22191
|
+
const sourceDirectory = path5.join(sourceProject, options.sourceRef.nativeSessionId, "subagents");
|
|
22192
|
+
const sourceDirectoryInfo = await lstat(sourceDirectory);
|
|
22193
|
+
if (!sourceDirectoryInfo.isDirectory() || sourceDirectoryInfo.isSymbolicLink())
|
|
22194
|
+
throw new CodeBuddyError("invalidRequest", "Redirected source Subagent directory");
|
|
22195
|
+
if (!sameResolvedPath(await realpath4(sourceDirectory), sourceDirectory))
|
|
22196
|
+
throw new CodeBuddyError("invalidRequest", "Redirected source Subagent directory");
|
|
22197
|
+
const targetHistoryFile = await realpath4(options.targetHistoryFile);
|
|
22198
|
+
const targetProject = path5.dirname(targetHistoryFile);
|
|
22199
|
+
if (!sameResolvedPath(targetHistoryFile, path5.join(targetProject, `${options.targetRef.nativeSessionId}.jsonl`)))
|
|
22200
|
+
throw new CodeBuddyError("invalidRequest", "Unexpected target history location");
|
|
22201
|
+
const targetSessionDirectory = await plainDirectory(targetProject, options.targetRef.nativeSessionId);
|
|
22202
|
+
const targetDirectory = await plainDirectory(targetSessionDirectory, "subagents");
|
|
22203
|
+
const descriptors = [];
|
|
22204
|
+
const created = [];
|
|
22205
|
+
try {
|
|
22206
|
+
for (const reference of references) {
|
|
22207
|
+
const sourceFile = path5.join(sourceDirectory, `${reference.childId}.jsonl`);
|
|
22208
|
+
const sourceInfo = await lstat(sourceFile);
|
|
22209
|
+
if (!sourceInfo.isFile() || sourceInfo.isSymbolicLink())
|
|
22210
|
+
throw new CodeBuddyError("invalidRequest", "Redirected source Subagent transcript");
|
|
22211
|
+
const before = await codeBuddyFileVersion(sourceFile);
|
|
22212
|
+
if (!sameResolvedPath(before.realFile, sourceFile))
|
|
22213
|
+
throw new CodeBuddyError("invalidRequest", "Redirected source Subagent transcript");
|
|
22214
|
+
if (before.size > CODEBUDDY_CHILD_MAX_BYTES)
|
|
22215
|
+
throw new CodeBuddyError("unsupported", "Subagent transcript exceeds 8 MB");
|
|
22216
|
+
const source = await readCodeBuddyVersionedText(sourceFile, CODEBUDDY_CHILD_MAX_BYTES, "Subagent transcript exceeds 8 MB", before);
|
|
22217
|
+
if (!source.reusableVersion)
|
|
22218
|
+
throw new CodeBuddyError("sessionBusy", "Source Subagent changed during Fork");
|
|
22219
|
+
const validated = await validateCodeBuddyChildContents(source.contents, options.sourceRef, reference.childId, options.sourceCwd, false);
|
|
22220
|
+
assertChildRanges(validated.entries, reference);
|
|
22221
|
+
const last = reference.ranges.at(-1)?.lastId;
|
|
22222
|
+
if (!last)
|
|
22223
|
+
throw new CodeBuddyError("protocolError", "Missing Agent result child range");
|
|
22224
|
+
const prefix = await codeBuddyChildPrefixThrough(source.contents, last, validated);
|
|
22225
|
+
const expected = Buffer.from(prefix.contents, "utf8");
|
|
22226
|
+
const targetFile = path5.join(targetDirectory, `${reference.childId}.jsonl`);
|
|
22227
|
+
const copy = await persistChildCopy(targetFile, expected);
|
|
22228
|
+
if (copy)
|
|
22229
|
+
created.push(copy);
|
|
22230
|
+
const after = await readCodeBuddyVersionedText(sourceFile, CODEBUDDY_CHILD_MAX_BYTES, "Subagent transcript exceeds 8 MB", before);
|
|
22231
|
+
if (!after.reusableVersion || !sameCodeBuddyFileVersion(before, after.reusableVersion) || after.contents !== source.contents)
|
|
22232
|
+
throw new CodeBuddyError("sessionBusy", "Source Subagent changed during Fork");
|
|
22233
|
+
descriptors.push(codeBuddyInheritedChildDescriptor(reference.childId, prefix.contents, prefix.child));
|
|
22234
|
+
}
|
|
22235
|
+
return { descriptors, created };
|
|
22236
|
+
} catch (failure2) {
|
|
22237
|
+
const cleanupFailures = [];
|
|
22238
|
+
for (const copy of created.toReversed()) {
|
|
22239
|
+
try {
|
|
22240
|
+
await cleanupBridge(copy);
|
|
22241
|
+
} catch (error51) {
|
|
22242
|
+
cleanupFailures.push(error51);
|
|
22243
|
+
}
|
|
22244
|
+
}
|
|
22245
|
+
if (cleanupFailures.length)
|
|
22246
|
+
throw new AggregateError([failure2, ...cleanupFailures], "Subagent copy and cleanup both failed");
|
|
22247
|
+
throw failure2;
|
|
22248
|
+
}
|
|
22249
|
+
}
|
|
22250
|
+
async function deriveCodeBuddySession(options) {
|
|
22251
|
+
const { input, environment, factory, signal } = options;
|
|
22252
|
+
const sourceCwd = options.sourceCwd ?? input.cwd;
|
|
22253
|
+
const profile = options.profile ?? CODEBUDDY_RUNTIME_PROFILE;
|
|
22254
|
+
const strictHistoryBinding = profile.historyCapabilities?.forkAcrossCwd === true;
|
|
22255
|
+
validateNativeRef(input.sourceRef, profile);
|
|
22256
|
+
const source = await codeBuddyNativeHistory(sourceCwd, input.sourceRef, environment, profile);
|
|
22257
|
+
const retained = retainedRowCount(input, source.contents, sourceCwd, profile);
|
|
22258
|
+
const sourceRows = nativeHistoryRows(source.contents);
|
|
22259
|
+
const childReferences = referencedChildren(sourceRows.slice(0, retained));
|
|
22260
|
+
const temporary = nativeSessionRefSchema.parse({
|
|
22261
|
+
harnessId: profile.harnessId,
|
|
22262
|
+
nativeSessionId: randomUUID(),
|
|
22263
|
+
formatVersion: 1
|
|
22264
|
+
});
|
|
22265
|
+
await (options.copy ?? copyCodeBuddySession)(sourceCwd, input.sourceRef.nativeSessionId, temporary.nativeSessionId, environment, signal, options.invocationFactory ?? codeBuddyInvocation);
|
|
22266
|
+
const nativeCopy = await codeBuddyNativeHistory(sourceCwd, temporary, environment, profile, {
|
|
22267
|
+
...strictHistoryBinding ? { requirePrimary: true } : {},
|
|
22268
|
+
inheritedContents: source.contents
|
|
22269
|
+
});
|
|
22270
|
+
if (!isDeepStrictEqual3(nativeHistoryRows(nativeCopy.contents), sourceRows))
|
|
22271
|
+
throw new CodeBuddyError("unsupported", "Native history copy changed the source prefix");
|
|
22272
|
+
const bridge = strictHistoryBinding ? await bridgeCopyToTarget(sourceCwd, input.cwd, temporary, nativeCopy.contents, environment, profile) : void 0;
|
|
22273
|
+
if (strictHistoryBinding) {
|
|
22274
|
+
let targetCopy;
|
|
22275
|
+
try {
|
|
22276
|
+
targetCopy = await codeBuddyNativeHistory(input.cwd, temporary, environment, profile, {
|
|
22277
|
+
requirePrimary: true,
|
|
22278
|
+
inheritedContents: nativeCopy.contents
|
|
22279
|
+
});
|
|
22280
|
+
} catch (error51) {
|
|
22281
|
+
return failAfterBridgeCleanup(error51, bridge);
|
|
22282
|
+
}
|
|
22283
|
+
if (targetCopy.contents !== nativeCopy.contents) {
|
|
22284
|
+
return failAfterBridgeCleanup(new CodeBuddyError("nativeFailure", "Cross-directory history bridge changed native bytes"), bridge);
|
|
22285
|
+
}
|
|
22286
|
+
}
|
|
22287
|
+
let derivedId;
|
|
22288
|
+
let failure2;
|
|
22289
|
+
let inheritedChildCopies = [];
|
|
22290
|
+
let derivationSucceeded = false;
|
|
22291
|
+
let receiveCommands;
|
|
22292
|
+
const commands = new Promise((resolve) => {
|
|
22293
|
+
receiveCommands = resolve;
|
|
22294
|
+
});
|
|
22295
|
+
let client2;
|
|
22296
|
+
try {
|
|
22297
|
+
client2 = factory({
|
|
22298
|
+
cwd: input.cwd,
|
|
22299
|
+
environment,
|
|
22300
|
+
ephemeral: false,
|
|
22301
|
+
temporarySessionId: temporary.nativeSessionId,
|
|
22302
|
+
handlers: {
|
|
22303
|
+
permission: async () => ({ outcome: { outcome: "cancelled" } }),
|
|
22304
|
+
question: async () => ({ outcome: "cancelled" }),
|
|
22305
|
+
fault: (error51) => {
|
|
22306
|
+
failure2 = error51;
|
|
22307
|
+
},
|
|
22308
|
+
update: ({ sessionId, update }) => {
|
|
22309
|
+
if (record2(update).sessionUpdate === "available_commands_update")
|
|
22310
|
+
receiveCommands(record2(update).availableCommands);
|
|
22311
|
+
const meta3 = record2(record2(update)._meta);
|
|
22312
|
+
if (meta3["codebuddy.ai/sessionReset"] === true && meta3["codebuddy.ai/newSessionId"] === sessionId)
|
|
22313
|
+
derivedId = sessionId;
|
|
22314
|
+
}
|
|
22315
|
+
}
|
|
22316
|
+
});
|
|
22317
|
+
} catch (error51) {
|
|
22318
|
+
return failAfterBridgeCleanup(error51, bridge);
|
|
22319
|
+
}
|
|
22320
|
+
const abort = () => {
|
|
22321
|
+
void client2.close();
|
|
22322
|
+
};
|
|
22323
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
22324
|
+
let primaryFailure;
|
|
22325
|
+
try {
|
|
22326
|
+
if (!client2.removeCopy)
|
|
22327
|
+
throw new CodeBuddyError("unsupported", "Native temporary Session cleanup is unavailable");
|
|
22328
|
+
if (signal.aborted)
|
|
22329
|
+
throw new CodeBuddyError("invalidState", "Adapter closed during Fork");
|
|
22330
|
+
await client2.initialize();
|
|
22331
|
+
const opened = await client2.open(input.cwd, temporary.nativeSessionId);
|
|
22332
|
+
if (opened.sessionId && opened.sessionId !== temporary.nativeSessionId)
|
|
22333
|
+
throw new CodeBuddyError("protocolError", "ACP loaded a different temporary Session");
|
|
22334
|
+
const nativeState = configuration(opened.configOptions, profile).state;
|
|
22335
|
+
const available = await bounded(commands, 5e3, "Native command discovery", abort);
|
|
22336
|
+
if (!Array.isArray(available) || !available.some((entry) => record2(entry).name === "fork"))
|
|
22337
|
+
throw new CodeBuddyError("unsupported", "Native Session does not advertise /fork");
|
|
22338
|
+
const result = await bounded(client2.prompt(temporary.nativeSessionId, "/fork"), 2e4, "Native Fork", abort);
|
|
22339
|
+
if (failure2)
|
|
22340
|
+
throw failure2;
|
|
22341
|
+
if (result.stopReason !== "end_turn" || !derivedId || [input.sourceRef.nativeSessionId, temporary.nativeSessionId].includes(derivedId))
|
|
22342
|
+
throw new CodeBuddyError("unsupported", "Native Fork did not report a separate Session");
|
|
22343
|
+
const preliminaryRef = nativeSessionRefSchema.parse({
|
|
22344
|
+
harnessId: profile.harnessId,
|
|
22345
|
+
nativeSessionId: derivedId,
|
|
22346
|
+
formatVersion: 1
|
|
22347
|
+
});
|
|
22348
|
+
const historicalCwds = [
|
|
22349
|
+
.../* @__PURE__ */ new Set([
|
|
22350
|
+
...sourceRows.flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []),
|
|
22351
|
+
...source.historicalCwds,
|
|
22352
|
+
sourceCwd,
|
|
22353
|
+
input.cwd
|
|
22354
|
+
])
|
|
22355
|
+
];
|
|
22356
|
+
const historyTransaction = strictHistoryBinding ? { requirePrimary: true, allowedHistoricalCwds: historicalCwds } : void 0;
|
|
22357
|
+
const forked = await codeBuddyNativeHistory(input.cwd, preliminaryRef, environment, profile, historyTransaction);
|
|
22358
|
+
const forkRows = nativeHistoryRows(forked.contents);
|
|
22359
|
+
assertCopiedPrefix(sourceRows, forkRows);
|
|
22360
|
+
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;
|
|
22361
|
+
if (strictHistoryBinding && !marker)
|
|
22362
|
+
throw new CodeBuddyError("unsupported", "Native Fork did not persist a target binding marker");
|
|
22363
|
+
if (!client2.rollback)
|
|
22364
|
+
throw new CodeBuddyError("unsupported", "Native history rewind is unavailable");
|
|
22365
|
+
const point = retained ? text(forkRows[retained - 1]?.id) : null;
|
|
22366
|
+
const rewound = await client2.rollback(derivedId, point);
|
|
22367
|
+
if (rewound.applied !== true || (rewound.actualForkPointId ?? null) !== point)
|
|
22368
|
+
throw new CodeBuddyError("nativeFailure", "Native history rewind was not confirmed");
|
|
22369
|
+
const verified = await codeBuddyNativeHistory(input.cwd, preliminaryRef, environment, profile, historyTransaction);
|
|
22370
|
+
const finalRows = nativeHistoryRows(verified.contents);
|
|
22371
|
+
if (!isDeepStrictEqual3(finalRows, forkRows.slice(0, retained)))
|
|
22372
|
+
throw new CodeBuddyError("nativeFailure", "Native history rewind did not persist the exact prefix");
|
|
22373
|
+
const inheritedChildren2 = await copyInheritedChildren({
|
|
22374
|
+
references: childReferences,
|
|
22375
|
+
sourceRef: input.sourceRef,
|
|
22376
|
+
sourceCwd,
|
|
22377
|
+
sourceHistoryFile: source.file,
|
|
22378
|
+
targetRef: preliminaryRef,
|
|
22379
|
+
targetHistoryFile: verified.file
|
|
22380
|
+
});
|
|
22381
|
+
inheritedChildCopies = inheritedChildren2.created;
|
|
22382
|
+
const inheritedChildLocator = inheritedChildren2.descriptors.length ? { codebuddyInheritedChildren: inheritedChildren2.descriptors } : {};
|
|
22383
|
+
const ref = nativeSessionRefSchema.parse({
|
|
22384
|
+
...preliminaryRef,
|
|
22385
|
+
locator: strictHistoryBinding ? {
|
|
22386
|
+
codebuddyDerived: 1,
|
|
22387
|
+
boundCwd: codeBuddyCanonicalCwd(input.cwd),
|
|
22388
|
+
targetProjectSlug: codeBuddyProjectSlug(input.cwd, profile),
|
|
22389
|
+
inheritedPrefixRows: finalRows.length,
|
|
22390
|
+
inheritedPrefixSha256: nativeRowsDigest(finalRows),
|
|
22391
|
+
bindingMarkerId: text(marker?.id),
|
|
22392
|
+
...inheritedChildLocator
|
|
22393
|
+
} : { codebuddyDerived: 1, ...inheritedChildLocator }
|
|
22394
|
+
});
|
|
22395
|
+
await codeBuddyNativeHistory(input.cwd, ref, environment, profile);
|
|
22396
|
+
const after = await codeBuddyNativeHistory(sourceCwd, input.sourceRef, environment, profile);
|
|
22397
|
+
if (after.contents !== source.contents)
|
|
22398
|
+
throw new CodeBuddyError("sessionBusy", "Source history changed during Fork");
|
|
22399
|
+
if (signal.aborted)
|
|
22400
|
+
throw new CodeBuddyError("invalidState", "Adapter closed during Fork");
|
|
22401
|
+
const saved = record2(record2(input.sourceRef.locator).configuration);
|
|
22402
|
+
const state = options.state ?? {
|
|
22403
|
+
...nativeState,
|
|
22404
|
+
...text(saved.model) ? { effectiveModel: modelRef(text(saved.model)) } : {}
|
|
22405
|
+
};
|
|
22406
|
+
const model = input.kind === "rollbackLastTurn" && input.model ? input.model : state.effectiveModel;
|
|
22407
|
+
const thinking = input.kind === "rollbackLastTurn" && input.thinkingOptionId ? input.thinkingOptionId : options.state?.effectiveThinkingOptionId ?? (text(saved.thinking) ? harnessThinkingOptionIdSchema.parse(saved.thinking) : state.effectiveThinkingOptionId);
|
|
22408
|
+
const mode = input.kind === "rollbackLastTurn" && input.permissionModeId ? input.permissionModeId : options.state?.effectivePermissionModeId ?? (text(saved.mode) ? harnessPermissionModeIdSchema.parse(saved.mode) : state.effectivePermissionModeId);
|
|
22409
|
+
const resume = {
|
|
22410
|
+
kind: "resume",
|
|
22411
|
+
nativeRef: ref,
|
|
22412
|
+
cwd: input.cwd,
|
|
22413
|
+
...input.environment ? { environment: input.environment } : {},
|
|
22414
|
+
...model ? { model } : {},
|
|
22415
|
+
...thinking ? { thinkingOptionId: thinking } : {},
|
|
22416
|
+
...mode ? { permissionModeId: mode } : {}
|
|
22417
|
+
};
|
|
22418
|
+
derivationSucceeded = true;
|
|
22419
|
+
return resume;
|
|
22420
|
+
} catch (error51) {
|
|
22421
|
+
primaryFailure = error51;
|
|
22422
|
+
throw error51;
|
|
22423
|
+
} finally {
|
|
22424
|
+
signal.removeEventListener("abort", abort);
|
|
22425
|
+
const cleanupFailures = [];
|
|
22426
|
+
let temporaryCleanupFailed = false;
|
|
22427
|
+
try {
|
|
22428
|
+
if (client2.removeCopy)
|
|
22429
|
+
await client2.removeCopy();
|
|
22430
|
+
} catch (error51) {
|
|
22431
|
+
temporaryCleanupFailed = true;
|
|
22432
|
+
cleanupFailures.push(error51);
|
|
22433
|
+
}
|
|
22434
|
+
try {
|
|
22435
|
+
await client2.close();
|
|
22436
|
+
} catch (error51) {
|
|
22437
|
+
cleanupFailures.push(error51);
|
|
22438
|
+
}
|
|
22439
|
+
try {
|
|
22440
|
+
await cleanupBridge(bridge);
|
|
22441
|
+
} catch (error51) {
|
|
22442
|
+
cleanupFailures.push(error51);
|
|
22443
|
+
}
|
|
22444
|
+
if (!derivationSucceeded || cleanupFailures.length) {
|
|
22445
|
+
for (const copy of inheritedChildCopies.toReversed()) {
|
|
22446
|
+
try {
|
|
22447
|
+
await cleanupBridge(copy);
|
|
22448
|
+
} catch (error51) {
|
|
22449
|
+
cleanupFailures.push(error51);
|
|
22450
|
+
}
|
|
22451
|
+
}
|
|
22452
|
+
}
|
|
22453
|
+
if (cleanupFailures.length) {
|
|
22454
|
+
if (primaryFailure)
|
|
22455
|
+
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"}`);
|
|
22456
|
+
if (cleanupFailures.length === 1)
|
|
22457
|
+
throw cleanupFailures[0];
|
|
22458
|
+
throw new AggregateError(cleanupFailures, "Native derivation cleanup failed");
|
|
22459
|
+
}
|
|
22460
|
+
}
|
|
22461
|
+
}
|
|
22462
|
+
|
|
21184
22463
|
// dist/interactions.js
|
|
21185
22464
|
var CodeBuddyInteractions = class {
|
|
21186
22465
|
emit;
|
|
21187
22466
|
client;
|
|
22467
|
+
profile;
|
|
21188
22468
|
#pending = /* @__PURE__ */ new Map();
|
|
21189
22469
|
#sequence = 0;
|
|
21190
|
-
constructor(emit, client2) {
|
|
22470
|
+
constructor(emit, client2, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21191
22471
|
this.emit = emit;
|
|
21192
22472
|
this.client = client2;
|
|
22473
|
+
this.profile = profile;
|
|
21193
22474
|
}
|
|
21194
22475
|
#question(turnId, input) {
|
|
21195
22476
|
const questions = rows(record2(input).questions);
|
|
21196
22477
|
if (!questions.length || questions.length > 4)
|
|
21197
|
-
throw new CodeBuddyError("protocolError",
|
|
22478
|
+
throw new CodeBuddyError("protocolError", `Invalid ${this.profile.displayName} question count`);
|
|
21198
22479
|
return {
|
|
21199
22480
|
type: "question",
|
|
21200
|
-
interactionId: hostInteractionIdSchema.parse(
|
|
22481
|
+
interactionId: hostInteractionIdSchema.parse(`${this.profile.interactionIdPrefix}-question-${++this.#sequence}`),
|
|
21201
22482
|
turnId,
|
|
21202
|
-
title:
|
|
22483
|
+
title: this.profile.displayName,
|
|
21203
22484
|
questions: questions.map((question, index) => {
|
|
21204
22485
|
const options = rows(question.options).map((option) => ({
|
|
21205
22486
|
value: text(option.label),
|
|
@@ -21207,7 +22488,7 @@ var CodeBuddyInteractions = class {
|
|
|
21207
22488
|
...option.description ? { description: text(option.description) } : {}
|
|
21208
22489
|
}));
|
|
21209
22490
|
if (!text(question.question) || !options.length || options.some((option) => !option.value))
|
|
21210
|
-
throw new CodeBuddyError("protocolError",
|
|
22491
|
+
throw new CodeBuddyError("protocolError", `Malformed ${this.profile.displayName} question`);
|
|
21211
22492
|
return {
|
|
21212
22493
|
id: text(question.id) || `q_${index}`,
|
|
21213
22494
|
type: "choice",
|
|
@@ -21240,16 +22521,16 @@ var CodeBuddyInteractions = class {
|
|
|
21240
22521
|
});
|
|
21241
22522
|
}
|
|
21242
22523
|
const actions = request.options.flatMap((option) => {
|
|
21243
|
-
const effect = option.kind === "allow_once" ? "allowOnce" : option.kind === "allow_always" ? "
|
|
22524
|
+
const effect = option.kind === "allow_once" ? "allowOnce" : option.kind === "allow_always" ? "allowForSession" : option.kind === "reject_once" || option.kind === "reject_always" ? "deny" : void 0;
|
|
21244
22525
|
return effect ? [{ id: option.optionId, label: option.name, effect }] : [];
|
|
21245
22526
|
});
|
|
21246
22527
|
if (!actions.some((action) => action.effect === "deny"))
|
|
21247
22528
|
throw new CodeBuddyError("unsupported", "ACP approval does not provide a reject action");
|
|
21248
22529
|
const interaction = {
|
|
21249
22530
|
type: "approval",
|
|
21250
|
-
interactionId: hostInteractionIdSchema.parse(
|
|
22531
|
+
interactionId: hostInteractionIdSchema.parse(`${this.profile.interactionIdPrefix}-approval-${++this.#sequence}`),
|
|
21251
22532
|
turnId,
|
|
21252
|
-
title: name || request.toolCall.title ||
|
|
22533
|
+
title: name || request.toolCall.title || `${this.profile.displayName} tool approval`,
|
|
21253
22534
|
subject: { type: "nativeAction" },
|
|
21254
22535
|
actions,
|
|
21255
22536
|
description: JSON.stringify(request.toolCall.rawInput ?? {}).slice(0, 16e3)
|
|
@@ -21285,7 +22566,7 @@ var CodeBuddyInteractions = class {
|
|
|
21285
22566
|
async respond(command) {
|
|
21286
22567
|
const pending = this.#pending.get(command.interactionId);
|
|
21287
22568
|
if (!pending || pending.responding)
|
|
21288
|
-
return failure("invalidRequest", "Interaction is not awaiting a response");
|
|
22569
|
+
return failure("invalidRequest", "Interaction is not awaiting a response", this.profile);
|
|
21289
22570
|
const validation = validateHostInteractionResponse(pending.interaction, command.response);
|
|
21290
22571
|
if (validation)
|
|
21291
22572
|
return { ok: false, error: validation };
|
|
@@ -21296,7 +22577,7 @@ var CodeBuddyInteractions = class {
|
|
|
21296
22577
|
return { ok: true, value: { accepted: true } };
|
|
21297
22578
|
} catch (error51) {
|
|
21298
22579
|
pending.responding = false;
|
|
21299
|
-
return { ok: false, error: nativeError(error51) };
|
|
22580
|
+
return { ok: false, error: nativeError(error51, this.profile) };
|
|
21300
22581
|
}
|
|
21301
22582
|
}
|
|
21302
22583
|
#finish(pending, reason) {
|
|
@@ -21321,33 +22602,23 @@ var CodeBuddyInteractions = class {
|
|
|
21321
22602
|
};
|
|
21322
22603
|
|
|
21323
22604
|
// dist/subagent-history.js
|
|
21324
|
-
import { readdir as readdir2, realpath as
|
|
21325
|
-
import
|
|
21326
|
-
var
|
|
22605
|
+
import { readdir as readdir2, realpath as realpath5 } from "node:fs/promises";
|
|
22606
|
+
import path6 from "node:path";
|
|
22607
|
+
var equalPath2 = (a, b) => process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
21327
22608
|
var MAX_CACHED_CHILDREN = 16;
|
|
21328
|
-
function childContents(contents) {
|
|
21329
|
-
const lines = contents.split(/\r?\n/u);
|
|
21330
|
-
if (lines.at(-1)?.trim()) {
|
|
21331
|
-
try {
|
|
21332
|
-
JSON.parse(lines.at(-1) ?? "");
|
|
21333
|
-
} catch {
|
|
21334
|
-
lines.pop();
|
|
21335
|
-
}
|
|
21336
|
-
}
|
|
21337
|
-
const entries = lines.filter((line) => line.trim()).map((line) => record2(JSON.parse(line)));
|
|
21338
|
-
return { contents: lines.join("\n"), entries };
|
|
21339
|
-
}
|
|
21340
22609
|
var CodeBuddyChildObserver = class {
|
|
21341
22610
|
parent;
|
|
21342
22611
|
cwd;
|
|
21343
22612
|
environment;
|
|
22613
|
+
profile;
|
|
21344
22614
|
#children = /* @__PURE__ */ new Map();
|
|
21345
22615
|
#parent;
|
|
21346
22616
|
#closed = false;
|
|
21347
|
-
constructor(parent, cwd, environment) {
|
|
22617
|
+
constructor(parent, cwd, environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21348
22618
|
this.parent = parent;
|
|
21349
22619
|
this.cwd = cwd;
|
|
21350
22620
|
this.environment = environment;
|
|
22621
|
+
this.profile = profile;
|
|
21351
22622
|
}
|
|
21352
22623
|
close() {
|
|
21353
22624
|
this.#closed = true;
|
|
@@ -21358,16 +22629,16 @@ var CodeBuddyChildObserver = class {
|
|
|
21358
22629
|
if (this.#closed)
|
|
21359
22630
|
throw new CodeBuddyError("invalidRequest", "Subagent observer is closed");
|
|
21360
22631
|
}
|
|
21361
|
-
async #validateWorkspaces(cwds
|
|
21362
|
-
const expected = await
|
|
22632
|
+
async #validateWorkspaces(cwds) {
|
|
22633
|
+
const expected = await realpath5(this.cwd);
|
|
21363
22634
|
for (const cwd of new Set(cwds)) {
|
|
21364
|
-
const actual = await
|
|
21365
|
-
if (
|
|
22635
|
+
const actual = await realpath5(cwd).catch((error51) => {
|
|
22636
|
+
if (["ENOENT", "ENOTDIR"].includes(String(record2(error51).code)))
|
|
21366
22637
|
throw new CodeBuddyError("invalidRequest", "Native Session historical working directory is unavailable; ownership cannot be verified");
|
|
21367
22638
|
throw error51;
|
|
21368
22639
|
});
|
|
21369
|
-
if (!
|
|
21370
|
-
throw new CodeBuddyError("invalidRequest",
|
|
22640
|
+
if (!equalPath2(actual, expected))
|
|
22641
|
+
throw new CodeBuddyError("invalidRequest", "Native Session belongs to a different working directory");
|
|
21371
22642
|
}
|
|
21372
22643
|
}
|
|
21373
22644
|
async #parentHistory() {
|
|
@@ -21384,7 +22655,7 @@ var CodeBuddyChildObserver = class {
|
|
|
21384
22655
|
return this.#parent;
|
|
21385
22656
|
}
|
|
21386
22657
|
}
|
|
21387
|
-
const history = await codeBuddyLiveNativeHistory(this.cwd, this.parent, this.environment);
|
|
22658
|
+
const history = await codeBuddyLiveNativeHistory(this.cwd, this.parent, this.environment, this.profile);
|
|
21388
22659
|
this.#assertOpen();
|
|
21389
22660
|
this.#parent = {
|
|
21390
22661
|
file: history.file,
|
|
@@ -21396,31 +22667,34 @@ var CodeBuddyChildObserver = class {
|
|
|
21396
22667
|
}
|
|
21397
22668
|
async #directory() {
|
|
21398
22669
|
const history = await this.#parentHistory();
|
|
21399
|
-
const project =
|
|
21400
|
-
const expected =
|
|
21401
|
-
const actual = await
|
|
22670
|
+
const project = path6.dirname(await realpath5(history.file));
|
|
22671
|
+
const expected = path6.join(project, this.parent.nativeSessionId, "subagents");
|
|
22672
|
+
const actual = await realpath5(expected);
|
|
21402
22673
|
this.#assertOpen();
|
|
21403
|
-
if (!
|
|
21404
|
-
throw new CodeBuddyError("invalidRequest",
|
|
22674
|
+
if (!equalPath2(actual, expected))
|
|
22675
|
+
throw new CodeBuddyError("invalidRequest", `Redirected ${this.profile.displayName} Subagent directory`);
|
|
21405
22676
|
return actual;
|
|
21406
22677
|
}
|
|
21407
22678
|
async #child(directory, childId) {
|
|
21408
22679
|
if (!validCodeBuddyChildId(childId))
|
|
21409
22680
|
throw new CodeBuddyError("invalidRequest", "Invalid native Subagent ID");
|
|
21410
|
-
const file2 =
|
|
22681
|
+
const file2 = path6.join(directory, `${childId}.jsonl`);
|
|
21411
22682
|
const before = await codeBuddyFileVersion(file2);
|
|
21412
|
-
if (!
|
|
22683
|
+
if (!equalPath2(before.realFile, file2))
|
|
21413
22684
|
throw new CodeBuddyError("invalidRequest", "Redirected Subagent transcript");
|
|
21414
22685
|
this.#assertOpen();
|
|
21415
|
-
if (before.size >
|
|
22686
|
+
if (before.size > CODEBUDDY_CHILD_MAX_BYTES)
|
|
21416
22687
|
throw new CodeBuddyError("unsupported", "Subagent transcript exceeds 8 MB");
|
|
21417
22688
|
const cached2 = this.#children.get(childId);
|
|
21418
|
-
if (cached2 && sameCodeBuddyFileVersion(cached2.version, before))
|
|
22689
|
+
if (cached2 && sameCodeBuddyFileVersion(cached2.version, before)) {
|
|
22690
|
+
await validateCodeBuddyChildContents(cached2.rawContents, this.parent, childId, this.cwd, true);
|
|
21419
22691
|
return cached2;
|
|
21420
|
-
|
|
22692
|
+
}
|
|
22693
|
+
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);
|
|
21421
22694
|
this.#assertOpen();
|
|
21422
22695
|
const next = {
|
|
21423
22696
|
...data,
|
|
22697
|
+
rawContents: source.contents,
|
|
21424
22698
|
version: source.reusableVersion
|
|
21425
22699
|
};
|
|
21426
22700
|
this.#children.delete(childId);
|
|
@@ -21456,26 +22730,19 @@ var CodeBuddyChildObserver = class {
|
|
|
21456
22730
|
async read(childId, status) {
|
|
21457
22731
|
if (!status) {
|
|
21458
22732
|
const source = await this.#parentHistory();
|
|
21459
|
-
const states = snapshotFromHistory(source.contents, this.parent, this.cwd).turns.flatMap((turn) => turn.items.flatMap(({ item }) => item.type === "subagentDelegation" ? item.subagents : []));
|
|
22733
|
+
const states = snapshotFromHistory(source.contents, this.parent, this.cwd, this.profile).turns.flatMap((turn) => turn.items.flatMap(({ item }) => item.type === "subagentDelegation" ? item.subagents : []));
|
|
21460
22734
|
status = states.findLast((child) => child.nativeSubagentId === childId)?.status;
|
|
21461
22735
|
}
|
|
21462
22736
|
const data = await this.#child(await this.#directory(), childId);
|
|
21463
|
-
const sessions = new Set(data.entries.map((row) => text(row.sessionId)).filter(Boolean));
|
|
21464
|
-
if (sessions.size !== 1)
|
|
21465
|
-
throw new CodeBuddyError("protocolError", "Subagent transcript identity is missing or mixed");
|
|
21466
|
-
await this.#validateWorkspaces(data.entries.flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []), true);
|
|
21467
22737
|
this.#assertOpen();
|
|
21468
|
-
|
|
21469
|
-
if (!childSessionId)
|
|
21470
|
-
throw new CodeBuddyError("protocolError", "Missing native child Session");
|
|
21471
|
-
data.snapshot ??= snapshotFromHistory(data.contents, { ...this.parent, nativeSessionId: childSessionId }, this.cwd);
|
|
22738
|
+
data.snapshot ??= snapshotFromHistory(data.contents, { ...this.parent, nativeSessionId: data.nativeSessionId }, this.cwd, this.profile);
|
|
21472
22739
|
const snapshot = structuredClone(data.snapshot);
|
|
21473
22740
|
projectChildSnapshot(snapshot, this.parent, childId, status);
|
|
21474
22741
|
return snapshot;
|
|
21475
22742
|
}
|
|
21476
22743
|
};
|
|
21477
|
-
async function readCodeBuddyChild(parent, childId, cwd, environment, status) {
|
|
21478
|
-
const observer = new CodeBuddyChildObserver(parent, cwd, environment);
|
|
22744
|
+
async function readCodeBuddyChild(parent, childId, cwd, environment, status, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
22745
|
+
const observer = new CodeBuddyChildObserver(parent, cwd, environment, profile);
|
|
21479
22746
|
try {
|
|
21480
22747
|
return await observer.read(childId, status);
|
|
21481
22748
|
} finally {
|
|
@@ -21489,6 +22756,7 @@ function projectChildSnapshot(snapshot, parent, childId, status) {
|
|
|
21489
22756
|
nativeSessionId: parent.nativeSessionId,
|
|
21490
22757
|
nativeTurnKey: `${childId}:${turn.nativeTurnRef.nativeTurnKey}`
|
|
21491
22758
|
};
|
|
22759
|
+
delete turn.checkpoint;
|
|
21492
22760
|
turn.items = turn.items.filter(({ outcome }) => !(outcome.status === "failed" && outcome.error.message.includes("Tool completion was not recorded")));
|
|
21493
22761
|
if (!status || status === "running" || status === "pending")
|
|
21494
22762
|
turn.outcome = { status: "unknown", reason: "Subagent completion has not been confirmed" };
|
|
@@ -21514,6 +22782,9 @@ var CodeBuddySubagents = class {
|
|
|
21514
22782
|
constructor(options) {
|
|
21515
22783
|
this.options = options;
|
|
21516
22784
|
}
|
|
22785
|
+
get profile() {
|
|
22786
|
+
return this.options.profile ?? CODEBUDDY_RUNTIME_PROFILE;
|
|
22787
|
+
}
|
|
21517
22788
|
begin(turnId) {
|
|
21518
22789
|
this.#turnId = turnId;
|
|
21519
22790
|
}
|
|
@@ -21554,7 +22825,7 @@ var CodeBuddySubagents = class {
|
|
|
21554
22825
|
return true;
|
|
21555
22826
|
call = {
|
|
21556
22827
|
turnId: this.#turnId,
|
|
21557
|
-
item: codeBuddyDelegation(callId, update.rawInput, "running"),
|
|
22828
|
+
item: codeBuddyDelegation(callId, update.rawInput, "running", void 0, this.profile.displayName),
|
|
21558
22829
|
itemCompleted: false,
|
|
21559
22830
|
observationDone: false
|
|
21560
22831
|
};
|
|
@@ -21585,7 +22856,7 @@ var CodeBuddySubagents = class {
|
|
|
21585
22856
|
status: "failed",
|
|
21586
22857
|
error: {
|
|
21587
22858
|
code: "nativeFailure",
|
|
21588
|
-
message:
|
|
22859
|
+
message: `${this.profile.displayName} Subagent invocation failed`,
|
|
21589
22860
|
retryable: false
|
|
21590
22861
|
}
|
|
21591
22862
|
} : { status: "succeeded" }
|
|
@@ -21636,19 +22907,19 @@ var CodeBuddySubagents = class {
|
|
|
21636
22907
|
const parent = this.options.parent();
|
|
21637
22908
|
if (!parent)
|
|
21638
22909
|
return;
|
|
21639
|
-
this.#observer ??= new CodeBuddyChildObserver(parent, this.options.cwd, this.options.environment);
|
|
22910
|
+
this.#observer ??= new CodeBuddyChildObserver(parent, this.options.cwd, this.options.environment, this.profile);
|
|
21640
22911
|
this.#refreshing = true;
|
|
21641
22912
|
try {
|
|
21642
22913
|
for (const call of this.#calls.values()) {
|
|
21643
22914
|
if (call.observationDone)
|
|
21644
22915
|
continue;
|
|
21645
22916
|
try {
|
|
21646
|
-
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);
|
|
22917
|
+
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);
|
|
21647
22918
|
if (!id || this.#closed || call.observationDone)
|
|
21648
22919
|
continue;
|
|
21649
22920
|
if (!call.item.subagents[0]?.nativeSubagentId)
|
|
21650
22921
|
this.#update(call, { nativeSubagentId: id, subagentId: id });
|
|
21651
|
-
const snapshot = await (this.options.read ? this.options.read(parent, id, this.options.cwd, this.options.environment, "running") : this.#observer.read(id, "running"));
|
|
22922
|
+
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"));
|
|
21652
22923
|
if (this.#closed || call.observationDone)
|
|
21653
22924
|
continue;
|
|
21654
22925
|
const observedModel = snapshot.turns.at(-1)?.model;
|
|
@@ -21704,8 +22975,11 @@ var CodeBuddySession = class {
|
|
|
21704
22975
|
factory;
|
|
21705
22976
|
readHistory;
|
|
21706
22977
|
onClose;
|
|
21707
|
-
|
|
21708
|
-
|
|
22978
|
+
profile;
|
|
22979
|
+
harnessId;
|
|
22980
|
+
#commands = { commands: [] };
|
|
22981
|
+
commands;
|
|
22982
|
+
capabilities;
|
|
21709
22983
|
initialState = {};
|
|
21710
22984
|
initialUsage = null;
|
|
21711
22985
|
#channel = new HarnessOutputChannel();
|
|
@@ -21727,19 +23001,29 @@ var CodeBuddySession = class {
|
|
|
21727
23001
|
#usage = null;
|
|
21728
23002
|
#context = {};
|
|
21729
23003
|
constructor(input, environment, factory, readHistory = readNativeHistory, onClose = () => {
|
|
21730
|
-
}) {
|
|
23004
|
+
}, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21731
23005
|
this.input = input;
|
|
21732
23006
|
this.environment = environment;
|
|
21733
23007
|
this.factory = factory;
|
|
21734
23008
|
this.readHistory = readHistory;
|
|
21735
23009
|
this.onClose = onClose;
|
|
23010
|
+
this.profile = profile;
|
|
23011
|
+
this.harnessId = profile.harnessId;
|
|
23012
|
+
this.capabilities = capabilitiesForProfile(profile);
|
|
23013
|
+
this.#commands = structuredClone(profile.staticCommandCatalog ?? { commands: [] });
|
|
23014
|
+
if (nativeCommandsEnabled(profile))
|
|
23015
|
+
this.commands = {
|
|
23016
|
+
list: async () => this.#closed || this.#fault ? failure("invalidState", "Session is closed or faulted", this.profile) : { ok: true, value: structuredClone(this.#commands) },
|
|
23017
|
+
execute: (command) => this.#executeCommand(command)
|
|
23018
|
+
};
|
|
21736
23019
|
this.subagents = new CodeBuddySubagents({
|
|
21737
23020
|
parent: () => this.#ref,
|
|
21738
23021
|
cwd: input.cwd,
|
|
21739
23022
|
environment,
|
|
21740
|
-
emit: (event) => this.#emit(event)
|
|
23023
|
+
emit: (event) => this.#emit(event),
|
|
23024
|
+
profile
|
|
21741
23025
|
});
|
|
21742
|
-
this.#interactions = new CodeBuddyInteractions((output) => this.#channel.emit(output), () => this.#client);
|
|
23026
|
+
this.#interactions = new CodeBuddyInteractions((output) => this.#channel.emit(output), () => this.#client, profile);
|
|
21743
23027
|
this.#client = this.#createClient();
|
|
21744
23028
|
}
|
|
21745
23029
|
#createClient() {
|
|
@@ -21754,16 +23038,23 @@ var CodeBuddySession = class {
|
|
|
21754
23038
|
this.#onFault(error51);
|
|
21755
23039
|
},
|
|
21756
23040
|
update: (notification) => {
|
|
21757
|
-
if (generation !== this.#generation || this.#
|
|
23041
|
+
if (generation !== this.#generation || this.#closed)
|
|
21758
23042
|
return;
|
|
21759
23043
|
if (this.#ref && notification.sessionId !== this.#ref.nativeSessionId)
|
|
21760
23044
|
return;
|
|
21761
23045
|
try {
|
|
21762
23046
|
const update = record2(notification.update);
|
|
23047
|
+
if (nativeCommandsEnabled(this.profile) && update.sessionUpdate === "available_commands_update") {
|
|
23048
|
+
if (!this.profile.staticCommandCatalog)
|
|
23049
|
+
this.#commands = commandCatalog(update.availableCommands, this.profile);
|
|
23050
|
+
return;
|
|
23051
|
+
}
|
|
23052
|
+
if (this.#replaying)
|
|
23053
|
+
return;
|
|
21763
23054
|
if (this.subagents.update(update))
|
|
21764
23055
|
return;
|
|
21765
23056
|
if (update.sessionUpdate === "config_option_update" && this.#config)
|
|
21766
|
-
this.#apply(configuration(update.configOptions));
|
|
23057
|
+
this.#apply(configuration(update.configOptions, this.profile));
|
|
21767
23058
|
if (update.sessionUpdate === "usage_update" && typeof update.used === "number" && typeof update.size === "number" && update.size > 0) {
|
|
21768
23059
|
this.#context = {
|
|
21769
23060
|
contextUsedTokens: update.used,
|
|
@@ -21785,32 +23076,54 @@ var CodeBuddySession = class {
|
|
|
21785
23076
|
}
|
|
21786
23077
|
});
|
|
21787
23078
|
}
|
|
21788
|
-
|
|
21789
|
-
|
|
21790
|
-
|
|
21791
|
-
|
|
21792
|
-
|
|
23079
|
+
/** Every fresh process must restore an unanchored rewind before it can accept prompts. */
|
|
23080
|
+
async #openClient() {
|
|
23081
|
+
let rewind;
|
|
23082
|
+
if (this.#ref) {
|
|
23083
|
+
const history = await this.readHistory(this.input.cwd, this.#ref, this.environment, this.profile);
|
|
23084
|
+
this.#hasTurn = snapshotFromHistory(history, this.#ref, this.input.cwd, this.profile).turns.length > 0;
|
|
21793
23085
|
this.#usage = historyUsage(history);
|
|
23086
|
+
rewind = pendingNativeHistoryRewind(history);
|
|
21794
23087
|
}
|
|
21795
23088
|
await this.#client.initialize();
|
|
21796
23089
|
const opened = await this.#client.open(this.input.cwd, this.#ref?.nativeSessionId);
|
|
21797
23090
|
const sessionId = this.#ref?.nativeSessionId ?? text(opened.sessionId);
|
|
21798
23091
|
if (!sessionId || opened.sessionId && opened.sessionId !== sessionId)
|
|
21799
23092
|
throw new CodeBuddyError("protocolError", "ACP returned a different Native Session identity");
|
|
23093
|
+
if (rewind) {
|
|
23094
|
+
if (!this.#client.rollback)
|
|
23095
|
+
throw new CodeBuddyError("unsupported", "Native history rewind is unavailable");
|
|
23096
|
+
const result = await this.#client.rollback(sessionId, rewind.forkPointId);
|
|
23097
|
+
if (result.applied !== true || (result.actualForkPointId ?? null) !== rewind.forkPointId)
|
|
23098
|
+
throw new CodeBuddyError("nativeFailure", "Native history rewind was not confirmed");
|
|
23099
|
+
}
|
|
23100
|
+
return { ...opened, sessionId };
|
|
23101
|
+
}
|
|
23102
|
+
async initialize() {
|
|
23103
|
+
const saved = this.input.kind === "resume" && record2(this.input.nativeRef.locator).codebuddyDerived === 1 ? record2(record2(this.input.nativeRef.locator).configuration) : {};
|
|
23104
|
+
if (this.input.kind === "resume")
|
|
23105
|
+
this.#ref = this.input.nativeRef;
|
|
23106
|
+
const opened = await this.#openClient();
|
|
21800
23107
|
this.#ref = nativeSessionRefSchema.parse({
|
|
21801
|
-
harnessId:
|
|
21802
|
-
nativeSessionId: sessionId,
|
|
21803
|
-
formatVersion: 1
|
|
23108
|
+
harnessId: this.profile.harnessId,
|
|
23109
|
+
nativeSessionId: opened.sessionId,
|
|
23110
|
+
formatVersion: 1,
|
|
23111
|
+
...this.#ref?.locator || this.capabilities.history.fork ? {
|
|
23112
|
+
locator: {
|
|
23113
|
+
...record2(this.#ref?.locator),
|
|
23114
|
+
...this.capabilities.history.fork ? { boundCwd: codeBuddyCanonicalCwd(this.input.cwd) } : {}
|
|
23115
|
+
}
|
|
23116
|
+
} : {}
|
|
21804
23117
|
});
|
|
21805
|
-
this.#apply(configuration(opened.configOptions), false);
|
|
23118
|
+
this.#apply(configuration(opened.configOptions, this.profile), false);
|
|
21806
23119
|
if (this.input.kind === "create" && this.input.executionPolicy === "unattended-full-access") {
|
|
21807
23120
|
await this.#configure("mode", "fullAccess");
|
|
21808
|
-
} else if (this.input.permissionModeId)
|
|
21809
|
-
await this.#configure("mode", this.input.permissionModeId);
|
|
21810
|
-
if (this.input.model)
|
|
21811
|
-
await this.#configure("model", nativeModel(this.input.model));
|
|
21812
|
-
if (this.input.thinkingOptionId)
|
|
21813
|
-
await this.#configure("thought_level", this.input.thinkingOptionId);
|
|
23121
|
+
} else if (this.input.permissionModeId || text(saved.mode))
|
|
23122
|
+
await this.#configure("mode", this.input.permissionModeId ?? text(saved.mode));
|
|
23123
|
+
if (this.input.model || text(saved.model))
|
|
23124
|
+
await this.#configure("model", this.input.model ? nativeModel(this.input.model) : text(saved.model));
|
|
23125
|
+
if (this.input.thinkingOptionId || text(saved.thinking))
|
|
23126
|
+
await this.#configure("thought_level", this.input.thinkingOptionId ?? text(saved.thinking));
|
|
21814
23127
|
if (this.#fault || this.#closed)
|
|
21815
23128
|
throw new CodeBuddyError("invalidState", "Native Session failed while opening");
|
|
21816
23129
|
this.initialState = { ...this.#state };
|
|
@@ -21821,29 +23134,43 @@ var CodeBuddySession = class {
|
|
|
21821
23134
|
}
|
|
21822
23135
|
#apply(config2, emit = true) {
|
|
21823
23136
|
this.#config = config2;
|
|
23137
|
+
if (this.#ref && record2(this.#ref.locator).codebuddyDerived === 1)
|
|
23138
|
+
this.#ref = nativeSessionRefSchema.parse({
|
|
23139
|
+
...this.#ref,
|
|
23140
|
+
locator: {
|
|
23141
|
+
...record2(this.#ref.locator),
|
|
23142
|
+
configuration: {
|
|
23143
|
+
model: config2.state.effectiveModel ? nativeModel(config2.state.effectiveModel) : "",
|
|
23144
|
+
mode: config2.state.effectivePermissionModeId ?? "",
|
|
23145
|
+
thinking: config2.state.effectiveThinkingOptionId ?? ""
|
|
23146
|
+
}
|
|
23147
|
+
}
|
|
23148
|
+
});
|
|
21824
23149
|
this.#state = { ...config2.state, ...this.#ref ? { nativeRef: this.#ref } : {} };
|
|
21825
23150
|
if (emit)
|
|
21826
23151
|
this.#emit({ type: "session.state.changed", state: this.#state });
|
|
21827
23152
|
}
|
|
21828
23153
|
async #configure(id, value) {
|
|
21829
23154
|
const option = this.#config?.options.find((option2) => option2.id === id);
|
|
21830
|
-
|
|
21831
|
-
|
|
23155
|
+
const listed = Array.isArray(option?.options) && option.options.some((option2) => record2(option2).value === value);
|
|
23156
|
+
const allowedProductModel = id === "model" && this.profile.allowUnlistedModelSelection;
|
|
23157
|
+
if (!listed && !allowedProductModel)
|
|
23158
|
+
throw new CodeBuddyError("invalidRequest", `Unavailable ${this.profile.displayName} ${id} selection`);
|
|
21832
23159
|
if (!this.#ref)
|
|
21833
23160
|
throw new CodeBuddyError("invalidState", "Session is not open");
|
|
21834
23161
|
const result = await this.#client.configure(this.#ref.nativeSessionId, id, value);
|
|
21835
23162
|
if (this.#closed || this.#fault)
|
|
21836
23163
|
throw new CodeBuddyError("invalidState", "Session closed during configuration");
|
|
21837
|
-
this.#apply(confirmedConfiguration(result, id, value));
|
|
23164
|
+
this.#apply(confirmedConfiguration(result, id, value, this.profile));
|
|
21838
23165
|
}
|
|
21839
23166
|
async #snapshot() {
|
|
21840
23167
|
if (!this.#ref)
|
|
21841
23168
|
throw new CodeBuddyError("invalidState", "Session is not open");
|
|
21842
23169
|
try {
|
|
21843
|
-
const history = await this.readHistory(this.input.cwd, this.#ref, this.environment);
|
|
23170
|
+
const history = await this.readHistory(this.input.cwd, this.#ref, this.environment, this.profile);
|
|
21844
23171
|
this.#usage = historyUsage(history);
|
|
21845
23172
|
return {
|
|
21846
|
-
...this.subagents.project(snapshotFromHistory(history, this.#ref, this.input.cwd)),
|
|
23173
|
+
...this.subagents.project(snapshotFromHistory(history, this.#ref, this.input.cwd, this.profile)),
|
|
21847
23174
|
state: this.#state
|
|
21848
23175
|
};
|
|
21849
23176
|
} catch (error51) {
|
|
@@ -21854,34 +23181,47 @@ var CodeBuddySession = class {
|
|
|
21854
23181
|
}
|
|
21855
23182
|
async readSnapshot() {
|
|
21856
23183
|
if (this.#closed || this.#fault)
|
|
21857
|
-
return failure("invalidState", "Session is closed or faulted");
|
|
23184
|
+
return failure("invalidState", "Session is closed or faulted", this.profile);
|
|
21858
23185
|
if (this.#busy || this.#active)
|
|
21859
|
-
return failure("sessionBusy", "Session is executing an operation");
|
|
23186
|
+
return failure("sessionBusy", "Session is executing an operation", this.profile);
|
|
21860
23187
|
this.#busy = true;
|
|
21861
23188
|
try {
|
|
21862
23189
|
return { ok: true, value: await this.#snapshot() };
|
|
21863
23190
|
} catch (error51) {
|
|
21864
|
-
return { ok: false, error: nativeError(error51) };
|
|
23191
|
+
return { ok: false, error: nativeError(error51, this.profile) };
|
|
21865
23192
|
} finally {
|
|
21866
23193
|
this.#busy = false;
|
|
21867
23194
|
}
|
|
21868
23195
|
}
|
|
23196
|
+
async #executeCommand(command) {
|
|
23197
|
+
const parsed = commandPrompt(command, this.#commands, this.profile);
|
|
23198
|
+
if (!parsed.ok)
|
|
23199
|
+
return parsed;
|
|
23200
|
+
const result = await this.#execute({ type: "turn.start", turnId: command.turnId, input: [{ type: "text", text: parsed.value }] }, true);
|
|
23201
|
+
return result.ok ? { ok: true, value: { turnId: command.turnId } } : result;
|
|
23202
|
+
}
|
|
21869
23203
|
async execute(command) {
|
|
23204
|
+
const invocation = command.type === "turn.start" ? command.input.map((item) => item.text).join("\n").trim().split(/\s/u)[0] : void 0;
|
|
23205
|
+
if (nativeCommandsEnabled(this.profile) && isExcludedInvocation(invocation))
|
|
23206
|
+
return failure("unsupported", "Command is not available in this Session", this.profile);
|
|
23207
|
+
return this.#execute(command, nativeCommandsEnabled(this.profile) && this.#commands.commands.some((entry) => entry.invocation === invocation));
|
|
23208
|
+
}
|
|
23209
|
+
async #execute(command, nativeCommand = false) {
|
|
21870
23210
|
if (this.#closed || this.#fault)
|
|
21871
|
-
return failure("invalidState", "Session is closed or faulted");
|
|
23211
|
+
return failure("invalidState", "Session is closed or faulted", this.profile);
|
|
21872
23212
|
if (command.type === "interaction.respond")
|
|
21873
23213
|
return this.#interactions.respond(command);
|
|
21874
23214
|
if (command.type === "turn.cancel") {
|
|
21875
23215
|
const active = this.#active;
|
|
21876
23216
|
if (!active || active.command.turnId !== command.turnId || !this.#ref)
|
|
21877
|
-
return failure("invalidRequest", "Turn is not active");
|
|
23217
|
+
return failure("invalidRequest", "Turn is not active", this.profile);
|
|
21878
23218
|
if (!active.cancelled) {
|
|
21879
23219
|
active.cancelled = true;
|
|
21880
23220
|
try {
|
|
21881
23221
|
await this.#client.cancel(this.#ref.nativeSessionId);
|
|
21882
23222
|
} catch (error51) {
|
|
21883
23223
|
this.#onFault(error51);
|
|
21884
|
-
return { ok: false, error: nativeError(error51) };
|
|
23224
|
+
return { ok: false, error: nativeError(error51, this.profile) };
|
|
21885
23225
|
}
|
|
21886
23226
|
this.#interactions.close();
|
|
21887
23227
|
void bounded(active.completion, 3e4, "ACP cancel acknowledgement").catch((error51) => this.#onFault(error51));
|
|
@@ -21889,26 +23229,31 @@ var CodeBuddySession = class {
|
|
|
21889
23229
|
return { ok: true, value: { cancellationRequested: true } };
|
|
21890
23230
|
}
|
|
21891
23231
|
if (this.#busy || this.#active && command.type !== "model.select" && command.type !== "thinking.select")
|
|
21892
|
-
return failure("sessionBusy", "Session is executing an operation");
|
|
23232
|
+
return failure("sessionBusy", "Session is executing an operation", this.profile);
|
|
21893
23233
|
this.#busy = true;
|
|
21894
23234
|
try {
|
|
21895
23235
|
if (command.type === "turn.start") {
|
|
21896
23236
|
if (!command.turnId.trim() || !command.input.length || command.input.some((item) => item.type !== "text") || !command.input.map((item) => item.text).join("").trim())
|
|
21897
|
-
return failure("invalidRequest", "A nonempty text prompt is required");
|
|
21898
|
-
const
|
|
23237
|
+
return failure("invalidRequest", "A nonempty text prompt is required", this.profile);
|
|
23238
|
+
const snapshot = await this.#snapshot();
|
|
23239
|
+
const before = new Set(snapshot.turns.map((turn) => turn.nativeTurnRef.nativeTurnKey));
|
|
23240
|
+
const beforeItems = new Set(snapshot.turns.flatMap((turn) => turn.items.map((snapshot2) => snapshot2.item.itemId)));
|
|
21899
23241
|
if (this.#closed || this.#fault)
|
|
21900
|
-
return failure("invalidState", "Session closed before Turn start");
|
|
23242
|
+
return failure("invalidState", "Session closed before Turn start", this.profile);
|
|
21901
23243
|
const active = {
|
|
21902
23244
|
command,
|
|
21903
23245
|
before,
|
|
21904
|
-
|
|
23246
|
+
beforeItems,
|
|
23247
|
+
output: new CodeBuddyTurnOutput(command.turnId, this.input.cwd, (event) => this.#emit(event), this.profile),
|
|
23248
|
+
nativeCommand,
|
|
21905
23249
|
cancelled: false,
|
|
21906
23250
|
done: false,
|
|
21907
23251
|
completion: Promise.resolve()
|
|
21908
23252
|
};
|
|
21909
23253
|
this.#active = active;
|
|
21910
23254
|
this.subagents.begin(command.turnId);
|
|
21911
|
-
|
|
23255
|
+
if (!nativeCommand)
|
|
23256
|
+
this.#hasTurn = true;
|
|
21912
23257
|
this.#emit({ type: "turn.started", turnId: command.turnId });
|
|
21913
23258
|
active.completion = this.#run(active);
|
|
21914
23259
|
return { ok: true, value: { turnId: command.turnId } };
|
|
@@ -21916,7 +23261,7 @@ var CodeBuddySession = class {
|
|
|
21916
23261
|
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);
|
|
21917
23262
|
return { ok: true, value: { completed: true } };
|
|
21918
23263
|
} catch (error51) {
|
|
21919
|
-
return { ok: false, error: nativeError(error51) };
|
|
23264
|
+
return { ok: false, error: nativeError(error51, this.profile) };
|
|
21920
23265
|
} finally {
|
|
21921
23266
|
this.#busy = false;
|
|
21922
23267
|
}
|
|
@@ -21933,23 +23278,36 @@ var CodeBuddySession = class {
|
|
|
21933
23278
|
// Those remain visible on individual Items; they do not fail the completed Turn.
|
|
21934
23279
|
(!meta3["codebuddy.ai/outcome"] || meta3["codebuddy.ai/outcome"] === "SUCCESS" || meta3["codebuddy.ai/outcome"] === "PARTIAL_SUCCESS") ? { status: "succeeded" } : {
|
|
21935
23280
|
status: "failed",
|
|
21936
|
-
error: nativeError(new CodeBuddyError("nativeFailure", `Native Turn stopped: ${text(stop) || "unknown"} (${text(meta3["codebuddy.ai/outcome"]) || "no native outcome"})`))
|
|
23281
|
+
error: nativeError(new CodeBuddyError("nativeFailure", `Native Turn stopped: ${text(stop) || "unknown"} (${text(meta3["codebuddy.ai/outcome"]) || "no native outcome"})`), this.profile)
|
|
21937
23282
|
};
|
|
21938
23283
|
const snapshot = await this.#snapshot();
|
|
21939
23284
|
const added = snapshot.turns.filter((turn) => !active.before.has(turn.nativeTurnRef.nativeTurnKey));
|
|
21940
|
-
if (added.length > 1 || outcome.status === "succeeded" && added.length !== 1)
|
|
23285
|
+
if (added.length > 1 || !active.nativeCommand && outcome.status === "succeeded" && added.length !== 1)
|
|
21941
23286
|
throw new CodeBuddyError("protocolError", "Could not identify exactly one persisted Native Turn");
|
|
23287
|
+
active.output.confirmCompaction(snapshot.turns.flatMap((turn) => turn.items).filter((snapshot2) => !active.beforeItems.has(snapshot2.item.itemId)));
|
|
23288
|
+
if (active.nativeCommand)
|
|
23289
|
+
active.output.replayCommandResult(added[0]?.items ?? []);
|
|
21942
23290
|
const nativeTurnRef = added[0]?.nativeTurnRef;
|
|
23291
|
+
if (nativeTurnRef)
|
|
23292
|
+
this.#hasTurn = true;
|
|
21943
23293
|
if (response.userMessageId && nativeTurnRef?.nativeTurnKey !== response.userMessageId)
|
|
21944
23294
|
throw new CodeBuddyError("protocolError", "ACP terminal and native history disagree on Turn identity");
|
|
21945
23295
|
if (outcome.status === "cancelled")
|
|
21946
23296
|
await this.#resumeAfterCancel();
|
|
21947
|
-
|
|
23297
|
+
const compactCommand = active.nativeCommand && /^\/compact(?:\s|$)/u.test(active.command.input.map((item) => item.text).join("\n").trim());
|
|
23298
|
+
const persisted = compactCommand ? added[0]?.outcome : void 0;
|
|
23299
|
+
if (compactCommand && (!persisted || persisted.status === "unknown"))
|
|
23300
|
+
throw new CodeBuddyError("protocolError", "Native compaction terminal outcome was not persisted");
|
|
23301
|
+
const terminalOutcome = persisted && persisted.status !== "unknown" ? persisted : outcome;
|
|
23302
|
+
this.#finish(active, {
|
|
23303
|
+
...terminalOutcome,
|
|
23304
|
+
...added[0]?.checkpoint ? { checkpoint: added[0].checkpoint } : {}
|
|
23305
|
+
}, nativeTurnRef);
|
|
21948
23306
|
if (this.#usage)
|
|
21949
23307
|
this.#emit({ type: "session.usage.changed", usage: { ...this.#usage, ...this.#context } });
|
|
21950
23308
|
} catch (error51) {
|
|
21951
23309
|
if (!active.done)
|
|
21952
|
-
this.#finish(active, { status: "failed", error: nativeError(error51) });
|
|
23310
|
+
this.#finish(active, { status: "failed", error: nativeError(error51, this.profile) });
|
|
21953
23311
|
}
|
|
21954
23312
|
}
|
|
21955
23313
|
async #resumeAfterCancel() {
|
|
@@ -21964,11 +23322,8 @@ var CodeBuddySession = class {
|
|
|
21964
23322
|
if (this.#closed)
|
|
21965
23323
|
return;
|
|
21966
23324
|
this.#client = this.#createClient();
|
|
21967
|
-
await this.#
|
|
21968
|
-
|
|
21969
|
-
if (loaded.sessionId && loaded.sessionId !== this.#ref.nativeSessionId)
|
|
21970
|
-
throw new CodeBuddyError("protocolError", "Cancellation recovery changed Native Session identity");
|
|
21971
|
-
this.#apply(configuration(loaded.configOptions));
|
|
23325
|
+
const loaded = await this.#openClient();
|
|
23326
|
+
this.#apply(configuration(loaded.configOptions, this.profile));
|
|
21972
23327
|
if (saved.effectiveModel)
|
|
21973
23328
|
await this.#configure("model", nativeModel(saved.effectiveModel));
|
|
21974
23329
|
if (saved.effectiveThinkingOptionId)
|
|
@@ -22001,7 +23356,7 @@ var CodeBuddySession = class {
|
|
|
22001
23356
|
#onFault(error51) {
|
|
22002
23357
|
if (this.#fault || this.#closed)
|
|
22003
23358
|
return;
|
|
22004
|
-
this.#fault = nativeError(error51);
|
|
23359
|
+
this.#fault = nativeError(error51, this.profile);
|
|
22005
23360
|
if (this.#active)
|
|
22006
23361
|
this.#finish(this.#active, { status: "failed", error: this.#fault });
|
|
22007
23362
|
this.#interactions.close();
|
|
@@ -22032,30 +23387,43 @@ var CodeBuddySession = class {
|
|
|
22032
23387
|
// dist/codebuddy-adapter.js
|
|
22033
23388
|
var CodeBuddyAdapter = class {
|
|
22034
23389
|
options;
|
|
22035
|
-
harnessId
|
|
23390
|
+
harnessId;
|
|
23391
|
+
commandCatalog;
|
|
22036
23392
|
subagents = {
|
|
22037
23393
|
readSnapshot: async ({ parent, nativeSubagentId, cwd }) => {
|
|
22038
23394
|
try {
|
|
22039
23395
|
if (this.#closed)
|
|
22040
|
-
return failure("invalidState", "Adapter is closed");
|
|
23396
|
+
return failure("invalidState", "Adapter is closed", this.#profile);
|
|
22041
23397
|
const session = [...this.#sessions].find((s) => s.initialState.nativeRef?.nativeSessionId === parent.nativeSessionId);
|
|
22042
|
-
const snapshot = await readCodeBuddyChild(parent, nativeSubagentId, cwd, session?.environment ?? this.#environment, session?.subagents.state(nativeSubagentId)?.status);
|
|
23398
|
+
const snapshot = await readCodeBuddyChild(parent, nativeSubagentId, cwd, session?.environment ?? this.#environment, session?.subagents.state(nativeSubagentId)?.status, this.#profile);
|
|
22043
23399
|
return { ok: true, value: snapshot };
|
|
22044
23400
|
} catch (error51) {
|
|
22045
|
-
return { ok: false, error: nativeError(error51) };
|
|
23401
|
+
return { ok: false, error: nativeError(error51, this.#profile) };
|
|
22046
23402
|
}
|
|
22047
23403
|
}
|
|
22048
23404
|
};
|
|
22049
23405
|
#environment;
|
|
23406
|
+
#profile;
|
|
22050
23407
|
#factory;
|
|
23408
|
+
#invocation;
|
|
22051
23409
|
#sessions = /* @__PURE__ */ new Set();
|
|
22052
23410
|
#inspections = /* @__PURE__ */ new Set();
|
|
22053
23411
|
#cache = /* @__PURE__ */ new Map();
|
|
22054
23412
|
#closed = false;
|
|
23413
|
+
#abort = new AbortController();
|
|
23414
|
+
#derivations = /* @__PURE__ */ new Set();
|
|
22055
23415
|
constructor(options = {}) {
|
|
22056
23416
|
this.options = options;
|
|
23417
|
+
this.#profile = options.profile ?? CODEBUDDY_RUNTIME_PROFILE;
|
|
23418
|
+
this.harnessId = this.#profile.harnessId;
|
|
23419
|
+
if (nativeCommandsEnabled(this.#profile)) {
|
|
23420
|
+
const commandCatalog2 = this.#profile.staticCommandCatalog ?? (this.#profile.harnessId === CODEBUDDY_RUNTIME_PROFILE.harnessId ? CODEBUDDY_COMMAND_CATALOG : void 0);
|
|
23421
|
+
if (commandCatalog2)
|
|
23422
|
+
this.commandCatalog = commandCatalog2;
|
|
23423
|
+
}
|
|
22057
23424
|
this.#environment = { ...options.environment ?? process.env };
|
|
22058
|
-
this.#
|
|
23425
|
+
this.#invocation = options.invocationFactory ?? codeBuddyInvocation;
|
|
23426
|
+
this.#factory = options.clientFactory ?? ((clientOptions) => new CodeBuddyAcpClient(clientOptions, void 0, this.#invocation));
|
|
22059
23427
|
}
|
|
22060
23428
|
inspect(input = {}) {
|
|
22061
23429
|
const cwd = input.cwd ?? process.cwd();
|
|
@@ -22091,15 +23459,15 @@ var CodeBuddyAdapter = class {
|
|
|
22091
23459
|
this.#inspections.add(client2);
|
|
22092
23460
|
await client2.initialize();
|
|
22093
23461
|
const opened = await client2.open(cwd);
|
|
22094
|
-
const config2 = configuration(opened.configOptions);
|
|
23462
|
+
const config2 = configuration(opened.configOptions, this.#profile);
|
|
22095
23463
|
return harnessInspectionSchema.parse({
|
|
22096
23464
|
status: "ready",
|
|
22097
23465
|
catalog: config2.catalog,
|
|
22098
23466
|
permissionModes: config2.permissionModes,
|
|
22099
|
-
capabilities:
|
|
23467
|
+
capabilities: capabilitiesForProfile(this.#profile)
|
|
22100
23468
|
});
|
|
22101
23469
|
} catch (error51) {
|
|
22102
|
-
const issue2 = nativeError(error51);
|
|
23470
|
+
const issue2 = nativeError(error51, this.#profile);
|
|
22103
23471
|
return {
|
|
22104
23472
|
status: issue2.code === "notInstalled" ? "notInstalled" : "unavailable",
|
|
22105
23473
|
error: issue2
|
|
@@ -22114,19 +23482,56 @@ var CodeBuddyAdapter = class {
|
|
|
22114
23482
|
}
|
|
22115
23483
|
async open(input) {
|
|
22116
23484
|
if (this.#closed)
|
|
22117
|
-
return failure("invalidState", "Adapter is closed");
|
|
22118
|
-
if (input.kind === "
|
|
22119
|
-
return failure("
|
|
23485
|
+
return failure("invalidState", "Adapter is closed", this.#profile);
|
|
23486
|
+
if (input.kind === "create" && input.executionPolicy === "unattended-full-access" && input.permissionModeId && input.permissionModeId !== "fullAccess")
|
|
23487
|
+
return failure("invalidRequest", "Unattended execution requires native fullAccess permissions", this.#profile);
|
|
22120
23488
|
let session;
|
|
22121
23489
|
try {
|
|
22122
23490
|
if (!(await stat2(input.cwd)).isDirectory())
|
|
22123
23491
|
throw new CodeBuddyError("invalidRequest", "Working directory is not a directory");
|
|
23492
|
+
if (this.#closed)
|
|
23493
|
+
throw new CodeBuddyError("invalidState", "Adapter closed while opening Session");
|
|
22124
23494
|
if (input.kind === "resume")
|
|
22125
|
-
validateNativeRef(input.nativeRef);
|
|
23495
|
+
validateNativeRef(input.nativeRef, this.#profile);
|
|
23496
|
+
if (input.kind === "fork" || input.kind === "rollbackLastTurn") {
|
|
23497
|
+
const capabilities = capabilitiesForProfile(this.#profile).history;
|
|
23498
|
+
if (input.kind === "fork" && !capabilities.fork || input.kind === "rollbackLastTurn" && !capabilities.rollbackLastTurn)
|
|
23499
|
+
throw new CodeBuddyError("unsupported", `${this.#profile.displayName} does not expose this verified history operation`);
|
|
23500
|
+
const sourceRef = input.sourceRef;
|
|
23501
|
+
validateNativeRef(sourceRef, this.#profile);
|
|
23502
|
+
const source = [...this.#sessions].find((candidate) => candidate.initialState.nativeRef?.nativeSessionId === sourceRef.nativeSessionId);
|
|
23503
|
+
const snapshot = await source?.readSnapshot();
|
|
23504
|
+
if (this.#closed)
|
|
23505
|
+
throw new CodeBuddyError("invalidState", "Adapter closed while reading source Session");
|
|
23506
|
+
if (snapshot && !snapshot.ok)
|
|
23507
|
+
return snapshot;
|
|
23508
|
+
const boundCwd = text(record2(sourceRef.locator).boundCwd);
|
|
23509
|
+
const sourceCwd = (source?.input.cwd ?? boundCwd) || input.cwd;
|
|
23510
|
+
if (input.kind === "fork" && !capabilities.forkAcrossCwd && codeBuddyCanonicalCwd(sourceCwd) !== codeBuddyCanonicalCwd(input.cwd))
|
|
23511
|
+
throw new CodeBuddyError("unsupported", `${this.#profile.displayName} does not support cross-directory Fork`);
|
|
23512
|
+
const derivation = deriveCodeBuddySession({
|
|
23513
|
+
input,
|
|
23514
|
+
sourceCwd,
|
|
23515
|
+
environment: { ...this.#environment, ...input.environment },
|
|
23516
|
+
factory: this.#factory,
|
|
23517
|
+
invocationFactory: this.#invocation,
|
|
23518
|
+
profile: this.#profile,
|
|
23519
|
+
signal: this.#abort.signal,
|
|
23520
|
+
...snapshot?.ok && snapshot.value.state ? { state: snapshot.value.state } : {}
|
|
23521
|
+
});
|
|
23522
|
+
this.#derivations.add(derivation);
|
|
23523
|
+
try {
|
|
23524
|
+
input = await derivation;
|
|
23525
|
+
} finally {
|
|
23526
|
+
this.#derivations.delete(derivation);
|
|
23527
|
+
}
|
|
23528
|
+
}
|
|
23529
|
+
if (this.#closed)
|
|
23530
|
+
throw new CodeBuddyError("invalidState", "Adapter closed while opening Session");
|
|
22126
23531
|
session = new CodeBuddySession(input, { ...this.#environment, ...input.environment }, this.#factory, this.options.readHistory, () => {
|
|
22127
23532
|
if (session)
|
|
22128
23533
|
this.#sessions.delete(session);
|
|
22129
|
-
});
|
|
23534
|
+
}, this.#profile);
|
|
22130
23535
|
this.#sessions.add(session);
|
|
22131
23536
|
await session.initialize();
|
|
22132
23537
|
if (this.#closed)
|
|
@@ -22139,24 +23544,26 @@ var CodeBuddyAdapter = class {
|
|
|
22139
23544
|
this.#sessions.delete(session);
|
|
22140
23545
|
}
|
|
22141
23546
|
const issue2 = record2(error51).code === "ENOENT" ? new CodeBuddyError("invalidRequest", "Working directory does not exist") : error51;
|
|
22142
|
-
return { ok: false, error: nativeError(issue2) };
|
|
23547
|
+
return { ok: false, error: nativeError(issue2, this.#profile) };
|
|
22143
23548
|
}
|
|
22144
23549
|
}
|
|
22145
23550
|
async close() {
|
|
22146
23551
|
this.#closed = true;
|
|
23552
|
+
this.#abort.abort();
|
|
23553
|
+
await Promise.allSettled([...this.#derivations]);
|
|
22147
23554
|
const results = await Promise.allSettled([...this.#sessions, ...this.#inspections].map((resource) => resource.close()));
|
|
22148
23555
|
this.#sessions.clear();
|
|
22149
23556
|
this.#inspections.clear();
|
|
22150
23557
|
this.#cache.clear();
|
|
22151
23558
|
const errors = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
22152
23559
|
if (errors.length)
|
|
22153
|
-
throw new AggregateError(errors,
|
|
23560
|
+
throw new AggregateError(errors, `${this.#profile.displayName} process cleanup failed`);
|
|
22154
23561
|
}
|
|
22155
23562
|
};
|
|
22156
23563
|
|
|
22157
23564
|
// ../../harness-broker/dist/client.js
|
|
22158
|
-
import { randomUUID } from "node:crypto";
|
|
22159
|
-
import { lstat, readFile as
|
|
23565
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
23566
|
+
import { lstat as lstat2, readFile as readFile3 } from "node:fs/promises";
|
|
22160
23567
|
import net, {} from "node:net";
|
|
22161
23568
|
|
|
22162
23569
|
// ../../harness-broker/dist/protocol.js
|
|
@@ -22271,18 +23678,18 @@ function consumeBrokerFrames(socket, onFrame, onError) {
|
|
|
22271
23678
|
|
|
22272
23679
|
// ../../harness-broker/dist/paths.js
|
|
22273
23680
|
import os2 from "node:os";
|
|
22274
|
-
import
|
|
23681
|
+
import path7 from "node:path";
|
|
22275
23682
|
var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
|
|
22276
23683
|
var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
|
|
22277
23684
|
function defaultHarnessBrokerDirectory(environment = process.env) {
|
|
22278
23685
|
const home = environment.HOME || os2.homedir();
|
|
22279
|
-
return
|
|
23686
|
+
return path7.join(home, ".codexhost", "harness-broker");
|
|
22280
23687
|
}
|
|
22281
23688
|
function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
|
|
22282
23689
|
harnessPluginIdSchema.parse(harnessId);
|
|
22283
23690
|
if (harnessId !== "claude-code")
|
|
22284
|
-
return
|
|
22285
|
-
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ??
|
|
23691
|
+
return path7.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
|
|
23692
|
+
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path7.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
|
|
22286
23693
|
}
|
|
22287
23694
|
|
|
22288
23695
|
// ../../harness-broker/dist/validation.js
|
|
@@ -22559,7 +23966,7 @@ function parseSessionMetadata(value) {
|
|
|
22559
23966
|
};
|
|
22560
23967
|
}
|
|
22561
23968
|
async function readDescriptor(descriptorPath) {
|
|
22562
|
-
const metadata = await
|
|
23969
|
+
const metadata = await lstat2(descriptorPath);
|
|
22563
23970
|
if (metadata.isSymbolicLink())
|
|
22564
23971
|
throw new Error("Aqua Harness broker descriptor must not be a symlink");
|
|
22565
23972
|
if (!metadata.isFile())
|
|
@@ -22571,12 +23978,12 @@ async function readDescriptor(descriptorPath) {
|
|
|
22571
23978
|
throw new Error("Aqua Harness broker descriptor belongs to another user");
|
|
22572
23979
|
}
|
|
22573
23980
|
}
|
|
22574
|
-
const descriptor = harnessBrokerDescriptorSchema.parse(JSON.parse(await
|
|
23981
|
+
const descriptor = harnessBrokerDescriptorSchema.parse(JSON.parse(await readFile3(descriptorPath, "utf8")));
|
|
22575
23982
|
if (process.platform === "darwin" && Buffer.byteLength(descriptor.socketPath) > 103) {
|
|
22576
23983
|
throw new Error("Aqua Harness broker socket path is too long for macOS");
|
|
22577
23984
|
}
|
|
22578
23985
|
if (process.platform !== "win32") {
|
|
22579
|
-
const socket = await
|
|
23986
|
+
const socket = await lstat2(descriptor.socketPath);
|
|
22580
23987
|
if (socket.isSymbolicLink() || !socket.isSocket()) {
|
|
22581
23988
|
throw new Error("Aqua Harness broker endpoint is not a Unix socket");
|
|
22582
23989
|
}
|
|
@@ -22673,7 +24080,7 @@ var BrokerConnection = class _BrokerConnection {
|
|
|
22673
24080
|
throw new Error("Aqua Harness broker request limit exceeded");
|
|
22674
24081
|
}
|
|
22675
24082
|
this.#inputSequence += 1;
|
|
22676
|
-
const id =
|
|
24083
|
+
const id = randomUUID2();
|
|
22677
24084
|
const response = new Promise((resolve, reject) => {
|
|
22678
24085
|
const timeout = setTimeout(() => {
|
|
22679
24086
|
this.#pending.delete(id);
|
|
@@ -23069,6 +24476,7 @@ function createHarnessAdapter(context) {
|
|
|
23069
24476
|
return new BrokeredHarnessAdapter({
|
|
23070
24477
|
harnessId: "codebuddy",
|
|
23071
24478
|
forwardDelegationEnvironment: true,
|
|
24479
|
+
commandCatalog: CODEBUDDY_COMMAND_CATALOG,
|
|
23072
24480
|
environment: { ...context.environment }
|
|
23073
24481
|
});
|
|
23074
24482
|
return new CodeBuddyAdapter({ environment: { ...context.environment } });
|