@liberseek/boft-cli-win32-arm64 0.7.0 → 0.7.1

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