@codexhost/cli-darwin-x64 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/THIRD_PARTY_NOTICES.txt +12 -0
- package/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +67 -26
- package/app/host-runtime.mjs +3774 -6483
- package/app/plugins/antigravity/plugin.mjs +114 -93
- package/app/plugins/claude-code/plugin.mjs +480 -239
- package/app/plugins/codebuddy/plugin.mjs +2177 -846
- package/app/plugins/cursor-cli/plugin.mjs +35065 -10156
- package/app/plugins/deepseek-harness/plugin.mjs +72 -84
- package/app/plugins/enabled.json +4 -1
- package/app/plugins/grok/plugin.mjs +60 -78
- package/app/plugins/hermes/plugin.mjs +2431 -174
- package/app/plugins/kiro-cli/plugin.mjs +67 -80
- package/app/plugins/omp/plugin.mjs +106 -91
- package/app/plugins/opencode/plugin.mjs +109 -123
- package/app/plugins/pi/plugin.mjs +71 -84
- package/app/plugins/qoder/assets/icon.svg +1 -0
- package/app/plugins/qoder/manifest.json +12 -0
- package/app/plugins/qoder/plugin.mjs +52267 -0
- package/app/plugins/qoder-cn/assets/icon.svg +1 -0
- package/app/plugins/qoder-cn/manifest.json +12 -0
- package/app/plugins/qoder-cn/plugin.mjs +52265 -0
- package/app/plugins/workbuddy/assets/icon.svg +29 -0
- package/app/plugins/workbuddy/manifest.json +14 -0
- package/app/plugins/workbuddy/plugin.mjs +24818 -0
- package/app/renderer-extension.js +3182 -960
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- package/licenses/Qoder-Agent-SDK-LICENSE.txt +7 -0
- package/licenses/QoderCN-Agent-SDK-LICENSE.txt +7 -0
- package/licenses/tailwindcss-LICENSE.txt +21 -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
|
}
|
|
@@ -14525,6 +14522,46 @@ config(en_default());
|
|
|
14525
14522
|
// ../../shared-contracts/dist/version.js
|
|
14526
14523
|
var WORKSPACE_CONTRACT_VERSION = 1;
|
|
14527
14524
|
|
|
14525
|
+
// ../../shared-contracts/dist/idle-release.js
|
|
14526
|
+
var IDLE_RELEASE_TIMEOUT_MINUTES_MIN = 5;
|
|
14527
|
+
var IDLE_RELEASE_TIMEOUT_MINUTES_MAX = 1440;
|
|
14528
|
+
var idleReleaseSettingsSchema = external_exports.strictObject({
|
|
14529
|
+
enabled: external_exports.boolean(),
|
|
14530
|
+
timeoutMinutes: external_exports.number().int().min(IDLE_RELEASE_TIMEOUT_MINUTES_MIN).max(IDLE_RELEASE_TIMEOUT_MINUTES_MAX)
|
|
14531
|
+
});
|
|
14532
|
+
var DEFAULT_IDLE_RELEASE_SETTINGS = Object.freeze({
|
|
14533
|
+
enabled: false,
|
|
14534
|
+
timeoutMinutes: 30
|
|
14535
|
+
});
|
|
14536
|
+
|
|
14537
|
+
// ../../shared-contracts/dist/loaded-sessions.js
|
|
14538
|
+
var loadedSessionStateSchema = external_exports.enum([
|
|
14539
|
+
"idle",
|
|
14540
|
+
"running",
|
|
14541
|
+
"busy",
|
|
14542
|
+
"closing",
|
|
14543
|
+
"failed",
|
|
14544
|
+
"blocked"
|
|
14545
|
+
]);
|
|
14546
|
+
var loadedSessionReasonSchema = external_exports.enum([
|
|
14547
|
+
"none",
|
|
14548
|
+
"disabled",
|
|
14549
|
+
"timeout",
|
|
14550
|
+
"operation",
|
|
14551
|
+
"background",
|
|
14552
|
+
"identity",
|
|
14553
|
+
"persistence",
|
|
14554
|
+
"closeFailed"
|
|
14555
|
+
]);
|
|
14556
|
+
var loadedSessionsSchema = external_exports.array(external_exports.strictObject({
|
|
14557
|
+
threadId: external_exports.string(),
|
|
14558
|
+
title: external_exports.string(),
|
|
14559
|
+
harnessId: external_exports.string(),
|
|
14560
|
+
state: loadedSessionStateSchema,
|
|
14561
|
+
reason: loadedSessionReasonSchema,
|
|
14562
|
+
inactiveMs: external_exports.number().nonnegative()
|
|
14563
|
+
}));
|
|
14564
|
+
|
|
14528
14565
|
// ../../shared-contracts/dist/ids.js
|
|
14529
14566
|
var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
|
|
14530
14567
|
message: "Identifier must not be empty or whitespace"
|
|
@@ -15010,6 +15047,8 @@ var pluginPresentationShape = {
|
|
|
15010
15047
|
id: harnessPluginIdSchema,
|
|
15011
15048
|
name: external_exports.string().trim().min(1).max(128),
|
|
15012
15049
|
version: external_exports.string().min(1).max(128),
|
|
15050
|
+
/** The factory accepts a persisted local entrypoint through its construction context. */
|
|
15051
|
+
launchCommand: external_exports.literal(true).optional(),
|
|
15013
15052
|
links: external_exports.object({
|
|
15014
15053
|
documentation: documentationUrlSchema.optional(),
|
|
15015
15054
|
installation: documentationUrlSchema.optional()
|
|
@@ -15047,6 +15086,19 @@ var harnessPluginRouteSchema = external_exports.object({
|
|
|
15047
15086
|
permissionModeId: harnessPermissionModeIdSchema.optional()
|
|
15048
15087
|
}).strict();
|
|
15049
15088
|
|
|
15089
|
+
// ../../shared-contracts/dist/harness-launch-settings.js
|
|
15090
|
+
var harnessLaunchPathSchema = external_exports.string().trim().min(1).max(4096).refine((value) => !/[\u0000\r\n]/u.test(value), "Invalid entrypoint path");
|
|
15091
|
+
var harnessLaunchSettingsGetSchema = external_exports.object({
|
|
15092
|
+
harnessId: harnessPluginIdSchema
|
|
15093
|
+
}).strict();
|
|
15094
|
+
var harnessLaunchSettingsSetSchema = harnessLaunchSettingsGetSchema.extend({
|
|
15095
|
+
path: harnessLaunchPathSchema.nullable()
|
|
15096
|
+
});
|
|
15097
|
+
var harnessLaunchSettingsSchema = external_exports.object({
|
|
15098
|
+
path: harnessLaunchPathSchema.nullable(),
|
|
15099
|
+
restartRequired: external_exports.boolean()
|
|
15100
|
+
}).strict();
|
|
15101
|
+
|
|
15050
15102
|
// ../../shared-contracts/dist/codex-accounts.js
|
|
15051
15103
|
var accountIdSchema = external_exports.string().min(1).max(256).regex(/^[A-Za-z0-9._~-]+$/u);
|
|
15052
15104
|
var nonBlankTextSchema3 = external_exports.string().trim().min(1);
|
|
@@ -15075,75 +15127,15 @@ var codexAccountSchema = external_exports.object({
|
|
|
15075
15127
|
email: external_exports.string().email().max(320).optional(),
|
|
15076
15128
|
planType: codexAccountPlanTypeSchema.optional()
|
|
15077
15129
|
}).strict();
|
|
15078
|
-
var codexAccountPhaseSchema = external_exports.enum(["ready", "
|
|
15079
|
-
var codexAccountPendingOperationSchema = external_exports.object({
|
|
15080
|
-
operationId: nonBlankTextSchema3.max(1024),
|
|
15081
|
-
kind: external_exports.enum(["login", "switch", "logout", "recovery"])
|
|
15082
|
-
}).strict();
|
|
15083
|
-
var codexAccountCapabilitiesSchema = external_exports.object({
|
|
15084
|
-
manage: external_exports.boolean(),
|
|
15085
|
-
switch: external_exports.boolean(),
|
|
15086
|
-
login: external_exports.boolean(),
|
|
15087
|
-
delete: external_exports.boolean(),
|
|
15088
|
-
recover: external_exports.boolean().optional(),
|
|
15089
|
-
logout: external_exports.boolean().optional(),
|
|
15090
|
-
reason: external_exports.enum([
|
|
15091
|
-
"ssh-single-account",
|
|
15092
|
-
"unsupported-storage",
|
|
15093
|
-
"unsupported-version",
|
|
15094
|
-
"recovery-required",
|
|
15095
|
-
"keyring-unavailable",
|
|
15096
|
-
"migration-required"
|
|
15097
|
-
]).optional()
|
|
15098
|
-
}).strict();
|
|
15130
|
+
var codexAccountPhaseSchema = external_exports.enum(["ready", "unavailable"]);
|
|
15099
15131
|
var codexAccountListResultSchema = external_exports.object({
|
|
15100
15132
|
version: external_exports.literal(2),
|
|
15101
15133
|
currentAccountId: accountIdSchema.nullable(),
|
|
15102
15134
|
phase: codexAccountPhaseSchema,
|
|
15103
15135
|
revision: external_exports.number().int().nonnegative(),
|
|
15104
15136
|
instanceId: nonBlankTextSchema3.max(1024).optional(),
|
|
15105
|
-
|
|
15106
|
-
/** Credentials were adopted; other native homes/history remain unmerged. */
|
|
15107
|
-
legacyHistoryPreserved: external_exports.boolean().optional(),
|
|
15108
|
-
pendingOperation: codexAccountPendingOperationSchema.optional(),
|
|
15109
|
-
capabilities: codexAccountCapabilitiesSchema,
|
|
15110
|
-
accounts: external_exports.array(codexAccountSchema).max(128)
|
|
15137
|
+
accounts: external_exports.array(codexAccountSchema).max(1)
|
|
15111
15138
|
}).strict();
|
|
15112
|
-
var codexAccountActivateParamsSchema = external_exports.object({ accountId: accountIdSchema }).strict();
|
|
15113
|
-
var codexAccountSwitchParamsSchema = external_exports.object({ accountId: accountIdSchema }).strict();
|
|
15114
|
-
var codexAccountReadyMutationResultShape = {
|
|
15115
|
-
phase: external_exports.literal("ready"),
|
|
15116
|
-
revision: external_exports.number().int().nonnegative()
|
|
15117
|
-
};
|
|
15118
|
-
var codexAccountSwitchResultSchema = external_exports.object({
|
|
15119
|
-
currentAccountId: accountIdSchema,
|
|
15120
|
-
...codexAccountReadyMutationResultShape
|
|
15121
|
-
}).strict();
|
|
15122
|
-
var codexAccountDeleteParamsSchema = external_exports.object({ accountId: accountIdSchema }).strict();
|
|
15123
|
-
var codexAccountDeleteResultSchema = external_exports.object({ deletedAccountId: accountIdSchema }).strict();
|
|
15124
|
-
var codexAccountLoginStartParamsSchema = external_exports.object({ accountId: accountIdSchema.optional() }).strict();
|
|
15125
|
-
var codexAccountLoginStartResultSchema = external_exports.object({
|
|
15126
|
-
accountId: accountIdSchema,
|
|
15127
|
-
loginId: nonBlankTextSchema3.max(1024),
|
|
15128
|
-
verificationUrl: external_exports.string().url().max(16384),
|
|
15129
|
-
userCode: nonBlankTextSchema3.max(1024)
|
|
15130
|
-
}).strict();
|
|
15131
|
-
var codexAccountLoginCancelParamsSchema = external_exports.object({ loginId: nonBlankTextSchema3.max(1024) }).strict();
|
|
15132
|
-
var codexAccountLoginCancelResultSchema = external_exports.object({ cancelled: external_exports.boolean() }).strict();
|
|
15133
|
-
var codexAccountLoginCompletedSchema = external_exports.object({
|
|
15134
|
-
accountId: accountIdSchema,
|
|
15135
|
-
loginId: nonBlankTextSchema3.max(1024),
|
|
15136
|
-
success: external_exports.boolean(),
|
|
15137
|
-
error: external_exports.string().max(4096).nullable(),
|
|
15138
|
-
saved: external_exports.boolean().optional(),
|
|
15139
|
-
cleanupRequired: external_exports.boolean().optional()
|
|
15140
|
-
}).strict();
|
|
15141
|
-
var codexAccountLogoutParamsSchema = external_exports.object({}).strict();
|
|
15142
|
-
var codexAccountLogoutResultSchema = external_exports.object({
|
|
15143
|
-
currentAccountId: external_exports.null(),
|
|
15144
|
-
...codexAccountReadyMutationResultShape
|
|
15145
|
-
}).strict();
|
|
15146
|
-
var codexAccountRecoverParamsSchema = external_exports.object({}).strict();
|
|
15147
15139
|
var codexAccountUsageParamsSchema = external_exports.object({ accountId: accountIdSchema, refresh: external_exports.boolean().optional() }).strict();
|
|
15148
15140
|
var codexAccountUsageResultSchema = external_exports.object({
|
|
15149
15141
|
accountId: accountIdSchema,
|
|
@@ -15152,21 +15144,6 @@ var codexAccountUsageResultSchema = external_exports.object({
|
|
|
15152
15144
|
freshness: external_exports.enum(["live", "cached"]),
|
|
15153
15145
|
observedAt: external_exports.string().datetime().nullable()
|
|
15154
15146
|
}).strict();
|
|
15155
|
-
var codexAccountResetCreditConsumeParamsSchema = external_exports.object({
|
|
15156
|
-
accountId: accountIdSchema,
|
|
15157
|
-
idempotencyKey: external_exports.string().uuid().optional()
|
|
15158
|
-
}).strict();
|
|
15159
|
-
var codexAccountResetCreditConsumeOutcomeSchema = external_exports.enum([
|
|
15160
|
-
"reset",
|
|
15161
|
-
"nothingToReset",
|
|
15162
|
-
"noCredit",
|
|
15163
|
-
"alreadyRedeemed"
|
|
15164
|
-
]);
|
|
15165
|
-
var codexAccountResetCreditConsumeResultSchema = external_exports.object({
|
|
15166
|
-
accountId: accountIdSchema,
|
|
15167
|
-
outcome: codexAccountResetCreditConsumeOutcomeSchema,
|
|
15168
|
-
accountCredits: accountCreditsSnapshotSchema.optional()
|
|
15169
|
-
}).strict();
|
|
15170
15147
|
|
|
15171
15148
|
// ../../shared-contracts/dist/harness-session-import.js
|
|
15172
15149
|
var HARNESS_SESSION_IMPORT_ID_MAX_LENGTH = 1024;
|
|
@@ -15409,193 +15386,534 @@ var updateStatusResultSchema = external_exports.strictObject({
|
|
|
15409
15386
|
// ../../shared-contracts/dist/index.js
|
|
15410
15387
|
var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
|
|
15411
15388
|
|
|
15412
|
-
// dist/
|
|
15413
|
-
|
|
15414
|
-
|
|
15415
|
-
|
|
15416
|
-
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
|
|
15417
|
-
var AGENT_METHODS = {
|
|
15418
|
-
initialize: "initialize",
|
|
15419
|
-
authenticate: "authenticate",
|
|
15420
|
-
providers_list: "providers/list",
|
|
15421
|
-
providers_set: "providers/set",
|
|
15422
|
-
providers_disable: "providers/disable",
|
|
15423
|
-
session_new: "session/new",
|
|
15424
|
-
session_load: "session/load",
|
|
15425
|
-
session_set_mode: "session/set_mode",
|
|
15426
|
-
session_set_config_option: "session/set_config_option",
|
|
15427
|
-
session_prompt: "session/prompt",
|
|
15428
|
-
session_cancel: "session/cancel",
|
|
15429
|
-
mcp_message: "mcp/message",
|
|
15430
|
-
session_list: "session/list",
|
|
15431
|
-
session_delete: "session/delete",
|
|
15432
|
-
session_fork: "session/fork",
|
|
15433
|
-
session_resume: "session/resume",
|
|
15434
|
-
session_close: "session/close",
|
|
15435
|
-
logout: "logout",
|
|
15436
|
-
nes_start: "nes/start",
|
|
15437
|
-
nes_suggest: "nes/suggest",
|
|
15438
|
-
nes_accept: "nes/accept",
|
|
15439
|
-
nes_reject: "nes/reject",
|
|
15440
|
-
nes_close: "nes/close",
|
|
15441
|
-
document_did_open: "document/didOpen",
|
|
15442
|
-
document_did_change: "document/didChange",
|
|
15443
|
-
document_did_close: "document/didClose",
|
|
15444
|
-
document_did_save: "document/didSave",
|
|
15445
|
-
document_did_focus: "document/didFocus"
|
|
15446
|
-
};
|
|
15447
|
-
var CLIENT_METHODS = {
|
|
15448
|
-
session_request_permission: "session/request_permission",
|
|
15449
|
-
session_update: "session/update",
|
|
15450
|
-
fs_write_text_file: "fs/write_text_file",
|
|
15451
|
-
fs_read_text_file: "fs/read_text_file",
|
|
15452
|
-
terminal_create: "terminal/create",
|
|
15453
|
-
terminal_output: "terminal/output",
|
|
15454
|
-
terminal_release: "terminal/release",
|
|
15455
|
-
terminal_wait_for_exit: "terminal/wait_for_exit",
|
|
15456
|
-
terminal_kill: "terminal/kill",
|
|
15457
|
-
mcp_connect: "mcp/connect",
|
|
15458
|
-
mcp_message: "mcp/message",
|
|
15459
|
-
mcp_disconnect: "mcp/disconnect",
|
|
15460
|
-
elicitation_create: "elicitation/create",
|
|
15461
|
-
elicitation_complete: "elicitation/complete"
|
|
15462
|
-
};
|
|
15463
|
-
var PROTOCOL_METHODS = {
|
|
15464
|
-
cancel_request: "$/cancel_request"
|
|
15465
|
-
};
|
|
15466
|
-
|
|
15467
|
-
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema-deserialize.js
|
|
15468
|
-
var skippedItem = /* @__PURE__ */ Symbol("skippedItem");
|
|
15469
|
-
function defaultOnError(schema, fallback) {
|
|
15470
|
-
return schema.catch(fallback);
|
|
15389
|
+
// ../../harness-adapter/dist/approval.js
|
|
15390
|
+
function invalidRequest(message) {
|
|
15391
|
+
return { code: "invalidRequest", message, retryable: false };
|
|
15471
15392
|
}
|
|
15472
|
-
function
|
|
15473
|
-
|
|
15474
|
-
return external_exports.unknown().transform((value, context) => {
|
|
15475
|
-
if (value !== void 0)
|
|
15476
|
-
return schemaWithCatch.parse(value);
|
|
15477
|
-
context.addIssue({
|
|
15478
|
-
code: "custom",
|
|
15479
|
-
message: "Required value is missing"
|
|
15480
|
-
});
|
|
15481
|
-
return external_exports.NEVER;
|
|
15482
|
-
});
|
|
15393
|
+
function validateHostApprovalResponse(interaction, response) {
|
|
15394
|
+
return interaction.actions.some(({ id }) => id === response.actionId) ? null : invalidRequest("Approval Response contains an undeclared action ID");
|
|
15483
15395
|
}
|
|
15484
|
-
|
|
15485
|
-
|
|
15486
|
-
|
|
15487
|
-
}
|
|
15488
|
-
const tag = value[key];
|
|
15489
|
-
return typeof tag === "string" ? tag : void 0;
|
|
15396
|
+
|
|
15397
|
+
// ../../harness-adapter/dist/question.js
|
|
15398
|
+
function invalidRequest2(message) {
|
|
15399
|
+
return { code: "invalidRequest", message, retryable: false };
|
|
15490
15400
|
}
|
|
15491
|
-
function
|
|
15492
|
-
|
|
15493
|
-
|
|
15494
|
-
|
|
15495
|
-
|
|
15496
|
-
|
|
15497
|
-
|
|
15498
|
-
|
|
15499
|
-
});
|
|
15401
|
+
function validateHostQuestionResponse(interaction, response) {
|
|
15402
|
+
const questionIds = new Set(interaction.questions.map(({ id }) => id));
|
|
15403
|
+
if (response.cancelled) {
|
|
15404
|
+
return Object.keys(response.answers).length === 0 ? null : invalidRequest2("Cancelled Question Response must not contain answers");
|
|
15405
|
+
}
|
|
15406
|
+
for (const answerId of Object.keys(response.answers)) {
|
|
15407
|
+
if (!questionIds.has(answerId)) {
|
|
15408
|
+
return invalidRequest2("Question Response contains an unknown Question ID");
|
|
15500
15409
|
}
|
|
15501
|
-
}
|
|
15502
|
-
|
|
15503
|
-
|
|
15504
|
-
|
|
15505
|
-
|
|
15506
|
-
if (!result.success) {
|
|
15507
|
-
for (const issue2 of result.error.issues) {
|
|
15508
|
-
context.addIssue({ ...issue2, input: value });
|
|
15509
|
-
}
|
|
15510
|
-
return external_exports.NEVER;
|
|
15410
|
+
}
|
|
15411
|
+
for (const question of interaction.questions) {
|
|
15412
|
+
const answers = response.answers[question.id] ?? [];
|
|
15413
|
+
if (!question.optional && answers.length === 0) {
|
|
15414
|
+
return invalidRequest2("Question Response omits a required answer");
|
|
15511
15415
|
}
|
|
15512
|
-
|
|
15513
|
-
|
|
15514
|
-
|
|
15515
|
-
const raw = value;
|
|
15516
|
-
for (const [property, rawValue] of Object.entries(raw)) {
|
|
15517
|
-
if (property === "__proto__")
|
|
15518
|
-
continue;
|
|
15519
|
-
if (!Object.hasOwn(output, property))
|
|
15520
|
-
output[property] = rawValue;
|
|
15416
|
+
if (question.type === "text") {
|
|
15417
|
+
if (answers.length > 1) {
|
|
15418
|
+
return invalidRequest2("Text Question accepts at most one answer");
|
|
15521
15419
|
}
|
|
15420
|
+
continue;
|
|
15522
15421
|
}
|
|
15523
|
-
|
|
15524
|
-
|
|
15422
|
+
if (!question.multiple && answers.length > 1) {
|
|
15423
|
+
return invalidRequest2("Single-choice Question accepts at most one answer");
|
|
15424
|
+
}
|
|
15425
|
+
const declared = new Set(question.options.map(({ value }) => value));
|
|
15426
|
+
if (!question.allowOther && answers.some((answer) => !declared.has(answer))) {
|
|
15427
|
+
return invalidRequest2("Question Response contains an undeclared choice");
|
|
15428
|
+
}
|
|
15429
|
+
}
|
|
15430
|
+
return null;
|
|
15525
15431
|
}
|
|
15526
|
-
|
|
15527
|
-
|
|
15432
|
+
|
|
15433
|
+
// ../../harness-adapter/dist/interaction.js
|
|
15434
|
+
function invalidRequest3(message) {
|
|
15435
|
+
return { code: "invalidRequest", message, retryable: false };
|
|
15436
|
+
}
|
|
15437
|
+
function invalidState(message) {
|
|
15438
|
+
return { code: "invalidState", message, retryable: false };
|
|
15439
|
+
}
|
|
15440
|
+
function validateHostInteractionResponse(interaction, response) {
|
|
15441
|
+
if (!interaction) {
|
|
15442
|
+
return invalidState("Interaction Response must reference a pending Interaction");
|
|
15443
|
+
}
|
|
15444
|
+
if (interaction.type === "question") {
|
|
15445
|
+
return response.type === "question" ? validateHostQuestionResponse(interaction, response) : invalidRequest3("Interaction Response type does not match the pending Interaction");
|
|
15446
|
+
}
|
|
15447
|
+
return response.type === "approval" ? validateHostApprovalResponse(interaction, response) : invalidRequest3("Interaction Response type does not match the pending Interaction");
|
|
15528
15448
|
}
|
|
15529
15449
|
|
|
15530
|
-
//
|
|
15531
|
-
var
|
|
15532
|
-
|
|
15533
|
-
|
|
15534
|
-
|
|
15535
|
-
|
|
15536
|
-
|
|
15537
|
-
|
|
15538
|
-
|
|
15539
|
-
|
|
15540
|
-
|
|
15541
|
-
|
|
15542
|
-
|
|
15543
|
-
|
|
15544
|
-
|
|
15545
|
-
|
|
15546
|
-
|
|
15547
|
-
|
|
15548
|
-
|
|
15549
|
-
}
|
|
15550
|
-
|
|
15551
|
-
|
|
15552
|
-
|
|
15553
|
-
|
|
15554
|
-
|
|
15555
|
-
|
|
15556
|
-
|
|
15557
|
-
|
|
15558
|
-
|
|
15559
|
-
|
|
15560
|
-
|
|
15561
|
-
|
|
15562
|
-
|
|
15563
|
-
|
|
15564
|
-
|
|
15565
|
-
|
|
15566
|
-
|
|
15567
|
-
|
|
15568
|
-
|
|
15569
|
-
|
|
15570
|
-
|
|
15571
|
-
|
|
15572
|
-
|
|
15573
|
-
|
|
15574
|
-
|
|
15575
|
-
|
|
15576
|
-
|
|
15577
|
-
|
|
15578
|
-
|
|
15579
|
-
|
|
15580
|
-
|
|
15581
|
-
var
|
|
15582
|
-
|
|
15583
|
-
|
|
15584
|
-
|
|
15585
|
-
|
|
15586
|
-
|
|
15587
|
-
|
|
15588
|
-
|
|
15589
|
-
|
|
15590
|
-
|
|
15591
|
-
|
|
15592
|
-
|
|
15593
|
-
|
|
15594
|
-
|
|
15595
|
-
|
|
15596
|
-
|
|
15597
|
-
|
|
15598
|
-
|
|
15450
|
+
// ../../harness-adapter/dist/output-channel.js
|
|
15451
|
+
var HarnessOutputChannel = class {
|
|
15452
|
+
outputs;
|
|
15453
|
+
#consumerCreated = false;
|
|
15454
|
+
#ended = false;
|
|
15455
|
+
#pending = [];
|
|
15456
|
+
#values = [];
|
|
15457
|
+
constructor() {
|
|
15458
|
+
this.outputs = {
|
|
15459
|
+
[Symbol.asyncIterator]: () => {
|
|
15460
|
+
if (this.#consumerCreated) {
|
|
15461
|
+
throw new Error("Harness outputs allow only one consumer");
|
|
15462
|
+
}
|
|
15463
|
+
this.#consumerCreated = true;
|
|
15464
|
+
return {
|
|
15465
|
+
next: () => this.#next()
|
|
15466
|
+
};
|
|
15467
|
+
}
|
|
15468
|
+
};
|
|
15469
|
+
}
|
|
15470
|
+
emit(value) {
|
|
15471
|
+
if (this.#ended)
|
|
15472
|
+
return false;
|
|
15473
|
+
const resolve = this.#pending.shift();
|
|
15474
|
+
if (resolve)
|
|
15475
|
+
resolve({ done: false, value });
|
|
15476
|
+
else
|
|
15477
|
+
this.#values.push(value);
|
|
15478
|
+
return true;
|
|
15479
|
+
}
|
|
15480
|
+
end() {
|
|
15481
|
+
if (this.#ended)
|
|
15482
|
+
return;
|
|
15483
|
+
this.#ended = true;
|
|
15484
|
+
if (this.#values.length !== 0)
|
|
15485
|
+
return;
|
|
15486
|
+
for (const resolve of this.#pending.splice(0))
|
|
15487
|
+
resolve({ done: true, value: void 0 });
|
|
15488
|
+
}
|
|
15489
|
+
#next() {
|
|
15490
|
+
const value = this.#values.shift();
|
|
15491
|
+
if (value !== void 0)
|
|
15492
|
+
return Promise.resolve({ done: false, value });
|
|
15493
|
+
if (this.#ended)
|
|
15494
|
+
return Promise.resolve({ done: true, value: void 0 });
|
|
15495
|
+
return new Promise((resolve) => this.#pending.push(resolve));
|
|
15496
|
+
}
|
|
15497
|
+
};
|
|
15498
|
+
|
|
15499
|
+
// ../../harness-adapter/dist/diagnostics.js
|
|
15500
|
+
var DIAGNOSTIC_TAIL_MAX_LENGTH = 8e3;
|
|
15501
|
+
var SENSITIVE_VALUE_PATTERN = /(api[_-]?key|access[_-]?token|auth(?:orization)?|password|secret)(\s*[:=]\s*)([^\s,;]+)/giu;
|
|
15502
|
+
var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/giu;
|
|
15503
|
+
function sanitizeDiagnosticTail(value) {
|
|
15504
|
+
const redacted = value.replace(BEARER_PATTERN, "Bearer [redacted]").replace(SENSITIVE_VALUE_PATTERN, "$1$2[redacted]");
|
|
15505
|
+
return redacted.length <= DIAGNOSTIC_TAIL_MAX_LENGTH ? redacted : redacted.slice(-DIAGNOSTIC_TAIL_MAX_LENGTH);
|
|
15506
|
+
}
|
|
15507
|
+
|
|
15508
|
+
// ../../harness-adapter/dist/usage.js
|
|
15509
|
+
var tokenFields = [
|
|
15510
|
+
"inputTokens",
|
|
15511
|
+
"cachedInputTokens",
|
|
15512
|
+
"cacheWriteInputTokens",
|
|
15513
|
+
"outputTokens",
|
|
15514
|
+
"outputTokensPerSecond",
|
|
15515
|
+
"reasoningOutputTokens",
|
|
15516
|
+
"totalTokens",
|
|
15517
|
+
"contextWindowTokens",
|
|
15518
|
+
"contextUsedTokens"
|
|
15519
|
+
];
|
|
15520
|
+
var safeIntegerFields = [
|
|
15521
|
+
"planFiveHourResetsAtUnix",
|
|
15522
|
+
"planSevenDayResetsAtUnix"
|
|
15523
|
+
];
|
|
15524
|
+
var percentFields = [
|
|
15525
|
+
"cacheHitRatePercent",
|
|
15526
|
+
"planFiveHourUsedPercent",
|
|
15527
|
+
"planSevenDayUsedPercent"
|
|
15528
|
+
];
|
|
15529
|
+
var usageFields = /* @__PURE__ */ new Set([
|
|
15530
|
+
...tokenFields,
|
|
15531
|
+
...safeIntegerFields,
|
|
15532
|
+
...percentFields,
|
|
15533
|
+
"totalCostUsd",
|
|
15534
|
+
"totalCredits",
|
|
15535
|
+
"contextUsagePercent"
|
|
15536
|
+
]);
|
|
15537
|
+
function isRecord(value) {
|
|
15538
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15539
|
+
}
|
|
15540
|
+
function parseHostUsage(value) {
|
|
15541
|
+
if (!isRecord(value))
|
|
15542
|
+
throw new Error("Harness Usage must be an object");
|
|
15543
|
+
const keys = Object.keys(value);
|
|
15544
|
+
if (keys.length === 0)
|
|
15545
|
+
throw new Error("Harness Usage must contain a reliable field");
|
|
15546
|
+
for (const key of keys) {
|
|
15547
|
+
if (!usageFields.has(key)) {
|
|
15548
|
+
throw new Error(`Harness Usage contains unknown field '${key}'`);
|
|
15549
|
+
}
|
|
15550
|
+
}
|
|
15551
|
+
for (const field of ["totalCredits", "contextUsagePercent"]) {
|
|
15552
|
+
const candidate = value[field];
|
|
15553
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)) {
|
|
15554
|
+
throw new Error(`Harness Usage '${field}' must be a finite non-negative number`);
|
|
15555
|
+
}
|
|
15556
|
+
}
|
|
15557
|
+
for (const field of tokenFields) {
|
|
15558
|
+
const candidate = value[field];
|
|
15559
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
15560
|
+
throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
|
|
15561
|
+
}
|
|
15562
|
+
}
|
|
15563
|
+
for (const field of safeIntegerFields) {
|
|
15564
|
+
const candidate = value[field];
|
|
15565
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
15566
|
+
throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
|
|
15567
|
+
}
|
|
15568
|
+
}
|
|
15569
|
+
if (value.outputTokensPerSecond !== void 0 && (typeof value.outputTokensPerSecond !== "number" || !Number.isFinite(value.outputTokensPerSecond) || value.outputTokensPerSecond < 0)) {
|
|
15570
|
+
throw new Error("Harness Usage 'outputTokensPerSecond' must be a finite non-negative number");
|
|
15571
|
+
}
|
|
15572
|
+
if (value.totalCostUsd !== void 0 && (typeof value.totalCostUsd !== "number" || !Number.isFinite(value.totalCostUsd) || value.totalCostUsd < 0)) {
|
|
15573
|
+
throw new Error("Harness Usage 'totalCostUsd' must be a finite non-negative number");
|
|
15574
|
+
}
|
|
15575
|
+
for (const field of percentFields) {
|
|
15576
|
+
const candidate = value[field];
|
|
15577
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0 || candidate > 100)) {
|
|
15578
|
+
throw new Error(`Harness Usage '${field}' must be between 0 and 100`);
|
|
15579
|
+
}
|
|
15580
|
+
}
|
|
15581
|
+
const hasContextUsed = value.contextUsedTokens !== void 0;
|
|
15582
|
+
const hasContextWindow = value.contextWindowTokens !== void 0;
|
|
15583
|
+
if (hasContextUsed !== hasContextWindow) {
|
|
15584
|
+
throw new Error("Harness Usage context fields must be provided together");
|
|
15585
|
+
}
|
|
15586
|
+
if (hasContextWindow && value.contextWindowTokens === 0) {
|
|
15587
|
+
throw new Error("Harness Usage 'contextWindowTokens' must be greater than zero");
|
|
15588
|
+
}
|
|
15589
|
+
if (value.planFiveHourResetsAtUnix !== void 0 && value.planFiveHourUsedPercent === void 0) {
|
|
15590
|
+
throw new Error("Harness Usage 'planFiveHourResetsAtUnix' must be provided with 'planFiveHourUsedPercent'");
|
|
15591
|
+
}
|
|
15592
|
+
if (value.planSevenDayResetsAtUnix !== void 0 && value.planSevenDayUsedPercent === void 0) {
|
|
15593
|
+
throw new Error("Harness Usage 'planSevenDayResetsAtUnix' must be provided with 'planSevenDayUsedPercent'");
|
|
15594
|
+
}
|
|
15595
|
+
return { ...value };
|
|
15596
|
+
}
|
|
15597
|
+
|
|
15598
|
+
// dist/common.js
|
|
15599
|
+
var CODEBUDDY_ID = harnessIdSchema.parse("codebuddy");
|
|
15600
|
+
var CODEBUDDY_RUNTIME_PROFILE = {
|
|
15601
|
+
harnessId: CODEBUDDY_ID,
|
|
15602
|
+
displayName: "CodeBuddy",
|
|
15603
|
+
interactionIdPrefix: "codebuddy",
|
|
15604
|
+
configDirectoryEnvironmentVariables: ["CODEBUDDY_CONFIG_DIR"],
|
|
15605
|
+
defaultConfigDirectoryName: ".codebuddy"
|
|
15606
|
+
};
|
|
15607
|
+
var OUTPUT_LIMIT = 64e3;
|
|
15608
|
+
var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
15609
|
+
var rows = (value) => Array.isArray(value) ? value.map(record2) : [];
|
|
15610
|
+
var text = (value) => typeof value === "string" ? value : "";
|
|
15611
|
+
var CodeBuddyError = class extends Error {
|
|
15612
|
+
code;
|
|
15613
|
+
constructor(code, message) {
|
|
15614
|
+
super(message);
|
|
15615
|
+
this.code = code;
|
|
15616
|
+
}
|
|
15617
|
+
};
|
|
15618
|
+
function nativeError(error51, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15619
|
+
const diagnostic = sanitizeDiagnosticTail(error51 instanceof Error ? error51.message : String(error51));
|
|
15620
|
+
const nativeCode = record2(error51).code;
|
|
15621
|
+
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";
|
|
15622
|
+
return {
|
|
15623
|
+
code,
|
|
15624
|
+
message: `${profile.displayName}: ${diagnostic || "native operation failed"}`,
|
|
15625
|
+
retryable: ["sessionBusy", "unavailable"].includes(code)
|
|
15626
|
+
};
|
|
15627
|
+
}
|
|
15628
|
+
function failure(code, message, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15629
|
+
return { ok: false, error: nativeError(new CodeBuddyError(code, message), profile) };
|
|
15630
|
+
}
|
|
15631
|
+
async function bounded(operation, milliseconds, label, onTimeout) {
|
|
15632
|
+
let timer;
|
|
15633
|
+
try {
|
|
15634
|
+
return await Promise.race([
|
|
15635
|
+
operation,
|
|
15636
|
+
new Promise((_, reject) => {
|
|
15637
|
+
timer = setTimeout(() => {
|
|
15638
|
+
const error51 = new CodeBuddyError("unavailable", `${label} timed out`);
|
|
15639
|
+
try {
|
|
15640
|
+
onTimeout?.(error51);
|
|
15641
|
+
} finally {
|
|
15642
|
+
reject(error51);
|
|
15643
|
+
}
|
|
15644
|
+
}, milliseconds);
|
|
15645
|
+
})
|
|
15646
|
+
]);
|
|
15647
|
+
} finally {
|
|
15648
|
+
clearTimeout(timer);
|
|
15649
|
+
}
|
|
15650
|
+
}
|
|
15651
|
+
|
|
15652
|
+
// dist/slash-commands.js
|
|
15653
|
+
var excluded = /* @__PURE__ */ new Set([
|
|
15654
|
+
"background",
|
|
15655
|
+
"bg",
|
|
15656
|
+
"branch",
|
|
15657
|
+
"fork",
|
|
15658
|
+
"fork-bg",
|
|
15659
|
+
"clear",
|
|
15660
|
+
"resume",
|
|
15661
|
+
"exit",
|
|
15662
|
+
"rewind",
|
|
15663
|
+
"multitask",
|
|
15664
|
+
"agent-mode",
|
|
15665
|
+
"btw",
|
|
15666
|
+
"loop",
|
|
15667
|
+
"goal",
|
|
15668
|
+
"login",
|
|
15669
|
+
"logout",
|
|
15670
|
+
"feedback",
|
|
15671
|
+
"keybindings",
|
|
15672
|
+
"copy",
|
|
15673
|
+
"statusline",
|
|
15674
|
+
"gateway",
|
|
15675
|
+
"remote-control",
|
|
15676
|
+
"_compact"
|
|
15677
|
+
]);
|
|
15678
|
+
function isExcludedInvocation(invocation) {
|
|
15679
|
+
return invocation?.startsWith("/") === true && excluded.has(invocation.slice(1));
|
|
15680
|
+
}
|
|
15681
|
+
function nativeCommandsEnabled(profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15682
|
+
return profile.nativeCommands ?? profile.harnessId === CODEBUDDY_RUNTIME_PROFILE.harnessId;
|
|
15683
|
+
}
|
|
15684
|
+
function commandCatalog(value, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15685
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15686
|
+
return {
|
|
15687
|
+
commands: rows(value).flatMap((entry) => {
|
|
15688
|
+
const name = text(entry.name).replace(/^\//u, "");
|
|
15689
|
+
if (excluded.has(name) || seen.has(name))
|
|
15690
|
+
return [];
|
|
15691
|
+
const parsed = harnessCommandCatalogSchema.safeParse({
|
|
15692
|
+
commands: [
|
|
15693
|
+
{
|
|
15694
|
+
id: `${profile.harnessId}.${name}`,
|
|
15695
|
+
invocation: `/${name}`,
|
|
15696
|
+
label: name,
|
|
15697
|
+
...text(entry.description).trim() ? { description: text(entry.description).trim().slice(0, 512) } : {},
|
|
15698
|
+
argumentMode: name === "compact" || record2(entry.input).hint || record2(entry._meta).type === "skill" ? "text" : "none"
|
|
15699
|
+
}
|
|
15700
|
+
]
|
|
15701
|
+
});
|
|
15702
|
+
if (!parsed.success)
|
|
15703
|
+
return [];
|
|
15704
|
+
seen.add(name);
|
|
15705
|
+
return parsed.data.commands;
|
|
15706
|
+
})
|
|
15707
|
+
};
|
|
15708
|
+
}
|
|
15709
|
+
var CODEBUDDY_COMMAND_CATALOG = commandCatalog([
|
|
15710
|
+
{
|
|
15711
|
+
name: "compact",
|
|
15712
|
+
description: "Summarize conversation context with optional focus instructions"
|
|
15713
|
+
},
|
|
15714
|
+
{ name: "cost", description: "Show current Session usage and cost" }
|
|
15715
|
+
]);
|
|
15716
|
+
function commandPrompt(command, catalog, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
15717
|
+
const descriptor = catalog.commands.find((entry) => entry.id === command.commandId);
|
|
15718
|
+
if (!descriptor)
|
|
15719
|
+
return failure("unsupported", "Command is not available in this Session", profile);
|
|
15720
|
+
const args = command.arguments;
|
|
15721
|
+
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))
|
|
15722
|
+
return failure("invalidRequest", "Command arguments must match the native command", profile);
|
|
15723
|
+
const argument = typeof args?.text === "string" ? args.text.trim() : "";
|
|
15724
|
+
return { ok: true, value: `${descriptor.invocation}${argument ? ` ${argument}` : ""}` };
|
|
15725
|
+
}
|
|
15726
|
+
|
|
15727
|
+
// dist/codebuddy-adapter.js
|
|
15728
|
+
import { stat as stat2 } from "node:fs/promises";
|
|
15729
|
+
|
|
15730
|
+
// dist/acp-client.js
|
|
15731
|
+
import { execFile, spawn } from "node:child_process";
|
|
15732
|
+
import { Readable as Readable2, Writable } from "node:stream";
|
|
15733
|
+
|
|
15734
|
+
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
|
|
15735
|
+
var AGENT_METHODS = {
|
|
15736
|
+
initialize: "initialize",
|
|
15737
|
+
authenticate: "authenticate",
|
|
15738
|
+
providers_list: "providers/list",
|
|
15739
|
+
providers_set: "providers/set",
|
|
15740
|
+
providers_disable: "providers/disable",
|
|
15741
|
+
session_new: "session/new",
|
|
15742
|
+
session_load: "session/load",
|
|
15743
|
+
session_set_mode: "session/set_mode",
|
|
15744
|
+
session_set_config_option: "session/set_config_option",
|
|
15745
|
+
session_prompt: "session/prompt",
|
|
15746
|
+
session_cancel: "session/cancel",
|
|
15747
|
+
mcp_message: "mcp/message",
|
|
15748
|
+
session_list: "session/list",
|
|
15749
|
+
session_delete: "session/delete",
|
|
15750
|
+
session_fork: "session/fork",
|
|
15751
|
+
session_resume: "session/resume",
|
|
15752
|
+
session_close: "session/close",
|
|
15753
|
+
logout: "logout",
|
|
15754
|
+
nes_start: "nes/start",
|
|
15755
|
+
nes_suggest: "nes/suggest",
|
|
15756
|
+
nes_accept: "nes/accept",
|
|
15757
|
+
nes_reject: "nes/reject",
|
|
15758
|
+
nes_close: "nes/close",
|
|
15759
|
+
document_did_open: "document/didOpen",
|
|
15760
|
+
document_did_change: "document/didChange",
|
|
15761
|
+
document_did_close: "document/didClose",
|
|
15762
|
+
document_did_save: "document/didSave",
|
|
15763
|
+
document_did_focus: "document/didFocus"
|
|
15764
|
+
};
|
|
15765
|
+
var CLIENT_METHODS = {
|
|
15766
|
+
session_request_permission: "session/request_permission",
|
|
15767
|
+
session_update: "session/update",
|
|
15768
|
+
fs_write_text_file: "fs/write_text_file",
|
|
15769
|
+
fs_read_text_file: "fs/read_text_file",
|
|
15770
|
+
terminal_create: "terminal/create",
|
|
15771
|
+
terminal_output: "terminal/output",
|
|
15772
|
+
terminal_release: "terminal/release",
|
|
15773
|
+
terminal_wait_for_exit: "terminal/wait_for_exit",
|
|
15774
|
+
terminal_kill: "terminal/kill",
|
|
15775
|
+
mcp_connect: "mcp/connect",
|
|
15776
|
+
mcp_message: "mcp/message",
|
|
15777
|
+
mcp_disconnect: "mcp/disconnect",
|
|
15778
|
+
elicitation_create: "elicitation/create",
|
|
15779
|
+
elicitation_complete: "elicitation/complete"
|
|
15780
|
+
};
|
|
15781
|
+
var PROTOCOL_METHODS = {
|
|
15782
|
+
cancel_request: "$/cancel_request"
|
|
15783
|
+
};
|
|
15784
|
+
|
|
15785
|
+
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema-deserialize.js
|
|
15786
|
+
var skippedItem = /* @__PURE__ */ Symbol("skippedItem");
|
|
15787
|
+
function defaultOnError(schema, fallback) {
|
|
15788
|
+
return schema.catch(fallback);
|
|
15789
|
+
}
|
|
15790
|
+
function requiredDefaultOnError(schema, fallback) {
|
|
15791
|
+
const schemaWithCatch = schema.catch(fallback);
|
|
15792
|
+
return external_exports.unknown().transform((value, context) => {
|
|
15793
|
+
if (value !== void 0)
|
|
15794
|
+
return schemaWithCatch.parse(value);
|
|
15795
|
+
context.addIssue({
|
|
15796
|
+
code: "custom",
|
|
15797
|
+
message: "Required value is missing"
|
|
15798
|
+
});
|
|
15799
|
+
return external_exports.NEVER;
|
|
15800
|
+
});
|
|
15801
|
+
}
|
|
15802
|
+
function stringTag(value, key) {
|
|
15803
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
15804
|
+
return void 0;
|
|
15805
|
+
}
|
|
15806
|
+
const tag = value[key];
|
|
15807
|
+
return typeof tag === "string" ? tag : void 0;
|
|
15808
|
+
}
|
|
15809
|
+
function excludeKnownTags(schema, key, knownTags) {
|
|
15810
|
+
return schema.superRefine((value, context) => {
|
|
15811
|
+
const tag = stringTag(value, key);
|
|
15812
|
+
if (tag !== void 0 && knownTags.includes(tag)) {
|
|
15813
|
+
context.addIssue({
|
|
15814
|
+
code: "custom",
|
|
15815
|
+
path: [key],
|
|
15816
|
+
message: `${key} ${JSON.stringify(tag)} is reserved by a known variant, but the value does not match that variant's schema`
|
|
15817
|
+
});
|
|
15818
|
+
}
|
|
15819
|
+
});
|
|
15820
|
+
}
|
|
15821
|
+
function preserveCustomPayload(schema, key, knownTags) {
|
|
15822
|
+
return external_exports.unknown().transform((value, context) => {
|
|
15823
|
+
const result = schema.safeParse(value);
|
|
15824
|
+
if (!result.success) {
|
|
15825
|
+
for (const issue2 of result.error.issues) {
|
|
15826
|
+
context.addIssue({ ...issue2, input: value });
|
|
15827
|
+
}
|
|
15828
|
+
return external_exports.NEVER;
|
|
15829
|
+
}
|
|
15830
|
+
const output = result.data;
|
|
15831
|
+
const tag = stringTag(value, key);
|
|
15832
|
+
if (tag !== void 0 && !knownTags.includes(tag)) {
|
|
15833
|
+
const raw = value;
|
|
15834
|
+
for (const [property, rawValue] of Object.entries(raw)) {
|
|
15835
|
+
if (property === "__proto__")
|
|
15836
|
+
continue;
|
|
15837
|
+
if (!Object.hasOwn(output, property))
|
|
15838
|
+
output[property] = rawValue;
|
|
15839
|
+
}
|
|
15840
|
+
}
|
|
15841
|
+
return output;
|
|
15842
|
+
});
|
|
15843
|
+
}
|
|
15844
|
+
function vecSkipError(itemSchema) {
|
|
15845
|
+
return external_exports.array(itemSchema.catch(skippedItem)).transform((items) => items.filter((item) => item !== skippedItem));
|
|
15846
|
+
}
|
|
15847
|
+
|
|
15848
|
+
// ../../../node_modules/@agentclientprotocol/sdk/dist/schema/zod.gen.js
|
|
15849
|
+
var zRequestId = union([number2(), string2()]).nullable();
|
|
15850
|
+
var zSessionId = string2();
|
|
15851
|
+
var zWriteTextFileRequest = object({
|
|
15852
|
+
sessionId: zSessionId,
|
|
15853
|
+
path: string2(),
|
|
15854
|
+
content: string2(),
|
|
15855
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15856
|
+
});
|
|
15857
|
+
var zReadTextFileRequest = object({
|
|
15858
|
+
sessionId: zSessionId,
|
|
15859
|
+
path: string2(),
|
|
15860
|
+
line: defaultOnError(int().gte(0).max(4294967295, {
|
|
15861
|
+
error: "Invalid value: Expected uint32 to be <= 4294967295"
|
|
15862
|
+
}).nullish(), () => void 0),
|
|
15863
|
+
limit: defaultOnError(int().gte(0).max(4294967295, {
|
|
15864
|
+
error: "Invalid value: Expected uint32 to be <= 4294967295"
|
|
15865
|
+
}).nullish(), () => void 0),
|
|
15866
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15867
|
+
});
|
|
15868
|
+
var zToolCallId = string2();
|
|
15869
|
+
var zToolKind = union([
|
|
15870
|
+
literal("read"),
|
|
15871
|
+
literal("edit"),
|
|
15872
|
+
literal("delete"),
|
|
15873
|
+
literal("move"),
|
|
15874
|
+
literal("search"),
|
|
15875
|
+
literal("execute"),
|
|
15876
|
+
literal("think"),
|
|
15877
|
+
literal("fetch"),
|
|
15878
|
+
literal("switch_mode"),
|
|
15879
|
+
literal("other")
|
|
15880
|
+
]);
|
|
15881
|
+
var zToolCallStatus = union([
|
|
15882
|
+
literal("pending"),
|
|
15883
|
+
literal("in_progress"),
|
|
15884
|
+
literal("completed"),
|
|
15885
|
+
literal("failed")
|
|
15886
|
+
]);
|
|
15887
|
+
var zRole = union([literal("assistant"), literal("user")]);
|
|
15888
|
+
var zAnnotations = object({
|
|
15889
|
+
audience: defaultOnError(vecSkipError(zRole).nullish(), () => void 0),
|
|
15890
|
+
lastModified: defaultOnError(string2().nullish(), () => void 0),
|
|
15891
|
+
priority: defaultOnError(number2().nullish(), () => void 0),
|
|
15892
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15893
|
+
});
|
|
15894
|
+
var zTextContent = object({
|
|
15895
|
+
annotations: defaultOnError(zAnnotations.nullish(), () => void 0),
|
|
15896
|
+
text: string2(),
|
|
15897
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15898
|
+
});
|
|
15899
|
+
var zImageContent = object({
|
|
15900
|
+
annotations: defaultOnError(zAnnotations.nullish(), () => void 0),
|
|
15901
|
+
data: string2(),
|
|
15902
|
+
mimeType: string2(),
|
|
15903
|
+
uri: defaultOnError(string2().nullish(), () => void 0),
|
|
15904
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15905
|
+
});
|
|
15906
|
+
var zAudioContent = object({
|
|
15907
|
+
annotations: defaultOnError(zAnnotations.nullish(), () => void 0),
|
|
15908
|
+
data: string2(),
|
|
15909
|
+
mimeType: string2(),
|
|
15910
|
+
_meta: defaultOnError(record(string2(), unknown()).nullish(), () => void 0)
|
|
15911
|
+
});
|
|
15912
|
+
var zResourceLink = object({
|
|
15913
|
+
annotations: defaultOnError(zAnnotations.nullish(), () => void 0),
|
|
15914
|
+
description: defaultOnError(string2().nullish(), () => void 0),
|
|
15915
|
+
mimeType: defaultOnError(string2().nullish(), () => void 0),
|
|
15916
|
+
name: string2(),
|
|
15599
15917
|
size: defaultOnError(number2().nullish(), () => void 0),
|
|
15600
15918
|
title: defaultOnError(string2().nullish(), () => void 0),
|
|
15601
15919
|
uri: string2(),
|
|
@@ -17147,17 +17465,17 @@ function isResponseMessage(value) {
|
|
|
17147
17465
|
function isNotificationMessage(value) {
|
|
17148
17466
|
return isJsonRpcEnvelope(value) && !("id" in value) && typeof value["method"] === "string";
|
|
17149
17467
|
}
|
|
17150
|
-
function
|
|
17468
|
+
function isRecord2(value) {
|
|
17151
17469
|
return typeof value === "object" && value !== null;
|
|
17152
17470
|
}
|
|
17153
17471
|
function isJsonRpcEnvelope(value) {
|
|
17154
|
-
return
|
|
17472
|
+
return isRecord2(value) && value["jsonrpc"] === "2.0";
|
|
17155
17473
|
}
|
|
17156
17474
|
function isJsonRpcId(value) {
|
|
17157
17475
|
return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
17158
17476
|
}
|
|
17159
17477
|
function isResponseShapedMessage(value) {
|
|
17160
|
-
return
|
|
17478
|
+
return isRecord2(value) && !("method" in value) && ("id" in value || "result" in value || "error" in value);
|
|
17161
17479
|
}
|
|
17162
17480
|
function isResponseBatch(batch) {
|
|
17163
17481
|
let hasValidCall = false;
|
|
@@ -17167,7 +17485,7 @@ function isResponseBatch(batch) {
|
|
|
17167
17485
|
for (const entry of batch) {
|
|
17168
17486
|
hasValidCall ||= isRequestMessage(entry) || isNotificationMessage(entry);
|
|
17169
17487
|
hasValidResponse ||= isResponseMessage(entry);
|
|
17170
|
-
if (!
|
|
17488
|
+
if (!isRecord2(entry)) {
|
|
17171
17489
|
continue;
|
|
17172
17490
|
}
|
|
17173
17491
|
hasCallShape ||= "method" in entry;
|
|
@@ -17182,13 +17500,13 @@ function isResponseBatch(batch) {
|
|
|
17182
17500
|
return hasResponseShape && !hasCallShape;
|
|
17183
17501
|
}
|
|
17184
17502
|
function cancelRequestId(params) {
|
|
17185
|
-
if (!
|
|
17503
|
+
if (!isRecord2(params) || !isJsonRpcId(params["requestId"])) {
|
|
17186
17504
|
return void 0;
|
|
17187
17505
|
}
|
|
17188
17506
|
return params["requestId"];
|
|
17189
17507
|
}
|
|
17190
17508
|
function isErrorResponse(value) {
|
|
17191
|
-
return
|
|
17509
|
+
return isRecord2(value) && typeof value["code"] === "number" && Number.isInteger(value["code"]) && typeof value["message"] === "string";
|
|
17192
17510
|
}
|
|
17193
17511
|
var Handled = {
|
|
17194
17512
|
/**
|
|
@@ -17679,7 +17997,7 @@ var Connection = class {
|
|
|
17679
17997
|
this.receiveBatch(message);
|
|
17680
17998
|
return;
|
|
17681
17999
|
}
|
|
17682
|
-
if (!
|
|
18000
|
+
if (!isRecord2(message)) {
|
|
17683
18001
|
console.error("Invalid message", { message });
|
|
17684
18002
|
return;
|
|
17685
18003
|
}
|
|
@@ -17742,7 +18060,7 @@ var Connection = class {
|
|
|
17742
18060
|
if (this.abortController.signal.aborted) {
|
|
17743
18061
|
return Promise.resolve();
|
|
17744
18062
|
}
|
|
17745
|
-
if (!
|
|
18063
|
+
if (!isRecord2(message)) {
|
|
17746
18064
|
console.error("Invalid message", { message });
|
|
17747
18065
|
return Promise.resolve();
|
|
17748
18066
|
}
|
|
@@ -18112,7 +18430,7 @@ function ndJsonStream(output, input) {
|
|
|
18112
18430
|
if (trimmedLine) {
|
|
18113
18431
|
try {
|
|
18114
18432
|
const message = JSON.parse(trimmedLine);
|
|
18115
|
-
if (
|
|
18433
|
+
if (isRecord2(message) || Array.isArray(message)) {
|
|
18116
18434
|
controller.enqueue(message);
|
|
18117
18435
|
} else {
|
|
18118
18436
|
console.warn("Skipping JSON line that is not an object:", trimmedLine);
|
|
@@ -19573,6 +19891,69 @@ var ClientSideConnection = class {
|
|
|
19573
19891
|
}
|
|
19574
19892
|
};
|
|
19575
19893
|
|
|
19894
|
+
// dist/copy-cleanup.js
|
|
19895
|
+
import { randomBytes } from "node:crypto";
|
|
19896
|
+
import { createInterface } from "node:readline";
|
|
19897
|
+
import { stripVTControlCharacters } from "node:util";
|
|
19898
|
+
import { Readable } from "node:stream";
|
|
19899
|
+
var CodeBuddyCopyCleanup = class {
|
|
19900
|
+
copyId;
|
|
19901
|
+
cwd;
|
|
19902
|
+
password = randomBytes(32).toString("base64url");
|
|
19903
|
+
arguments = [
|
|
19904
|
+
"--acp",
|
|
19905
|
+
"--serve",
|
|
19906
|
+
"--host",
|
|
19907
|
+
"127.0.0.1",
|
|
19908
|
+
"--port",
|
|
19909
|
+
"0",
|
|
19910
|
+
"--auth",
|
|
19911
|
+
"password"
|
|
19912
|
+
];
|
|
19913
|
+
#endpoint;
|
|
19914
|
+
constructor(copyId, cwd) {
|
|
19915
|
+
this.copyId = copyId;
|
|
19916
|
+
this.cwd = cwd;
|
|
19917
|
+
}
|
|
19918
|
+
environment(environment) {
|
|
19919
|
+
return {
|
|
19920
|
+
...environment,
|
|
19921
|
+
CODEBUDDY_GATEWAY_AUTH: "password",
|
|
19922
|
+
CODEBUDDY_GATEWAY_PASSWORD: this.password,
|
|
19923
|
+
CODEBUDDY_GATEWAY_BASE_PATH: ""
|
|
19924
|
+
};
|
|
19925
|
+
}
|
|
19926
|
+
/** Native --serve banners include its password; never pass them to the ACP parser/logs. */
|
|
19927
|
+
protocolOutput(stdout) {
|
|
19928
|
+
return Readable.from(this.#protocolLines(stdout));
|
|
19929
|
+
}
|
|
19930
|
+
async *#protocolLines(stdout) {
|
|
19931
|
+
for await (const line of createInterface({ input: stdout })) {
|
|
19932
|
+
const endpoint = /^\s*Endpoint\s+(http:\/\/127\.0\.0\.1:\d+)\s*$/u.exec(stripVTControlCharacters(line));
|
|
19933
|
+
if (endpoint)
|
|
19934
|
+
this.#endpoint = endpoint[1];
|
|
19935
|
+
if (line.trimStart().startsWith("{"))
|
|
19936
|
+
yield Buffer.from(`${line}
|
|
19937
|
+
`);
|
|
19938
|
+
}
|
|
19939
|
+
}
|
|
19940
|
+
async remove() {
|
|
19941
|
+
if (!this.#endpoint)
|
|
19942
|
+
throw new CodeBuddyError("nativeFailure", `Native cleanup endpoint was not reported; temporary Session ${this.copyId} remains`);
|
|
19943
|
+
const response = await fetch(`${this.#endpoint}/api/v1/sessions/${encodeURIComponent(this.copyId)}?cwd=${encodeURIComponent(this.cwd)}`, {
|
|
19944
|
+
method: "DELETE",
|
|
19945
|
+
headers: { Authorization: `Bearer ${this.password}`, "x-codebuddy-request": "true" },
|
|
19946
|
+
signal: AbortSignal.timeout(5e3),
|
|
19947
|
+
redirect: "error"
|
|
19948
|
+
}).catch(() => {
|
|
19949
|
+
throw new CodeBuddyError("nativeFailure", `Native cleanup request failed; temporary Session ${this.copyId} remains`);
|
|
19950
|
+
});
|
|
19951
|
+
await response.body?.cancel();
|
|
19952
|
+
if (response.status !== 204)
|
|
19953
|
+
throw new CodeBuddyError("nativeFailure", `Native cleanup failed (${response.status}); temporary Session ${this.copyId} remains`);
|
|
19954
|
+
}
|
|
19955
|
+
};
|
|
19956
|
+
|
|
19576
19957
|
// ../../harness-discovery/dist/environment.js
|
|
19577
19958
|
import fs from "node:fs";
|
|
19578
19959
|
import path from "node:path";
|
|
@@ -19644,7 +20025,7 @@ function withNodeRuntimeOnPath(environment, runtimeExecutable = process.execPath
|
|
|
19644
20025
|
const directories = (environment[pathKey] ?? "").split(delimiter).filter(Boolean);
|
|
19645
20026
|
const equal = platform === "win32" ? (value) => value.toLowerCase() : (value) => value;
|
|
19646
20027
|
if (!directories.some((directory) => equal(directory) === equal(runtimeDirectory))) {
|
|
19647
|
-
directories.
|
|
20028
|
+
directories.push(runtimeDirectory);
|
|
19648
20029
|
}
|
|
19649
20030
|
return { ...environment, [pathKey]: directories.join(delimiter) };
|
|
19650
20031
|
}
|
|
@@ -19706,366 +20087,110 @@ function versionManagerBinaryDirectories(context) {
|
|
|
19706
20087
|
for (const formula of newestFirst(list(prefix).filter((name) => name.startsWith("node@")))) {
|
|
19707
20088
|
directories.push(pathFlavor.join(prefix, formula, "bin"));
|
|
19708
20089
|
}
|
|
19709
|
-
}
|
|
19710
|
-
return directories;
|
|
19711
|
-
}
|
|
19712
|
-
|
|
19713
|
-
// ../../harness-discovery/dist/resolve.js
|
|
19714
|
-
var VERSION_MANAGER_ROOTS = "<version-managers>";
|
|
19715
|
-
function installRootExtensions(platform) {
|
|
19716
|
-
return platform === "win32" ? [".exe", ".cmd"] : [""];
|
|
19717
|
-
}
|
|
19718
|
-
function resolveHomeDirectory(input) {
|
|
19719
|
-
return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
|
|
19720
|
-
}
|
|
19721
|
-
function templateVariables(environment, platform, home) {
|
|
19722
|
-
const pathFlavor = targetPath(platform);
|
|
19723
|
-
return {
|
|
19724
|
-
HOME: home,
|
|
19725
|
-
USERPROFILE: home,
|
|
19726
|
-
APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
|
|
19727
|
-
LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
|
|
19728
|
-
};
|
|
19729
|
-
}
|
|
19730
|
-
function joinTemplate(platform, value) {
|
|
19731
|
-
const pathFlavor = targetPath(platform);
|
|
19732
|
-
const segments = value.split("/");
|
|
19733
|
-
const head = segments[0] ?? "";
|
|
19734
|
-
const tail = segments.slice(1);
|
|
19735
|
-
if (head === "")
|
|
19736
|
-
return pathFlavor.join(pathFlavor.sep, ...tail);
|
|
19737
|
-
return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
|
|
19738
|
-
}
|
|
19739
|
-
function expandInstallRoot(template, environment, platform, home) {
|
|
19740
|
-
const variables = templateVariables(environment, platform, home);
|
|
19741
|
-
let unresolved = false;
|
|
19742
|
-
const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
|
|
19743
|
-
const value = variables[name] ?? environmentValue(environment, name);
|
|
19744
|
-
if (value === void 0 || value === "") {
|
|
19745
|
-
unresolved = true;
|
|
19746
|
-
return "";
|
|
19747
|
-
}
|
|
19748
|
-
return value;
|
|
19749
|
-
});
|
|
19750
|
-
return unresolved ? void 0 : joinTemplate(platform, substituted);
|
|
19751
|
-
}
|
|
19752
|
-
function installRootDirectories(spec, input, dependencies, platform, home) {
|
|
19753
|
-
const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
|
|
19754
|
-
const directories = [];
|
|
19755
|
-
for (const template of templates) {
|
|
19756
|
-
if (template === VERSION_MANAGER_ROOTS) {
|
|
19757
|
-
directories.push(...versionManagerBinaryDirectories({
|
|
19758
|
-
platform,
|
|
19759
|
-
environment: input.environment,
|
|
19760
|
-
home,
|
|
19761
|
-
...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
|
|
19762
|
-
}));
|
|
19763
|
-
continue;
|
|
19764
|
-
}
|
|
19765
|
-
const directory = expandInstallRoot(template, input.environment, platform, home);
|
|
19766
|
-
if (directory !== void 0)
|
|
19767
|
-
directories.push(directory);
|
|
19768
|
-
}
|
|
19769
|
-
return directories;
|
|
19770
|
-
}
|
|
19771
|
-
function harnessCandidates(spec, input, dependencies = {}) {
|
|
19772
|
-
const platform = input.platform ?? process.platform;
|
|
19773
|
-
const pathFlavor = targetPath(platform);
|
|
19774
|
-
const configured = input.command ?? (spec.commandEnvironmentVariable ? environmentValue(input.environment, spec.commandEnvironmentVariable) : void 0);
|
|
19775
|
-
const command = configured ?? spec.command;
|
|
19776
|
-
if (pathFlavor.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
|
|
19777
|
-
return [{ candidate: command, source: "configured" }];
|
|
19778
|
-
}
|
|
19779
|
-
const candidates = [];
|
|
19780
|
-
const extensions = executableExtensions(command, platform, input.environment);
|
|
19781
|
-
for (const directory of pathDirectories(input.environment, platform)) {
|
|
19782
|
-
for (const extension of extensions) {
|
|
19783
|
-
candidates.push({
|
|
19784
|
-
candidate: pathFlavor.join(directory, command + extension),
|
|
19785
|
-
source: "path"
|
|
19786
|
-
});
|
|
19787
|
-
}
|
|
19788
|
-
}
|
|
19789
|
-
if (configured !== void 0)
|
|
19790
|
-
return candidates;
|
|
19791
|
-
const home = resolveHomeDirectory(input);
|
|
19792
|
-
for (const directory of installRootDirectories(spec, input, dependencies, platform, home)) {
|
|
19793
|
-
for (const extension of installRootExtensions(platform)) {
|
|
19794
|
-
candidates.push({
|
|
19795
|
-
candidate: pathFlavor.join(directory, spec.command + extension),
|
|
19796
|
-
source: "install-root"
|
|
19797
|
-
});
|
|
19798
|
-
}
|
|
19799
|
-
}
|
|
19800
|
-
return candidates;
|
|
19801
|
-
}
|
|
19802
|
-
function resolveHarnessExecutable(spec, input, dependencies = {}) {
|
|
19803
|
-
const platform = input.platform ?? process.platform;
|
|
19804
|
-
const isExecutable = dependencies.isExecutable ?? ((candidate) => isExecutableFile(candidate, platform));
|
|
19805
|
-
const runnable = spec.runnableCandidate ?? ((candidate) => candidate);
|
|
19806
|
-
const context = { platform, isExecutable };
|
|
19807
|
-
for (const { candidate, source } of harnessCandidates(spec, input, dependencies)) {
|
|
19808
|
-
const executable = runnable(candidate, context);
|
|
19809
|
-
if (executable !== void 0 && isExecutable(executable))
|
|
19810
|
-
return { executable, source };
|
|
19811
|
-
}
|
|
19812
|
-
return void 0;
|
|
19813
|
-
}
|
|
19814
|
-
|
|
19815
|
-
// ../../harness-adapter/dist/approval.js
|
|
19816
|
-
function invalidRequest(message) {
|
|
19817
|
-
return { code: "invalidRequest", message, retryable: false };
|
|
19818
|
-
}
|
|
19819
|
-
function validateHostApprovalResponse(interaction, response) {
|
|
19820
|
-
return interaction.actions.some(({ id }) => id === response.actionId) ? null : invalidRequest("Approval Response contains an undeclared action ID");
|
|
19821
|
-
}
|
|
19822
|
-
|
|
19823
|
-
// ../../harness-adapter/dist/question.js
|
|
19824
|
-
function invalidRequest2(message) {
|
|
19825
|
-
return { code: "invalidRequest", message, retryable: false };
|
|
19826
|
-
}
|
|
19827
|
-
function validateHostQuestionResponse(interaction, response) {
|
|
19828
|
-
const questionIds = new Set(interaction.questions.map(({ id }) => id));
|
|
19829
|
-
if (response.cancelled) {
|
|
19830
|
-
return Object.keys(response.answers).length === 0 ? null : invalidRequest2("Cancelled Question Response must not contain answers");
|
|
19831
|
-
}
|
|
19832
|
-
for (const answerId of Object.keys(response.answers)) {
|
|
19833
|
-
if (!questionIds.has(answerId)) {
|
|
19834
|
-
return invalidRequest2("Question Response contains an unknown Question ID");
|
|
19835
|
-
}
|
|
19836
|
-
}
|
|
19837
|
-
for (const question of interaction.questions) {
|
|
19838
|
-
const answers = response.answers[question.id] ?? [];
|
|
19839
|
-
if (!question.optional && answers.length === 0) {
|
|
19840
|
-
return invalidRequest2("Question Response omits a required answer");
|
|
19841
|
-
}
|
|
19842
|
-
if (question.type === "text") {
|
|
19843
|
-
if (answers.length > 1) {
|
|
19844
|
-
return invalidRequest2("Text Question accepts at most one answer");
|
|
19845
|
-
}
|
|
19846
|
-
continue;
|
|
19847
|
-
}
|
|
19848
|
-
if (!question.multiple && answers.length > 1) {
|
|
19849
|
-
return invalidRequest2("Single-choice Question accepts at most one answer");
|
|
19850
|
-
}
|
|
19851
|
-
const declared = new Set(question.options.map(({ value }) => value));
|
|
19852
|
-
if (!question.allowOther && answers.some((answer) => !declared.has(answer))) {
|
|
19853
|
-
return invalidRequest2("Question Response contains an undeclared choice");
|
|
19854
|
-
}
|
|
19855
|
-
}
|
|
19856
|
-
return null;
|
|
19857
|
-
}
|
|
19858
|
-
|
|
19859
|
-
// ../../harness-adapter/dist/interaction.js
|
|
19860
|
-
function invalidRequest3(message) {
|
|
19861
|
-
return { code: "invalidRequest", message, retryable: false };
|
|
19862
|
-
}
|
|
19863
|
-
function invalidState(message) {
|
|
19864
|
-
return { code: "invalidState", message, retryable: false };
|
|
19865
|
-
}
|
|
19866
|
-
function validateHostInteractionResponse(interaction, response) {
|
|
19867
|
-
if (!interaction) {
|
|
19868
|
-
return invalidState("Interaction Response must reference a pending Interaction");
|
|
19869
|
-
}
|
|
19870
|
-
if (interaction.type === "question") {
|
|
19871
|
-
return response.type === "question" ? validateHostQuestionResponse(interaction, response) : invalidRequest3("Interaction Response type does not match the pending Interaction");
|
|
19872
|
-
}
|
|
19873
|
-
return response.type === "approval" ? validateHostApprovalResponse(interaction, response) : invalidRequest3("Interaction Response type does not match the pending Interaction");
|
|
19874
|
-
}
|
|
19875
|
-
|
|
19876
|
-
// ../../harness-adapter/dist/output-channel.js
|
|
19877
|
-
var HarnessOutputChannel = class {
|
|
19878
|
-
outputs;
|
|
19879
|
-
#consumerCreated = false;
|
|
19880
|
-
#ended = false;
|
|
19881
|
-
#pending = [];
|
|
19882
|
-
#values = [];
|
|
19883
|
-
constructor() {
|
|
19884
|
-
this.outputs = {
|
|
19885
|
-
[Symbol.asyncIterator]: () => {
|
|
19886
|
-
if (this.#consumerCreated) {
|
|
19887
|
-
throw new Error("Harness outputs allow only one consumer");
|
|
19888
|
-
}
|
|
19889
|
-
this.#consumerCreated = true;
|
|
19890
|
-
return {
|
|
19891
|
-
next: () => this.#next()
|
|
19892
|
-
};
|
|
19893
|
-
}
|
|
19894
|
-
};
|
|
19895
|
-
}
|
|
19896
|
-
emit(value) {
|
|
19897
|
-
if (this.#ended)
|
|
19898
|
-
return false;
|
|
19899
|
-
const resolve = this.#pending.shift();
|
|
19900
|
-
if (resolve)
|
|
19901
|
-
resolve({ done: false, value });
|
|
19902
|
-
else
|
|
19903
|
-
this.#values.push(value);
|
|
19904
|
-
return true;
|
|
19905
|
-
}
|
|
19906
|
-
end() {
|
|
19907
|
-
if (this.#ended)
|
|
19908
|
-
return;
|
|
19909
|
-
this.#ended = true;
|
|
19910
|
-
if (this.#values.length !== 0)
|
|
19911
|
-
return;
|
|
19912
|
-
for (const resolve of this.#pending.splice(0))
|
|
19913
|
-
resolve({ done: true, value: void 0 });
|
|
19914
|
-
}
|
|
19915
|
-
#next() {
|
|
19916
|
-
const value = this.#values.shift();
|
|
19917
|
-
if (value !== void 0)
|
|
19918
|
-
return Promise.resolve({ done: false, value });
|
|
19919
|
-
if (this.#ended)
|
|
19920
|
-
return Promise.resolve({ done: true, value: void 0 });
|
|
19921
|
-
return new Promise((resolve) => this.#pending.push(resolve));
|
|
19922
|
-
}
|
|
19923
|
-
};
|
|
19924
|
-
|
|
19925
|
-
// ../../harness-adapter/dist/diagnostics.js
|
|
19926
|
-
var DIAGNOSTIC_TAIL_MAX_LENGTH = 8e3;
|
|
19927
|
-
var SENSITIVE_VALUE_PATTERN = /(api[_-]?key|access[_-]?token|auth(?:orization)?|password|secret)(\s*[:=]\s*)([^\s,;]+)/giu;
|
|
19928
|
-
var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/giu;
|
|
19929
|
-
function sanitizeDiagnosticTail(value) {
|
|
19930
|
-
const redacted = value.replace(BEARER_PATTERN, "Bearer [redacted]").replace(SENSITIVE_VALUE_PATTERN, "$1$2[redacted]");
|
|
19931
|
-
return redacted.length <= DIAGNOSTIC_TAIL_MAX_LENGTH ? redacted : redacted.slice(-DIAGNOSTIC_TAIL_MAX_LENGTH);
|
|
20090
|
+
}
|
|
20091
|
+
return directories;
|
|
19932
20092
|
}
|
|
19933
20093
|
|
|
19934
|
-
// ../../harness-
|
|
19935
|
-
var
|
|
19936
|
-
|
|
19937
|
-
"
|
|
19938
|
-
"cacheWriteInputTokens",
|
|
19939
|
-
"outputTokens",
|
|
19940
|
-
"outputTokensPerSecond",
|
|
19941
|
-
"reasoningOutputTokens",
|
|
19942
|
-
"totalTokens",
|
|
19943
|
-
"contextWindowTokens",
|
|
19944
|
-
"contextUsedTokens"
|
|
19945
|
-
];
|
|
19946
|
-
var safeIntegerFields = [
|
|
19947
|
-
"planFiveHourResetsAtUnix",
|
|
19948
|
-
"planSevenDayResetsAtUnix"
|
|
19949
|
-
];
|
|
19950
|
-
var percentFields = [
|
|
19951
|
-
"cacheHitRatePercent",
|
|
19952
|
-
"planFiveHourUsedPercent",
|
|
19953
|
-
"planSevenDayUsedPercent"
|
|
19954
|
-
];
|
|
19955
|
-
var usageFields = /* @__PURE__ */ new Set([
|
|
19956
|
-
...tokenFields,
|
|
19957
|
-
...safeIntegerFields,
|
|
19958
|
-
...percentFields,
|
|
19959
|
-
"totalCostUsd",
|
|
19960
|
-
"totalCredits",
|
|
19961
|
-
"contextUsagePercent"
|
|
19962
|
-
]);
|
|
19963
|
-
function isRecord2(value) {
|
|
19964
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20094
|
+
// ../../harness-discovery/dist/resolve.js
|
|
20095
|
+
var VERSION_MANAGER_ROOTS = "<version-managers>";
|
|
20096
|
+
function installRootExtensions(platform) {
|
|
20097
|
+
return platform === "win32" ? [".exe", ".cmd"] : [""];
|
|
19965
20098
|
}
|
|
19966
|
-
function
|
|
19967
|
-
|
|
19968
|
-
|
|
19969
|
-
|
|
19970
|
-
|
|
19971
|
-
|
|
19972
|
-
|
|
19973
|
-
|
|
19974
|
-
|
|
20099
|
+
function resolveHomeDirectory(input) {
|
|
20100
|
+
return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
|
|
20101
|
+
}
|
|
20102
|
+
function templateVariables(environment, platform, home) {
|
|
20103
|
+
const pathFlavor = targetPath(platform);
|
|
20104
|
+
return {
|
|
20105
|
+
HOME: home,
|
|
20106
|
+
USERPROFILE: home,
|
|
20107
|
+
APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
|
|
20108
|
+
LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
|
|
20109
|
+
};
|
|
20110
|
+
}
|
|
20111
|
+
function joinTemplate(platform, value) {
|
|
20112
|
+
const pathFlavor = targetPath(platform);
|
|
20113
|
+
const segments = value.split("/");
|
|
20114
|
+
const head = segments[0] ?? "";
|
|
20115
|
+
const tail = segments.slice(1);
|
|
20116
|
+
if (head === "")
|
|
20117
|
+
return pathFlavor.join(pathFlavor.sep, ...tail);
|
|
20118
|
+
return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
|
|
20119
|
+
}
|
|
20120
|
+
function expandInstallRoot(template, environment, platform, home) {
|
|
20121
|
+
const variables = templateVariables(environment, platform, home);
|
|
20122
|
+
let unresolved = false;
|
|
20123
|
+
const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
|
|
20124
|
+
const value = variables[name] ?? environmentValue(environment, name);
|
|
20125
|
+
if (value === void 0 || value === "") {
|
|
20126
|
+
unresolved = true;
|
|
20127
|
+
return "";
|
|
19975
20128
|
}
|
|
19976
|
-
|
|
19977
|
-
|
|
19978
|
-
|
|
19979
|
-
|
|
19980
|
-
|
|
20129
|
+
return value;
|
|
20130
|
+
});
|
|
20131
|
+
return unresolved ? void 0 : joinTemplate(platform, substituted);
|
|
20132
|
+
}
|
|
20133
|
+
function installRootDirectories(spec, input, dependencies, platform, home) {
|
|
20134
|
+
const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
|
|
20135
|
+
const directories = [];
|
|
20136
|
+
for (const template of templates) {
|
|
20137
|
+
if (template === VERSION_MANAGER_ROOTS) {
|
|
20138
|
+
directories.push(...versionManagerBinaryDirectories({
|
|
20139
|
+
platform,
|
|
20140
|
+
environment: input.environment,
|
|
20141
|
+
home,
|
|
20142
|
+
...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
|
|
20143
|
+
}));
|
|
20144
|
+
continue;
|
|
19981
20145
|
}
|
|
20146
|
+
const directory = expandInstallRoot(template, input.environment, platform, home);
|
|
20147
|
+
if (directory !== void 0)
|
|
20148
|
+
directories.push(directory);
|
|
19982
20149
|
}
|
|
19983
|
-
|
|
19984
|
-
|
|
19985
|
-
|
|
19986
|
-
|
|
19987
|
-
|
|
20150
|
+
return directories;
|
|
20151
|
+
}
|
|
20152
|
+
function harnessCandidates(spec, input, dependencies = {}) {
|
|
20153
|
+
const platform = input.platform ?? process.platform;
|
|
20154
|
+
const pathFlavor = targetPath(platform);
|
|
20155
|
+
const configured = input.command ?? (spec.commandEnvironmentVariable ? environmentValue(input.environment, spec.commandEnvironmentVariable) : void 0);
|
|
20156
|
+
const command = configured ?? spec.command;
|
|
20157
|
+
if (pathFlavor.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
|
|
20158
|
+
return [{ candidate: command, source: "configured" }];
|
|
19988
20159
|
}
|
|
19989
|
-
|
|
19990
|
-
|
|
19991
|
-
|
|
19992
|
-
|
|
20160
|
+
const candidates = [];
|
|
20161
|
+
const extensions = executableExtensions(command, platform, input.environment);
|
|
20162
|
+
for (const directory of pathDirectories(input.environment, platform)) {
|
|
20163
|
+
for (const extension of extensions) {
|
|
20164
|
+
candidates.push({
|
|
20165
|
+
candidate: pathFlavor.join(directory, command + extension),
|
|
20166
|
+
source: "path"
|
|
20167
|
+
});
|
|
19993
20168
|
}
|
|
19994
20169
|
}
|
|
19995
|
-
if (
|
|
19996
|
-
|
|
19997
|
-
|
|
19998
|
-
|
|
19999
|
-
|
|
20000
|
-
|
|
20001
|
-
|
|
20002
|
-
|
|
20003
|
-
|
|
20004
|
-
throw new Error(`Harness Usage '${field}' must be between 0 and 100`);
|
|
20170
|
+
if (configured !== void 0)
|
|
20171
|
+
return candidates;
|
|
20172
|
+
const home = resolveHomeDirectory(input);
|
|
20173
|
+
for (const directory of installRootDirectories(spec, input, dependencies, platform, home)) {
|
|
20174
|
+
for (const extension of installRootExtensions(platform)) {
|
|
20175
|
+
candidates.push({
|
|
20176
|
+
candidate: pathFlavor.join(directory, spec.command + extension),
|
|
20177
|
+
source: "install-root"
|
|
20178
|
+
});
|
|
20005
20179
|
}
|
|
20006
20180
|
}
|
|
20007
|
-
|
|
20008
|
-
const hasContextWindow = value.contextWindowTokens !== void 0;
|
|
20009
|
-
if (hasContextUsed !== hasContextWindow) {
|
|
20010
|
-
throw new Error("Harness Usage context fields must be provided together");
|
|
20011
|
-
}
|
|
20012
|
-
if (hasContextWindow && value.contextWindowTokens === 0) {
|
|
20013
|
-
throw new Error("Harness Usage 'contextWindowTokens' must be greater than zero");
|
|
20014
|
-
}
|
|
20015
|
-
if (value.planFiveHourResetsAtUnix !== void 0 && value.planFiveHourUsedPercent === void 0) {
|
|
20016
|
-
throw new Error("Harness Usage 'planFiveHourResetsAtUnix' must be provided with 'planFiveHourUsedPercent'");
|
|
20017
|
-
}
|
|
20018
|
-
if (value.planSevenDayResetsAtUnix !== void 0 && value.planSevenDayUsedPercent === void 0) {
|
|
20019
|
-
throw new Error("Harness Usage 'planSevenDayResetsAtUnix' must be provided with 'planSevenDayUsedPercent'");
|
|
20020
|
-
}
|
|
20021
|
-
return { ...value };
|
|
20022
|
-
}
|
|
20023
|
-
|
|
20024
|
-
// dist/common.js
|
|
20025
|
-
var CODEBUDDY_ID = harnessIdSchema.parse("codebuddy");
|
|
20026
|
-
var OUTPUT_LIMIT = 64e3;
|
|
20027
|
-
var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
20028
|
-
var rows = (value) => Array.isArray(value) ? value.map(record2) : [];
|
|
20029
|
-
var text = (value) => typeof value === "string" ? value : "";
|
|
20030
|
-
var CodeBuddyError = class extends Error {
|
|
20031
|
-
code;
|
|
20032
|
-
constructor(code, message) {
|
|
20033
|
-
super(message);
|
|
20034
|
-
this.code = code;
|
|
20035
|
-
}
|
|
20036
|
-
};
|
|
20037
|
-
function nativeError(error51) {
|
|
20038
|
-
const diagnostic = sanitizeDiagnosticTail(error51 instanceof Error ? error51.message : String(error51));
|
|
20039
|
-
const nativeCode = record2(error51).code;
|
|
20040
|
-
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";
|
|
20041
|
-
return {
|
|
20042
|
-
code,
|
|
20043
|
-
message: `CodeBuddy: ${diagnostic || "native operation failed"}`,
|
|
20044
|
-
retryable: ["sessionBusy", "unavailable"].includes(code)
|
|
20045
|
-
};
|
|
20046
|
-
}
|
|
20047
|
-
function failure(code, message) {
|
|
20048
|
-
return { ok: false, error: nativeError(new CodeBuddyError(code, message)) };
|
|
20181
|
+
return candidates;
|
|
20049
20182
|
}
|
|
20050
|
-
|
|
20051
|
-
|
|
20052
|
-
|
|
20053
|
-
|
|
20054
|
-
|
|
20055
|
-
|
|
20056
|
-
|
|
20057
|
-
|
|
20058
|
-
|
|
20059
|
-
onTimeout?.(error51);
|
|
20060
|
-
} finally {
|
|
20061
|
-
reject(error51);
|
|
20062
|
-
}
|
|
20063
|
-
}, milliseconds);
|
|
20064
|
-
})
|
|
20065
|
-
]);
|
|
20066
|
-
} finally {
|
|
20067
|
-
clearTimeout(timer);
|
|
20183
|
+
function resolveHarnessExecutable(spec, input, dependencies = {}) {
|
|
20184
|
+
const platform = input.platform ?? process.platform;
|
|
20185
|
+
const isExecutable = dependencies.isExecutable ?? ((candidate) => isExecutableFile(candidate, platform));
|
|
20186
|
+
const runnable = spec.runnableCandidate ?? ((candidate) => candidate);
|
|
20187
|
+
const context = { platform, isExecutable };
|
|
20188
|
+
for (const { candidate, source } of harnessCandidates(spec, input, dependencies)) {
|
|
20189
|
+
const executable = runnable(candidate, context);
|
|
20190
|
+
if (executable !== void 0 && isExecutable(executable))
|
|
20191
|
+
return { executable, source };
|
|
20068
20192
|
}
|
|
20193
|
+
return void 0;
|
|
20069
20194
|
}
|
|
20070
20195
|
|
|
20071
20196
|
// dist/command.js
|
|
@@ -20084,21 +20209,34 @@ var codeBuddyDiscoverySpec = {
|
|
|
20084
20209
|
]
|
|
20085
20210
|
}
|
|
20086
20211
|
};
|
|
20087
|
-
function codeBuddyInvocation(environment, ephemeral) {
|
|
20212
|
+
function codeBuddyInvocation(environment, ephemeral, argumentsOverride) {
|
|
20088
20213
|
const resolved = resolveHarnessExecutable(codeBuddyDiscoverySpec, { environment });
|
|
20089
20214
|
if (!resolved)
|
|
20090
20215
|
throw new CodeBuddyError("notInstalled", "CLI is not installed; run codebuddy and sign in first");
|
|
20091
20216
|
const env = withNodeRuntimeOnPath(environment);
|
|
20092
20217
|
return {
|
|
20093
|
-
...commandInvocation(resolved.executable,
|
|
20218
|
+
...commandInvocation(resolved.executable, argumentsOverride ?? [
|
|
20219
|
+
"--acp",
|
|
20220
|
+
...ephemeral ? ["--no-session-persistence"] : [],
|
|
20221
|
+
...!ephemeral && [
|
|
20222
|
+
"CODEXHOST_CLI_PATH",
|
|
20223
|
+
"CODEXHOST_RUNTIME_ENDPOINT",
|
|
20224
|
+
"CODEXHOST_RUNTIME_TOKEN",
|
|
20225
|
+
"CODEXHOST_THREAD_ID"
|
|
20226
|
+
].every((key) => environment[key]) ? ["--append-system-prompt", CODEBUDDY_DELEGATION_INSTRUCTIONS] : []
|
|
20227
|
+
], env),
|
|
20094
20228
|
environment: env
|
|
20095
20229
|
};
|
|
20096
20230
|
}
|
|
20231
|
+
var CODEBUDDY_DELEGATION_INSTRUCTIONS = `This Session runs inside codexhost.
|
|
20232
|
+
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.`;
|
|
20097
20233
|
|
|
20098
20234
|
// dist/acp-client.js
|
|
20099
20235
|
var CodeBuddyAcpClient = class {
|
|
20100
20236
|
options;
|
|
20101
20237
|
operationTimeoutMs;
|
|
20238
|
+
invocationFactory;
|
|
20239
|
+
#copyCleanup;
|
|
20102
20240
|
#child;
|
|
20103
20241
|
#connection;
|
|
20104
20242
|
#exited;
|
|
@@ -20110,12 +20248,14 @@ var CodeBuddyAcpClient = class {
|
|
|
20110
20248
|
#failed = new Promise((_, reject) => {
|
|
20111
20249
|
this.#rejectFailure = reject;
|
|
20112
20250
|
});
|
|
20113
|
-
constructor(options, operationTimeoutMs = 15e3) {
|
|
20251
|
+
constructor(options, operationTimeoutMs = 15e3, invocationFactory = codeBuddyInvocation) {
|
|
20114
20252
|
this.options = options;
|
|
20115
20253
|
this.operationTimeoutMs = operationTimeoutMs;
|
|
20254
|
+
this.invocationFactory = invocationFactory;
|
|
20116
20255
|
void this.#failed.catch(() => {
|
|
20117
20256
|
});
|
|
20118
|
-
|
|
20257
|
+
this.#copyCleanup = options.temporarySessionId ? new CodeBuddyCopyCleanup(options.temporarySessionId, options.cwd) : void 0;
|
|
20258
|
+
const invocation = invocationFactory(this.#copyCleanup?.environment(options.environment) ?? options.environment, options.ephemeral, this.#copyCleanup?.arguments);
|
|
20119
20259
|
this.#child = spawn(invocation.command, invocation.arguments, {
|
|
20120
20260
|
cwd: options.cwd,
|
|
20121
20261
|
env: invocation.environment,
|
|
@@ -20152,7 +20292,7 @@ var CodeBuddyAcpClient = class {
|
|
|
20152
20292
|
return { outcome: "cancelled" };
|
|
20153
20293
|
return options.handlers.question(params);
|
|
20154
20294
|
}
|
|
20155
|
-
}), ndJsonStream2(Writable.toWeb(this.#child.stdin),
|
|
20295
|
+
}), ndJsonStream2(Writable.toWeb(this.#child.stdin), Readable2.toWeb(this.#copyCleanup?.protocolOutput(this.#child.stdout) ?? this.#child.stdout)));
|
|
20156
20296
|
void this.#connection.closed.then(() => {
|
|
20157
20297
|
this.#fault(new CodeBuddyError("processExited", "ACP connection closed"));
|
|
20158
20298
|
}).catch((error51) => {
|
|
@@ -20202,13 +20342,27 @@ var CodeBuddyAcpClient = class {
|
|
|
20202
20342
|
async cancel(sessionId) {
|
|
20203
20343
|
await this.#request(() => this.#connection.cancel({ sessionId }), "ACP cancel");
|
|
20204
20344
|
}
|
|
20345
|
+
async removeCopy() {
|
|
20346
|
+
const cleanup = this.#copyCleanup;
|
|
20347
|
+
if (!cleanup)
|
|
20348
|
+
throw new CodeBuddyError("invalidState", "No temporary copy is owned by this process");
|
|
20349
|
+
await this.#request(() => cleanup.remove(), "Native temporary Session cleanup");
|
|
20350
|
+
}
|
|
20351
|
+
async rollback(sessionId, forkPointId) {
|
|
20352
|
+
return record2(await this.#request(() => this.#connection.extMethod("_codebuddy.ai/session/rollback", {
|
|
20353
|
+
sessionId,
|
|
20354
|
+
forkPointId,
|
|
20355
|
+
reason: "resend_edit",
|
|
20356
|
+
files: false
|
|
20357
|
+
}), "ACP history rewind"));
|
|
20358
|
+
}
|
|
20205
20359
|
async answer(sessionId, toolCallId, answers) {
|
|
20206
20360
|
const response = await this.#request(() => this.#connection.extMethod("_codebuddy.ai/resolveInterruption", {
|
|
20207
20361
|
sessionId,
|
|
20208
20362
|
toolCallId,
|
|
20209
20363
|
decision: answers === null ? "deny" : "allow",
|
|
20210
20364
|
...answers ? { answers } : {}
|
|
20211
|
-
}), "
|
|
20365
|
+
}), "ACP question response");
|
|
20212
20366
|
if (record2(response).resolved !== true)
|
|
20213
20367
|
throw new CodeBuddyError("protocolError", "Native question is no longer pending");
|
|
20214
20368
|
}
|
|
@@ -20250,19 +20404,25 @@ var CODEBUDDY_CAPABILITIES = {
|
|
|
20250
20404
|
selectPermissionMode: true,
|
|
20251
20405
|
permissionModeScope: "live"
|
|
20252
20406
|
},
|
|
20253
|
-
history: { fork:
|
|
20407
|
+
history: { fork: true, forkAcrossCwd: false, rollbackLastTurn: true },
|
|
20254
20408
|
subagents: { observe: true, readTranscript: true }
|
|
20255
20409
|
};
|
|
20410
|
+
function capabilitiesForProfile(profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20411
|
+
return {
|
|
20412
|
+
...CODEBUDDY_CAPABILITIES,
|
|
20413
|
+
history: profile.historyCapabilities ?? CODEBUDDY_CAPABILITIES.history
|
|
20414
|
+
};
|
|
20415
|
+
}
|
|
20256
20416
|
function modelRef(modelId) {
|
|
20257
20417
|
return harnessModelRefSchema.parse({ id: `cb.${Buffer.from(modelId).toString("base64url")}` });
|
|
20258
20418
|
}
|
|
20259
20419
|
function nativeModel(ref) {
|
|
20260
20420
|
const value = Buffer.from(ref.id.slice(3), "base64url").toString("utf8");
|
|
20261
20421
|
if (!value || !ref.id.startsWith("cb.") || modelRef(value).id !== ref.id)
|
|
20262
|
-
throw new CodeBuddyError("invalidRequest", "Invalid
|
|
20422
|
+
throw new CodeBuddyError("invalidRequest", "Invalid native Model Ref");
|
|
20263
20423
|
return value;
|
|
20264
20424
|
}
|
|
20265
|
-
function configuration(value) {
|
|
20425
|
+
function configuration(value, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20266
20426
|
const options = rows(value);
|
|
20267
20427
|
const get = (id) => options.find((option) => option.id === id) ?? {};
|
|
20268
20428
|
const model = get("model"), mode = get("mode"), thought = get("thought_level");
|
|
@@ -20272,7 +20432,12 @@ function configuration(value) {
|
|
|
20272
20432
|
ref: modelRef(text(option.value)),
|
|
20273
20433
|
label: text(option.name)
|
|
20274
20434
|
}));
|
|
20275
|
-
const
|
|
20435
|
+
const currentModelRef = modelRef(text(model.currentValue));
|
|
20436
|
+
let currentModel = models.find((item) => item.ref.id === currentModelRef.id);
|
|
20437
|
+
if (!currentModel && profile.allowUnlistedModelSelection) {
|
|
20438
|
+
currentModel = { ref: currentModelRef, label: text(model.currentValue) };
|
|
20439
|
+
models.push(currentModel);
|
|
20440
|
+
}
|
|
20276
20441
|
if (!currentModel)
|
|
20277
20442
|
throw new CodeBuddyError("protocolError", "ACP did not report a valid current Model");
|
|
20278
20443
|
const catalog = harnessModelCatalogSchema.parse({
|
|
@@ -20302,18 +20467,28 @@ function configuration(value) {
|
|
|
20302
20467
|
};
|
|
20303
20468
|
return { catalog, permissionModes, state, options };
|
|
20304
20469
|
}
|
|
20305
|
-
function confirmedConfiguration(response, id, value) {
|
|
20306
|
-
const result = configuration(record2(response).configOptions);
|
|
20470
|
+
function confirmedConfiguration(response, id, value, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20471
|
+
const result = configuration(record2(response).configOptions, profile);
|
|
20307
20472
|
if (result.options.find((option) => option.id === id)?.currentValue !== value) {
|
|
20308
20473
|
throw new CodeBuddyError("protocolError", `ACP did not confirm ${id}`);
|
|
20309
20474
|
}
|
|
20310
20475
|
return result;
|
|
20311
20476
|
}
|
|
20312
20477
|
|
|
20478
|
+
// dist/derivation.js
|
|
20479
|
+
import { randomUUID } from "node:crypto";
|
|
20480
|
+
import { execFile as execFile2, spawn as spawn2 } from "node:child_process";
|
|
20481
|
+
import { lstat, mkdir, readFile as readFile2, realpath as realpath4, unlink, writeFile } from "node:fs/promises";
|
|
20482
|
+
import path5 from "node:path";
|
|
20483
|
+
import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
|
|
20484
|
+
|
|
20313
20485
|
// dist/history.js
|
|
20486
|
+
import { createHash } from "node:crypto";
|
|
20487
|
+
import { realpathSync } from "node:fs";
|
|
20314
20488
|
import { access, readdir, realpath as realpath2 } from "node:fs/promises";
|
|
20315
20489
|
import { homedir } from "node:os";
|
|
20316
20490
|
import path4 from "node:path";
|
|
20491
|
+
import { isDeepStrictEqual } from "node:util";
|
|
20317
20492
|
|
|
20318
20493
|
// ../../../node_modules/diff/libesm/diff/base.js
|
|
20319
20494
|
var Diff = class {
|
|
@@ -20415,16 +20590,16 @@ var Diff = class {
|
|
|
20415
20590
|
}
|
|
20416
20591
|
}
|
|
20417
20592
|
}
|
|
20418
|
-
addToPath(
|
|
20419
|
-
const last =
|
|
20593
|
+
addToPath(path8, added, removed, oldPosInc, options) {
|
|
20594
|
+
const last = path8.lastComponent;
|
|
20420
20595
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
20421
20596
|
return {
|
|
20422
|
-
oldPos:
|
|
20597
|
+
oldPos: path8.oldPos + oldPosInc,
|
|
20423
20598
|
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
20424
20599
|
};
|
|
20425
20600
|
} else {
|
|
20426
20601
|
return {
|
|
20427
|
-
oldPos:
|
|
20602
|
+
oldPos: path8.oldPos + oldPosInc,
|
|
20428
20603
|
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
20429
20604
|
};
|
|
20430
20605
|
}
|
|
@@ -20762,28 +20937,31 @@ function toolOutput(value) {
|
|
|
20762
20937
|
...output.length > OUTPUT_LIMIT ? { truncated: true } : {}
|
|
20763
20938
|
};
|
|
20764
20939
|
}
|
|
20765
|
-
function toolOutcome(status) {
|
|
20940
|
+
function toolOutcome(status, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20766
20941
|
if (status === "completed")
|
|
20767
20942
|
return { status: "succeeded" };
|
|
20768
20943
|
if (status === "cancelled" || status === "interrupted")
|
|
20769
20944
|
return { status: "cancelled" };
|
|
20770
20945
|
return {
|
|
20771
20946
|
status: "failed",
|
|
20772
|
-
error: nativeError(new CodeBuddyError("nativeFailure", status === "failed" ? "Tool execution failed" : "Tool completion was not recorded"))
|
|
20947
|
+
error: nativeError(new CodeBuddyError("nativeFailure", status === "failed" ? "Tool execution failed" : "Tool completion was not recorded"), profile)
|
|
20773
20948
|
};
|
|
20774
20949
|
}
|
|
20775
20950
|
var CodeBuddyTurnOutput = class {
|
|
20776
20951
|
turnId;
|
|
20777
20952
|
cwd;
|
|
20778
20953
|
emit;
|
|
20954
|
+
profile;
|
|
20779
20955
|
#items = /* @__PURE__ */ new Map();
|
|
20780
20956
|
#finished = /* @__PURE__ */ new Set();
|
|
20781
20957
|
#tools = /* @__PURE__ */ new Map();
|
|
20782
20958
|
#diffs = /* @__PURE__ */ new Set();
|
|
20783
|
-
|
|
20959
|
+
#compactionOutcome;
|
|
20960
|
+
constructor(turnId, cwd, emit, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
20784
20961
|
this.turnId = turnId;
|
|
20785
20962
|
this.cwd = cwd;
|
|
20786
20963
|
this.emit = emit;
|
|
20964
|
+
this.profile = profile;
|
|
20787
20965
|
}
|
|
20788
20966
|
#start(item) {
|
|
20789
20967
|
this.#items.set(item.itemId, { item, outcome: { status: "succeeded" } });
|
|
@@ -20800,11 +20978,33 @@ var CodeBuddyTurnOutput = class {
|
|
|
20800
20978
|
snapshot: structuredClone({ item, outcome })
|
|
20801
20979
|
});
|
|
20802
20980
|
}
|
|
20981
|
+
replayCommandResult(items) {
|
|
20982
|
+
if (this.#items.size)
|
|
20983
|
+
return;
|
|
20984
|
+
for (const snapshot of items) {
|
|
20985
|
+
const item = structuredClone(snapshot.item);
|
|
20986
|
+
this.#start(item);
|
|
20987
|
+
this.#finish(item, snapshot.outcome);
|
|
20988
|
+
}
|
|
20989
|
+
}
|
|
20990
|
+
confirmCompaction(items) {
|
|
20991
|
+
const persisted = items.find((snapshot) => snapshot.item.type === "contextCompaction");
|
|
20992
|
+
this.#compactionOutcome = persisted ? structuredClone(persisted.outcome) : void 0;
|
|
20993
|
+
}
|
|
20994
|
+
compact() {
|
|
20995
|
+
const itemId = hostItemIdSchema.parse(`compact-${this.turnId}`);
|
|
20996
|
+
if (!this.#items.has(itemId))
|
|
20997
|
+
this.#start({ type: "contextCompaction", itemId });
|
|
20998
|
+
}
|
|
20803
20999
|
update(value) {
|
|
20804
21000
|
const update = record2(value), meta3 = record2(update._meta);
|
|
20805
21001
|
if (meta3["codebuddy.ai/memberEvent"])
|
|
20806
21002
|
return;
|
|
20807
21003
|
const kind = update.sessionUpdate;
|
|
21004
|
+
if (nativeCommandsEnabled(this.profile) && meta3["codebuddy.ai/isCompactInternal"] === true) {
|
|
21005
|
+
this.compact();
|
|
21006
|
+
return;
|
|
21007
|
+
}
|
|
20808
21008
|
if (kind === "agent_message_chunk" || kind === "agent_thought_chunk") {
|
|
20809
21009
|
const delta = contentText(update.content);
|
|
20810
21010
|
if (!delta)
|
|
@@ -20844,7 +21044,7 @@ var CodeBuddyTurnOutput = class {
|
|
|
20844
21044
|
const terminal = update.status === "completed" || update.status === "failed";
|
|
20845
21045
|
if (!terminal && !record2(merged._meta)["codebuddy.ai/toolArgumentsComplete"])
|
|
20846
21046
|
return;
|
|
20847
|
-
const name = text(record2(merged._meta)["codebuddy.ai/toolName"]) || text(merged.title) ||
|
|
21047
|
+
const name = text(record2(merged._meta)["codebuddy.ai/toolName"]) || text(merged.title) || `${this.profile.displayName} tool`;
|
|
20848
21048
|
const id = `tool-${callId}`;
|
|
20849
21049
|
let item = this.#items.get(id)?.item;
|
|
20850
21050
|
if (!item) {
|
|
@@ -20875,7 +21075,7 @@ var CodeBuddyTurnOutput = class {
|
|
|
20875
21075
|
update: { type: "output.replace", output }
|
|
20876
21076
|
});
|
|
20877
21077
|
}
|
|
20878
|
-
this.#finish(item, toolOutcome(update.status));
|
|
21078
|
+
this.#finish(item, toolOutcome(update.status, this.profile));
|
|
20879
21079
|
if (update.status === "completed" && !this.#diffs.has(callId)) {
|
|
20880
21080
|
const changes = [];
|
|
20881
21081
|
for (const diff of rows(merged.content)) {
|
|
@@ -20904,9 +21104,13 @@ var CodeBuddyTurnOutput = class {
|
|
|
20904
21104
|
}
|
|
20905
21105
|
finish(status, error51) {
|
|
20906
21106
|
for (const { item } of this.#items.values()) {
|
|
20907
|
-
|
|
20908
|
-
|
|
20909
|
-
|
|
21107
|
+
if (item.type === "contextCompaction" && this.#compactionOutcome) {
|
|
21108
|
+
this.#finish(item, this.#compactionOutcome);
|
|
21109
|
+
continue;
|
|
21110
|
+
}
|
|
21111
|
+
const outcome = status === "failed" || item.type === "contextCompaction" && status === "succeeded" && !this.#compactionOutcome ? {
|
|
21112
|
+
status: "failed",
|
|
21113
|
+
error: error51 ?? nativeError(new CodeBuddyError("nativeFailure", item.type === "contextCompaction" ? "Native compaction completion was not confirmed" : "Turn failed"), this.profile)
|
|
20910
21114
|
} : { status };
|
|
20911
21115
|
this.#finish(item, outcome);
|
|
20912
21116
|
}
|
|
@@ -20923,7 +21127,7 @@ function codeBuddyChildId(value) {
|
|
|
20923
21127
|
const id = structured || /\[Agent ID: (agent-[a-zA-Z0-9_-]+)\]\s*$/u.exec(body)?.[1];
|
|
20924
21128
|
return id && validCodeBuddyChildId(id) ? id : void 0;
|
|
20925
21129
|
}
|
|
20926
|
-
function codeBuddyDelegation(callId, input, status, childId) {
|
|
21130
|
+
function codeBuddyDelegation(callId, input, status, childId, displayName = "CodeBuddy") {
|
|
20927
21131
|
const args = record2(input);
|
|
20928
21132
|
const resumed = text(args.resume);
|
|
20929
21133
|
const nativeId = childId ?? (validCodeBuddyChildId(resumed) ? resumed : void 0);
|
|
@@ -20936,7 +21140,7 @@ function codeBuddyDelegation(callId, input, status, childId) {
|
|
|
20936
21140
|
{
|
|
20937
21141
|
subagentId: nativeId ?? callId,
|
|
20938
21142
|
...nativeId ? { nativeSubagentId: nativeId } : {},
|
|
20939
|
-
description: text(args.description) ||
|
|
21143
|
+
description: text(args.description) || `${displayName} Subagent`,
|
|
20940
21144
|
...text(args.subagent_type) ? { role: text(args.subagent_type) } : {},
|
|
20941
21145
|
...text(args.model) ? { model: text(args.model) } : {},
|
|
20942
21146
|
background: args.run_in_background === true,
|
|
@@ -20970,9 +21174,55 @@ async function readCodeBuddyVersionedText(file2, maximumBytes, tooLargeMessage,
|
|
|
20970
21174
|
}
|
|
20971
21175
|
|
|
20972
21176
|
// dist/history.js
|
|
20973
|
-
function
|
|
20974
|
-
|
|
20975
|
-
|
|
21177
|
+
function codeBuddyProjectSlug(cwd, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21178
|
+
const canonical = codeBuddyCanonicalCwd(cwd);
|
|
21179
|
+
if (profile.projectDirectoryName)
|
|
21180
|
+
return profile.projectDirectoryName(canonical);
|
|
21181
|
+
return canonical.replace(/[^a-z0-9]/giu, "-").replace(/-+/gu, "-").replace(/^-|-$/gu, "").toLowerCase();
|
|
21182
|
+
}
|
|
21183
|
+
function codeBuddyCanonicalCwd(cwd) {
|
|
21184
|
+
try {
|
|
21185
|
+
return realpathSync.native(cwd);
|
|
21186
|
+
} catch {
|
|
21187
|
+
return path4.resolve(cwd);
|
|
21188
|
+
}
|
|
21189
|
+
}
|
|
21190
|
+
function codeBuddyConfigRoot(environment, profile) {
|
|
21191
|
+
const configuredRoot = profile.configDirectoryEnvironmentVariables.map((name) => environment[name]).find((value) => typeof value === "string" && value.trim().length > 0);
|
|
21192
|
+
return configuredRoot || path4.join(environment.HOME || environment.USERPROFILE || homedir(), profile.defaultConfigDirectoryName);
|
|
21193
|
+
}
|
|
21194
|
+
function codeBuddyPrimaryHistoryPath(cwd, ref, environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21195
|
+
return path4.join(codeBuddyConfigRoot(environment, profile), "projects", codeBuddyProjectSlug(cwd, profile), `${ref.nativeSessionId}.jsonl`);
|
|
21196
|
+
}
|
|
21197
|
+
function derivedLocator(ref) {
|
|
21198
|
+
const locator = record2(ref.locator);
|
|
21199
|
+
if (locator.codebuddyDerived !== 1)
|
|
21200
|
+
return void 0;
|
|
21201
|
+
const fields = [
|
|
21202
|
+
locator.boundCwd,
|
|
21203
|
+
locator.targetProjectSlug,
|
|
21204
|
+
locator.inheritedPrefixRows,
|
|
21205
|
+
locator.inheritedPrefixSha256,
|
|
21206
|
+
locator.bindingMarkerId
|
|
21207
|
+
];
|
|
21208
|
+
if (fields.every((value) => value === void 0))
|
|
21209
|
+
return void 0;
|
|
21210
|
+
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)
|
|
21211
|
+
throw new CodeBuddyError("protocolError", "Derived Native Session locator is incomplete");
|
|
21212
|
+
return {
|
|
21213
|
+
boundCwd: locator.boundCwd,
|
|
21214
|
+
targetProjectSlug: locator.targetProjectSlug,
|
|
21215
|
+
inheritedPrefixRows: Number(locator.inheritedPrefixRows),
|
|
21216
|
+
inheritedPrefixSha256: locator.inheritedPrefixSha256,
|
|
21217
|
+
bindingMarkerId: locator.bindingMarkerId
|
|
21218
|
+
};
|
|
21219
|
+
}
|
|
21220
|
+
function nativeRowsDigest(rows2) {
|
|
21221
|
+
return createHash("sha256").update(JSON.stringify(rows2)).digest("hex");
|
|
21222
|
+
}
|
|
21223
|
+
function validateNativeRef(ref, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21224
|
+
if (ref.harnessId !== profile.harnessId || ref.formatVersion !== 1 || !/^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/u.test(ref.nativeSessionId)) {
|
|
21225
|
+
throw new CodeBuddyError("invalidRequest", `Invalid ${profile.displayName} Native Session identity`);
|
|
20976
21226
|
}
|
|
20977
21227
|
}
|
|
20978
21228
|
async function sameCwd(left, right) {
|
|
@@ -20984,18 +21234,37 @@ async function sameCwd(left, right) {
|
|
|
20984
21234
|
});
|
|
20985
21235
|
return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
20986
21236
|
}
|
|
20987
|
-
async function
|
|
20988
|
-
|
|
21237
|
+
async function matchesAnyHistoricalCwd(value, candidates) {
|
|
21238
|
+
const resolved = path4.resolve(value);
|
|
21239
|
+
for (const candidate of candidates) {
|
|
21240
|
+
const other = path4.resolve(candidate);
|
|
21241
|
+
if (process.platform === "win32" ? resolved.toLowerCase() === other.toLowerCase() : resolved === other)
|
|
21242
|
+
return true;
|
|
21243
|
+
try {
|
|
21244
|
+
if (await sameCwd(value, candidate))
|
|
21245
|
+
return true;
|
|
21246
|
+
} catch (error51) {
|
|
21247
|
+
if (!(error51 instanceof CodeBuddyError) && !["ENOENT", "ENOTDIR"].includes(text(record2(error51).code)))
|
|
21248
|
+
throw error51;
|
|
21249
|
+
}
|
|
21250
|
+
}
|
|
21251
|
+
return false;
|
|
21252
|
+
}
|
|
21253
|
+
async function codeBuddyNativeHistory(cwd, ref, environment, profileOrVerifiedSource = CODEBUDDY_RUNTIME_PROFILE, transaction) {
|
|
21254
|
+
const profile = typeof profileOrVerifiedSource === "string" ? CODEBUDDY_RUNTIME_PROFILE : profileOrVerifiedSource;
|
|
21255
|
+
const effectiveTransaction = typeof profileOrVerifiedSource === "string" ? { inheritedContents: profileOrVerifiedSource } : transaction;
|
|
21256
|
+
return codeBuddyHistory(cwd, ref, environment, false, profile, effectiveTransaction);
|
|
20989
21257
|
}
|
|
20990
|
-
async function codeBuddyLiveNativeHistory(cwd, ref, environment) {
|
|
20991
|
-
return codeBuddyHistory(cwd, ref, environment, true);
|
|
21258
|
+
async function codeBuddyLiveNativeHistory(cwd, ref, environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21259
|
+
return codeBuddyHistory(cwd, ref, environment, true, profile);
|
|
20992
21260
|
}
|
|
20993
|
-
async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail) {
|
|
20994
|
-
validateNativeRef(ref);
|
|
20995
|
-
const configRoot =
|
|
21261
|
+
async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail, profile, transaction) {
|
|
21262
|
+
validateNativeRef(ref, profile);
|
|
21263
|
+
const configRoot = codeBuddyConfigRoot(environment, profile);
|
|
20996
21264
|
const root = path4.join(configRoot, "projects");
|
|
20997
|
-
const slug =
|
|
21265
|
+
const slug = codeBuddyProjectSlug(cwd, profile);
|
|
20998
21266
|
const primary = path4.join(root, slug, `${ref.nativeSessionId}.jsonl`);
|
|
21267
|
+
const provenance = derivedLocator(ref);
|
|
20999
21268
|
let candidates = [];
|
|
21000
21269
|
try {
|
|
21001
21270
|
await access(primary);
|
|
@@ -21003,6 +21272,8 @@ async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail) {
|
|
|
21003
21272
|
} catch (error51) {
|
|
21004
21273
|
if (record2(error51).code !== "ENOENT")
|
|
21005
21274
|
throw error51;
|
|
21275
|
+
if (transaction?.requirePrimary || provenance)
|
|
21276
|
+
throw new CodeBuddyError("sessionNotFound", "Native Session history was not found");
|
|
21006
21277
|
const directories = await readdir(root, { withFileTypes: true }).catch((error52) => {
|
|
21007
21278
|
if (record2(error52).code === "ENOENT")
|
|
21008
21279
|
return [];
|
|
@@ -21026,15 +21297,63 @@ async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail) {
|
|
|
21026
21297
|
const file2 = candidates[0];
|
|
21027
21298
|
if (!file2)
|
|
21028
21299
|
throw new CodeBuddyError("sessionNotFound", "Native Session history was not found");
|
|
21300
|
+
if (profile.historyCapabilities?.fork && !transaction && path4.resolve(file2) !== path4.resolve(primary))
|
|
21301
|
+
throw new CodeBuddyError("invalidRequest", "Native Session is not stored in the requested working directory");
|
|
21029
21302
|
const source = await readCodeBuddyVersionedText(file2, 64e6, "Native history exceeds the supported 64 MB snapshot size"), parsed = parseJsonl(source.contents, tolerateIncompleteTail);
|
|
21030
21303
|
const checkedDirectories = /* @__PURE__ */ new Set();
|
|
21031
|
-
|
|
21032
|
-
|
|
21033
|
-
|
|
21034
|
-
|
|
21035
|
-
|
|
21036
|
-
|
|
21037
|
-
|
|
21304
|
+
const inheritedRows = /* @__PURE__ */ new Map();
|
|
21305
|
+
for (const row of transaction?.inheritedContents ? parseRows(transaction.inheritedContents) : []) {
|
|
21306
|
+
const id = text(row.id);
|
|
21307
|
+
const candidates2 = inheritedRows.get(id) ?? [];
|
|
21308
|
+
candidates2.push(row);
|
|
21309
|
+
inheritedRows.set(id, candidates2);
|
|
21310
|
+
}
|
|
21311
|
+
const inherited = (row) => inheritedRows.get(text(row.id))?.some((candidate) => isDeepStrictEqual(candidate, row)) === true;
|
|
21312
|
+
if (transaction) {
|
|
21313
|
+
for (const row of parsed.rows) {
|
|
21314
|
+
if (inherited(row)) {
|
|
21315
|
+
if (typeof row.cwd === "string")
|
|
21316
|
+
checkedDirectories.add(row.cwd);
|
|
21317
|
+
continue;
|
|
21318
|
+
}
|
|
21319
|
+
if (row.sessionId && row.sessionId !== ref.nativeSessionId)
|
|
21320
|
+
throw new CodeBuddyError("protocolError", "Native history has a different Session identity");
|
|
21321
|
+
if (typeof row.cwd === "string" && !checkedDirectories.has(row.cwd)) {
|
|
21322
|
+
const allowed = [cwd, ...transaction.allowedHistoricalCwds ?? []];
|
|
21323
|
+
if (!await matchesAnyHistoricalCwd(row.cwd, allowed))
|
|
21324
|
+
throw new CodeBuddyError("invalidRequest", "Native Session belongs to a different working directory");
|
|
21325
|
+
checkedDirectories.add(row.cwd);
|
|
21326
|
+
}
|
|
21327
|
+
}
|
|
21328
|
+
} else if (provenance) {
|
|
21329
|
+
if (!await sameCwd(provenance.boundCwd, cwd) || provenance.targetProjectSlug !== slug || path4.resolve(file2) !== path4.resolve(primary))
|
|
21330
|
+
throw new CodeBuddyError("invalidRequest", "Derived Native Session target binding changed");
|
|
21331
|
+
const active = nativeHistoryRows(parsed.contents);
|
|
21332
|
+
if (provenance.inheritedPrefixRows > active.length || nativeRowsDigest(active.slice(0, provenance.inheritedPrefixRows)) !== provenance.inheritedPrefixSha256)
|
|
21333
|
+
throw new CodeBuddyError("protocolError", "Derived Native Session prefix verification failed");
|
|
21334
|
+
const marker = parsed.rows.find((row) => text(row.id) === provenance.bindingMarkerId);
|
|
21335
|
+
if (!marker || marker.sessionId !== ref.nativeSessionId || typeof marker.cwd !== "string" || !await sameCwd(marker.cwd, cwd))
|
|
21336
|
+
throw new CodeBuddyError("protocolError", "Derived Native Session target marker is missing");
|
|
21337
|
+
checkedDirectories.add(cwd);
|
|
21338
|
+
const verifiedSuffixCwds = /* @__PURE__ */ new Set();
|
|
21339
|
+
for (const row of active.slice(provenance.inheritedPrefixRows)) {
|
|
21340
|
+
if (row.sessionId && row.sessionId !== ref.nativeSessionId)
|
|
21341
|
+
throw new CodeBuddyError("protocolError", "Derived Native Session appended foreign history");
|
|
21342
|
+
if (typeof row.cwd === "string" && !verifiedSuffixCwds.has(row.cwd)) {
|
|
21343
|
+
if (!await sameCwd(row.cwd, cwd))
|
|
21344
|
+
throw new CodeBuddyError("invalidRequest", "Derived Native Session left its target directory");
|
|
21345
|
+
verifiedSuffixCwds.add(row.cwd);
|
|
21346
|
+
}
|
|
21347
|
+
}
|
|
21348
|
+
} else {
|
|
21349
|
+
for (const row of parsed.rows) {
|
|
21350
|
+
if (row.sessionId && row.sessionId !== ref.nativeSessionId)
|
|
21351
|
+
throw new CodeBuddyError("protocolError", "Native history has a different Session identity");
|
|
21352
|
+
if (typeof row.cwd === "string" && !checkedDirectories.has(row.cwd)) {
|
|
21353
|
+
if (!await sameCwd(row.cwd, cwd))
|
|
21354
|
+
throw new CodeBuddyError("invalidRequest", "Native Session belongs to a different working directory");
|
|
21355
|
+
checkedDirectories.add(row.cwd);
|
|
21356
|
+
}
|
|
21038
21357
|
}
|
|
21039
21358
|
}
|
|
21040
21359
|
return {
|
|
@@ -21044,12 +21363,15 @@ async function codeBuddyHistory(cwd, ref, environment, tolerateIncompleteTail) {
|
|
|
21044
21363
|
reusableVersion: source.reusableVersion
|
|
21045
21364
|
};
|
|
21046
21365
|
}
|
|
21047
|
-
async function readNativeHistory(cwd, ref, environment) {
|
|
21048
|
-
return (await codeBuddyNativeHistory(cwd, ref, environment)).contents;
|
|
21366
|
+
async function readNativeHistory(cwd, ref, environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21367
|
+
return (await codeBuddyNativeHistory(cwd, ref, environment, profile)).contents;
|
|
21049
21368
|
}
|
|
21050
21369
|
function parseRows(contents, tolerateIncompleteTail = false) {
|
|
21051
21370
|
return parseJsonl(contents, tolerateIncompleteTail).rows;
|
|
21052
21371
|
}
|
|
21372
|
+
function nativeRawHistoryRows(contents) {
|
|
21373
|
+
return parseRows(contents);
|
|
21374
|
+
}
|
|
21053
21375
|
function parseJsonl(contents, tolerateIncompleteTail) {
|
|
21054
21376
|
const lines = contents.split(/\r?\n/u);
|
|
21055
21377
|
const completeLines = [], rows2 = [];
|
|
@@ -21070,11 +21392,25 @@ function parseJsonl(contents, tolerateIncompleteTail) {
|
|
|
21070
21392
|
contents: tolerateIncompleteTail ? completeLines.join("\n") : contents
|
|
21071
21393
|
};
|
|
21072
21394
|
}
|
|
21395
|
+
var NATIVE_MESSAGE_TYPES = /* @__PURE__ */ new Set([
|
|
21396
|
+
"message",
|
|
21397
|
+
"reasoning",
|
|
21398
|
+
"function_call",
|
|
21399
|
+
"function_call_result"
|
|
21400
|
+
]);
|
|
21401
|
+
function pendingNativeHistoryRewind(contents) {
|
|
21402
|
+
const last = parseRows(contents).findLast((row) => row.type === "resend-fork-notice" || NATIVE_MESSAGE_TYPES.has(text(row.type)));
|
|
21403
|
+
return last?.type === "resend-fork-notice" ? { forkPointId: text(last.parentId) || null } : void 0;
|
|
21404
|
+
}
|
|
21073
21405
|
function nativeHistoryRows(contents) {
|
|
21074
21406
|
const entries = /* @__PURE__ */ new Map();
|
|
21075
21407
|
let leaf = "";
|
|
21076
21408
|
for (const row of parseRows(contents)) {
|
|
21077
|
-
if (
|
|
21409
|
+
if (row.type === "resend-fork-notice") {
|
|
21410
|
+
leaf = text(row.parentId);
|
|
21411
|
+
continue;
|
|
21412
|
+
}
|
|
21413
|
+
if (!NATIVE_MESSAGE_TYPES.has(text(row.type)))
|
|
21078
21414
|
continue;
|
|
21079
21415
|
if (!text(row.id))
|
|
21080
21416
|
throw new CodeBuddyError("protocolError", "Native message is missing its stable ID");
|
|
@@ -21094,39 +21430,118 @@ function nativeHistoryRows(contents) {
|
|
|
21094
21430
|
}
|
|
21095
21431
|
return chain.reverse();
|
|
21096
21432
|
}
|
|
21097
|
-
function snapshotFromHistory(contents, ref, cwd) {
|
|
21433
|
+
function snapshotFromHistory(contents, ref, cwd, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21434
|
+
const supportsNativeCommands = nativeCommandsEnabled(profile);
|
|
21435
|
+
const supportsFork = capabilitiesForProfile(profile).history.fork;
|
|
21098
21436
|
const turns = [];
|
|
21099
21437
|
let current;
|
|
21100
21438
|
const tools = /* @__PURE__ */ new Map();
|
|
21101
|
-
|
|
21439
|
+
const earlyResults = /* @__PURE__ */ new Map();
|
|
21440
|
+
const applyResult = (snapshot, row) => {
|
|
21441
|
+
snapshot.outcome = toolOutcome(row.status, profile);
|
|
21442
|
+
if (snapshot.item.type === "subagentDelegation") {
|
|
21443
|
+
const childId = codeBuddyChildId(row);
|
|
21444
|
+
snapshot.item.subagents = snapshot.item.subagents.map((child) => ({
|
|
21445
|
+
...child,
|
|
21446
|
+
...childId ? { subagentId: childId, nativeSubagentId: childId } : {},
|
|
21447
|
+
status: snapshot.outcome.status === "failed" ? "failed" : child.background ? "interrupted" : "completed",
|
|
21448
|
+
resultSummary: child.background ? "Live background observation is unavailable after reload" : contentText(row.output).slice(0, 2e3)
|
|
21449
|
+
}));
|
|
21450
|
+
}
|
|
21451
|
+
if (snapshot.item.type === "toolExecution")
|
|
21452
|
+
snapshot.item.output = toolOutput(row.output);
|
|
21453
|
+
if (snapshot.item.type === "commandExecution") {
|
|
21454
|
+
const output = toolOutput(row.output);
|
|
21455
|
+
snapshot.item.output = contentText(output.content);
|
|
21456
|
+
snapshot.item.outputTruncated = Boolean(output.truncated);
|
|
21457
|
+
}
|
|
21458
|
+
};
|
|
21459
|
+
const history = nativeHistoryRows(contents);
|
|
21460
|
+
const manualCompactions = /* @__PURE__ */ new Set();
|
|
21461
|
+
let compactUser;
|
|
21462
|
+
if (supportsNativeCommands)
|
|
21463
|
+
for (const row of history) {
|
|
21464
|
+
const data = record2(row.providerData);
|
|
21465
|
+
if (row.type === "message" && row.role === "user")
|
|
21466
|
+
compactUser = data.agent === "compact" ? text(row.id) : void 0;
|
|
21467
|
+
if (compactUser && row.role === "assistant" && data.compactType === "user-command")
|
|
21468
|
+
manualCompactions.add(compactUser);
|
|
21469
|
+
}
|
|
21470
|
+
for (const row of history) {
|
|
21471
|
+
const data = record2(row.providerData);
|
|
21472
|
+
const body = contentText(row.content);
|
|
21473
|
+
const localCommand = supportsNativeCommands && data.skipRun === true ? /^<command-name>([^<]+)<\/command-name>(?:\s*<command-args>([\s\S]*)<\/command-args>)?$/u.exec(body) : null;
|
|
21474
|
+
const localOutput = supportsNativeCommands && data.skipRun === true ? /^<local-command-stdout>([\s\S]*)<\/local-command-stdout>$/u.exec(body) : null;
|
|
21475
|
+
if (localOutput) {
|
|
21476
|
+
if (current) {
|
|
21477
|
+
current.items.push({
|
|
21478
|
+
item: {
|
|
21479
|
+
type: "agentMessage",
|
|
21480
|
+
itemId: hostItemIdSchema.parse(`agentMessage-${text(row.id)}`),
|
|
21481
|
+
text: localOutput[1] ?? ""
|
|
21482
|
+
},
|
|
21483
|
+
outcome: { status: "succeeded" }
|
|
21484
|
+
});
|
|
21485
|
+
current.outcome = { status: "succeeded" };
|
|
21486
|
+
}
|
|
21487
|
+
continue;
|
|
21488
|
+
}
|
|
21489
|
+
if (supportsNativeCommands && data.skipRun === true && body.startsWith('<system-reminder data-role="command-caveat">'))
|
|
21490
|
+
continue;
|
|
21491
|
+
if (supportsNativeCommands && row.type === "message" && row.role === "user" && data.agent === "compact" && !manualCompactions.has(text(row.id)))
|
|
21492
|
+
continue;
|
|
21102
21493
|
if (row.type === "message" && row.role === "user") {
|
|
21103
21494
|
current = {
|
|
21104
21495
|
nativeTurnRef: nativeTurnRefSchema.parse({
|
|
21105
|
-
harnessId:
|
|
21496
|
+
harnessId: profile.harnessId,
|
|
21106
21497
|
nativeSessionId: ref.nativeSessionId,
|
|
21107
21498
|
nativeTurnKey: row.id,
|
|
21108
21499
|
formatVersion: 1
|
|
21109
21500
|
}),
|
|
21110
|
-
input: [
|
|
21501
|
+
input: [
|
|
21502
|
+
{
|
|
21503
|
+
type: "text",
|
|
21504
|
+
text: supportsNativeCommands && data.agent === "compact" ? "/compact" : localCommand ? `${localCommand[1]}${localCommand[2] ? ` ${localCommand[2]}` : ""}` : body
|
|
21505
|
+
}
|
|
21506
|
+
],
|
|
21111
21507
|
items: [],
|
|
21112
21508
|
outcome: { status: "unknown", reason: "Native terminal outcome was not recorded" },
|
|
21113
21509
|
...typeof row.timestamp === "number" ? { startedAtMs: row.timestamp } : {}
|
|
21114
21510
|
};
|
|
21115
21511
|
turns.push(current);
|
|
21116
21512
|
tools.clear();
|
|
21513
|
+
earlyResults.clear();
|
|
21117
21514
|
continue;
|
|
21118
21515
|
}
|
|
21119
21516
|
if (!current)
|
|
21120
21517
|
continue;
|
|
21518
|
+
if (supportsNativeCommands && (data.agent === "compact" || data.isCompactInternal === true)) {
|
|
21519
|
+
if (row.role === "assistant") {
|
|
21520
|
+
const outcome = row.status === "completed" && data.isCompacted === true ? { status: "succeeded" } : row.status === "cancelled" || row.status === "interrupted" ? { status: "cancelled" } : {
|
|
21521
|
+
status: "failed",
|
|
21522
|
+
error: nativeError(new CodeBuddyError("nativeFailure", "Native compaction did not complete"), profile)
|
|
21523
|
+
};
|
|
21524
|
+
current.items.push({
|
|
21525
|
+
item: {
|
|
21526
|
+
type: "contextCompaction",
|
|
21527
|
+
itemId: hostItemIdSchema.parse(`compact-${text(row.id)}`)
|
|
21528
|
+
},
|
|
21529
|
+
outcome
|
|
21530
|
+
});
|
|
21531
|
+
if (data.compactType === "user-command")
|
|
21532
|
+
current.outcome = outcome;
|
|
21533
|
+
}
|
|
21534
|
+
continue;
|
|
21535
|
+
}
|
|
21121
21536
|
const model = text(record2(row.providerData).model);
|
|
21122
21537
|
if (model)
|
|
21123
21538
|
current.model = modelRef(model);
|
|
21124
21539
|
if (row.type === "message" && row.role === "assistant" || row.type === "reasoning") {
|
|
21125
21540
|
const type = row.type === "reasoning" ? "reasoning" : "agentMessage";
|
|
21126
|
-
const
|
|
21127
|
-
if (
|
|
21541
|
+
const body2 = contentText(row.content) || contentText(row.rawContent);
|
|
21542
|
+
if (body2)
|
|
21128
21543
|
current.items.push({
|
|
21129
|
-
item: { type, itemId: hostItemIdSchema.parse(`${type}-${text(row.id)}`), text:
|
|
21544
|
+
item: { type, itemId: hostItemIdSchema.parse(`${type}-${text(row.id)}`), text: body2 },
|
|
21130
21545
|
outcome: { status: "succeeded" }
|
|
21131
21546
|
});
|
|
21132
21547
|
if (row.role === "assistant" && row.status === "completed") {
|
|
@@ -21143,36 +21558,36 @@ function snapshotFromHistory(contents, ref, cwd) {
|
|
|
21143
21558
|
throw new CodeBuddyError("protocolError", "Invalid native Tool arguments");
|
|
21144
21559
|
}
|
|
21145
21560
|
}
|
|
21561
|
+
const callId = text(row.callId);
|
|
21146
21562
|
const snapshot = {
|
|
21147
|
-
item: row.name === "Agent" ? codeBuddyDelegation(
|
|
21148
|
-
outcome: toolOutcome("unknown")
|
|
21563
|
+
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),
|
|
21564
|
+
outcome: toolOutcome("unknown", profile)
|
|
21149
21565
|
};
|
|
21150
|
-
tools.set(
|
|
21566
|
+
tools.set(callId, snapshot);
|
|
21151
21567
|
current.items.push(snapshot);
|
|
21152
21568
|
current.outcome = { status: "unknown", reason: "Native Tool has not completed" };
|
|
21153
|
-
|
|
21154
|
-
|
|
21155
|
-
|
|
21156
|
-
|
|
21157
|
-
snapshot.outcome = toolOutcome(row.status);
|
|
21158
|
-
if (snapshot.item.type === "subagentDelegation") {
|
|
21159
|
-
const childId = codeBuddyChildId(row);
|
|
21160
|
-
snapshot.item.subagents = snapshot.item.subagents.map((child) => ({
|
|
21161
|
-
...child,
|
|
21162
|
-
...childId ? { subagentId: childId, nativeSubagentId: childId } : {},
|
|
21163
|
-
status: snapshot.outcome.status === "failed" ? "failed" : child.background ? "interrupted" : "completed",
|
|
21164
|
-
resultSummary: child.background ? "Live background observation is unavailable after reload" : contentText(row.output).slice(0, 2e3)
|
|
21165
|
-
}));
|
|
21166
|
-
}
|
|
21167
|
-
if (snapshot.item.type === "toolExecution")
|
|
21168
|
-
snapshot.item.output = toolOutput(row.output);
|
|
21169
|
-
if (snapshot.item.type === "commandExecution") {
|
|
21170
|
-
const output = toolOutput(row.output);
|
|
21171
|
-
snapshot.item.output = contentText(output.content);
|
|
21172
|
-
snapshot.item.outputTruncated = Boolean(output.truncated);
|
|
21569
|
+
const early = earlyResults.get(callId);
|
|
21570
|
+
if (early) {
|
|
21571
|
+
earlyResults.delete(callId);
|
|
21572
|
+
applyResult(snapshot, early);
|
|
21173
21573
|
}
|
|
21574
|
+
} else if (row.type === "function_call_result") {
|
|
21575
|
+
const callId = text(row.callId);
|
|
21576
|
+
const snapshot = tools.get(callId);
|
|
21577
|
+
if (snapshot)
|
|
21578
|
+
applyResult(snapshot, row);
|
|
21579
|
+
else
|
|
21580
|
+
earlyResults.set(callId, row);
|
|
21174
21581
|
}
|
|
21175
21582
|
}
|
|
21583
|
+
if (supportsFork)
|
|
21584
|
+
for (const turn of turns)
|
|
21585
|
+
turn.checkpoint = nativeCheckpointRefSchema.parse({
|
|
21586
|
+
harnessId: profile.harnessId,
|
|
21587
|
+
nativeSessionId: ref.nativeSessionId,
|
|
21588
|
+
checkpointId: turn.nativeTurnRef.nativeTurnKey,
|
|
21589
|
+
formatVersion: 1
|
|
21590
|
+
});
|
|
21176
21591
|
return { turns };
|
|
21177
21592
|
}
|
|
21178
21593
|
function historyUsage(contents) {
|
|
@@ -21203,25 +21618,814 @@ function historyUsage(contents) {
|
|
|
21203
21618
|
return Object.keys(result).length ? result : null;
|
|
21204
21619
|
}
|
|
21205
21620
|
|
|
21621
|
+
// dist/child-provenance.js
|
|
21622
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
21623
|
+
import { realpath as realpath3 } from "node:fs/promises";
|
|
21624
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
21625
|
+
var CODEBUDDY_CHILD_MAX_BYTES = 8e6;
|
|
21626
|
+
var equalPath = (left, right) => process.platform === "win32" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
21627
|
+
function codeBuddyChildDigest(contents) {
|
|
21628
|
+
return createHash2("sha256").update(contents).digest("hex");
|
|
21629
|
+
}
|
|
21630
|
+
function parseCodeBuddyChild(contents, tolerateIncompleteTail) {
|
|
21631
|
+
const lines = contents.split(/\r?\n/u);
|
|
21632
|
+
if (tolerateIncompleteTail && lines.at(-1)?.trim()) {
|
|
21633
|
+
try {
|
|
21634
|
+
JSON.parse(lines.at(-1) ?? "");
|
|
21635
|
+
} catch {
|
|
21636
|
+
lines.pop();
|
|
21637
|
+
}
|
|
21638
|
+
}
|
|
21639
|
+
const entries = lines.filter((line) => line.trim()).map((line) => record2(JSON.parse(line)));
|
|
21640
|
+
return { contents: lines.join("\n"), entries };
|
|
21641
|
+
}
|
|
21642
|
+
function inheritedChildren(parent) {
|
|
21643
|
+
const value = record2(parent.locator).codebuddyInheritedChildren;
|
|
21644
|
+
if (value === void 0)
|
|
21645
|
+
return [];
|
|
21646
|
+
if (!Array.isArray(value) || value.length > 256)
|
|
21647
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is invalid");
|
|
21648
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21649
|
+
return value.map((candidate) => {
|
|
21650
|
+
const child = record2(candidate);
|
|
21651
|
+
const historicalCwds = child.historicalCwds;
|
|
21652
|
+
const recordedCwds = child.recordedCwds;
|
|
21653
|
+
const workspaceBindings = child.workspaceBindings;
|
|
21654
|
+
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)
|
|
21655
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is invalid");
|
|
21656
|
+
const bindings = workspaceBindings.map((candidate2) => {
|
|
21657
|
+
const binding = record2(candidate2);
|
|
21658
|
+
if (typeof binding.recordedCwd !== "string" || !binding.recordedCwd || typeof binding.canonicalCwd !== "string" || !binding.canonicalCwd)
|
|
21659
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is invalid");
|
|
21660
|
+
return {
|
|
21661
|
+
recordedCwd: binding.recordedCwd,
|
|
21662
|
+
canonicalCwd: binding.canonicalCwd
|
|
21663
|
+
};
|
|
21664
|
+
});
|
|
21665
|
+
const boundRecorded = new Set(bindings.map((binding) => binding.recordedCwd));
|
|
21666
|
+
const boundCanonical = new Set(bindings.map((binding) => binding.canonicalCwd));
|
|
21667
|
+
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)))
|
|
21668
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is inconsistent");
|
|
21669
|
+
const childId = text(child.childId);
|
|
21670
|
+
if (seen.has(childId))
|
|
21671
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent provenance is ambiguous");
|
|
21672
|
+
seen.add(childId);
|
|
21673
|
+
return {
|
|
21674
|
+
childId,
|
|
21675
|
+
nativeSessionId: text(child.nativeSessionId),
|
|
21676
|
+
inheritedBytes: Number(child.inheritedBytes),
|
|
21677
|
+
inheritedRows: Number(child.inheritedRows),
|
|
21678
|
+
inheritedSha256: child.inheritedSha256,
|
|
21679
|
+
recordedCwds: [...recordedCwds],
|
|
21680
|
+
historicalCwds: [...historicalCwds],
|
|
21681
|
+
workspaceBindings: bindings
|
|
21682
|
+
};
|
|
21683
|
+
});
|
|
21684
|
+
}
|
|
21685
|
+
function codeBuddyInheritedChild(parent, childId) {
|
|
21686
|
+
return inheritedChildren(parent).find((child) => child.childId === childId);
|
|
21687
|
+
}
|
|
21688
|
+
async function canonicalCwds(cwds) {
|
|
21689
|
+
const result = /* @__PURE__ */ new Map();
|
|
21690
|
+
for (const cwd of new Set(cwds)) {
|
|
21691
|
+
const canonical = await realpath3(cwd).catch((error51) => {
|
|
21692
|
+
if (["ENOENT", "ENOTDIR"].includes(String(record2(error51).code)))
|
|
21693
|
+
throw new CodeBuddyError("invalidRequest", "Subagent historical working directory is unavailable; ownership cannot be verified");
|
|
21694
|
+
throw error51;
|
|
21695
|
+
});
|
|
21696
|
+
result.set(cwd, canonical);
|
|
21697
|
+
}
|
|
21698
|
+
return result;
|
|
21699
|
+
}
|
|
21700
|
+
async function validateCodeBuddyChildContents(contents, parent, childId, cwd, tolerateIncompleteTail) {
|
|
21701
|
+
if (!validCodeBuddyChildId(childId))
|
|
21702
|
+
throw new CodeBuddyError("invalidRequest", "Invalid native Subagent ID");
|
|
21703
|
+
const parsed = parseCodeBuddyChild(contents, tolerateIncompleteTail);
|
|
21704
|
+
const sessions = new Set(parsed.entries.map((row) => text(row.sessionId)).filter(Boolean));
|
|
21705
|
+
if (sessions.size !== 1)
|
|
21706
|
+
throw new CodeBuddyError("protocolError", "Subagent transcript identity is missing or mixed");
|
|
21707
|
+
const nativeSessionId = [...sessions][0];
|
|
21708
|
+
if (!nativeSessionId || !/^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/u.test(nativeSessionId))
|
|
21709
|
+
throw new CodeBuddyError("protocolError", "Missing or invalid native child Session");
|
|
21710
|
+
const inherited = codeBuddyInheritedChild(parent, childId);
|
|
21711
|
+
let inheritedEntries = [];
|
|
21712
|
+
if (inherited) {
|
|
21713
|
+
const bytes = Buffer.from(contents, "utf8");
|
|
21714
|
+
if (inherited.inheritedBytes > bytes.length)
|
|
21715
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent prefix is incomplete");
|
|
21716
|
+
const prefix = bytes.subarray(0, inherited.inheritedBytes);
|
|
21717
|
+
const prefixText = prefix.toString("utf8");
|
|
21718
|
+
if (!isDeepStrictEqual2(Buffer.from(prefixText, "utf8"), prefix) || codeBuddyChildDigest(prefix) !== inherited.inheritedSha256)
|
|
21719
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent prefix verification failed");
|
|
21720
|
+
let prefixParsed;
|
|
21721
|
+
try {
|
|
21722
|
+
prefixParsed = parseCodeBuddyChild(prefixText, false);
|
|
21723
|
+
} catch {
|
|
21724
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent prefix is malformed");
|
|
21725
|
+
}
|
|
21726
|
+
if (prefixParsed.entries.length !== inherited.inheritedRows || parsed.entries.length < inherited.inheritedRows || !isDeepStrictEqual2(prefixParsed.entries, parsed.entries.slice(0, inherited.inheritedRows)) || nativeSessionId !== inherited.nativeSessionId)
|
|
21727
|
+
throw new CodeBuddyError("protocolError", "Inherited Subagent identity changed");
|
|
21728
|
+
inheritedEntries = prefixParsed.entries;
|
|
21729
|
+
}
|
|
21730
|
+
const target = await realpath3(cwd);
|
|
21731
|
+
const inheritedCwds = inheritedEntries.flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []);
|
|
21732
|
+
const suffixCwds = parsed.entries.slice(inheritedEntries.length).flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []);
|
|
21733
|
+
const canonical = await canonicalCwds(suffixCwds);
|
|
21734
|
+
if (inherited) {
|
|
21735
|
+
const allowed = new Set(inherited.recordedCwds);
|
|
21736
|
+
const observed = new Set(inheritedCwds);
|
|
21737
|
+
if (allowed.size !== observed.size || [...allowed].some((value) => !observed.has(value)) || inheritedCwds.some((value) => !allowed.has(value)))
|
|
21738
|
+
throw new CodeBuddyError("invalidRequest", "Inherited Subagent workspace changed");
|
|
21739
|
+
}
|
|
21740
|
+
for (const value of suffixCwds) {
|
|
21741
|
+
const actual = canonical.get(value);
|
|
21742
|
+
if (!actual || !equalPath(actual, target))
|
|
21743
|
+
throw new CodeBuddyError("invalidRequest", "Subagent workspace differs from parent");
|
|
21744
|
+
}
|
|
21745
|
+
const bindings = new Map((inherited?.workspaceBindings ?? []).map((binding) => [
|
|
21746
|
+
binding.recordedCwd,
|
|
21747
|
+
binding.canonicalCwd
|
|
21748
|
+
]));
|
|
21749
|
+
for (const value of new Set(suffixCwds)) {
|
|
21750
|
+
const resolved = canonical.get(value);
|
|
21751
|
+
if (!resolved)
|
|
21752
|
+
throw new CodeBuddyError("invalidRequest", "Subagent workspace is unavailable");
|
|
21753
|
+
const existing = bindings.get(value);
|
|
21754
|
+
if (existing && !equalPath(existing, resolved))
|
|
21755
|
+
throw new CodeBuddyError("invalidRequest", "Subagent workspace binding changed");
|
|
21756
|
+
bindings.set(value, resolved);
|
|
21757
|
+
}
|
|
21758
|
+
return {
|
|
21759
|
+
...parsed,
|
|
21760
|
+
nativeSessionId,
|
|
21761
|
+
recordedCwds: [...bindings.keys()],
|
|
21762
|
+
historicalCwds: [...new Set(bindings.values())],
|
|
21763
|
+
workspaceBindings: [...bindings].map(([recordedCwd, canonicalCwd]) => ({
|
|
21764
|
+
recordedCwd,
|
|
21765
|
+
canonicalCwd
|
|
21766
|
+
}))
|
|
21767
|
+
};
|
|
21768
|
+
}
|
|
21769
|
+
function codeBuddyInheritedChildDescriptor(childId, contents, child) {
|
|
21770
|
+
if (child.recordedCwds.length > 256 || child.historicalCwds.length > 256)
|
|
21771
|
+
throw new CodeBuddyError("unsupported", "Too many Subagent historical workspaces");
|
|
21772
|
+
return {
|
|
21773
|
+
childId,
|
|
21774
|
+
nativeSessionId: child.nativeSessionId,
|
|
21775
|
+
inheritedBytes: Buffer.byteLength(contents, "utf8"),
|
|
21776
|
+
inheritedRows: child.entries.length,
|
|
21777
|
+
inheritedSha256: codeBuddyChildDigest(contents),
|
|
21778
|
+
recordedCwds: child.recordedCwds,
|
|
21779
|
+
historicalCwds: child.historicalCwds,
|
|
21780
|
+
workspaceBindings: child.workspaceBindings
|
|
21781
|
+
};
|
|
21782
|
+
}
|
|
21783
|
+
async function codeBuddyChildPrefixThrough(contents, lastId, child) {
|
|
21784
|
+
let cursor = 0;
|
|
21785
|
+
let rowIndex = 0;
|
|
21786
|
+
let match = -1;
|
|
21787
|
+
let end = -1;
|
|
21788
|
+
while (cursor < contents.length) {
|
|
21789
|
+
const newline2 = contents.indexOf("\n", cursor);
|
|
21790
|
+
const next = newline2 < 0 ? contents.length : newline2 + 1;
|
|
21791
|
+
const physicalLine = contents.slice(cursor, next);
|
|
21792
|
+
const line = physicalLine.replace(/\r?\n$/u, "");
|
|
21793
|
+
if (line.trim()) {
|
|
21794
|
+
const row = child.entries[rowIndex++];
|
|
21795
|
+
if (!row)
|
|
21796
|
+
throw new CodeBuddyError("protocolError", "Subagent transcript rows changed");
|
|
21797
|
+
if (text(row.id) === lastId) {
|
|
21798
|
+
if (match >= 0)
|
|
21799
|
+
throw new CodeBuddyError("protocolError", "Agent result has an ambiguous child range");
|
|
21800
|
+
match = rowIndex - 1;
|
|
21801
|
+
end = next;
|
|
21802
|
+
}
|
|
21803
|
+
}
|
|
21804
|
+
cursor = next;
|
|
21805
|
+
}
|
|
21806
|
+
if (rowIndex !== child.entries.length || match < 0 || end < 0)
|
|
21807
|
+
throw new CodeBuddyError("protocolError", "Agent result child range was not found");
|
|
21808
|
+
const entries = child.entries.slice(0, match + 1);
|
|
21809
|
+
const cwdValues = entries.flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []);
|
|
21810
|
+
const inheritedBindings = new Map(child.workspaceBindings.map((binding) => [binding.recordedCwd, binding.canonicalCwd]));
|
|
21811
|
+
const bindings = [...new Set(cwdValues)].map((recordedCwd) => {
|
|
21812
|
+
const canonicalCwd = inheritedBindings.get(recordedCwd);
|
|
21813
|
+
if (!canonicalCwd)
|
|
21814
|
+
throw new CodeBuddyError("protocolError", "Subagent workspace binding is missing");
|
|
21815
|
+
return { recordedCwd, canonicalCwd };
|
|
21816
|
+
});
|
|
21817
|
+
return {
|
|
21818
|
+
contents: contents.slice(0, end),
|
|
21819
|
+
child: {
|
|
21820
|
+
contents: contents.slice(0, end),
|
|
21821
|
+
entries,
|
|
21822
|
+
nativeSessionId: child.nativeSessionId,
|
|
21823
|
+
recordedCwds: bindings.map((binding) => binding.recordedCwd),
|
|
21824
|
+
historicalCwds: [...new Set(bindings.map((binding) => binding.canonicalCwd))],
|
|
21825
|
+
workspaceBindings: bindings
|
|
21826
|
+
}
|
|
21827
|
+
};
|
|
21828
|
+
}
|
|
21829
|
+
|
|
21830
|
+
// dist/derivation.js
|
|
21831
|
+
async function copyCodeBuddySession(cwd, sourceId, targetId, environment, signal, invocationFactory = codeBuddyInvocation) {
|
|
21832
|
+
if (signal.aborted)
|
|
21833
|
+
throw new CodeBuddyError("invalidState", "Adapter closed before history copy");
|
|
21834
|
+
const invocation = invocationFactory(environment, false, [
|
|
21835
|
+
"--resume",
|
|
21836
|
+
sourceId,
|
|
21837
|
+
"--fork-session",
|
|
21838
|
+
"--session-id",
|
|
21839
|
+
targetId,
|
|
21840
|
+
"--print",
|
|
21841
|
+
"--input-format",
|
|
21842
|
+
"stream-json",
|
|
21843
|
+
"--output-format",
|
|
21844
|
+
"stream-json"
|
|
21845
|
+
]);
|
|
21846
|
+
await new Promise((resolve, reject) => {
|
|
21847
|
+
const child = spawn2(invocation.command, invocation.arguments, {
|
|
21848
|
+
cwd,
|
|
21849
|
+
env: invocation.environment,
|
|
21850
|
+
stdio: "pipe",
|
|
21851
|
+
windowsHide: true,
|
|
21852
|
+
windowsVerbatimArguments: invocation.windowsVerbatimArguments,
|
|
21853
|
+
detached: process.platform !== "win32"
|
|
21854
|
+
});
|
|
21855
|
+
let output = "", bytes = 0, failed = false;
|
|
21856
|
+
let termination = Promise.resolve();
|
|
21857
|
+
const stop = () => {
|
|
21858
|
+
if (failed)
|
|
21859
|
+
return;
|
|
21860
|
+
failed = true;
|
|
21861
|
+
if (child.exitCode !== null || child.signalCode !== null) {
|
|
21862
|
+
child.stdout.destroy();
|
|
21863
|
+
child.stderr.destroy();
|
|
21864
|
+
} else if (process.platform === "win32" && child.pid) {
|
|
21865
|
+
termination = new Promise((done) => {
|
|
21866
|
+
execFile2("taskkill", ["/PID", String(child.pid), "/T", "/F"], { windowsHide: true, timeout: 3e3 }, () => {
|
|
21867
|
+
child.kill();
|
|
21868
|
+
done();
|
|
21869
|
+
});
|
|
21870
|
+
});
|
|
21871
|
+
} else if (child.pid) {
|
|
21872
|
+
try {
|
|
21873
|
+
process.kill(-child.pid, "SIGKILL");
|
|
21874
|
+
} catch {
|
|
21875
|
+
child.kill("SIGKILL");
|
|
21876
|
+
}
|
|
21877
|
+
} else
|
|
21878
|
+
child.kill("SIGKILL");
|
|
21879
|
+
};
|
|
21880
|
+
const timer = setTimeout(stop, 3e4);
|
|
21881
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
21882
|
+
child.stdout.on("data", (data) => {
|
|
21883
|
+
bytes += data.length;
|
|
21884
|
+
if (bytes > 64e6) {
|
|
21885
|
+
stop();
|
|
21886
|
+
return;
|
|
21887
|
+
}
|
|
21888
|
+
output += data.toString();
|
|
21889
|
+
});
|
|
21890
|
+
child.stderr.resume();
|
|
21891
|
+
child.stdin.on("error", () => {
|
|
21892
|
+
});
|
|
21893
|
+
child.once("error", reject);
|
|
21894
|
+
child.once("close", async (code) => {
|
|
21895
|
+
await termination;
|
|
21896
|
+
clearTimeout(timer);
|
|
21897
|
+
signal.removeEventListener("abort", stop);
|
|
21898
|
+
if (failed || signal.aborted || code !== 0) {
|
|
21899
|
+
reject(new CodeBuddyError("nativeFailure", "Native history copy failed or was interrupted"));
|
|
21900
|
+
return;
|
|
21901
|
+
}
|
|
21902
|
+
try {
|
|
21903
|
+
const rows2 = output.trim().split(/\r?\n/u).filter(Boolean).map((line) => record2(JSON.parse(line)));
|
|
21904
|
+
const init = rows2.find((row) => row.type === "system" && row.subtype === "init");
|
|
21905
|
+
const result = rows2.findLast((row) => row.type === "result");
|
|
21906
|
+
if (init?.session_id !== targetId || result?.session_id !== targetId || result?.is_error !== false || result?.duration_api_ms !== 0)
|
|
21907
|
+
throw new CodeBuddyError("unsupported", "Native CLI did not confirm a model-free history copy");
|
|
21908
|
+
resolve();
|
|
21909
|
+
} catch (error51) {
|
|
21910
|
+
reject(error51);
|
|
21911
|
+
}
|
|
21912
|
+
});
|
|
21913
|
+
if (signal.aborted)
|
|
21914
|
+
stop();
|
|
21915
|
+
child.stdin.end();
|
|
21916
|
+
});
|
|
21917
|
+
}
|
|
21918
|
+
function withoutIdentity(row) {
|
|
21919
|
+
const result = { ...row };
|
|
21920
|
+
delete result.id;
|
|
21921
|
+
delete result.parentId;
|
|
21922
|
+
delete result.logicalParentId;
|
|
21923
|
+
delete result.sessionId;
|
|
21924
|
+
return result;
|
|
21925
|
+
}
|
|
21926
|
+
function assertCopiedPrefix(source, copied) {
|
|
21927
|
+
if (copied.length < source.length)
|
|
21928
|
+
throw new CodeBuddyError("unsupported", "Native Fork omitted history");
|
|
21929
|
+
const ids = new Map(source.map((row, index) => [text(row.id), text(copied[index]?.id)]));
|
|
21930
|
+
for (const [index, row] of source.entries()) {
|
|
21931
|
+
const clone2 = copied[index];
|
|
21932
|
+
if (!clone2)
|
|
21933
|
+
throw new CodeBuddyError("unsupported", "Native Fork omitted history");
|
|
21934
|
+
if (!isDeepStrictEqual3(withoutIdentity(row), withoutIdentity(clone2)) || ["parentId", "logicalParentId"].some((key) => text(clone2[key]) !== (ids.get(text(row[key])) ?? "")))
|
|
21935
|
+
throw new CodeBuddyError("unsupported", "Native Fork did not preserve the exact history prefix");
|
|
21936
|
+
}
|
|
21937
|
+
}
|
|
21938
|
+
function commandCaveat(row) {
|
|
21939
|
+
return record2(row?.providerData).skipRun === true && JSON.stringify(row?.content).includes('data-role=\\"command-caveat\\"');
|
|
21940
|
+
}
|
|
21941
|
+
function retainedRowCount(input, contents, sourceCwd = input.cwd, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21942
|
+
const rows2 = nativeHistoryRows(contents);
|
|
21943
|
+
const turns = snapshotFromHistory(contents, input.sourceRef, sourceCwd, profile).turns;
|
|
21944
|
+
let excluded2;
|
|
21945
|
+
if (input.kind === "rollbackLastTurn") {
|
|
21946
|
+
if (!turns.length)
|
|
21947
|
+
throw new CodeBuddyError("invalidState", "Native Session has no Turn to revise");
|
|
21948
|
+
excluded2 = turns.at(-1)?.nativeTurnRef.nativeTurnKey;
|
|
21949
|
+
} else {
|
|
21950
|
+
const checkpoint = input.checkpoint;
|
|
21951
|
+
const index = turns.findIndex((turn) => turn.nativeTurnRef.nativeTurnKey === checkpoint.checkpointId);
|
|
21952
|
+
if (checkpoint.harnessId !== profile.harnessId || checkpoint.nativeSessionId !== input.sourceRef.nativeSessionId || checkpoint.formatVersion !== 1 || index < 0)
|
|
21953
|
+
throw new CodeBuddyError("checkpointNotFound", "Native Fork checkpoint was not found");
|
|
21954
|
+
excluded2 = turns[index + 1]?.nativeTurnRef.nativeTurnKey;
|
|
21955
|
+
}
|
|
21956
|
+
let count = excluded2 ? rows2.findIndex((row) => row.id === excluded2) : rows2.length;
|
|
21957
|
+
if (count < 0)
|
|
21958
|
+
throw new CodeBuddyError("protocolError", "Native Turn boundary is missing");
|
|
21959
|
+
if (excluded2)
|
|
21960
|
+
while (count > 0 && commandCaveat(rows2[count - 1]))
|
|
21961
|
+
count--;
|
|
21962
|
+
return count;
|
|
21963
|
+
}
|
|
21964
|
+
function sameResolvedPath(left, right) {
|
|
21965
|
+
const a = codeBuddyCanonicalCwd(left), b = codeBuddyCanonicalCwd(right);
|
|
21966
|
+
return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
21967
|
+
}
|
|
21968
|
+
async function bridgeCopyToTarget(sourceCwd, targetCwd, ref, contents, environment, profile) {
|
|
21969
|
+
const sourceFile = codeBuddyPrimaryHistoryPath(sourceCwd, ref, environment, profile);
|
|
21970
|
+
const targetFile = codeBuddyPrimaryHistoryPath(targetCwd, ref, environment, profile);
|
|
21971
|
+
if (sameResolvedPath(sourceFile, targetFile))
|
|
21972
|
+
return void 0;
|
|
21973
|
+
const targetDirectory = path5.dirname(targetFile);
|
|
21974
|
+
const projectsDirectory = path5.dirname(targetDirectory);
|
|
21975
|
+
await mkdir(targetDirectory, { recursive: true });
|
|
21976
|
+
const [realProjects, realTargetDirectory] = await Promise.all([
|
|
21977
|
+
realpath4(projectsDirectory),
|
|
21978
|
+
realpath4(targetDirectory)
|
|
21979
|
+
]);
|
|
21980
|
+
if (!sameResolvedPath(realTargetDirectory, path5.join(realProjects, codeBuddyProjectSlug(targetCwd, profile))))
|
|
21981
|
+
throw new CodeBuddyError("invalidRequest", "Cross-directory history bridge target escaped the native projects root");
|
|
21982
|
+
const expected = Buffer.from(contents, "utf8");
|
|
21983
|
+
await writeFile(targetFile, expected, { flag: "wx", mode: 384 });
|
|
21984
|
+
const bridge = { file: targetFile, expected };
|
|
21985
|
+
try {
|
|
21986
|
+
const persisted = await readFile2(targetFile);
|
|
21987
|
+
if (!isDeepStrictEqual3(persisted, expected))
|
|
21988
|
+
throw new CodeBuddyError("nativeFailure", "Cross-directory history bridge changed native bytes");
|
|
21989
|
+
return bridge;
|
|
21990
|
+
} catch (error51) {
|
|
21991
|
+
return failAfterBridgeCleanup(error51, bridge);
|
|
21992
|
+
}
|
|
21993
|
+
}
|
|
21994
|
+
async function cleanupBridge(bridge) {
|
|
21995
|
+
if (!bridge)
|
|
21996
|
+
return;
|
|
21997
|
+
try {
|
|
21998
|
+
const info = await lstat(bridge.file);
|
|
21999
|
+
if (!info.isFile() || process.platform !== "win32" && (info.mode & 63) !== 0)
|
|
22000
|
+
return;
|
|
22001
|
+
if (!isDeepStrictEqual3(await readFile2(bridge.file), bridge.expected))
|
|
22002
|
+
return;
|
|
22003
|
+
await unlink(bridge.file);
|
|
22004
|
+
} catch (error51) {
|
|
22005
|
+
if (record2(error51).code !== "ENOENT")
|
|
22006
|
+
throw error51;
|
|
22007
|
+
}
|
|
22008
|
+
}
|
|
22009
|
+
async function failAfterBridgeCleanup(failure2, bridge) {
|
|
22010
|
+
try {
|
|
22011
|
+
await cleanupBridge(bridge);
|
|
22012
|
+
} catch (cleanupFailure) {
|
|
22013
|
+
throw new AggregateError([failure2, cleanupFailure], "Native derivation and bridge cleanup both failed");
|
|
22014
|
+
}
|
|
22015
|
+
throw failure2;
|
|
22016
|
+
}
|
|
22017
|
+
function argumentsRecord(value) {
|
|
22018
|
+
if (typeof value !== "string")
|
|
22019
|
+
return record2(value);
|
|
22020
|
+
try {
|
|
22021
|
+
return record2(JSON.parse(value));
|
|
22022
|
+
} catch {
|
|
22023
|
+
return {};
|
|
22024
|
+
}
|
|
22025
|
+
}
|
|
22026
|
+
function referencedChildren(rows2) {
|
|
22027
|
+
const calls = /* @__PURE__ */ new Map();
|
|
22028
|
+
const children = /* @__PURE__ */ new Map();
|
|
22029
|
+
for (const row of rows2) {
|
|
22030
|
+
if (row.type === "function_call" && row.name === "Agent") {
|
|
22031
|
+
const callId2 = text(row.callId);
|
|
22032
|
+
if (!callId2 || calls.has(callId2))
|
|
22033
|
+
throw new CodeBuddyError("protocolError", "Agent delegation identity is ambiguous");
|
|
22034
|
+
const resumed2 = text(argumentsRecord(row.arguments).resume);
|
|
22035
|
+
if (resumed2 && !validCodeBuddyChildId(resumed2))
|
|
22036
|
+
throw new CodeBuddyError("protocolError", "Agent delegation has an invalid child identity");
|
|
22037
|
+
calls.set(callId2, resumed2 || void 0);
|
|
22038
|
+
continue;
|
|
22039
|
+
}
|
|
22040
|
+
if (row.type !== "function_call_result")
|
|
22041
|
+
continue;
|
|
22042
|
+
const callId = text(row.callId);
|
|
22043
|
+
if (!calls.has(callId))
|
|
22044
|
+
continue;
|
|
22045
|
+
const subagent = record2(record2(record2(row.providerData).toolResult).subAgent);
|
|
22046
|
+
const childId = text(subagent.sessionId);
|
|
22047
|
+
if (!validCodeBuddyChildId(childId))
|
|
22048
|
+
throw new CodeBuddyError("unsupported", "Retained Agent result has no verified native child identity");
|
|
22049
|
+
const resumed = calls.get(callId);
|
|
22050
|
+
if (resumed && resumed !== childId)
|
|
22051
|
+
throw new CodeBuddyError("protocolError", "Agent result changed its child identity");
|
|
22052
|
+
const lastId = text(subagent.lastId);
|
|
22053
|
+
const afterId = text(subagent.afterId);
|
|
22054
|
+
if (!lastId)
|
|
22055
|
+
throw new CodeBuddyError("unsupported", "Retained Agent result has no bounded child transcript range");
|
|
22056
|
+
const child = children.get(childId) ?? { childId, ranges: [] };
|
|
22057
|
+
child.ranges.push({ ...afterId ? { afterId } : {}, lastId });
|
|
22058
|
+
children.set(childId, child);
|
|
22059
|
+
if (children.size > 256)
|
|
22060
|
+
throw new CodeBuddyError("unsupported", "Too many retained Subagent transcripts");
|
|
22061
|
+
calls.delete(callId);
|
|
22062
|
+
}
|
|
22063
|
+
if (calls.size)
|
|
22064
|
+
throw new CodeBuddyError("unsupported", "Retained Agent delegation is incomplete");
|
|
22065
|
+
return [...children.values()];
|
|
22066
|
+
}
|
|
22067
|
+
function assertChildRanges(rows2, child) {
|
|
22068
|
+
const positions = /* @__PURE__ */ new Map();
|
|
22069
|
+
for (const [index, row] of rows2.entries()) {
|
|
22070
|
+
const id = text(row.id);
|
|
22071
|
+
if (!id)
|
|
22072
|
+
continue;
|
|
22073
|
+
const matches = positions.get(id) ?? [];
|
|
22074
|
+
matches.push(index);
|
|
22075
|
+
positions.set(id, matches);
|
|
22076
|
+
}
|
|
22077
|
+
let previous = -1;
|
|
22078
|
+
for (const range of child.ranges) {
|
|
22079
|
+
const last = positions.get(range.lastId);
|
|
22080
|
+
const after = range.afterId ? positions.get(range.afterId) : void 0;
|
|
22081
|
+
if (last?.length !== 1 || after && after.length !== 1 || range.afterId && !after || after && (after[0] ?? -1) >= (last[0] ?? -1) || (last[0] ?? -1) < previous)
|
|
22082
|
+
throw new CodeBuddyError("protocolError", "Agent result child range is inconsistent");
|
|
22083
|
+
previous = last[0] ?? -1;
|
|
22084
|
+
}
|
|
22085
|
+
}
|
|
22086
|
+
async function plainDirectory(parent, name) {
|
|
22087
|
+
const directory = path5.join(parent, name);
|
|
22088
|
+
await mkdir(directory, { mode: 448 }).catch((error51) => {
|
|
22089
|
+
if (record2(error51).code !== "EEXIST")
|
|
22090
|
+
throw error51;
|
|
22091
|
+
});
|
|
22092
|
+
const info = await lstat(directory);
|
|
22093
|
+
if (!info.isDirectory() || info.isSymbolicLink() || process.platform !== "win32" && (info.mode & 18) !== 0)
|
|
22094
|
+
throw new CodeBuddyError("invalidRequest", "Redirected native Subagent directory");
|
|
22095
|
+
const actual = await realpath4(directory);
|
|
22096
|
+
if (!sameResolvedPath(actual, directory))
|
|
22097
|
+
throw new CodeBuddyError("invalidRequest", "Redirected native Subagent directory");
|
|
22098
|
+
return directory;
|
|
22099
|
+
}
|
|
22100
|
+
async function verifiedChildFile(file2, expected) {
|
|
22101
|
+
const info = await lstat(file2);
|
|
22102
|
+
if (!info.isFile() || info.isSymbolicLink() || process.platform !== "win32" && (info.mode & 63) !== 0)
|
|
22103
|
+
throw new CodeBuddyError("invalidRequest", "Unsafe derived Subagent transcript");
|
|
22104
|
+
if (!sameResolvedPath(await realpath4(file2), file2))
|
|
22105
|
+
throw new CodeBuddyError("invalidRequest", "Redirected derived Subagent transcript");
|
|
22106
|
+
const before = await codeBuddyFileVersion(file2);
|
|
22107
|
+
const actual = await readCodeBuddyVersionedText(file2, CODEBUDDY_CHILD_MAX_BYTES, "Subagent transcript exceeds 8 MB", before);
|
|
22108
|
+
if (!actual.reusableVersion || !sameCodeBuddyFileVersion(before, actual.reusableVersion) || !isDeepStrictEqual3(Buffer.from(actual.contents, "utf8"), expected))
|
|
22109
|
+
throw new CodeBuddyError("nativeFailure", "Native Fork produced a different Subagent transcript");
|
|
22110
|
+
}
|
|
22111
|
+
async function persistChildCopy(file2, expected) {
|
|
22112
|
+
try {
|
|
22113
|
+
await writeFile(file2, expected, { flag: "wx", mode: 384 });
|
|
22114
|
+
} catch (error51) {
|
|
22115
|
+
if (record2(error51).code !== "EEXIST")
|
|
22116
|
+
throw error51;
|
|
22117
|
+
await verifiedChildFile(file2, expected);
|
|
22118
|
+
return void 0;
|
|
22119
|
+
}
|
|
22120
|
+
const copy = { file: file2, expected };
|
|
22121
|
+
try {
|
|
22122
|
+
await verifiedChildFile(file2, expected);
|
|
22123
|
+
return copy;
|
|
22124
|
+
} catch (error51) {
|
|
22125
|
+
return failAfterBridgeCleanup(error51, copy);
|
|
22126
|
+
}
|
|
22127
|
+
}
|
|
22128
|
+
async function copyInheritedChildren(options) {
|
|
22129
|
+
const { references } = options;
|
|
22130
|
+
if (!references.length)
|
|
22131
|
+
return { descriptors: [], created: [] };
|
|
22132
|
+
const sourceHistoryFile = await realpath4(options.sourceHistoryFile);
|
|
22133
|
+
const sourceProject = path5.dirname(sourceHistoryFile);
|
|
22134
|
+
if (!sameResolvedPath(sourceHistoryFile, path5.join(sourceProject, `${options.sourceRef.nativeSessionId}.jsonl`)))
|
|
22135
|
+
throw new CodeBuddyError("invalidRequest", "Unexpected source history location");
|
|
22136
|
+
const sourceDirectory = path5.join(sourceProject, options.sourceRef.nativeSessionId, "subagents");
|
|
22137
|
+
const sourceDirectoryInfo = await lstat(sourceDirectory);
|
|
22138
|
+
if (!sourceDirectoryInfo.isDirectory() || sourceDirectoryInfo.isSymbolicLink())
|
|
22139
|
+
throw new CodeBuddyError("invalidRequest", "Redirected source Subagent directory");
|
|
22140
|
+
if (!sameResolvedPath(await realpath4(sourceDirectory), sourceDirectory))
|
|
22141
|
+
throw new CodeBuddyError("invalidRequest", "Redirected source Subagent directory");
|
|
22142
|
+
const targetHistoryFile = await realpath4(options.targetHistoryFile);
|
|
22143
|
+
const targetProject = path5.dirname(targetHistoryFile);
|
|
22144
|
+
if (!sameResolvedPath(targetHistoryFile, path5.join(targetProject, `${options.targetRef.nativeSessionId}.jsonl`)))
|
|
22145
|
+
throw new CodeBuddyError("invalidRequest", "Unexpected target history location");
|
|
22146
|
+
const targetSessionDirectory = await plainDirectory(targetProject, options.targetRef.nativeSessionId);
|
|
22147
|
+
const targetDirectory = await plainDirectory(targetSessionDirectory, "subagents");
|
|
22148
|
+
const descriptors = [];
|
|
22149
|
+
const created = [];
|
|
22150
|
+
try {
|
|
22151
|
+
for (const reference of references) {
|
|
22152
|
+
const sourceFile = path5.join(sourceDirectory, `${reference.childId}.jsonl`);
|
|
22153
|
+
const sourceInfo = await lstat(sourceFile);
|
|
22154
|
+
if (!sourceInfo.isFile() || sourceInfo.isSymbolicLink())
|
|
22155
|
+
throw new CodeBuddyError("invalidRequest", "Redirected source Subagent transcript");
|
|
22156
|
+
const before = await codeBuddyFileVersion(sourceFile);
|
|
22157
|
+
if (!sameResolvedPath(before.realFile, sourceFile))
|
|
22158
|
+
throw new CodeBuddyError("invalidRequest", "Redirected source Subagent transcript");
|
|
22159
|
+
if (before.size > CODEBUDDY_CHILD_MAX_BYTES)
|
|
22160
|
+
throw new CodeBuddyError("unsupported", "Subagent transcript exceeds 8 MB");
|
|
22161
|
+
const source = await readCodeBuddyVersionedText(sourceFile, CODEBUDDY_CHILD_MAX_BYTES, "Subagent transcript exceeds 8 MB", before);
|
|
22162
|
+
if (!source.reusableVersion)
|
|
22163
|
+
throw new CodeBuddyError("sessionBusy", "Source Subagent changed during Fork");
|
|
22164
|
+
const validated = await validateCodeBuddyChildContents(source.contents, options.sourceRef, reference.childId, options.sourceCwd, false);
|
|
22165
|
+
assertChildRanges(validated.entries, reference);
|
|
22166
|
+
const last = reference.ranges.at(-1)?.lastId;
|
|
22167
|
+
if (!last)
|
|
22168
|
+
throw new CodeBuddyError("protocolError", "Missing Agent result child range");
|
|
22169
|
+
const prefix = await codeBuddyChildPrefixThrough(source.contents, last, validated);
|
|
22170
|
+
const expected = Buffer.from(prefix.contents, "utf8");
|
|
22171
|
+
const targetFile = path5.join(targetDirectory, `${reference.childId}.jsonl`);
|
|
22172
|
+
const copy = await persistChildCopy(targetFile, expected);
|
|
22173
|
+
if (copy)
|
|
22174
|
+
created.push(copy);
|
|
22175
|
+
const after = await readCodeBuddyVersionedText(sourceFile, CODEBUDDY_CHILD_MAX_BYTES, "Subagent transcript exceeds 8 MB", before);
|
|
22176
|
+
if (!after.reusableVersion || !sameCodeBuddyFileVersion(before, after.reusableVersion) || after.contents !== source.contents)
|
|
22177
|
+
throw new CodeBuddyError("sessionBusy", "Source Subagent changed during Fork");
|
|
22178
|
+
descriptors.push(codeBuddyInheritedChildDescriptor(reference.childId, prefix.contents, prefix.child));
|
|
22179
|
+
}
|
|
22180
|
+
return { descriptors, created };
|
|
22181
|
+
} catch (failure2) {
|
|
22182
|
+
const cleanupFailures = [];
|
|
22183
|
+
for (const copy of created.toReversed()) {
|
|
22184
|
+
try {
|
|
22185
|
+
await cleanupBridge(copy);
|
|
22186
|
+
} catch (error51) {
|
|
22187
|
+
cleanupFailures.push(error51);
|
|
22188
|
+
}
|
|
22189
|
+
}
|
|
22190
|
+
if (cleanupFailures.length)
|
|
22191
|
+
throw new AggregateError([failure2, ...cleanupFailures], "Subagent copy and cleanup both failed");
|
|
22192
|
+
throw failure2;
|
|
22193
|
+
}
|
|
22194
|
+
}
|
|
22195
|
+
async function deriveCodeBuddySession(options) {
|
|
22196
|
+
const { input, environment, factory, signal } = options;
|
|
22197
|
+
const sourceCwd = options.sourceCwd ?? input.cwd;
|
|
22198
|
+
const profile = options.profile ?? CODEBUDDY_RUNTIME_PROFILE;
|
|
22199
|
+
const strictHistoryBinding = profile.historyCapabilities?.forkAcrossCwd === true;
|
|
22200
|
+
validateNativeRef(input.sourceRef, profile);
|
|
22201
|
+
const source = await codeBuddyNativeHistory(sourceCwd, input.sourceRef, environment, profile);
|
|
22202
|
+
const retained = retainedRowCount(input, source.contents, sourceCwd, profile);
|
|
22203
|
+
const sourceRows = nativeHistoryRows(source.contents);
|
|
22204
|
+
const childReferences = referencedChildren(sourceRows.slice(0, retained));
|
|
22205
|
+
const temporary = nativeSessionRefSchema.parse({
|
|
22206
|
+
harnessId: profile.harnessId,
|
|
22207
|
+
nativeSessionId: randomUUID(),
|
|
22208
|
+
formatVersion: 1
|
|
22209
|
+
});
|
|
22210
|
+
await (options.copy ?? copyCodeBuddySession)(sourceCwd, input.sourceRef.nativeSessionId, temporary.nativeSessionId, environment, signal, options.invocationFactory ?? codeBuddyInvocation);
|
|
22211
|
+
const nativeCopy = await codeBuddyNativeHistory(sourceCwd, temporary, environment, profile, {
|
|
22212
|
+
...strictHistoryBinding ? { requirePrimary: true } : {},
|
|
22213
|
+
inheritedContents: source.contents
|
|
22214
|
+
});
|
|
22215
|
+
if (!isDeepStrictEqual3(nativeHistoryRows(nativeCopy.contents), sourceRows))
|
|
22216
|
+
throw new CodeBuddyError("unsupported", "Native history copy changed the source prefix");
|
|
22217
|
+
const bridge = strictHistoryBinding ? await bridgeCopyToTarget(sourceCwd, input.cwd, temporary, nativeCopy.contents, environment, profile) : void 0;
|
|
22218
|
+
if (strictHistoryBinding) {
|
|
22219
|
+
let targetCopy;
|
|
22220
|
+
try {
|
|
22221
|
+
targetCopy = await codeBuddyNativeHistory(input.cwd, temporary, environment, profile, {
|
|
22222
|
+
requirePrimary: true,
|
|
22223
|
+
inheritedContents: nativeCopy.contents
|
|
22224
|
+
});
|
|
22225
|
+
} catch (error51) {
|
|
22226
|
+
return failAfterBridgeCleanup(error51, bridge);
|
|
22227
|
+
}
|
|
22228
|
+
if (targetCopy.contents !== nativeCopy.contents) {
|
|
22229
|
+
return failAfterBridgeCleanup(new CodeBuddyError("nativeFailure", "Cross-directory history bridge changed native bytes"), bridge);
|
|
22230
|
+
}
|
|
22231
|
+
}
|
|
22232
|
+
let derivedId;
|
|
22233
|
+
let failure2;
|
|
22234
|
+
let inheritedChildCopies = [];
|
|
22235
|
+
let derivationSucceeded = false;
|
|
22236
|
+
let receiveCommands;
|
|
22237
|
+
const commands = new Promise((resolve) => {
|
|
22238
|
+
receiveCommands = resolve;
|
|
22239
|
+
});
|
|
22240
|
+
let client2;
|
|
22241
|
+
try {
|
|
22242
|
+
client2 = factory({
|
|
22243
|
+
cwd: input.cwd,
|
|
22244
|
+
environment,
|
|
22245
|
+
ephemeral: false,
|
|
22246
|
+
temporarySessionId: temporary.nativeSessionId,
|
|
22247
|
+
handlers: {
|
|
22248
|
+
permission: async () => ({ outcome: { outcome: "cancelled" } }),
|
|
22249
|
+
question: async () => ({ outcome: "cancelled" }),
|
|
22250
|
+
fault: (error51) => {
|
|
22251
|
+
failure2 = error51;
|
|
22252
|
+
},
|
|
22253
|
+
update: ({ sessionId, update }) => {
|
|
22254
|
+
if (record2(update).sessionUpdate === "available_commands_update")
|
|
22255
|
+
receiveCommands(record2(update).availableCommands);
|
|
22256
|
+
const meta3 = record2(record2(update)._meta);
|
|
22257
|
+
if (meta3["codebuddy.ai/sessionReset"] === true && meta3["codebuddy.ai/newSessionId"] === sessionId)
|
|
22258
|
+
derivedId = sessionId;
|
|
22259
|
+
}
|
|
22260
|
+
}
|
|
22261
|
+
});
|
|
22262
|
+
} catch (error51) {
|
|
22263
|
+
return failAfterBridgeCleanup(error51, bridge);
|
|
22264
|
+
}
|
|
22265
|
+
const abort = () => {
|
|
22266
|
+
void client2.close();
|
|
22267
|
+
};
|
|
22268
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
22269
|
+
let primaryFailure;
|
|
22270
|
+
try {
|
|
22271
|
+
if (!client2.removeCopy)
|
|
22272
|
+
throw new CodeBuddyError("unsupported", "Native temporary Session cleanup is unavailable");
|
|
22273
|
+
if (signal.aborted)
|
|
22274
|
+
throw new CodeBuddyError("invalidState", "Adapter closed during Fork");
|
|
22275
|
+
await client2.initialize();
|
|
22276
|
+
const opened = await client2.open(input.cwd, temporary.nativeSessionId);
|
|
22277
|
+
if (opened.sessionId && opened.sessionId !== temporary.nativeSessionId)
|
|
22278
|
+
throw new CodeBuddyError("protocolError", "ACP loaded a different temporary Session");
|
|
22279
|
+
const nativeState = configuration(opened.configOptions, profile).state;
|
|
22280
|
+
const available = await bounded(commands, 5e3, "Native command discovery", abort);
|
|
22281
|
+
if (!Array.isArray(available) || !available.some((entry) => record2(entry).name === "fork"))
|
|
22282
|
+
throw new CodeBuddyError("unsupported", "Native Session does not advertise /fork");
|
|
22283
|
+
const result = await bounded(client2.prompt(temporary.nativeSessionId, "/fork"), 2e4, "Native Fork", abort);
|
|
22284
|
+
if (failure2)
|
|
22285
|
+
throw failure2;
|
|
22286
|
+
if (result.stopReason !== "end_turn" || !derivedId || [input.sourceRef.nativeSessionId, temporary.nativeSessionId].includes(derivedId))
|
|
22287
|
+
throw new CodeBuddyError("unsupported", "Native Fork did not report a separate Session");
|
|
22288
|
+
const preliminaryRef = nativeSessionRefSchema.parse({
|
|
22289
|
+
harnessId: profile.harnessId,
|
|
22290
|
+
nativeSessionId: derivedId,
|
|
22291
|
+
formatVersion: 1
|
|
22292
|
+
});
|
|
22293
|
+
const historicalCwds = [
|
|
22294
|
+
.../* @__PURE__ */ new Set([
|
|
22295
|
+
...sourceRows.flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []),
|
|
22296
|
+
...source.historicalCwds,
|
|
22297
|
+
sourceCwd,
|
|
22298
|
+
input.cwd
|
|
22299
|
+
])
|
|
22300
|
+
];
|
|
22301
|
+
const historyTransaction = strictHistoryBinding ? { requirePrimary: true, allowedHistoricalCwds: historicalCwds } : void 0;
|
|
22302
|
+
const forked = await codeBuddyNativeHistory(input.cwd, preliminaryRef, environment, profile, historyTransaction);
|
|
22303
|
+
const forkRows = nativeHistoryRows(forked.contents);
|
|
22304
|
+
assertCopiedPrefix(sourceRows, forkRows);
|
|
22305
|
+
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;
|
|
22306
|
+
if (strictHistoryBinding && !marker)
|
|
22307
|
+
throw new CodeBuddyError("unsupported", "Native Fork did not persist a target binding marker");
|
|
22308
|
+
if (!client2.rollback)
|
|
22309
|
+
throw new CodeBuddyError("unsupported", "Native history rewind is unavailable");
|
|
22310
|
+
const point = retained ? text(forkRows[retained - 1]?.id) : null;
|
|
22311
|
+
const rewound = await client2.rollback(derivedId, point);
|
|
22312
|
+
if (rewound.applied !== true || (rewound.actualForkPointId ?? null) !== point)
|
|
22313
|
+
throw new CodeBuddyError("nativeFailure", "Native history rewind was not confirmed");
|
|
22314
|
+
const verified = await codeBuddyNativeHistory(input.cwd, preliminaryRef, environment, profile, historyTransaction);
|
|
22315
|
+
const finalRows = nativeHistoryRows(verified.contents);
|
|
22316
|
+
if (!isDeepStrictEqual3(finalRows, forkRows.slice(0, retained)))
|
|
22317
|
+
throw new CodeBuddyError("nativeFailure", "Native history rewind did not persist the exact prefix");
|
|
22318
|
+
const inheritedChildren2 = await copyInheritedChildren({
|
|
22319
|
+
references: childReferences,
|
|
22320
|
+
sourceRef: input.sourceRef,
|
|
22321
|
+
sourceCwd,
|
|
22322
|
+
sourceHistoryFile: source.file,
|
|
22323
|
+
targetRef: preliminaryRef,
|
|
22324
|
+
targetHistoryFile: verified.file
|
|
22325
|
+
});
|
|
22326
|
+
inheritedChildCopies = inheritedChildren2.created;
|
|
22327
|
+
const inheritedChildLocator = inheritedChildren2.descriptors.length ? { codebuddyInheritedChildren: inheritedChildren2.descriptors } : {};
|
|
22328
|
+
const ref = nativeSessionRefSchema.parse({
|
|
22329
|
+
...preliminaryRef,
|
|
22330
|
+
locator: strictHistoryBinding ? {
|
|
22331
|
+
codebuddyDerived: 1,
|
|
22332
|
+
boundCwd: codeBuddyCanonicalCwd(input.cwd),
|
|
22333
|
+
targetProjectSlug: codeBuddyProjectSlug(input.cwd, profile),
|
|
22334
|
+
inheritedPrefixRows: finalRows.length,
|
|
22335
|
+
inheritedPrefixSha256: nativeRowsDigest(finalRows),
|
|
22336
|
+
bindingMarkerId: text(marker?.id),
|
|
22337
|
+
...inheritedChildLocator
|
|
22338
|
+
} : { codebuddyDerived: 1, ...inheritedChildLocator }
|
|
22339
|
+
});
|
|
22340
|
+
await codeBuddyNativeHistory(input.cwd, ref, environment, profile);
|
|
22341
|
+
const after = await codeBuddyNativeHistory(sourceCwd, input.sourceRef, environment, profile);
|
|
22342
|
+
if (after.contents !== source.contents)
|
|
22343
|
+
throw new CodeBuddyError("sessionBusy", "Source history changed during Fork");
|
|
22344
|
+
if (signal.aborted)
|
|
22345
|
+
throw new CodeBuddyError("invalidState", "Adapter closed during Fork");
|
|
22346
|
+
const saved = record2(record2(input.sourceRef.locator).configuration);
|
|
22347
|
+
const state = options.state ?? {
|
|
22348
|
+
...nativeState,
|
|
22349
|
+
...text(saved.model) ? { effectiveModel: modelRef(text(saved.model)) } : {}
|
|
22350
|
+
};
|
|
22351
|
+
const model = input.kind === "rollbackLastTurn" && input.model ? input.model : state.effectiveModel;
|
|
22352
|
+
const thinking = input.kind === "rollbackLastTurn" && input.thinkingOptionId ? input.thinkingOptionId : options.state?.effectiveThinkingOptionId ?? (text(saved.thinking) ? harnessThinkingOptionIdSchema.parse(saved.thinking) : state.effectiveThinkingOptionId);
|
|
22353
|
+
const mode = input.kind === "rollbackLastTurn" && input.permissionModeId ? input.permissionModeId : options.state?.effectivePermissionModeId ?? (text(saved.mode) ? harnessPermissionModeIdSchema.parse(saved.mode) : state.effectivePermissionModeId);
|
|
22354
|
+
const resume = {
|
|
22355
|
+
kind: "resume",
|
|
22356
|
+
nativeRef: ref,
|
|
22357
|
+
cwd: input.cwd,
|
|
22358
|
+
...input.environment ? { environment: input.environment } : {},
|
|
22359
|
+
...model ? { model } : {},
|
|
22360
|
+
...thinking ? { thinkingOptionId: thinking } : {},
|
|
22361
|
+
...mode ? { permissionModeId: mode } : {}
|
|
22362
|
+
};
|
|
22363
|
+
derivationSucceeded = true;
|
|
22364
|
+
return resume;
|
|
22365
|
+
} catch (error51) {
|
|
22366
|
+
primaryFailure = error51;
|
|
22367
|
+
throw error51;
|
|
22368
|
+
} finally {
|
|
22369
|
+
signal.removeEventListener("abort", abort);
|
|
22370
|
+
const cleanupFailures = [];
|
|
22371
|
+
let temporaryCleanupFailed = false;
|
|
22372
|
+
try {
|
|
22373
|
+
if (client2.removeCopy)
|
|
22374
|
+
await client2.removeCopy();
|
|
22375
|
+
} catch (error51) {
|
|
22376
|
+
temporaryCleanupFailed = true;
|
|
22377
|
+
cleanupFailures.push(error51);
|
|
22378
|
+
}
|
|
22379
|
+
try {
|
|
22380
|
+
await client2.close();
|
|
22381
|
+
} catch (error51) {
|
|
22382
|
+
cleanupFailures.push(error51);
|
|
22383
|
+
}
|
|
22384
|
+
try {
|
|
22385
|
+
await cleanupBridge(bridge);
|
|
22386
|
+
} catch (error51) {
|
|
22387
|
+
cleanupFailures.push(error51);
|
|
22388
|
+
}
|
|
22389
|
+
if (!derivationSucceeded || cleanupFailures.length) {
|
|
22390
|
+
for (const copy of inheritedChildCopies.toReversed()) {
|
|
22391
|
+
try {
|
|
22392
|
+
await cleanupBridge(copy);
|
|
22393
|
+
} catch (error51) {
|
|
22394
|
+
cleanupFailures.push(error51);
|
|
22395
|
+
}
|
|
22396
|
+
}
|
|
22397
|
+
}
|
|
22398
|
+
if (cleanupFailures.length) {
|
|
22399
|
+
if (primaryFailure)
|
|
22400
|
+
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"}`);
|
|
22401
|
+
if (cleanupFailures.length === 1)
|
|
22402
|
+
throw cleanupFailures[0];
|
|
22403
|
+
throw new AggregateError(cleanupFailures, "Native derivation cleanup failed");
|
|
22404
|
+
}
|
|
22405
|
+
}
|
|
22406
|
+
}
|
|
22407
|
+
|
|
21206
22408
|
// dist/interactions.js
|
|
21207
22409
|
var CodeBuddyInteractions = class {
|
|
21208
22410
|
emit;
|
|
21209
22411
|
client;
|
|
22412
|
+
profile;
|
|
21210
22413
|
#pending = /* @__PURE__ */ new Map();
|
|
21211
22414
|
#sequence = 0;
|
|
21212
|
-
constructor(emit, client2) {
|
|
22415
|
+
constructor(emit, client2, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21213
22416
|
this.emit = emit;
|
|
21214
22417
|
this.client = client2;
|
|
22418
|
+
this.profile = profile;
|
|
21215
22419
|
}
|
|
21216
22420
|
#question(turnId, input) {
|
|
21217
22421
|
const questions = rows(record2(input).questions);
|
|
21218
22422
|
if (!questions.length || questions.length > 4)
|
|
21219
|
-
throw new CodeBuddyError("protocolError",
|
|
22423
|
+
throw new CodeBuddyError("protocolError", `Invalid ${this.profile.displayName} question count`);
|
|
21220
22424
|
return {
|
|
21221
22425
|
type: "question",
|
|
21222
|
-
interactionId: hostInteractionIdSchema.parse(
|
|
22426
|
+
interactionId: hostInteractionIdSchema.parse(`${this.profile.interactionIdPrefix}-question-${++this.#sequence}`),
|
|
21223
22427
|
turnId,
|
|
21224
|
-
title:
|
|
22428
|
+
title: this.profile.displayName,
|
|
21225
22429
|
questions: questions.map((question, index) => {
|
|
21226
22430
|
const options = rows(question.options).map((option) => ({
|
|
21227
22431
|
value: text(option.label),
|
|
@@ -21229,7 +22433,7 @@ var CodeBuddyInteractions = class {
|
|
|
21229
22433
|
...option.description ? { description: text(option.description) } : {}
|
|
21230
22434
|
}));
|
|
21231
22435
|
if (!text(question.question) || !options.length || options.some((option) => !option.value))
|
|
21232
|
-
throw new CodeBuddyError("protocolError",
|
|
22436
|
+
throw new CodeBuddyError("protocolError", `Malformed ${this.profile.displayName} question`);
|
|
21233
22437
|
return {
|
|
21234
22438
|
id: text(question.id) || `q_${index}`,
|
|
21235
22439
|
type: "choice",
|
|
@@ -21269,9 +22473,9 @@ var CodeBuddyInteractions = class {
|
|
|
21269
22473
|
throw new CodeBuddyError("unsupported", "ACP approval does not provide a reject action");
|
|
21270
22474
|
const interaction = {
|
|
21271
22475
|
type: "approval",
|
|
21272
|
-
interactionId: hostInteractionIdSchema.parse(
|
|
22476
|
+
interactionId: hostInteractionIdSchema.parse(`${this.profile.interactionIdPrefix}-approval-${++this.#sequence}`),
|
|
21273
22477
|
turnId,
|
|
21274
|
-
title: name || request.toolCall.title ||
|
|
22478
|
+
title: name || request.toolCall.title || `${this.profile.displayName} tool approval`,
|
|
21275
22479
|
subject: { type: "nativeAction" },
|
|
21276
22480
|
actions,
|
|
21277
22481
|
description: JSON.stringify(request.toolCall.rawInput ?? {}).slice(0, 16e3)
|
|
@@ -21307,7 +22511,7 @@ var CodeBuddyInteractions = class {
|
|
|
21307
22511
|
async respond(command) {
|
|
21308
22512
|
const pending = this.#pending.get(command.interactionId);
|
|
21309
22513
|
if (!pending || pending.responding)
|
|
21310
|
-
return failure("invalidRequest", "Interaction is not awaiting a response");
|
|
22514
|
+
return failure("invalidRequest", "Interaction is not awaiting a response", this.profile);
|
|
21311
22515
|
const validation = validateHostInteractionResponse(pending.interaction, command.response);
|
|
21312
22516
|
if (validation)
|
|
21313
22517
|
return { ok: false, error: validation };
|
|
@@ -21318,7 +22522,7 @@ var CodeBuddyInteractions = class {
|
|
|
21318
22522
|
return { ok: true, value: { accepted: true } };
|
|
21319
22523
|
} catch (error51) {
|
|
21320
22524
|
pending.responding = false;
|
|
21321
|
-
return { ok: false, error: nativeError(error51) };
|
|
22525
|
+
return { ok: false, error: nativeError(error51, this.profile) };
|
|
21322
22526
|
}
|
|
21323
22527
|
}
|
|
21324
22528
|
#finish(pending, reason) {
|
|
@@ -21343,33 +22547,23 @@ var CodeBuddyInteractions = class {
|
|
|
21343
22547
|
};
|
|
21344
22548
|
|
|
21345
22549
|
// dist/subagent-history.js
|
|
21346
|
-
import { readdir as readdir2, realpath as
|
|
21347
|
-
import
|
|
21348
|
-
var
|
|
22550
|
+
import { readdir as readdir2, realpath as realpath5 } from "node:fs/promises";
|
|
22551
|
+
import path6 from "node:path";
|
|
22552
|
+
var equalPath2 = (a, b) => process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
21349
22553
|
var MAX_CACHED_CHILDREN = 16;
|
|
21350
|
-
function childContents(contents) {
|
|
21351
|
-
const lines = contents.split(/\r?\n/u);
|
|
21352
|
-
if (lines.at(-1)?.trim()) {
|
|
21353
|
-
try {
|
|
21354
|
-
JSON.parse(lines.at(-1) ?? "");
|
|
21355
|
-
} catch {
|
|
21356
|
-
lines.pop();
|
|
21357
|
-
}
|
|
21358
|
-
}
|
|
21359
|
-
const entries = lines.filter((line) => line.trim()).map((line) => record2(JSON.parse(line)));
|
|
21360
|
-
return { contents: lines.join("\n"), entries };
|
|
21361
|
-
}
|
|
21362
22554
|
var CodeBuddyChildObserver = class {
|
|
21363
22555
|
parent;
|
|
21364
22556
|
cwd;
|
|
21365
22557
|
environment;
|
|
22558
|
+
profile;
|
|
21366
22559
|
#children = /* @__PURE__ */ new Map();
|
|
21367
22560
|
#parent;
|
|
21368
22561
|
#closed = false;
|
|
21369
|
-
constructor(parent, cwd, environment) {
|
|
22562
|
+
constructor(parent, cwd, environment, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21370
22563
|
this.parent = parent;
|
|
21371
22564
|
this.cwd = cwd;
|
|
21372
22565
|
this.environment = environment;
|
|
22566
|
+
this.profile = profile;
|
|
21373
22567
|
}
|
|
21374
22568
|
close() {
|
|
21375
22569
|
this.#closed = true;
|
|
@@ -21380,16 +22574,16 @@ var CodeBuddyChildObserver = class {
|
|
|
21380
22574
|
if (this.#closed)
|
|
21381
22575
|
throw new CodeBuddyError("invalidRequest", "Subagent observer is closed");
|
|
21382
22576
|
}
|
|
21383
|
-
async #validateWorkspaces(cwds
|
|
21384
|
-
const expected = await
|
|
22577
|
+
async #validateWorkspaces(cwds) {
|
|
22578
|
+
const expected = await realpath5(this.cwd);
|
|
21385
22579
|
for (const cwd of new Set(cwds)) {
|
|
21386
|
-
const actual = await
|
|
21387
|
-
if (
|
|
22580
|
+
const actual = await realpath5(cwd).catch((error51) => {
|
|
22581
|
+
if (["ENOENT", "ENOTDIR"].includes(String(record2(error51).code)))
|
|
21388
22582
|
throw new CodeBuddyError("invalidRequest", "Native Session historical working directory is unavailable; ownership cannot be verified");
|
|
21389
22583
|
throw error51;
|
|
21390
22584
|
});
|
|
21391
|
-
if (!
|
|
21392
|
-
throw new CodeBuddyError("invalidRequest",
|
|
22585
|
+
if (!equalPath2(actual, expected))
|
|
22586
|
+
throw new CodeBuddyError("invalidRequest", "Native Session belongs to a different working directory");
|
|
21393
22587
|
}
|
|
21394
22588
|
}
|
|
21395
22589
|
async #parentHistory() {
|
|
@@ -21406,7 +22600,7 @@ var CodeBuddyChildObserver = class {
|
|
|
21406
22600
|
return this.#parent;
|
|
21407
22601
|
}
|
|
21408
22602
|
}
|
|
21409
|
-
const history = await codeBuddyLiveNativeHistory(this.cwd, this.parent, this.environment);
|
|
22603
|
+
const history = await codeBuddyLiveNativeHistory(this.cwd, this.parent, this.environment, this.profile);
|
|
21410
22604
|
this.#assertOpen();
|
|
21411
22605
|
this.#parent = {
|
|
21412
22606
|
file: history.file,
|
|
@@ -21418,31 +22612,34 @@ var CodeBuddyChildObserver = class {
|
|
|
21418
22612
|
}
|
|
21419
22613
|
async #directory() {
|
|
21420
22614
|
const history = await this.#parentHistory();
|
|
21421
|
-
const project =
|
|
21422
|
-
const expected =
|
|
21423
|
-
const actual = await
|
|
22615
|
+
const project = path6.dirname(await realpath5(history.file));
|
|
22616
|
+
const expected = path6.join(project, this.parent.nativeSessionId, "subagents");
|
|
22617
|
+
const actual = await realpath5(expected);
|
|
21424
22618
|
this.#assertOpen();
|
|
21425
|
-
if (!
|
|
21426
|
-
throw new CodeBuddyError("invalidRequest",
|
|
22619
|
+
if (!equalPath2(actual, expected))
|
|
22620
|
+
throw new CodeBuddyError("invalidRequest", `Redirected ${this.profile.displayName} Subagent directory`);
|
|
21427
22621
|
return actual;
|
|
21428
22622
|
}
|
|
21429
22623
|
async #child(directory, childId) {
|
|
21430
22624
|
if (!validCodeBuddyChildId(childId))
|
|
21431
22625
|
throw new CodeBuddyError("invalidRequest", "Invalid native Subagent ID");
|
|
21432
|
-
const file2 =
|
|
22626
|
+
const file2 = path6.join(directory, `${childId}.jsonl`);
|
|
21433
22627
|
const before = await codeBuddyFileVersion(file2);
|
|
21434
|
-
if (!
|
|
22628
|
+
if (!equalPath2(before.realFile, file2))
|
|
21435
22629
|
throw new CodeBuddyError("invalidRequest", "Redirected Subagent transcript");
|
|
21436
22630
|
this.#assertOpen();
|
|
21437
|
-
if (before.size >
|
|
22631
|
+
if (before.size > CODEBUDDY_CHILD_MAX_BYTES)
|
|
21438
22632
|
throw new CodeBuddyError("unsupported", "Subagent transcript exceeds 8 MB");
|
|
21439
22633
|
const cached2 = this.#children.get(childId);
|
|
21440
|
-
if (cached2 && sameCodeBuddyFileVersion(cached2.version, before))
|
|
22634
|
+
if (cached2 && sameCodeBuddyFileVersion(cached2.version, before)) {
|
|
22635
|
+
await validateCodeBuddyChildContents(cached2.rawContents, this.parent, childId, this.cwd, true);
|
|
21441
22636
|
return cached2;
|
|
21442
|
-
|
|
22637
|
+
}
|
|
22638
|
+
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);
|
|
21443
22639
|
this.#assertOpen();
|
|
21444
22640
|
const next = {
|
|
21445
22641
|
...data,
|
|
22642
|
+
rawContents: source.contents,
|
|
21446
22643
|
version: source.reusableVersion
|
|
21447
22644
|
};
|
|
21448
22645
|
this.#children.delete(childId);
|
|
@@ -21478,26 +22675,19 @@ var CodeBuddyChildObserver = class {
|
|
|
21478
22675
|
async read(childId, status) {
|
|
21479
22676
|
if (!status) {
|
|
21480
22677
|
const source = await this.#parentHistory();
|
|
21481
|
-
const states = snapshotFromHistory(source.contents, this.parent, this.cwd).turns.flatMap((turn) => turn.items.flatMap(({ item }) => item.type === "subagentDelegation" ? item.subagents : []));
|
|
22678
|
+
const states = snapshotFromHistory(source.contents, this.parent, this.cwd, this.profile).turns.flatMap((turn) => turn.items.flatMap(({ item }) => item.type === "subagentDelegation" ? item.subagents : []));
|
|
21482
22679
|
status = states.findLast((child) => child.nativeSubagentId === childId)?.status;
|
|
21483
22680
|
}
|
|
21484
22681
|
const data = await this.#child(await this.#directory(), childId);
|
|
21485
|
-
const sessions = new Set(data.entries.map((row) => text(row.sessionId)).filter(Boolean));
|
|
21486
|
-
if (sessions.size !== 1)
|
|
21487
|
-
throw new CodeBuddyError("protocolError", "Subagent transcript identity is missing or mixed");
|
|
21488
|
-
await this.#validateWorkspaces(data.entries.flatMap((row) => typeof row.cwd === "string" ? [row.cwd] : []), true);
|
|
21489
22682
|
this.#assertOpen();
|
|
21490
|
-
|
|
21491
|
-
if (!childSessionId)
|
|
21492
|
-
throw new CodeBuddyError("protocolError", "Missing native child Session");
|
|
21493
|
-
data.snapshot ??= snapshotFromHistory(data.contents, { ...this.parent, nativeSessionId: childSessionId }, this.cwd);
|
|
22683
|
+
data.snapshot ??= snapshotFromHistory(data.contents, { ...this.parent, nativeSessionId: data.nativeSessionId }, this.cwd, this.profile);
|
|
21494
22684
|
const snapshot = structuredClone(data.snapshot);
|
|
21495
22685
|
projectChildSnapshot(snapshot, this.parent, childId, status);
|
|
21496
22686
|
return snapshot;
|
|
21497
22687
|
}
|
|
21498
22688
|
};
|
|
21499
|
-
async function readCodeBuddyChild(parent, childId, cwd, environment, status) {
|
|
21500
|
-
const observer = new CodeBuddyChildObserver(parent, cwd, environment);
|
|
22689
|
+
async function readCodeBuddyChild(parent, childId, cwd, environment, status, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
22690
|
+
const observer = new CodeBuddyChildObserver(parent, cwd, environment, profile);
|
|
21501
22691
|
try {
|
|
21502
22692
|
return await observer.read(childId, status);
|
|
21503
22693
|
} finally {
|
|
@@ -21511,6 +22701,7 @@ function projectChildSnapshot(snapshot, parent, childId, status) {
|
|
|
21511
22701
|
nativeSessionId: parent.nativeSessionId,
|
|
21512
22702
|
nativeTurnKey: `${childId}:${turn.nativeTurnRef.nativeTurnKey}`
|
|
21513
22703
|
};
|
|
22704
|
+
delete turn.checkpoint;
|
|
21514
22705
|
turn.items = turn.items.filter(({ outcome }) => !(outcome.status === "failed" && outcome.error.message.includes("Tool completion was not recorded")));
|
|
21515
22706
|
if (!status || status === "running" || status === "pending")
|
|
21516
22707
|
turn.outcome = { status: "unknown", reason: "Subagent completion has not been confirmed" };
|
|
@@ -21536,6 +22727,9 @@ var CodeBuddySubagents = class {
|
|
|
21536
22727
|
constructor(options) {
|
|
21537
22728
|
this.options = options;
|
|
21538
22729
|
}
|
|
22730
|
+
get profile() {
|
|
22731
|
+
return this.options.profile ?? CODEBUDDY_RUNTIME_PROFILE;
|
|
22732
|
+
}
|
|
21539
22733
|
begin(turnId) {
|
|
21540
22734
|
this.#turnId = turnId;
|
|
21541
22735
|
}
|
|
@@ -21576,7 +22770,7 @@ var CodeBuddySubagents = class {
|
|
|
21576
22770
|
return true;
|
|
21577
22771
|
call = {
|
|
21578
22772
|
turnId: this.#turnId,
|
|
21579
|
-
item: codeBuddyDelegation(callId, update.rawInput, "running"),
|
|
22773
|
+
item: codeBuddyDelegation(callId, update.rawInput, "running", void 0, this.profile.displayName),
|
|
21580
22774
|
itemCompleted: false,
|
|
21581
22775
|
observationDone: false
|
|
21582
22776
|
};
|
|
@@ -21607,7 +22801,7 @@ var CodeBuddySubagents = class {
|
|
|
21607
22801
|
status: "failed",
|
|
21608
22802
|
error: {
|
|
21609
22803
|
code: "nativeFailure",
|
|
21610
|
-
message:
|
|
22804
|
+
message: `${this.profile.displayName} Subagent invocation failed`,
|
|
21611
22805
|
retryable: false
|
|
21612
22806
|
}
|
|
21613
22807
|
} : { status: "succeeded" }
|
|
@@ -21658,19 +22852,19 @@ var CodeBuddySubagents = class {
|
|
|
21658
22852
|
const parent = this.options.parent();
|
|
21659
22853
|
if (!parent)
|
|
21660
22854
|
return;
|
|
21661
|
-
this.#observer ??= new CodeBuddyChildObserver(parent, this.options.cwd, this.options.environment);
|
|
22855
|
+
this.#observer ??= new CodeBuddyChildObserver(parent, this.options.cwd, this.options.environment, this.profile);
|
|
21662
22856
|
this.#refreshing = true;
|
|
21663
22857
|
try {
|
|
21664
22858
|
for (const call of this.#calls.values()) {
|
|
21665
22859
|
if (call.observationDone)
|
|
21666
22860
|
continue;
|
|
21667
22861
|
try {
|
|
21668
|
-
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);
|
|
22862
|
+
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);
|
|
21669
22863
|
if (!id || this.#closed || call.observationDone)
|
|
21670
22864
|
continue;
|
|
21671
22865
|
if (!call.item.subagents[0]?.nativeSubagentId)
|
|
21672
22866
|
this.#update(call, { nativeSubagentId: id, subagentId: id });
|
|
21673
|
-
const snapshot = await (this.options.read ? this.options.read(parent, id, this.options.cwd, this.options.environment, "running") : this.#observer.read(id, "running"));
|
|
22867
|
+
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"));
|
|
21674
22868
|
if (this.#closed || call.observationDone)
|
|
21675
22869
|
continue;
|
|
21676
22870
|
const observedModel = snapshot.turns.at(-1)?.model;
|
|
@@ -21726,8 +22920,11 @@ var CodeBuddySession = class {
|
|
|
21726
22920
|
factory;
|
|
21727
22921
|
readHistory;
|
|
21728
22922
|
onClose;
|
|
21729
|
-
|
|
21730
|
-
|
|
22923
|
+
profile;
|
|
22924
|
+
harnessId;
|
|
22925
|
+
#commands = { commands: [] };
|
|
22926
|
+
commands;
|
|
22927
|
+
capabilities;
|
|
21731
22928
|
initialState = {};
|
|
21732
22929
|
initialUsage = null;
|
|
21733
22930
|
#channel = new HarnessOutputChannel();
|
|
@@ -21749,19 +22946,29 @@ var CodeBuddySession = class {
|
|
|
21749
22946
|
#usage = null;
|
|
21750
22947
|
#context = {};
|
|
21751
22948
|
constructor(input, environment, factory, readHistory = readNativeHistory, onClose = () => {
|
|
21752
|
-
}) {
|
|
22949
|
+
}, profile = CODEBUDDY_RUNTIME_PROFILE) {
|
|
21753
22950
|
this.input = input;
|
|
21754
22951
|
this.environment = environment;
|
|
21755
22952
|
this.factory = factory;
|
|
21756
22953
|
this.readHistory = readHistory;
|
|
21757
22954
|
this.onClose = onClose;
|
|
22955
|
+
this.profile = profile;
|
|
22956
|
+
this.harnessId = profile.harnessId;
|
|
22957
|
+
this.capabilities = capabilitiesForProfile(profile);
|
|
22958
|
+
this.#commands = structuredClone(profile.staticCommandCatalog ?? { commands: [] });
|
|
22959
|
+
if (nativeCommandsEnabled(profile))
|
|
22960
|
+
this.commands = {
|
|
22961
|
+
list: async () => this.#closed || this.#fault ? failure("invalidState", "Session is closed or faulted", this.profile) : { ok: true, value: structuredClone(this.#commands) },
|
|
22962
|
+
execute: (command) => this.#executeCommand(command)
|
|
22963
|
+
};
|
|
21758
22964
|
this.subagents = new CodeBuddySubagents({
|
|
21759
22965
|
parent: () => this.#ref,
|
|
21760
22966
|
cwd: input.cwd,
|
|
21761
22967
|
environment,
|
|
21762
|
-
emit: (event) => this.#emit(event)
|
|
22968
|
+
emit: (event) => this.#emit(event),
|
|
22969
|
+
profile
|
|
21763
22970
|
});
|
|
21764
|
-
this.#interactions = new CodeBuddyInteractions((output) => this.#channel.emit(output), () => this.#client);
|
|
22971
|
+
this.#interactions = new CodeBuddyInteractions((output) => this.#channel.emit(output), () => this.#client, profile);
|
|
21765
22972
|
this.#client = this.#createClient();
|
|
21766
22973
|
}
|
|
21767
22974
|
#createClient() {
|
|
@@ -21776,16 +22983,23 @@ var CodeBuddySession = class {
|
|
|
21776
22983
|
this.#onFault(error51);
|
|
21777
22984
|
},
|
|
21778
22985
|
update: (notification) => {
|
|
21779
|
-
if (generation !== this.#generation || this.#
|
|
22986
|
+
if (generation !== this.#generation || this.#closed)
|
|
21780
22987
|
return;
|
|
21781
22988
|
if (this.#ref && notification.sessionId !== this.#ref.nativeSessionId)
|
|
21782
22989
|
return;
|
|
21783
22990
|
try {
|
|
21784
22991
|
const update = record2(notification.update);
|
|
22992
|
+
if (nativeCommandsEnabled(this.profile) && update.sessionUpdate === "available_commands_update") {
|
|
22993
|
+
if (!this.profile.staticCommandCatalog)
|
|
22994
|
+
this.#commands = commandCatalog(update.availableCommands, this.profile);
|
|
22995
|
+
return;
|
|
22996
|
+
}
|
|
22997
|
+
if (this.#replaying)
|
|
22998
|
+
return;
|
|
21785
22999
|
if (this.subagents.update(update))
|
|
21786
23000
|
return;
|
|
21787
23001
|
if (update.sessionUpdate === "config_option_update" && this.#config)
|
|
21788
|
-
this.#apply(configuration(update.configOptions));
|
|
23002
|
+
this.#apply(configuration(update.configOptions, this.profile));
|
|
21789
23003
|
if (update.sessionUpdate === "usage_update" && typeof update.used === "number" && typeof update.size === "number" && update.size > 0) {
|
|
21790
23004
|
this.#context = {
|
|
21791
23005
|
contextUsedTokens: update.used,
|
|
@@ -21807,32 +23021,54 @@ var CodeBuddySession = class {
|
|
|
21807
23021
|
}
|
|
21808
23022
|
});
|
|
21809
23023
|
}
|
|
21810
|
-
|
|
21811
|
-
|
|
21812
|
-
|
|
21813
|
-
|
|
21814
|
-
|
|
23024
|
+
/** Every fresh process must restore an unanchored rewind before it can accept prompts. */
|
|
23025
|
+
async #openClient() {
|
|
23026
|
+
let rewind;
|
|
23027
|
+
if (this.#ref) {
|
|
23028
|
+
const history = await this.readHistory(this.input.cwd, this.#ref, this.environment, this.profile);
|
|
23029
|
+
this.#hasTurn = snapshotFromHistory(history, this.#ref, this.input.cwd, this.profile).turns.length > 0;
|
|
21815
23030
|
this.#usage = historyUsage(history);
|
|
23031
|
+
rewind = pendingNativeHistoryRewind(history);
|
|
21816
23032
|
}
|
|
21817
23033
|
await this.#client.initialize();
|
|
21818
23034
|
const opened = await this.#client.open(this.input.cwd, this.#ref?.nativeSessionId);
|
|
21819
23035
|
const sessionId = this.#ref?.nativeSessionId ?? text(opened.sessionId);
|
|
21820
23036
|
if (!sessionId || opened.sessionId && opened.sessionId !== sessionId)
|
|
21821
23037
|
throw new CodeBuddyError("protocolError", "ACP returned a different Native Session identity");
|
|
23038
|
+
if (rewind) {
|
|
23039
|
+
if (!this.#client.rollback)
|
|
23040
|
+
throw new CodeBuddyError("unsupported", "Native history rewind is unavailable");
|
|
23041
|
+
const result = await this.#client.rollback(sessionId, rewind.forkPointId);
|
|
23042
|
+
if (result.applied !== true || (result.actualForkPointId ?? null) !== rewind.forkPointId)
|
|
23043
|
+
throw new CodeBuddyError("nativeFailure", "Native history rewind was not confirmed");
|
|
23044
|
+
}
|
|
23045
|
+
return { ...opened, sessionId };
|
|
23046
|
+
}
|
|
23047
|
+
async initialize() {
|
|
23048
|
+
const saved = this.input.kind === "resume" && record2(this.input.nativeRef.locator).codebuddyDerived === 1 ? record2(record2(this.input.nativeRef.locator).configuration) : {};
|
|
23049
|
+
if (this.input.kind === "resume")
|
|
23050
|
+
this.#ref = this.input.nativeRef;
|
|
23051
|
+
const opened = await this.#openClient();
|
|
21822
23052
|
this.#ref = nativeSessionRefSchema.parse({
|
|
21823
|
-
harnessId:
|
|
21824
|
-
nativeSessionId: sessionId,
|
|
21825
|
-
formatVersion: 1
|
|
23053
|
+
harnessId: this.profile.harnessId,
|
|
23054
|
+
nativeSessionId: opened.sessionId,
|
|
23055
|
+
formatVersion: 1,
|
|
23056
|
+
...this.#ref?.locator || this.capabilities.history.fork ? {
|
|
23057
|
+
locator: {
|
|
23058
|
+
...record2(this.#ref?.locator),
|
|
23059
|
+
...this.capabilities.history.fork ? { boundCwd: codeBuddyCanonicalCwd(this.input.cwd) } : {}
|
|
23060
|
+
}
|
|
23061
|
+
} : {}
|
|
21826
23062
|
});
|
|
21827
|
-
this.#apply(configuration(opened.configOptions), false);
|
|
23063
|
+
this.#apply(configuration(opened.configOptions, this.profile), false);
|
|
21828
23064
|
if (this.input.kind === "create" && this.input.executionPolicy === "unattended-full-access") {
|
|
21829
23065
|
await this.#configure("mode", "fullAccess");
|
|
21830
|
-
} else if (this.input.permissionModeId)
|
|
21831
|
-
await this.#configure("mode", this.input.permissionModeId);
|
|
21832
|
-
if (this.input.model)
|
|
21833
|
-
await this.#configure("model", nativeModel(this.input.model));
|
|
21834
|
-
if (this.input.thinkingOptionId)
|
|
21835
|
-
await this.#configure("thought_level", this.input.thinkingOptionId);
|
|
23066
|
+
} else if (this.input.permissionModeId || text(saved.mode))
|
|
23067
|
+
await this.#configure("mode", this.input.permissionModeId ?? text(saved.mode));
|
|
23068
|
+
if (this.input.model || text(saved.model))
|
|
23069
|
+
await this.#configure("model", this.input.model ? nativeModel(this.input.model) : text(saved.model));
|
|
23070
|
+
if (this.input.thinkingOptionId || text(saved.thinking))
|
|
23071
|
+
await this.#configure("thought_level", this.input.thinkingOptionId ?? text(saved.thinking));
|
|
21836
23072
|
if (this.#fault || this.#closed)
|
|
21837
23073
|
throw new CodeBuddyError("invalidState", "Native Session failed while opening");
|
|
21838
23074
|
this.initialState = { ...this.#state };
|
|
@@ -21843,29 +23079,43 @@ var CodeBuddySession = class {
|
|
|
21843
23079
|
}
|
|
21844
23080
|
#apply(config2, emit = true) {
|
|
21845
23081
|
this.#config = config2;
|
|
23082
|
+
if (this.#ref && record2(this.#ref.locator).codebuddyDerived === 1)
|
|
23083
|
+
this.#ref = nativeSessionRefSchema.parse({
|
|
23084
|
+
...this.#ref,
|
|
23085
|
+
locator: {
|
|
23086
|
+
...record2(this.#ref.locator),
|
|
23087
|
+
configuration: {
|
|
23088
|
+
model: config2.state.effectiveModel ? nativeModel(config2.state.effectiveModel) : "",
|
|
23089
|
+
mode: config2.state.effectivePermissionModeId ?? "",
|
|
23090
|
+
thinking: config2.state.effectiveThinkingOptionId ?? ""
|
|
23091
|
+
}
|
|
23092
|
+
}
|
|
23093
|
+
});
|
|
21846
23094
|
this.#state = { ...config2.state, ...this.#ref ? { nativeRef: this.#ref } : {} };
|
|
21847
23095
|
if (emit)
|
|
21848
23096
|
this.#emit({ type: "session.state.changed", state: this.#state });
|
|
21849
23097
|
}
|
|
21850
23098
|
async #configure(id, value) {
|
|
21851
23099
|
const option = this.#config?.options.find((option2) => option2.id === id);
|
|
21852
|
-
|
|
21853
|
-
|
|
23100
|
+
const listed = Array.isArray(option?.options) && option.options.some((option2) => record2(option2).value === value);
|
|
23101
|
+
const allowedProductModel = id === "model" && this.profile.allowUnlistedModelSelection;
|
|
23102
|
+
if (!listed && !allowedProductModel)
|
|
23103
|
+
throw new CodeBuddyError("invalidRequest", `Unavailable ${this.profile.displayName} ${id} selection`);
|
|
21854
23104
|
if (!this.#ref)
|
|
21855
23105
|
throw new CodeBuddyError("invalidState", "Session is not open");
|
|
21856
23106
|
const result = await this.#client.configure(this.#ref.nativeSessionId, id, value);
|
|
21857
23107
|
if (this.#closed || this.#fault)
|
|
21858
23108
|
throw new CodeBuddyError("invalidState", "Session closed during configuration");
|
|
21859
|
-
this.#apply(confirmedConfiguration(result, id, value));
|
|
23109
|
+
this.#apply(confirmedConfiguration(result, id, value, this.profile));
|
|
21860
23110
|
}
|
|
21861
23111
|
async #snapshot() {
|
|
21862
23112
|
if (!this.#ref)
|
|
21863
23113
|
throw new CodeBuddyError("invalidState", "Session is not open");
|
|
21864
23114
|
try {
|
|
21865
|
-
const history = await this.readHistory(this.input.cwd, this.#ref, this.environment);
|
|
23115
|
+
const history = await this.readHistory(this.input.cwd, this.#ref, this.environment, this.profile);
|
|
21866
23116
|
this.#usage = historyUsage(history);
|
|
21867
23117
|
return {
|
|
21868
|
-
...this.subagents.project(snapshotFromHistory(history, this.#ref, this.input.cwd)),
|
|
23118
|
+
...this.subagents.project(snapshotFromHistory(history, this.#ref, this.input.cwd, this.profile)),
|
|
21869
23119
|
state: this.#state
|
|
21870
23120
|
};
|
|
21871
23121
|
} catch (error51) {
|
|
@@ -21876,61 +23126,79 @@ var CodeBuddySession = class {
|
|
|
21876
23126
|
}
|
|
21877
23127
|
async readSnapshot() {
|
|
21878
23128
|
if (this.#closed || this.#fault)
|
|
21879
|
-
return failure("invalidState", "Session is closed or faulted");
|
|
23129
|
+
return failure("invalidState", "Session is closed or faulted", this.profile);
|
|
21880
23130
|
if (this.#busy || this.#active)
|
|
21881
|
-
return failure("sessionBusy", "Session is executing an operation");
|
|
23131
|
+
return failure("sessionBusy", "Session is executing an operation", this.profile);
|
|
21882
23132
|
this.#busy = true;
|
|
21883
23133
|
try {
|
|
21884
23134
|
return { ok: true, value: await this.#snapshot() };
|
|
21885
23135
|
} catch (error51) {
|
|
21886
|
-
return { ok: false, error: nativeError(error51) };
|
|
23136
|
+
return { ok: false, error: nativeError(error51, this.profile) };
|
|
21887
23137
|
} finally {
|
|
21888
23138
|
this.#busy = false;
|
|
21889
23139
|
}
|
|
21890
23140
|
}
|
|
23141
|
+
async #executeCommand(command) {
|
|
23142
|
+
const parsed = commandPrompt(command, this.#commands, this.profile);
|
|
23143
|
+
if (!parsed.ok)
|
|
23144
|
+
return parsed;
|
|
23145
|
+
const result = await this.#execute({ type: "turn.start", turnId: command.turnId, input: [{ type: "text", text: parsed.value }] }, true);
|
|
23146
|
+
return result.ok ? { ok: true, value: { turnId: command.turnId } } : result;
|
|
23147
|
+
}
|
|
21891
23148
|
async execute(command) {
|
|
23149
|
+
const invocation = command.type === "turn.start" ? command.input.map((item) => item.text).join("\n").trim().split(/\s/u)[0] : void 0;
|
|
23150
|
+
if (nativeCommandsEnabled(this.profile) && isExcludedInvocation(invocation))
|
|
23151
|
+
return failure("unsupported", "Command is not available in this Session", this.profile);
|
|
23152
|
+
return this.#execute(command, nativeCommandsEnabled(this.profile) && this.#commands.commands.some((entry) => entry.invocation === invocation));
|
|
23153
|
+
}
|
|
23154
|
+
async #execute(command, nativeCommand = false) {
|
|
21892
23155
|
if (this.#closed || this.#fault)
|
|
21893
|
-
return failure("invalidState", "Session is closed or faulted");
|
|
23156
|
+
return failure("invalidState", "Session is closed or faulted", this.profile);
|
|
21894
23157
|
if (command.type === "interaction.respond")
|
|
21895
23158
|
return this.#interactions.respond(command);
|
|
21896
23159
|
if (command.type === "turn.cancel") {
|
|
21897
23160
|
const active = this.#active;
|
|
21898
23161
|
if (!active || active.command.turnId !== command.turnId || !this.#ref)
|
|
21899
|
-
return failure("invalidRequest", "Turn is not active");
|
|
23162
|
+
return failure("invalidRequest", "Turn is not active", this.profile);
|
|
21900
23163
|
if (!active.cancelled) {
|
|
21901
23164
|
active.cancelled = true;
|
|
21902
23165
|
try {
|
|
21903
23166
|
await this.#client.cancel(this.#ref.nativeSessionId);
|
|
21904
23167
|
} catch (error51) {
|
|
21905
23168
|
this.#onFault(error51);
|
|
21906
|
-
return { ok: false, error: nativeError(error51) };
|
|
23169
|
+
return { ok: false, error: nativeError(error51, this.profile) };
|
|
21907
23170
|
}
|
|
21908
23171
|
this.#interactions.close();
|
|
21909
23172
|
void bounded(active.completion, 3e4, "ACP cancel acknowledgement").catch((error51) => this.#onFault(error51));
|
|
21910
23173
|
}
|
|
21911
23174
|
return { ok: true, value: { cancellationRequested: true } };
|
|
21912
23175
|
}
|
|
21913
|
-
if (this.#busy || this.#active)
|
|
21914
|
-
return failure("sessionBusy", "Session is executing an operation");
|
|
23176
|
+
if (this.#busy || this.#active && command.type !== "model.select" && command.type !== "thinking.select")
|
|
23177
|
+
return failure("sessionBusy", "Session is executing an operation", this.profile);
|
|
21915
23178
|
this.#busy = true;
|
|
21916
23179
|
try {
|
|
21917
23180
|
if (command.type === "turn.start") {
|
|
21918
23181
|
if (!command.turnId.trim() || !command.input.length || command.input.some((item) => item.type !== "text") || !command.input.map((item) => item.text).join("").trim())
|
|
21919
|
-
return failure("invalidRequest", "A nonempty text prompt is required");
|
|
21920
|
-
const
|
|
23182
|
+
return failure("invalidRequest", "A nonempty text prompt is required", this.profile);
|
|
23183
|
+
const snapshot = await this.#snapshot();
|
|
23184
|
+
const before = new Set(snapshot.turns.map((turn) => turn.nativeTurnRef.nativeTurnKey));
|
|
23185
|
+
const beforeItems = new Set(snapshot.turns.flatMap((turn) => turn.items.map((snapshot2) => snapshot2.item.itemId)));
|
|
21921
23186
|
if (this.#closed || this.#fault)
|
|
21922
|
-
return failure("invalidState", "Session closed before Turn start");
|
|
23187
|
+
return failure("invalidState", "Session closed before Turn start", this.profile);
|
|
21923
23188
|
const active = {
|
|
21924
23189
|
command,
|
|
21925
23190
|
before,
|
|
21926
|
-
|
|
23191
|
+
beforeItems,
|
|
23192
|
+
output: new CodeBuddyTurnOutput(command.turnId, this.input.cwd, (event) => this.#emit(event), this.profile),
|
|
23193
|
+
nativeCommand,
|
|
21927
23194
|
cancelled: false,
|
|
21928
23195
|
done: false,
|
|
21929
23196
|
completion: Promise.resolve()
|
|
21930
23197
|
};
|
|
21931
23198
|
this.#active = active;
|
|
21932
23199
|
this.subagents.begin(command.turnId);
|
|
21933
|
-
|
|
23200
|
+
if (!nativeCommand)
|
|
23201
|
+
this.#hasTurn = true;
|
|
21934
23202
|
this.#emit({ type: "turn.started", turnId: command.turnId });
|
|
21935
23203
|
active.completion = this.#run(active);
|
|
21936
23204
|
return { ok: true, value: { turnId: command.turnId } };
|
|
@@ -21938,7 +23206,7 @@ var CodeBuddySession = class {
|
|
|
21938
23206
|
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);
|
|
21939
23207
|
return { ok: true, value: { completed: true } };
|
|
21940
23208
|
} catch (error51) {
|
|
21941
|
-
return { ok: false, error: nativeError(error51) };
|
|
23209
|
+
return { ok: false, error: nativeError(error51, this.profile) };
|
|
21942
23210
|
} finally {
|
|
21943
23211
|
this.#busy = false;
|
|
21944
23212
|
}
|
|
@@ -21955,23 +23223,36 @@ var CodeBuddySession = class {
|
|
|
21955
23223
|
// Those remain visible on individual Items; they do not fail the completed Turn.
|
|
21956
23224
|
(!meta3["codebuddy.ai/outcome"] || meta3["codebuddy.ai/outcome"] === "SUCCESS" || meta3["codebuddy.ai/outcome"] === "PARTIAL_SUCCESS") ? { status: "succeeded" } : {
|
|
21957
23225
|
status: "failed",
|
|
21958
|
-
error: nativeError(new CodeBuddyError("nativeFailure", `Native Turn stopped: ${text(stop) || "unknown"} (${text(meta3["codebuddy.ai/outcome"]) || "no native outcome"})`))
|
|
23226
|
+
error: nativeError(new CodeBuddyError("nativeFailure", `Native Turn stopped: ${text(stop) || "unknown"} (${text(meta3["codebuddy.ai/outcome"]) || "no native outcome"})`), this.profile)
|
|
21959
23227
|
};
|
|
21960
23228
|
const snapshot = await this.#snapshot();
|
|
21961
23229
|
const added = snapshot.turns.filter((turn) => !active.before.has(turn.nativeTurnRef.nativeTurnKey));
|
|
21962
|
-
if (added.length > 1 || outcome.status === "succeeded" && added.length !== 1)
|
|
23230
|
+
if (added.length > 1 || !active.nativeCommand && outcome.status === "succeeded" && added.length !== 1)
|
|
21963
23231
|
throw new CodeBuddyError("protocolError", "Could not identify exactly one persisted Native Turn");
|
|
23232
|
+
active.output.confirmCompaction(snapshot.turns.flatMap((turn) => turn.items).filter((snapshot2) => !active.beforeItems.has(snapshot2.item.itemId)));
|
|
23233
|
+
if (active.nativeCommand)
|
|
23234
|
+
active.output.replayCommandResult(added[0]?.items ?? []);
|
|
21964
23235
|
const nativeTurnRef = added[0]?.nativeTurnRef;
|
|
23236
|
+
if (nativeTurnRef)
|
|
23237
|
+
this.#hasTurn = true;
|
|
21965
23238
|
if (response.userMessageId && nativeTurnRef?.nativeTurnKey !== response.userMessageId)
|
|
21966
23239
|
throw new CodeBuddyError("protocolError", "ACP terminal and native history disagree on Turn identity");
|
|
21967
23240
|
if (outcome.status === "cancelled")
|
|
21968
23241
|
await this.#resumeAfterCancel();
|
|
21969
|
-
|
|
23242
|
+
const compactCommand = active.nativeCommand && /^\/compact(?:\s|$)/u.test(active.command.input.map((item) => item.text).join("\n").trim());
|
|
23243
|
+
const persisted = compactCommand ? added[0]?.outcome : void 0;
|
|
23244
|
+
if (compactCommand && (!persisted || persisted.status === "unknown"))
|
|
23245
|
+
throw new CodeBuddyError("protocolError", "Native compaction terminal outcome was not persisted");
|
|
23246
|
+
const terminalOutcome = persisted && persisted.status !== "unknown" ? persisted : outcome;
|
|
23247
|
+
this.#finish(active, {
|
|
23248
|
+
...terminalOutcome,
|
|
23249
|
+
...added[0]?.checkpoint ? { checkpoint: added[0].checkpoint } : {}
|
|
23250
|
+
}, nativeTurnRef);
|
|
21970
23251
|
if (this.#usage)
|
|
21971
23252
|
this.#emit({ type: "session.usage.changed", usage: { ...this.#usage, ...this.#context } });
|
|
21972
23253
|
} catch (error51) {
|
|
21973
23254
|
if (!active.done)
|
|
21974
|
-
this.#finish(active, { status: "failed", error: nativeError(error51) });
|
|
23255
|
+
this.#finish(active, { status: "failed", error: nativeError(error51, this.profile) });
|
|
21975
23256
|
}
|
|
21976
23257
|
}
|
|
21977
23258
|
async #resumeAfterCancel() {
|
|
@@ -21986,11 +23267,8 @@ var CodeBuddySession = class {
|
|
|
21986
23267
|
if (this.#closed)
|
|
21987
23268
|
return;
|
|
21988
23269
|
this.#client = this.#createClient();
|
|
21989
|
-
await this.#
|
|
21990
|
-
|
|
21991
|
-
if (loaded.sessionId && loaded.sessionId !== this.#ref.nativeSessionId)
|
|
21992
|
-
throw new CodeBuddyError("protocolError", "Cancellation recovery changed Native Session identity");
|
|
21993
|
-
this.#apply(configuration(loaded.configOptions));
|
|
23270
|
+
const loaded = await this.#openClient();
|
|
23271
|
+
this.#apply(configuration(loaded.configOptions, this.profile));
|
|
21994
23272
|
if (saved.effectiveModel)
|
|
21995
23273
|
await this.#configure("model", nativeModel(saved.effectiveModel));
|
|
21996
23274
|
if (saved.effectiveThinkingOptionId)
|
|
@@ -22023,7 +23301,7 @@ var CodeBuddySession = class {
|
|
|
22023
23301
|
#onFault(error51) {
|
|
22024
23302
|
if (this.#fault || this.#closed)
|
|
22025
23303
|
return;
|
|
22026
|
-
this.#fault = nativeError(error51);
|
|
23304
|
+
this.#fault = nativeError(error51, this.profile);
|
|
22027
23305
|
if (this.#active)
|
|
22028
23306
|
this.#finish(this.#active, { status: "failed", error: this.#fault });
|
|
22029
23307
|
this.#interactions.close();
|
|
@@ -22054,30 +23332,43 @@ var CodeBuddySession = class {
|
|
|
22054
23332
|
// dist/codebuddy-adapter.js
|
|
22055
23333
|
var CodeBuddyAdapter = class {
|
|
22056
23334
|
options;
|
|
22057
|
-
harnessId
|
|
23335
|
+
harnessId;
|
|
23336
|
+
commandCatalog;
|
|
22058
23337
|
subagents = {
|
|
22059
23338
|
readSnapshot: async ({ parent, nativeSubagentId, cwd }) => {
|
|
22060
23339
|
try {
|
|
22061
23340
|
if (this.#closed)
|
|
22062
|
-
return failure("invalidState", "Adapter is closed");
|
|
23341
|
+
return failure("invalidState", "Adapter is closed", this.#profile);
|
|
22063
23342
|
const session = [...this.#sessions].find((s) => s.initialState.nativeRef?.nativeSessionId === parent.nativeSessionId);
|
|
22064
|
-
const snapshot = await readCodeBuddyChild(parent, nativeSubagentId, cwd, session?.environment ?? this.#environment, session?.subagents.state(nativeSubagentId)?.status);
|
|
23343
|
+
const snapshot = await readCodeBuddyChild(parent, nativeSubagentId, cwd, session?.environment ?? this.#environment, session?.subagents.state(nativeSubagentId)?.status, this.#profile);
|
|
22065
23344
|
return { ok: true, value: snapshot };
|
|
22066
23345
|
} catch (error51) {
|
|
22067
|
-
return { ok: false, error: nativeError(error51) };
|
|
23346
|
+
return { ok: false, error: nativeError(error51, this.#profile) };
|
|
22068
23347
|
}
|
|
22069
23348
|
}
|
|
22070
23349
|
};
|
|
22071
23350
|
#environment;
|
|
23351
|
+
#profile;
|
|
22072
23352
|
#factory;
|
|
23353
|
+
#invocation;
|
|
22073
23354
|
#sessions = /* @__PURE__ */ new Set();
|
|
22074
23355
|
#inspections = /* @__PURE__ */ new Set();
|
|
22075
23356
|
#cache = /* @__PURE__ */ new Map();
|
|
22076
23357
|
#closed = false;
|
|
23358
|
+
#abort = new AbortController();
|
|
23359
|
+
#derivations = /* @__PURE__ */ new Set();
|
|
22077
23360
|
constructor(options = {}) {
|
|
22078
23361
|
this.options = options;
|
|
23362
|
+
this.#profile = options.profile ?? CODEBUDDY_RUNTIME_PROFILE;
|
|
23363
|
+
this.harnessId = this.#profile.harnessId;
|
|
23364
|
+
if (nativeCommandsEnabled(this.#profile)) {
|
|
23365
|
+
const commandCatalog2 = this.#profile.staticCommandCatalog ?? (this.#profile.harnessId === CODEBUDDY_RUNTIME_PROFILE.harnessId ? CODEBUDDY_COMMAND_CATALOG : void 0);
|
|
23366
|
+
if (commandCatalog2)
|
|
23367
|
+
this.commandCatalog = commandCatalog2;
|
|
23368
|
+
}
|
|
22079
23369
|
this.#environment = { ...options.environment ?? process.env };
|
|
22080
|
-
this.#
|
|
23370
|
+
this.#invocation = options.invocationFactory ?? codeBuddyInvocation;
|
|
23371
|
+
this.#factory = options.clientFactory ?? ((clientOptions) => new CodeBuddyAcpClient(clientOptions, void 0, this.#invocation));
|
|
22081
23372
|
}
|
|
22082
23373
|
inspect(input = {}) {
|
|
22083
23374
|
const cwd = input.cwd ?? process.cwd();
|
|
@@ -22113,15 +23404,15 @@ var CodeBuddyAdapter = class {
|
|
|
22113
23404
|
this.#inspections.add(client2);
|
|
22114
23405
|
await client2.initialize();
|
|
22115
23406
|
const opened = await client2.open(cwd);
|
|
22116
|
-
const config2 = configuration(opened.configOptions);
|
|
23407
|
+
const config2 = configuration(opened.configOptions, this.#profile);
|
|
22117
23408
|
return harnessInspectionSchema.parse({
|
|
22118
23409
|
status: "ready",
|
|
22119
23410
|
catalog: config2.catalog,
|
|
22120
23411
|
permissionModes: config2.permissionModes,
|
|
22121
|
-
capabilities:
|
|
23412
|
+
capabilities: capabilitiesForProfile(this.#profile)
|
|
22122
23413
|
});
|
|
22123
23414
|
} catch (error51) {
|
|
22124
|
-
const issue2 = nativeError(error51);
|
|
23415
|
+
const issue2 = nativeError(error51, this.#profile);
|
|
22125
23416
|
return {
|
|
22126
23417
|
status: issue2.code === "notInstalled" ? "notInstalled" : "unavailable",
|
|
22127
23418
|
error: issue2
|
|
@@ -22136,19 +23427,56 @@ var CodeBuddyAdapter = class {
|
|
|
22136
23427
|
}
|
|
22137
23428
|
async open(input) {
|
|
22138
23429
|
if (this.#closed)
|
|
22139
|
-
return failure("invalidState", "Adapter is closed");
|
|
22140
|
-
if (input.kind === "
|
|
22141
|
-
return failure("
|
|
23430
|
+
return failure("invalidState", "Adapter is closed", this.#profile);
|
|
23431
|
+
if (input.kind === "create" && input.executionPolicy === "unattended-full-access" && input.permissionModeId && input.permissionModeId !== "fullAccess")
|
|
23432
|
+
return failure("invalidRequest", "Unattended execution requires native fullAccess permissions", this.#profile);
|
|
22142
23433
|
let session;
|
|
22143
23434
|
try {
|
|
22144
23435
|
if (!(await stat2(input.cwd)).isDirectory())
|
|
22145
23436
|
throw new CodeBuddyError("invalidRequest", "Working directory is not a directory");
|
|
23437
|
+
if (this.#closed)
|
|
23438
|
+
throw new CodeBuddyError("invalidState", "Adapter closed while opening Session");
|
|
22146
23439
|
if (input.kind === "resume")
|
|
22147
|
-
validateNativeRef(input.nativeRef);
|
|
23440
|
+
validateNativeRef(input.nativeRef, this.#profile);
|
|
23441
|
+
if (input.kind === "fork" || input.kind === "rollbackLastTurn") {
|
|
23442
|
+
const capabilities = capabilitiesForProfile(this.#profile).history;
|
|
23443
|
+
if (input.kind === "fork" && !capabilities.fork || input.kind === "rollbackLastTurn" && !capabilities.rollbackLastTurn)
|
|
23444
|
+
throw new CodeBuddyError("unsupported", `${this.#profile.displayName} does not expose this verified history operation`);
|
|
23445
|
+
const sourceRef = input.sourceRef;
|
|
23446
|
+
validateNativeRef(sourceRef, this.#profile);
|
|
23447
|
+
const source = [...this.#sessions].find((candidate) => candidate.initialState.nativeRef?.nativeSessionId === sourceRef.nativeSessionId);
|
|
23448
|
+
const snapshot = await source?.readSnapshot();
|
|
23449
|
+
if (this.#closed)
|
|
23450
|
+
throw new CodeBuddyError("invalidState", "Adapter closed while reading source Session");
|
|
23451
|
+
if (snapshot && !snapshot.ok)
|
|
23452
|
+
return snapshot;
|
|
23453
|
+
const boundCwd = text(record2(sourceRef.locator).boundCwd);
|
|
23454
|
+
const sourceCwd = (source?.input.cwd ?? boundCwd) || input.cwd;
|
|
23455
|
+
if (input.kind === "fork" && !capabilities.forkAcrossCwd && codeBuddyCanonicalCwd(sourceCwd) !== codeBuddyCanonicalCwd(input.cwd))
|
|
23456
|
+
throw new CodeBuddyError("unsupported", `${this.#profile.displayName} does not support cross-directory Fork`);
|
|
23457
|
+
const derivation = deriveCodeBuddySession({
|
|
23458
|
+
input,
|
|
23459
|
+
sourceCwd,
|
|
23460
|
+
environment: { ...this.#environment, ...input.environment },
|
|
23461
|
+
factory: this.#factory,
|
|
23462
|
+
invocationFactory: this.#invocation,
|
|
23463
|
+
profile: this.#profile,
|
|
23464
|
+
signal: this.#abort.signal,
|
|
23465
|
+
...snapshot?.ok && snapshot.value.state ? { state: snapshot.value.state } : {}
|
|
23466
|
+
});
|
|
23467
|
+
this.#derivations.add(derivation);
|
|
23468
|
+
try {
|
|
23469
|
+
input = await derivation;
|
|
23470
|
+
} finally {
|
|
23471
|
+
this.#derivations.delete(derivation);
|
|
23472
|
+
}
|
|
23473
|
+
}
|
|
23474
|
+
if (this.#closed)
|
|
23475
|
+
throw new CodeBuddyError("invalidState", "Adapter closed while opening Session");
|
|
22148
23476
|
session = new CodeBuddySession(input, { ...this.#environment, ...input.environment }, this.#factory, this.options.readHistory, () => {
|
|
22149
23477
|
if (session)
|
|
22150
23478
|
this.#sessions.delete(session);
|
|
22151
|
-
});
|
|
23479
|
+
}, this.#profile);
|
|
22152
23480
|
this.#sessions.add(session);
|
|
22153
23481
|
await session.initialize();
|
|
22154
23482
|
if (this.#closed)
|
|
@@ -22161,24 +23489,26 @@ var CodeBuddyAdapter = class {
|
|
|
22161
23489
|
this.#sessions.delete(session);
|
|
22162
23490
|
}
|
|
22163
23491
|
const issue2 = record2(error51).code === "ENOENT" ? new CodeBuddyError("invalidRequest", "Working directory does not exist") : error51;
|
|
22164
|
-
return { ok: false, error: nativeError(issue2) };
|
|
23492
|
+
return { ok: false, error: nativeError(issue2, this.#profile) };
|
|
22165
23493
|
}
|
|
22166
23494
|
}
|
|
22167
23495
|
async close() {
|
|
22168
23496
|
this.#closed = true;
|
|
23497
|
+
this.#abort.abort();
|
|
23498
|
+
await Promise.allSettled([...this.#derivations]);
|
|
22169
23499
|
const results = await Promise.allSettled([...this.#sessions, ...this.#inspections].map((resource) => resource.close()));
|
|
22170
23500
|
this.#sessions.clear();
|
|
22171
23501
|
this.#inspections.clear();
|
|
22172
23502
|
this.#cache.clear();
|
|
22173
23503
|
const errors = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
22174
23504
|
if (errors.length)
|
|
22175
|
-
throw new AggregateError(errors,
|
|
23505
|
+
throw new AggregateError(errors, `${this.#profile.displayName} process cleanup failed`);
|
|
22176
23506
|
}
|
|
22177
23507
|
};
|
|
22178
23508
|
|
|
22179
23509
|
// ../../harness-broker/dist/client.js
|
|
22180
|
-
import { randomUUID } from "node:crypto";
|
|
22181
|
-
import { lstat, readFile as
|
|
23510
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
23511
|
+
import { lstat as lstat2, readFile as readFile3 } from "node:fs/promises";
|
|
22182
23512
|
import net, {} from "node:net";
|
|
22183
23513
|
|
|
22184
23514
|
// ../../harness-broker/dist/protocol.js
|
|
@@ -22293,18 +23623,18 @@ function consumeBrokerFrames(socket, onFrame, onError) {
|
|
|
22293
23623
|
|
|
22294
23624
|
// ../../harness-broker/dist/paths.js
|
|
22295
23625
|
import os2 from "node:os";
|
|
22296
|
-
import
|
|
23626
|
+
import path7 from "node:path";
|
|
22297
23627
|
var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
|
|
22298
23628
|
var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
|
|
22299
23629
|
function defaultHarnessBrokerDirectory(environment = process.env) {
|
|
22300
23630
|
const home = environment.HOME || os2.homedir();
|
|
22301
|
-
return
|
|
23631
|
+
return path7.join(home, ".codexhost", "harness-broker");
|
|
22302
23632
|
}
|
|
22303
23633
|
function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
|
|
22304
23634
|
harnessPluginIdSchema.parse(harnessId);
|
|
22305
23635
|
if (harnessId !== "claude-code")
|
|
22306
|
-
return
|
|
22307
|
-
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ??
|
|
23636
|
+
return path7.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
|
|
23637
|
+
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path7.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
|
|
22308
23638
|
}
|
|
22309
23639
|
|
|
22310
23640
|
// ../../harness-broker/dist/validation.js
|
|
@@ -22581,7 +23911,7 @@ function parseSessionMetadata(value) {
|
|
|
22581
23911
|
};
|
|
22582
23912
|
}
|
|
22583
23913
|
async function readDescriptor(descriptorPath) {
|
|
22584
|
-
const metadata = await
|
|
23914
|
+
const metadata = await lstat2(descriptorPath);
|
|
22585
23915
|
if (metadata.isSymbolicLink())
|
|
22586
23916
|
throw new Error("Aqua Harness broker descriptor must not be a symlink");
|
|
22587
23917
|
if (!metadata.isFile())
|
|
@@ -22593,12 +23923,12 @@ async function readDescriptor(descriptorPath) {
|
|
|
22593
23923
|
throw new Error("Aqua Harness broker descriptor belongs to another user");
|
|
22594
23924
|
}
|
|
22595
23925
|
}
|
|
22596
|
-
const descriptor = harnessBrokerDescriptorSchema.parse(JSON.parse(await
|
|
23926
|
+
const descriptor = harnessBrokerDescriptorSchema.parse(JSON.parse(await readFile3(descriptorPath, "utf8")));
|
|
22597
23927
|
if (process.platform === "darwin" && Buffer.byteLength(descriptor.socketPath) > 103) {
|
|
22598
23928
|
throw new Error("Aqua Harness broker socket path is too long for macOS");
|
|
22599
23929
|
}
|
|
22600
23930
|
if (process.platform !== "win32") {
|
|
22601
|
-
const socket = await
|
|
23931
|
+
const socket = await lstat2(descriptor.socketPath);
|
|
22602
23932
|
if (socket.isSymbolicLink() || !socket.isSocket()) {
|
|
22603
23933
|
throw new Error("Aqua Harness broker endpoint is not a Unix socket");
|
|
22604
23934
|
}
|
|
@@ -22695,7 +24025,7 @@ var BrokerConnection = class _BrokerConnection {
|
|
|
22695
24025
|
throw new Error("Aqua Harness broker request limit exceeded");
|
|
22696
24026
|
}
|
|
22697
24027
|
this.#inputSequence += 1;
|
|
22698
|
-
const id =
|
|
24028
|
+
const id = randomUUID2();
|
|
22699
24029
|
const response = new Promise((resolve, reject) => {
|
|
22700
24030
|
const timeout = setTimeout(() => {
|
|
22701
24031
|
this.#pending.delete(id);
|
|
@@ -23091,6 +24421,7 @@ function createHarnessAdapter(context) {
|
|
|
23091
24421
|
return new BrokeredHarnessAdapter({
|
|
23092
24422
|
harnessId: "codebuddy",
|
|
23093
24423
|
forwardDelegationEnvironment: true,
|
|
24424
|
+
commandCatalog: CODEBUDDY_COMMAND_CATALOG,
|
|
23094
24425
|
environment: { ...context.environment }
|
|
23095
24426
|
});
|
|
23096
24427
|
return new CodeBuddyAdapter({ environment: { ...context.environment } });
|