@cabane/companion 0.6.141 → 0.6.143

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.
Files changed (3) hide show
  1. package/dist/cli.js +276 -165
  2. package/dist/runtime.js +230 -126
  3. package/package.json +1 -1
package/dist/runtime.js CHANGED
@@ -17,14 +17,14 @@ import { z as z2 } from "zod";
17
17
 
18
18
  // src/errors.ts
19
19
  var CompanionError = class extends Error {
20
- constructor(message) {
21
- super(message);
20
+ constructor(message2) {
21
+ super(message2);
22
22
  this.name = "CompanionError";
23
23
  }
24
24
  };
25
25
  var ApiError = class extends CompanionError {
26
- constructor(status, message, body) {
27
- super(message);
26
+ constructor(status, message2, body) {
27
+ super(message2);
28
28
  this.status = status;
29
29
  this.body = body;
30
30
  this.name = "ApiError";
@@ -33,14 +33,14 @@ var ApiError = class extends CompanionError {
33
33
  body;
34
34
  };
35
35
  var ConfigError = class extends CompanionError {
36
- constructor(message) {
37
- super(message);
36
+ constructor(message2) {
37
+ super(message2);
38
38
  this.name = "ConfigError";
39
39
  }
40
40
  };
41
41
  var PrepareHookError = class extends CompanionError {
42
- constructor(message) {
43
- super(message);
42
+ constructor(message2) {
43
+ super(message2);
44
44
  this.name = "PrepareHookError";
45
45
  }
46
46
  };
@@ -1202,8 +1202,8 @@ function formatHumanLine(record) {
1202
1202
  let line = `${time} ${word ? `${word} ` : ""}${context ? `${context} ` : ""}${humanText(record.msg)}`;
1203
1203
  const err = record.err;
1204
1204
  const errorRecord = err !== null && typeof err === "object" ? err : null;
1205
- const message = humanText(errorRecord && "message" in errorRecord ? errorRecord.message : err);
1206
- const detail = typeof record.status === "number" ? `HTTP ${record.status}: ${humanText(record.responseBody) || message}` : message;
1205
+ const message2 = humanText(errorRecord && "message" in errorRecord ? errorRecord.message : err);
1206
+ const detail = typeof record.status === "number" ? `HTTP ${record.status}: ${humanText(record.responseBody) || message2}` : message2;
1207
1207
  if (detail && !line.includes(detail)) line += ` (${detail})`;
1208
1208
  if (level < 30) {
1209
1209
  const hidden = /* @__PURE__ */ new Set([
@@ -1337,9 +1337,9 @@ var CompanionStateHub = class {
1337
1337
  if (info.deviceLabel !== void 0) this.deviceLabel = info.deviceLabel;
1338
1338
  this.emitStatus();
1339
1339
  }
1340
- setDeviceError(message) {
1341
- if (this.deviceError === message) return;
1342
- this.deviceError = message;
1340
+ setDeviceError(message2) {
1341
+ if (this.deviceError === message2) return;
1342
+ this.deviceError = message2;
1343
1343
  this.emitStatus();
1344
1344
  }
1345
1345
  clearDeviceError() {
@@ -1960,7 +1960,7 @@ async function warnAboutHarnessReadiness(cfg, deps = {}) {
1960
1960
  const probeClaude = deps.probeClaude ?? claudeOnPath;
1961
1961
  const probeCodex = deps.probeCodex ?? codexOnPath;
1962
1962
  const resolveBundled = deps.resolveBundled ?? ((runtime) => resolveBundledBinary(runtime));
1963
- const warn = deps.warn ?? ((message) => process.stderr.write(`${message}
1963
+ const warn = deps.warn ?? ((message2) => process.stderr.write(`${message2}
1964
1964
  `));
1965
1965
  const connected = [
1966
1966
  ...isClaudeCodeConnected(cfg) ? ["Claude Code"] : [],
@@ -2305,8 +2305,8 @@ function apiErrorCode(err) {
2305
2305
  function apiErrorMessage(err) {
2306
2306
  const body = err instanceof ApiError ? err.body : void 0;
2307
2307
  if (body !== null && typeof body === "object") {
2308
- const message = body.message;
2309
- if (typeof message === "string" && message.length > 0) return message;
2308
+ const message2 = body.message;
2309
+ if (typeof message2 === "string" && message2.length > 0) return message2;
2310
2310
  }
2311
2311
  return err instanceof Error ? err.message : String(err);
2312
2312
  }
@@ -2341,9 +2341,9 @@ function describeErrorBody(body) {
2341
2341
  }
2342
2342
  var CAUSE_TEXT_CAP = 200;
2343
2343
  function describeError(err) {
2344
- const message = err instanceof Error ? err.message : String(err);
2344
+ const message2 = err instanceof Error ? err.message : String(err);
2345
2345
  const cause = describeCause(err);
2346
- return cause === void 0 ? message : `${message}: ${cause}`;
2346
+ return cause === void 0 ? message2 : `${message2}: ${cause}`;
2347
2347
  }
2348
2348
  function describeCause(err) {
2349
2349
  if (!(err instanceof Error)) return void 0;
@@ -3990,8 +3990,7 @@ function turnControlPromptGuidance(prefix) {
3990
3990
  var CLAUDE_CODE_ADDENDUM = [
3991
3991
  "On this harness the Cabane tools register under MCP prefixes. The workspace tools are",
3992
3992
  "`mcp__cabane__query`, `mcp__cabane__mutate` and `mcp__cabane__describe`; the ancillary",
3993
- "tools are `mcp__cabane__list_workspaces`,",
3994
- "`mcp__cabane__read_binary`, `mcp__cabane__upload`, `mcp__cabane__begin_upload`,",
3993
+ "tools are `mcp__cabane__read_binary`, `mcp__cabane__upload`, `mcp__cabane__begin_upload`,",
3995
3994
  "`mcp__cabane__finalize_upload`, and `mcp__cabane__mint_render_token`.",
3996
3995
  turnControlPromptGuidance("mcp__cabane_companion__"),
3997
3996
  "Where this prompt names a tool by its bare verb, call",
@@ -4379,15 +4378,15 @@ async function* decodeSdkStream(iter, ctx) {
4379
4378
  }
4380
4379
  } catch (err) {
4381
4380
  if (ctx.signal.aborted) throw err;
4382
- const message = err instanceof Error ? err.message : String(err);
4383
- const failure = mcpInventory.initReceived ? classifyErrorText(message) : classifyFailure(signals, { text: message });
4381
+ const message2 = err instanceof Error ? err.message : String(err);
4382
+ const failure = mcpInventory.initReceived ? classifyErrorText(message2) : classifyFailure(signals, { text: message2 });
4384
4383
  if (!failure && (mcpInventory.initReceived || ctx.resumedSessionId === null)) throw err;
4385
4384
  ok = false;
4386
4385
  if (failure) {
4387
4386
  resultReason = encodeFailureReason(failure);
4388
4387
  } else {
4389
4388
  resultReason = "session_start_failed";
4390
- if (ctx.startEvidence) ctx.startEvidence.thrown = message.slice(0, 200);
4389
+ if (ctx.startEvidence) ctx.startEvidence.thrown = message2.slice(0, 200);
4391
4390
  }
4392
4391
  sawResult = true;
4393
4392
  }
@@ -5228,7 +5227,7 @@ var OPENCODE_ADDENDUM = [
5228
5227
  "Every tool here goes by its plain name: the workspace tools are `query`, `mutate` and",
5229
5228
  "`describe`.",
5230
5229
  turnControlPromptGuidance(""),
5231
- "The ancillary tools are `list_workspaces`, `read_binary`, `upload`, `begin_upload`,",
5230
+ "The ancillary tools are `read_binary`, `upload`, `begin_upload`,",
5232
5231
  "`finalize_upload`, `mint_render_token`; and the host tools are plain verbs too (`bash`,",
5233
5232
  "`read`, `edit`). Mind the collision: a bare `read` or `edit` is the HOST tool, acting on the",
5234
5233
  "local machine \u2014 a workspace read is `query` with the operation name `files.read`. The",
@@ -5316,9 +5315,9 @@ function readSessionError(properties) {
5316
5315
  if (typeof err === "string") return err;
5317
5316
  const rec = asRecord(err);
5318
5317
  if (!rec) return "unknown";
5319
- const { name, message } = deepestError(rec);
5320
- if (message && name && !isGenericErrorName(name)) return `${name}: ${message}`;
5321
- if (message) return message;
5318
+ const { name, message: message2 } = deepestError(rec);
5319
+ if (message2 && name && !isGenericErrorName(name)) return `${name}: ${message2}`;
5320
+ if (message2) return message2;
5322
5321
  if (name) return name;
5323
5322
  if (typeof rec.name === "string") return rec.name;
5324
5323
  return "unknown";
@@ -5331,10 +5330,10 @@ function deepestError(node) {
5331
5330
  const best = {};
5332
5331
  let current = node;
5333
5332
  for (let depth = 0; current && depth < 8; depth++) {
5334
- const message = typeof current.message === "string" ? current.message : void 0;
5333
+ const message2 = typeof current.message === "string" ? current.message : void 0;
5335
5334
  const name = typeof current.name === "string" && !isGenericErrorName(current.name) ? current.name : void 0;
5336
- if (message) {
5337
- best.message = message;
5335
+ if (message2) {
5336
+ best.message = message2;
5338
5337
  if (name) best.name = name;
5339
5338
  } else if (name && !best.name) {
5340
5339
  best.name = name;
@@ -5925,9 +5924,9 @@ var echoedUserPart = (partId, messageID, text) => ({
5925
5924
  properties: { part: { type: "text", id: partId, messageID, text } }
5926
5925
  });
5927
5926
  var idle = () => ({ type: "session.idle", properties: {} });
5928
- var errored = (message) => ({
5927
+ var errored = (message2) => ({
5929
5928
  type: "session.error",
5930
- properties: { error: { message } }
5929
+ properties: { error: { message: message2 } }
5931
5930
  });
5932
5931
  var sessionEvent2 = (sessionId, directory = DIR, degraded = false) => ({
5933
5932
  type: "session",
@@ -6333,8 +6332,8 @@ var CODEX_ADDENDUM = [
6333
6332
  // in sat two lines under the instruction to invoke the exact qualified names,
6334
6333
  // so the sentence contradicted itself. The bare `query` / `mutate` below stay:
6335
6334
  // that sentence is about operation names, after the qualified forms are given.
6336
- "The ancillary tools are `mcp__cabane__list_workspaces`, `mcp__cabane__read_binary`,",
6337
- "`mcp__cabane__upload`, `mcp__cabane__begin_upload`, `mcp__cabane__finalize_upload` and",
6335
+ "The ancillary tools are `mcp__cabane__read_binary`, `mcp__cabane__upload`,",
6336
+ "`mcp__cabane__begin_upload`, `mcp__cabane__finalize_upload` and",
6338
6337
  "`mcp__cabane__mint_render_token` \u2014 all possibly deferred too.",
6339
6338
  "There is no Cabane `read`/`write`/`search` tool \u2014 those are",
6340
6339
  "operation NAMES you pass to `query` / `mutate`. One more harness fact: you can interleave",
@@ -6362,8 +6361,8 @@ function readItemText(item) {
6362
6361
  function readItemMessage(item) {
6363
6362
  return str(item.message) ?? "";
6364
6363
  }
6365
- function isModelMetadataError(message) {
6366
- return message.includes("Defaulting to fallback metadata");
6364
+ function isModelMetadataError(message2) {
6365
+ return message2.includes("Defaulting to fallback metadata");
6367
6366
  }
6368
6367
  function readToolItem(item, eventType) {
6369
6368
  const type = str(item.type);
@@ -6598,11 +6597,11 @@ async function* decodeCodexStream(events, ctx) {
6598
6597
  if (!item) continue;
6599
6598
  const itemType = readItemType(item);
6600
6599
  if (itemType === "error") {
6601
- const message = readItemMessage(item);
6602
- if (isModelMetadataError(message)) {
6600
+ const message2 = readItemMessage(item);
6601
+ if (isModelMetadataError(message2)) {
6603
6602
  yield* flushInterim();
6604
6603
  ok = false;
6605
- reason = `model_unavailable:${message.slice(0, 200)}`;
6604
+ reason = `model_unavailable:${message2.slice(0, 200)}`;
6606
6605
  settled = true;
6607
6606
  break;
6608
6607
  }
@@ -6759,7 +6758,7 @@ var ENV_ENVELOPE_KEYS = [
6759
6758
  "CABANE_CONVERSATION_TITLE",
6760
6759
  "CABANE_HOST_ACCESS"
6761
6760
  ];
6762
- function buildRunSpec2(req, resumeThreadId, instructionsFile = null, threadPromptFingerprint = null) {
6761
+ function buildRunSpec2(req, resumeThreadId, instructionsFile = null, threadPromptFingerprint = null, imagePaths = []) {
6763
6762
  const { policy, config } = req;
6764
6763
  const directory = req.local.cwd ?? "";
6765
6764
  const dialect = readCodexDialect(config.runtimeOptions);
@@ -6776,7 +6775,7 @@ function buildRunSpec2(req, resumeThreadId, instructionsFile = null, threadPromp
6776
6775
  skipGitRepoCheck: true,
6777
6776
  ...dialect.modelReasoningEffort ? { modelReasoningEffort: dialect.modelReasoningEffort } : {},
6778
6777
  baseInstructionsFile,
6779
- input: buildInput(req, promptRidesInput),
6778
+ input: withImages(buildInput(req, promptRidesInput), imagePaths),
6780
6779
  promptRidesInput,
6781
6780
  promptFingerprint,
6782
6781
  config: buildConfig(req, baseInstructionsFile),
@@ -6792,6 +6791,13 @@ function buildInput(req, promptRidesInput) {
6792
6791
 
6793
6792
  ${body}` : body;
6794
6793
  }
6794
+ function withImages(text, imagePaths) {
6795
+ if (imagePaths.length === 0) return text;
6796
+ return [
6797
+ { type: "text", text },
6798
+ ...imagePaths.map((path) => ({ type: "local_image", path }))
6799
+ ];
6800
+ }
6795
6801
  function buildConfig(req, baseInstructionsFile) {
6796
6802
  const mcp_servers = {};
6797
6803
  for (const [name, server] of Object.entries(req.local.mcpServers ?? {})) {
@@ -7033,12 +7039,35 @@ function createCodexAdapter(deps = {}) {
7033
7039
  }
7034
7040
  }
7035
7041
  }
7042
+ let images = null;
7036
7043
  try {
7044
+ const imageUrls = req.content.flatMap((b) => b.type === "image" ? [b.source.url] : []);
7045
+ if (imageUrls.length > 0) {
7046
+ if (!deps.prepareImages) {
7047
+ deps.onWarn?.(
7048
+ "codex adapter: no image preparer wired on this host \u2014 the turn runs without its images (CT1757)",
7049
+ { images: imageUrls.length }
7050
+ );
7051
+ } else {
7052
+ try {
7053
+ images = await deps.prepareImages(imageUrls, signal);
7054
+ } catch (err) {
7055
+ if (!signal.aborted) {
7056
+ deps.onWarn?.(
7057
+ "codex adapter: preparing the images failed \u2014 the turn runs without them (CT1757)",
7058
+ { err: err instanceof Error ? err.message : String(err) }
7059
+ );
7060
+ }
7061
+ }
7062
+ }
7063
+ if (signal.aborted) return;
7064
+ }
7037
7065
  const spec = buildRunSpec2(
7038
7066
  req,
7039
7067
  resumeThreadId,
7040
7068
  instructions?.path ?? null,
7041
- threadPromptFingerprint
7069
+ threadPromptFingerprint,
7070
+ images?.paths ?? []
7042
7071
  );
7043
7072
  if (spec.model === null) {
7044
7073
  deps.onWarn?.("Codex is using its default model because no model was resolved", {
@@ -7067,6 +7096,15 @@ function createCodexAdapter(deps = {}) {
7067
7096
  resolvedReasoningEffort: spec.modelReasoningEffort ?? null
7068
7097
  });
7069
7098
  } finally {
7099
+ if (images) {
7100
+ try {
7101
+ await images.cleanup();
7102
+ } catch (err) {
7103
+ deps.onWarn?.("codex adapter: image cleanup failed (CT1757)", {
7104
+ err: err instanceof Error ? err.message : String(err)
7105
+ });
7106
+ }
7107
+ }
7070
7108
  if (instructions) {
7071
7109
  try {
7072
7110
  await instructions.cleanup();
@@ -7133,14 +7171,14 @@ var turnCompleted = (usage) => ({
7133
7171
  type: "turn.completed",
7134
7172
  ...usage ? { usage } : {}
7135
7173
  });
7136
- var turnFailed = (message) => ({
7174
+ var turnFailed = (message2) => ({
7137
7175
  type: "turn.failed",
7138
- error: { message }
7176
+ error: { message: message2 }
7139
7177
  });
7140
- var fatalError = (message) => ({ type: "error", message });
7141
- var errorItem = (id, message) => ({
7178
+ var fatalError = (message2) => ({ type: "error", message: message2 });
7179
+ var errorItem = (id, message2) => ({
7142
7180
  type: "item.completed",
7143
- item: { id, type: "error", message }
7181
+ item: { id, type: "error", message: message2 }
7144
7182
  });
7145
7183
  var OP_SUCCESS = { ok: true, result: { source: "native" } };
7146
7184
  var OP_FAILURE = {
@@ -8059,7 +8097,7 @@ var ConnectorHealthStore = class {
8059
8097
  // src/dispatcher.ts
8060
8098
  import { randomUUID as randomUUID4 } from "crypto";
8061
8099
  import { existsSync as existsSync10, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
8062
- import { join as join14 } from "path";
8100
+ import { join as join15 } from "path";
8063
8101
 
8064
8102
  // src/runner/launch.ts
8065
8103
  import { createInterface } from "readline";
@@ -8125,8 +8163,8 @@ function unenforceable(policy) {
8125
8163
  deniedDomains: as === "deniedDomains" ? [host] : []
8126
8164
  });
8127
8165
  if (!check.success) {
8128
- const message = check.error.issues[0]?.message ?? "not a host pattern the sandbox accepts";
8129
- return `runners.policy.${field}.${i}: ${message}`;
8166
+ const message2 = check.error.issues[0]?.message ?? "not a host pattern the sandbox accepts";
8167
+ return `runners.policy.${field}.${i}: ${message2}`;
8130
8168
  }
8131
8169
  }
8132
8170
  }
@@ -8140,8 +8178,8 @@ function unenforceable(policy) {
8140
8178
  try {
8141
8179
  new RegExp(globToRegex(path));
8142
8180
  } catch (err) {
8143
- const message = err instanceof Error ? err.message : String(err);
8144
- return `runners.policy.${field}.${i}: not a pattern the sandbox can match (${message})`;
8181
+ const message2 = err instanceof Error ? err.message : String(err);
8182
+ return `runners.policy.${field}.${i}: not a pattern the sandbox can match (${message2})`;
8145
8183
  }
8146
8184
  }
8147
8185
  }
@@ -8260,8 +8298,8 @@ async function reapTurnScopes(turnId) {
8260
8298
  });
8261
8299
  return { failures: [] };
8262
8300
  } catch (err) {
8263
- const message = err instanceof Error ? err.message : String(err);
8264
- return classifyStopError(message) === "absent" ? { failures: [] } : { failures: [message.slice(0, 200)] };
8301
+ const message2 = err instanceof Error ? err.message : String(err);
8302
+ return classifyStopError(message2) === "absent" ? { failures: [] } : { failures: [message2.slice(0, 200)] };
8265
8303
  }
8266
8304
  }
8267
8305
  function scopeCapabilityUsable(env, timeoutMs = CAPABILITY_PROBE_TIMEOUT_MS) {
@@ -8277,13 +8315,13 @@ function scopeCapabilityUsable(env, timeoutMs = CAPABILITY_PROBE_TIMEOUT_MS) {
8277
8315
  return false;
8278
8316
  }
8279
8317
  }
8280
- function classifyStopError(message) {
8318
+ function classifyStopError(message2) {
8281
8319
  if (/failed to connect to bus|failed to get d-?bus connection|connection refused|refusing to operate|spawn systemctl|systemctl.*ENOENT|ENOENT.*systemctl/i.test(
8282
- message
8320
+ message2
8283
8321
  )) {
8284
8322
  return "failure";
8285
8323
  }
8286
- if (/not loaded|could not be found|no such unit|unit .* not found/i.test(message))
8324
+ if (/not loaded|could not be found|no such unit|unit .* not found/i.test(message2))
8287
8325
  return "absent";
8288
8326
  return "failure";
8289
8327
  }
@@ -8395,9 +8433,9 @@ function createTurnContainment(turnId, deps = {}) {
8395
8433
  timeout: (CONTAINMENT_STOP_GRACE_SEC + 10) * 1e3
8396
8434
  });
8397
8435
  } catch (err) {
8398
- const message = err instanceof Error ? err.message : String(err);
8399
- if (classifyStopError(message) === "failure") {
8400
- result.failures.push({ target: unit, error: message.slice(0, 200) });
8436
+ const message2 = err instanceof Error ? err.message : String(err);
8437
+ if (classifyStopError(message2) === "failure") {
8438
+ result.failures.push({ target: unit, error: message2.slice(0, 200) });
8401
8439
  continue;
8402
8440
  }
8403
8441
  result.reaped.push(unit);
@@ -8802,8 +8840,8 @@ function runnerStdin(input) {
8802
8840
  })}
8803
8841
  `;
8804
8842
  }
8805
- function encodeLauncherMessage(message) {
8806
- return `${JSON.stringify(message)}
8843
+ function encodeLauncherMessage(message2) {
8844
+ return `${JSON.stringify(message2)}
8807
8845
  `;
8808
8846
  }
8809
8847
  function decodeRunnerEvent(line) {
@@ -9535,6 +9573,68 @@ async function writeCodexInstructionsFile(contents) {
9535
9573
  };
9536
9574
  }
9537
9575
 
9576
+ // src/codex-images.ts
9577
+ import { mkdtemp as mkdtemp2, rm as rm2, writeFile as writeFile2 } from "fs/promises";
9578
+ import { tmpdir as tmpdir2 } from "os";
9579
+ import { join as join12 } from "path";
9580
+ var FETCH_TIMEOUT_MS = 3e4;
9581
+ var EXTENSIONS = {
9582
+ "image/png": "png",
9583
+ "image/jpeg": "jpg",
9584
+ "image/gif": "gif",
9585
+ "image/webp": "webp"
9586
+ };
9587
+ function createCodexImagePreparer(opts) {
9588
+ const doFetch = opts.fetch ?? fetch;
9589
+ const timeoutMs = opts.timeoutMs ?? FETCH_TIMEOUT_MS;
9590
+ return async (urls, signal) => {
9591
+ signal.throwIfAborted();
9592
+ const dir2 = await mkdtemp2(join12(tmpdir2(), `cabane-codex-images-${opts.turnId}-`));
9593
+ const cleanup = async () => {
9594
+ try {
9595
+ await rm2(dir2, { recursive: true, force: true });
9596
+ } catch (err) {
9597
+ opts.warn(
9598
+ { dir: dir2, err: message(err) },
9599
+ "codex images: could not remove the scratch directory"
9600
+ );
9601
+ }
9602
+ };
9603
+ const prepareOne = async (url, index) => {
9604
+ try {
9605
+ const res = await doFetch(url, {
9606
+ signal: AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)])
9607
+ });
9608
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
9609
+ const type = (res.headers.get("content-type") ?? "").split(";")[0].trim().toLowerCase();
9610
+ const ext = EXTENSIONS[type];
9611
+ if (!ext) throw new Error(`not a vision image type: ${type || "none"}`);
9612
+ const bytes = new Uint8Array(await res.arrayBuffer());
9613
+ const path = join12(dir2, `image-${index + 1}.${ext}`);
9614
+ await writeFile2(path, bytes, { mode: 384 });
9615
+ return path;
9616
+ } catch (err) {
9617
+ if (!signal.aborted) {
9618
+ opts.warn(
9619
+ { image: index + 1, of: urls.length, err: message(err) },
9620
+ "codex images: an image could not be prepared; the turn runs without it"
9621
+ );
9622
+ }
9623
+ return null;
9624
+ }
9625
+ };
9626
+ const paths = await Promise.all(urls.map(prepareOne));
9627
+ if (signal.aborted) {
9628
+ await cleanup();
9629
+ signal.throwIfAborted();
9630
+ }
9631
+ return { paths: paths.filter((p) => p !== null), cleanup };
9632
+ };
9633
+ }
9634
+ function message(err) {
9635
+ return err instanceof Error ? err.message : String(err);
9636
+ }
9637
+
9538
9638
  // src/turn-seq-floor.ts
9539
9639
  var SeqFloorUnavailable = class extends Error {
9540
9640
  constructor(detail) {
@@ -9572,15 +9672,15 @@ function readOutboxFloor(read, turnId, log) {
9572
9672
  import { spawn as spawn5 } from "child_process";
9573
9673
  import { hostname } from "os";
9574
9674
  function prepareFailureCause(error) {
9575
- const message = error instanceof Error ? error.message : String(error);
9576
- if (/timed out/i.test(message)) return "prepare hook timed out";
9577
- if (/MODULE_NOT_FOUND|Cannot find (?:module|package)/.test(message))
9675
+ const message2 = error instanceof Error ? error.message : String(error);
9676
+ if (/timed out/i.test(message2)) return "prepare hook timed out";
9677
+ if (/MODULE_NOT_FOUND|Cannot find (?:module|package)/.test(message2))
9578
9678
  return "prepare hook module missing; check the configured command and its installation for this device";
9579
- if (/not valid JSON|JSON must carry|produced no output/.test(message))
9679
+ if (/not valid JSON|JSON must carry|produced no output/.test(message2))
9580
9680
  return "prepare hook returned malformed output; expected a cwd path or JSON with a non-empty cwd";
9581
- if (/ENOENT/.test(message)) return "prepare hook executable missing (ENOENT)";
9582
- if (/EACCES/.test(message)) return "prepare hook executable is not accessible (EACCES)";
9583
- const exit = message.match(/exited with code (\d+)/)?.[1];
9681
+ if (/ENOENT/.test(message2)) return "prepare hook executable missing (ENOENT)";
9682
+ if (/EACCES/.test(message2)) return "prepare hook executable is not accessible (EACCES)";
9683
+ const exit = message2.match(/exited with code (\d+)/)?.[1];
9584
9684
  return exit ? `prepare hook exited with code ${exit}` : "prepare hook failed; inspect the device-local hook log";
9585
9685
  }
9586
9686
  async function runPrepareWithReporting(runner, hook, input, context, reportError) {
@@ -9632,15 +9732,15 @@ function reportFailure(config, body) {
9632
9732
 
9633
9733
  // src/prepared.ts
9634
9734
  import { mkdirSync as mkdirSync7, readFileSync as readFileSync7, rmSync as rmSync5, writeFileSync as writeFileSync5, existsSync as existsSync8 } from "fs";
9635
- import { join as join12 } from "path";
9735
+ import { join as join13 } from "path";
9636
9736
  function dirFor(workspaceId) {
9637
- return join12(cabaneDir(), "prepared", encodeURIComponent(workspaceId));
9737
+ return join13(cabaneDir(), "prepared", encodeURIComponent(workspaceId));
9638
9738
  }
9639
9739
  function conversationDir(workspaceId, conversationId) {
9640
- return join12(dirFor(workspaceId), encodeURIComponent(conversationId));
9740
+ return join13(dirFor(workspaceId), encodeURIComponent(conversationId));
9641
9741
  }
9642
9742
  function pathFor2(workspaceId, conversationId, agentId) {
9643
- return join12(conversationDir(workspaceId, conversationId), `${encodeURIComponent(agentId)}.json`);
9743
+ return join13(conversationDir(workspaceId, conversationId), `${encodeURIComponent(agentId)}.json`);
9644
9744
  }
9645
9745
  function readPrepared(workspaceId, conversationId, agentId) {
9646
9746
  const path = pathFor2(workspaceId, conversationId, agentId);
@@ -9672,9 +9772,9 @@ function clearPrepared(workspaceId, conversationId, agentId) {
9672
9772
 
9673
9773
  // src/transcript-writer.ts
9674
9774
  import { appendFileSync, chmodSync as chmodSync4, copyFileSync, mkdirSync as mkdirSync8, readdirSync, rmSync as rmSync6 } from "fs";
9675
- import { basename, dirname as dirname6, join as join13 } from "path";
9775
+ import { basename, dirname as dirname6, join as join14 } from "path";
9676
9776
  function transcriptsDir() {
9677
- return join13(runnerStateDir(), "transcripts");
9777
+ return join14(runnerStateDir(), "transcripts");
9678
9778
  }
9679
9779
  var RETAIN = 200;
9680
9780
  var ANOMALY_RETAIN = 50;
@@ -9684,7 +9784,7 @@ var TranscriptWriter = class {
9684
9784
  onWarn;
9685
9785
  constructor(dir2, meta, onWarn) {
9686
9786
  this.onWarn = onWarn;
9687
- this.path = join13(dir2, fileName(meta));
9787
+ this.path = join14(dir2, fileName(meta));
9688
9788
  try {
9689
9789
  mkdirSync8(dir2, { recursive: true });
9690
9790
  try {
@@ -9713,10 +9813,10 @@ var TranscriptWriter = class {
9713
9813
  preserveAnomaly() {
9714
9814
  if (this.broken) return;
9715
9815
  try {
9716
- const dir2 = join13(dirname6(this.path), "anomalies");
9816
+ const dir2 = join14(dirname6(this.path), "anomalies");
9717
9817
  mkdirSync8(dir2, { recursive: true, mode: 448 });
9718
9818
  chmodSync4(dir2, 448);
9719
- const target = join13(dir2, basename(this.path));
9819
+ const target = join14(dir2, basename(this.path));
9720
9820
  copyFileSync(this.path, target);
9721
9821
  chmodSync4(target, 384);
9722
9822
  pruneOld(dir2, ANOMALY_RETAIN);
@@ -9762,7 +9862,7 @@ function pruneOld(dir2, retain) {
9762
9862
  const drop = files.sort().slice(0, files.length - retain);
9763
9863
  for (const f of drop) {
9764
9864
  try {
9765
- rmSync6(join13(dir2, f), { force: true });
9865
+ rmSync6(join14(dir2, f), { force: true });
9766
9866
  } catch {
9767
9867
  }
9768
9868
  }
@@ -10333,16 +10433,16 @@ var TurnExecution = class {
10333
10433
  }
10334
10434
  gateTrigger() {
10335
10435
  const { payload, turnLog } = this;
10336
- const message = this.turnContext.message;
10337
- const isDispatchableTrigger = message.role === "user" || message.role === "agent" || message.role === "system";
10436
+ const message2 = this.turnContext.message;
10437
+ const isDispatchableTrigger = message2.role === "user" || message2.role === "agent" || message2.role === "system";
10338
10438
  if (!isDispatchableTrigger) {
10339
- turnLog.debug({ role: message.role }, "dispatcher: trigger role not dispatchable \u2014 skipping");
10439
+ turnLog.debug({ role: message2.role }, "dispatcher: trigger role not dispatchable \u2014 skipping");
10340
10440
  throw this.concluded("unexpected_role", UNEXPECTED_ROLE_REASON);
10341
10441
  }
10342
10442
  this.supervisor.notifyStart({
10343
10443
  id: this.dispatchId,
10344
10444
  conversationId: payload.conversationId,
10345
- message: message.body
10445
+ message: message2.body
10346
10446
  });
10347
10447
  }
10348
10448
  async resolveSecrets() {
@@ -10693,6 +10793,10 @@ var TurnExecution = class {
10693
10793
  enabled: true,
10694
10794
  onWarn,
10695
10795
  writeInstructionsFile: writeCodexInstructionsFile,
10796
+ prepareImages: createCodexImagePreparer({
10797
+ turnId: this.turnId,
10798
+ warn: (meta, msg) => turnLog.warn(meta, msg)
10799
+ }),
10696
10800
  ...codexPath ? { transport: createSdkCodexTransport({ codexPathOverride: codexPath }) } : {}
10697
10801
  })
10698
10802
  );
@@ -11172,7 +11276,7 @@ function checkoutState(cwd) {
11172
11276
  if (entries.length === 0) {
11173
11277
  return { ok: false, reason: `${cwd} is empty \u2014 a recreated shell, not a prepared directory` };
11174
11278
  }
11175
- const gitPath = join14(cwd, ".git");
11279
+ const gitPath = join15(cwd, ".git");
11176
11280
  if (!existsSync10(gitPath)) return { ok: true, reason: "usable" };
11177
11281
  let stat;
11178
11282
  try {
@@ -11180,7 +11284,7 @@ function checkoutState(cwd) {
11180
11284
  } catch (error) {
11181
11285
  return { ok: false, reason: `${gitPath} is unreadable (${error.message})` };
11182
11286
  }
11183
- if (stat.isDirectory() && !existsSync10(join14(gitPath, "HEAD")))
11287
+ if (stat.isDirectory() && !existsSync10(join15(gitPath, "HEAD")))
11184
11288
  return { ok: false, reason: `${gitPath} has no HEAD \u2014 an empty shell, not a checkout` };
11185
11289
  return { ok: true, reason: "usable" };
11186
11290
  }
@@ -11373,7 +11477,7 @@ function createLocalProcessProvider(opts = {}) {
11373
11477
 
11374
11478
  // src/providers/docker.ts
11375
11479
  import { createHash as createHash4, randomUUID as randomUUID5 } from "crypto";
11376
- import { constants as constants2, tmpdir as tmpdir2 } from "os";
11480
+ import { constants as constants2, tmpdir as tmpdir3 } from "os";
11377
11481
  import {
11378
11482
  createReadStream,
11379
11483
  createWriteStream as createWriteStream2,
@@ -11386,7 +11490,7 @@ import {
11386
11490
  statSync as statSync3,
11387
11491
  writeFileSync as writeFileSync6
11388
11492
  } from "fs";
11389
- import { join as join17 } from "path";
11493
+ import { join as join18 } from "path";
11390
11494
  import { Writable } from "stream";
11391
11495
 
11392
11496
  // src/providers/docker-cli.ts
@@ -11580,7 +11684,7 @@ import {
11580
11684
  renameSync as renameSync4,
11581
11685
  rmSync as rmSync8
11582
11686
  } from "fs";
11583
- import { join as join15 } from "path";
11687
+ import { join as join16 } from "path";
11584
11688
  function routes(t) {
11585
11689
  const conv = `/api/workspaces/${t.workspaceId}/conversations/${t.conversationId}`;
11586
11690
  const agent = `${conv}/participants/agents/${t.agentId}`;
@@ -11626,7 +11730,7 @@ function publishStaged(from, to, move = atomicMove) {
11626
11730
  const staged = readdirSync3(from).filter((n) => n.endsWith(".json")).map((name) => {
11627
11731
  let entry = {};
11628
11732
  try {
11629
- entry = JSON.parse(readFileSync8(join15(from, name), "utf8"));
11733
+ entry = JSON.parse(readFileSync8(join16(from, name), "utf8"));
11630
11734
  } catch {
11631
11735
  }
11632
11736
  return { name, entry };
@@ -11639,7 +11743,7 @@ function publishStaged(from, to, move = atomicMove) {
11639
11743
  let published = 0;
11640
11744
  for (const { name } of staged) {
11641
11745
  try {
11642
- move(join15(from, name), join15(to, name));
11746
+ move(join16(from, name), join16(to, name));
11643
11747
  } catch {
11644
11748
  return { published, complete: false };
11645
11749
  }
@@ -11652,7 +11756,7 @@ function publishStaged(from, to, move = atomicMove) {
11652
11756
  // src/providers/runner-base.ts
11653
11757
  import { createHash as createHash3 } from "crypto";
11654
11758
  import { existsSync as existsSync12, realpathSync as realpathSync2 } from "fs";
11655
- import { dirname as dirname7, join as join16, sep } from "path";
11759
+ import { dirname as dirname7, join as join17, sep } from "path";
11656
11760
  import { fileURLToPath as fileURLToPath3 } from "url";
11657
11761
  var COMPANION_MOUNT = "/opt/cabane/companion";
11658
11762
  var BASE_DOCKERFILE = `FROM node:22-slim
@@ -11700,11 +11804,11 @@ async function ensureBaseImage(docker, image, log) {
11700
11804
  function ownInstall(moduleFile = fileURLToPath3(import.meta.url)) {
11701
11805
  let dir2 = dirname7(moduleFile);
11702
11806
  for (let i = 0; i < 4; i++) {
11703
- if (existsSync12(join16(dir2, "dist", "cli.js")) && existsSync12(join16(dir2, "package.json"))) break;
11807
+ if (existsSync12(join17(dir2, "dist", "cli.js")) && existsSync12(join17(dir2, "package.json"))) break;
11704
11808
  dir2 = dirname7(dir2);
11705
11809
  }
11706
- if (!existsSync12(join16(dir2, "dist", "cli.js"))) return null;
11707
- const sdk = join16(dir2, "node_modules", "@anthropic-ai", "claude-agent-sdk");
11810
+ if (!existsSync12(join17(dir2, "dist", "cli.js"))) return null;
11811
+ const sdk = join17(dir2, "node_modules", "@anthropic-ai", "claude-agent-sdk");
11708
11812
  if (!existsSync12(sdk)) return null;
11709
11813
  const root = realpathSync2(dir2);
11710
11814
  return realpathSync2(sdk).startsWith(root + sep) ? root : null;
@@ -11843,21 +11947,21 @@ function networkCreateError(stderr) {
11843
11947
  }
11844
11948
  function sessionArchivePath(deviceDir, attemptId) {
11845
11949
  if (!UUID_RE.test(attemptId)) throw new Error(`docker: not an attempt id: ${attemptId}`);
11846
- return join17(deviceDir, "attempts", attemptId, "session.tar");
11950
+ return join18(deviceDir, "attempts", attemptId, "session.tar");
11847
11951
  }
11848
11952
  function pruneOtherAttempts(deviceDir, pair, keep) {
11849
- const root = join17(deviceDir, "attempts");
11953
+ const root = join18(deviceDir, "attempts");
11850
11954
  if (!existsSync13(root)) return;
11851
11955
  for (const id of readdirSync4(root)) {
11852
11956
  if (id === keep || !UUID_RE.test(id)) continue;
11853
11957
  let pairOf = "";
11854
11958
  try {
11855
- pairOf = readFileSync9(join17(root, id, "pair"), "utf8");
11959
+ pairOf = readFileSync9(join18(root, id, "pair"), "utf8");
11856
11960
  } catch {
11857
11961
  continue;
11858
11962
  }
11859
11963
  if (pairOf === `${pair.conversationId}/${pair.agentId}`) {
11860
- rmSync9(join17(root, id), { recursive: true, force: true });
11964
+ rmSync9(join18(root, id), { recursive: true, force: true });
11861
11965
  }
11862
11966
  }
11863
11967
  }
@@ -12057,11 +12161,11 @@ function createDockerProvider(opts) {
12057
12161
  await must(["network", "disconnect", "-f", other, name], "moving the container");
12058
12162
  if (others.includes(sharedNetwork)) await retireSharedNetwork();
12059
12163
  };
12060
- const socketRoot = opts.socketRoot ?? join17(
12061
- process.env.XDG_RUNTIME_DIR && existsSync13(process.env.XDG_RUNTIME_DIR) ? process.env.XDG_RUNTIME_DIR : tmpdir2(),
12164
+ const socketRoot = opts.socketRoot ?? join18(
12165
+ process.env.XDG_RUNTIME_DIR && existsSync13(process.env.XDG_RUNTIME_DIR) ? process.env.XDG_RUNTIME_DIR : tmpdir3(),
12062
12166
  `cabane-runners-${opts.deviceKey}`
12063
12167
  );
12064
- const socketDir = (name) => join17(socketRoot, createHash4("sha256").update(name).digest("hex").slice(0, 12));
12168
+ const socketDir = (name) => join18(socketRoot, createHash4("sha256").update(name).digest("hex").slice(0, 12));
12065
12169
  const create = async (name, attempt) => {
12066
12170
  mkdirSync10(socketRoot, { recursive: true, mode: 448 });
12067
12171
  mkdirSync10(socketDir(name), { recursive: true, mode: 457 });
@@ -12203,7 +12307,7 @@ function createDockerProvider(opts) {
12203
12307
  }
12204
12308
  };
12205
12309
  const removeIn = (name, from, names) => names.length ? execIn(name, ["sh", "-c", 'cd "$1" && shift && rm -f -- "$@"', "sh", from, ...names]) : Promise.resolve(null);
12206
- const pendingPath = (name) => join17(opts.deviceDir, "runners-pending", `${name}.json`);
12310
+ const pendingPath = (name) => join18(opts.deviceDir, "runners-pending", `${name}.json`);
12207
12311
  const readPending = (name) => {
12208
12312
  try {
12209
12313
  const ids = JSON.parse(readFileSync9(pendingPath(name), "utf8"));
@@ -12217,12 +12321,12 @@ function createDockerProvider(opts) {
12217
12321
  rmSync9(pendingPath(name), { force: true });
12218
12322
  return;
12219
12323
  }
12220
- mkdirSync10(join17(opts.deviceDir, "runners-pending"), { recursive: true });
12324
+ mkdirSync10(join18(opts.deviceDir, "runners-pending"), { recursive: true });
12221
12325
  writeFileSync6(pendingPath(name), JSON.stringify([...new Set(ids)]));
12222
12326
  };
12223
12327
  const keepSession = async (name, attempt, attemptId) => {
12224
12328
  const archive = sessionArchivePath(opts.deviceDir, attemptId);
12225
- mkdirSync10(join17(archive, ".."), { recursive: true });
12329
+ mkdirSync10(join18(archive, ".."), { recursive: true });
12226
12330
  const partial = `${archive}.${process.pid}.partial`;
12227
12331
  const file = new CappedFile(partial, sessionCap);
12228
12332
  const r = await execIn(
@@ -12239,7 +12343,7 @@ function createDockerProvider(opts) {
12239
12343
  );
12240
12344
  if (r.code === 0 && !file.over) {
12241
12345
  renameSync5(partial, archive);
12242
- writeFileSync6(join17(archive, "..", "pair"), `${attempt.conversationId}/${attempt.agentId}`);
12346
+ writeFileSync6(join18(archive, "..", "pair"), `${attempt.conversationId}/${attempt.agentId}`);
12243
12347
  pruneOtherAttempts(opts.deviceDir, attempt, attemptId);
12244
12348
  await writeMarker(name, attemptId);
12245
12349
  log.debug({ container: name, attemptId, bytes: file.bytes }, "runners: session files kept");
@@ -12253,7 +12357,7 @@ function createDockerProvider(opts) {
12253
12357
  file.over ? "runners: the session files are over the size cap and weren't kept; the next new container starts the session over" : "runners: couldn't keep the session files; the next new container starts the session over"
12254
12358
  );
12255
12359
  };
12256
- const stagingDir = (name) => join17(opts.deviceDir, "runners-pending", `${name}.outbox`);
12360
+ const stagingDir = (name) => join18(opts.deviceDir, "runners-pending", `${name}.outbox`);
12257
12361
  const ensureRunning = async (name) => {
12258
12362
  const seen = await docker.run(["inspect", "-f", "{{.State.Running}}", name]);
12259
12363
  if (seen.code !== 0) return false;
@@ -12261,7 +12365,7 @@ function createDockerProvider(opts) {
12261
12365
  return (await docker.run(["start", name])).code === 0;
12262
12366
  };
12263
12367
  const dropArchive = (attemptId) => {
12264
- rmSync9(join17(sessionArchivePath(opts.deviceDir, attemptId), ".."), {
12368
+ rmSync9(join18(sessionArchivePath(opts.deviceDir, attemptId), ".."), {
12265
12369
  recursive: true,
12266
12370
  force: true
12267
12371
  });
@@ -12330,7 +12434,7 @@ function createDockerProvider(opts) {
12330
12434
  if (seen.stdout.trim().split(" ")[0] !== "true")
12331
12435
  await must(["start", name], "starting the container");
12332
12436
  const git = await serveGitCredentials({
12333
- socketPath: join17(socketDir(name), "git.sock"),
12437
+ socketPath: join18(socketDir(name), "git.sock"),
12334
12438
  hosts: opts.gitHosts,
12335
12439
  fill: opts.gitFill,
12336
12440
  log
@@ -12479,15 +12583,15 @@ function createDockerProvider(opts) {
12479
12583
  const transcripts = await readDir(name, `${CONTAINER_STATE}/transcripts`);
12480
12584
  if (transcripts) {
12481
12585
  const kept = transcripts.files.filter((f) => SAFE_NAME_RE.test(f.name));
12482
- if (kept.length) mkdirSync10(join17(opts.hostStateDir, "transcripts"), { recursive: true });
12483
- for (const f of kept) writeFileSync6(join17(opts.hostStateDir, "transcripts", f.name), f.data);
12586
+ if (kept.length) mkdirSync10(join18(opts.hostStateDir, "transcripts"), { recursive: true });
12587
+ for (const f of kept) writeFileSync6(join18(opts.hostStateDir, "transcripts", f.name), f.data);
12484
12588
  await removeIn(
12485
12589
  name,
12486
12590
  `${CONTAINER_STATE}/transcripts`,
12487
12591
  kept.map((f) => f.name)
12488
12592
  );
12489
12593
  }
12490
- const outboxRel = join17("outbox", encodeURIComponent(attempt.agentId));
12594
+ const outboxRel = join18("outbox", encodeURIComponent(attempt.agentId));
12491
12595
  const outbox = await readDir(name, `${CONTAINER_STATE}/${outboxRel}`);
12492
12596
  let unpublished = false;
12493
12597
  if (outbox) {
@@ -12513,7 +12617,7 @@ function createDockerProvider(opts) {
12513
12617
  const staged = stagingDir(name);
12514
12618
  mkdirSync10(staged, { recursive: true });
12515
12619
  writeFileSync6(
12516
- join17(staged, `${encodeURIComponent(entry.turnId)}__${entry.seq}.json`),
12620
+ join18(staged, `${encodeURIComponent(entry.turnId)}__${entry.seq}.json`),
12517
12621
  `${JSON.stringify(entry)}
12518
12622
  `
12519
12623
  );
@@ -12526,7 +12630,7 @@ function createDockerProvider(opts) {
12526
12630
  if (outbox.complete) {
12527
12631
  const published = publishStaged(
12528
12632
  stagingDir(name),
12529
- join17(opts.hostStateDir, outboxRel),
12633
+ join18(opts.hostStateDir, outboxRel),
12530
12634
  opts.moveFile
12531
12635
  );
12532
12636
  queued = published.published;
@@ -12741,8 +12845,8 @@ import {
12741
12845
  } from "fs";
12742
12846
  import { createRequire as createRequire2 } from "module";
12743
12847
  import { isIP } from "net";
12744
- import { homedir as homedir3, networkInterfaces, tmpdir as tmpdir3, userInfo as userInfo2 } from "os";
12745
- import { dirname as dirname8, join as join18, sep as sep2 } from "path";
12848
+ import { homedir as homedir3, networkInterfaces, tmpdir as tmpdir4, userInfo as userInfo2 } from "os";
12849
+ import { dirname as dirname8, join as join19, sep as sep2 } from "path";
12746
12850
  import { fileURLToPath as fileURLToPath4 } from "url";
12747
12851
  import { SandboxManager } from "@anthropic-ai/sandbox-runtime";
12748
12852
  function accountHome() {
@@ -12952,7 +13056,7 @@ import {
12952
13056
  rmSync as rmSync11,
12953
13057
  writeFileSync as writeFileSync8
12954
13058
  } from "fs";
12955
- import { join as join19 } from "path";
13059
+ import { join as join20 } from "path";
12956
13060
  var MAX_ENTRIES = 2e3;
12957
13061
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
12958
13062
  var Outbox = class {
@@ -12965,10 +13069,10 @@ var Outbox = class {
12965
13069
  // Resolved lazily (per call, like cursor.ts) so tests that swap HOME between
12966
13070
  // cases route writes at the right tmpdir.
12967
13071
  dir() {
12968
- return join19(runnerStateDir(), "outbox", encodeURIComponent(this.workspaceId));
13072
+ return join20(runnerStateDir(), "outbox", encodeURIComponent(this.workspaceId));
12969
13073
  }
12970
13074
  fileFor(turnId, seq) {
12971
- return join19(this.dir(), `${encodeURIComponent(turnId)}__${seq}.json`);
13075
+ return join20(this.dir(), `${encodeURIComponent(turnId)}__${seq}.json`);
12972
13076
  }
12973
13077
  // Persist a commit for later draining. Atomic (temp file + rename) so a
12974
13078
  // concurrent `list()` never reads a half-written entry, then enforces the
@@ -13010,7 +13114,7 @@ var Outbox = class {
13010
13114
  const entries = [];
13011
13115
  for (const name of names) {
13012
13116
  if (!name.endsWith(".json")) continue;
13013
- const full = join19(dir2, name);
13117
+ const full = join20(dir2, name);
13014
13118
  try {
13015
13119
  const parsed = JSON.parse(readFileSync11(full, "utf8"));
13016
13120
  if (parsed && typeof parsed.turnId === "string" && typeof parsed.seq === "number" && typeof parsed.path === "string") {
@@ -14651,8 +14755,8 @@ function errorCode(err) {
14651
14755
  function isRecoverableSocketError(err) {
14652
14756
  const code = errorCode(err);
14653
14757
  if (code && RECOVERABLE_CODES.has(code)) return true;
14654
- const message = err instanceof Error ? err.message : String(err);
14655
- return /\bEPIPE\b|\bECONNRESET\b/.test(message);
14758
+ const message2 = err instanceof Error ? err.message : String(err);
14759
+ return /\bEPIPE\b|\bECONNRESET\b/.test(message2);
14656
14760
  }
14657
14761
  function installProcessSafetyNet(log, opts = {}) {
14658
14762
  const proc = opts.proc ?? process;
@@ -14667,26 +14771,26 @@ function installProcessSafetyNet(log, opts = {}) {
14667
14771
  );
14668
14772
  }
14669
14773
  function handleUncaught(log, err, origin) {
14670
- const message = err instanceof Error ? err.message : String(err);
14774
+ const message2 = err instanceof Error ? err.message : String(err);
14671
14775
  const code = errorCode(err);
14672
14776
  if (isRecoverableSocketError(err)) {
14673
14777
  log.debug(
14674
- { origin, code, err: message },
14778
+ { origin, code, err: message2 },
14675
14779
  "companion: recovered from a socket error (kept running \u2014 a broken pipe never kills the companion)"
14676
14780
  );
14677
14781
  return;
14678
14782
  }
14679
14783
  log.error(
14680
- { origin, code, err: message, stack: err instanceof Error ? err.stack : void 0 },
14784
+ { origin, code, err: message2, stack: err instanceof Error ? err.stack : void 0 },
14681
14785
  "An unexpected error occurred; the companion is still running."
14682
14786
  );
14683
14787
  }
14684
14788
 
14685
14789
  // src/crash-marker.ts
14686
14790
  import { existsSync as existsSync15, mkdirSync as mkdirSync13, readFileSync as readFileSync12, rmSync as rmSync12, writeFileSync as writeFileSync9 } from "fs";
14687
- import { join as join20 } from "path";
14791
+ import { join as join21 } from "path";
14688
14792
  function crashMarkerPath() {
14689
- return join20(cabaneDir(), "last-error.json");
14793
+ return join21(cabaneDir(), "last-error.json");
14690
14794
  }
14691
14795
  function recordCrash(rec) {
14692
14796
  try {