@codexhost/cli-linux-arm64 0.9.1-test.2 → 0.9.1

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