@autohq/cli 0.1.418 → 0.1.419

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.
@@ -652,8 +652,8 @@ var require_common = __commonJS({
652
652
  }
653
653
  return debug12;
654
654
  }
655
- function extend2(namespace, delimiter) {
656
- const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace);
655
+ function extend2(namespace, delimiter2) {
656
+ const newDebug = createDebug(this.namespace + (typeof delimiter2 === "undefined" ? ":" : delimiter2) + namespace);
657
657
  newDebug.log = this.log;
658
658
  return newDebug;
659
659
  }
@@ -13853,8 +13853,8 @@ function emoji() {
13853
13853
  }
13854
13854
  var ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
13855
13855
  var ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
13856
- var mac = (delimiter) => {
13857
- const escapedDelim = escapeRegex(delimiter ?? ":");
13856
+ var mac = (delimiter2) => {
13857
+ const escapedDelim = escapeRegex(delimiter2 ?? ":");
13858
13858
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
13859
13859
  };
13860
13860
  var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
@@ -30820,7 +30820,7 @@ Object.assign(lookup, {
30820
30820
  // package.json
30821
30821
  var package_default = {
30822
30822
  name: "@autohq/cli",
30823
- version: "0.1.418",
30823
+ version: "0.1.419",
30824
30824
  license: "SEE LICENSE IN README.md",
30825
30825
  publishConfig: {
30826
30826
  access: "public"
@@ -61465,6 +61465,233 @@ function uiChunk(chunk) {
61465
61465
  };
61466
61466
  }
61467
61467
 
61468
+ // src/commands/agent-bridge/harness/claude-code/read-state.ts
61469
+ import {
61470
+ existsSync as existsSync2,
61471
+ mkdirSync as mkdirSync2,
61472
+ readFileSync as readFileSync2,
61473
+ statSync,
61474
+ writeFileSync as writeFileSync2
61475
+ } from "fs";
61476
+ import { dirname as dirname2 } from "path";
61477
+
61478
+ // src/commands/agent-bridge/harness/claude-code/resume-store.ts
61479
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
61480
+ import { dirname } from "path";
61481
+ var AGENT_BRIDGE_RUNTIME_DIR = "/tmp/auto-bridge-runtime";
61482
+ var CLAUDE_SESSION_RESUME_PATH = `${AGENT_BRIDGE_RUNTIME_DIR}/claude-session-id`;
61483
+ function fileClaudeSessionResumeStore(path2 = CLAUDE_SESSION_RESUME_PATH) {
61484
+ return {
61485
+ read(sessionId) {
61486
+ if (!existsSync(path2)) {
61487
+ return null;
61488
+ }
61489
+ const record2 = parseResumeRecord(readFileSync(path2, "utf8"));
61490
+ if (!record2 || record2.sessionId !== sessionId) {
61491
+ return null;
61492
+ }
61493
+ return record2.agentId;
61494
+ },
61495
+ write(record2) {
61496
+ mkdirSync(dirname(path2), { recursive: true });
61497
+ writeFileSync(path2, `${JSON.stringify(record2)}
61498
+ `, "utf8");
61499
+ }
61500
+ };
61501
+ }
61502
+ function parseResumeRecord(raw) {
61503
+ try {
61504
+ const value2 = JSON.parse(raw);
61505
+ if (value2 !== null && typeof value2 === "object" && "sessionId" in value2 && "agentId" in value2 && typeof value2.sessionId === "string" && typeof value2.agentId === "string" && value2.agentId.length > 0) {
61506
+ return { sessionId: value2.sessionId, agentId: value2.agentId };
61507
+ }
61508
+ return null;
61509
+ } catch {
61510
+ return null;
61511
+ }
61512
+ }
61513
+
61514
+ // src/commands/agent-bridge/harness/claude-code/read-state.ts
61515
+ var CLAUDE_READ_STATE_PATH = `${AGENT_BRIDGE_RUNTIME_DIR}/claude-read-state`;
61516
+ var CLAUDE_READ_STATE_MAX_ENTRIES = 256;
61517
+ var ClaudeReadStateTracker = class {
61518
+ constructor(store) {
61519
+ this.store = store;
61520
+ }
61521
+ store;
61522
+ // Most-recently-observed entries last (Map preserves insertion order, and
61523
+ // touches re-insert), so eviction drops the stalest observation first.
61524
+ entriesByPath = /* @__PURE__ */ new Map();
61525
+ // tool_use ids of in-flight file-tool calls, mapped to the file they target.
61526
+ // Cleared at each turn's terminal result so interrupted calls cannot leak.
61527
+ pendingFileToolUses = /* @__PURE__ */ new Map();
61528
+ loadedForSessionId = null;
61529
+ // Feed every live SDK message through here. Successful Read/Write/Edit
61530
+ // results commit a path+mtime observation; everything else is ignored.
61531
+ observe(sessionId, message) {
61532
+ this.ensureLoaded(sessionId);
61533
+ if (message.type === "result") {
61534
+ this.pendingFileToolUses.clear();
61535
+ return;
61536
+ }
61537
+ if (message.type === "assistant" && message.parent_tool_use_id === null) {
61538
+ for (const block of contentBlocks(message.message.content)) {
61539
+ const use = fileToolUse(block);
61540
+ if (use) {
61541
+ this.pendingFileToolUses.set(use.toolUseId, use.path);
61542
+ }
61543
+ }
61544
+ return;
61545
+ }
61546
+ if (message.type !== "user" || message.parent_tool_use_id !== null) {
61547
+ return;
61548
+ }
61549
+ if ("isReplay" in message && message.isReplay === true) {
61550
+ return;
61551
+ }
61552
+ for (const block of contentBlocks(message.message.content)) {
61553
+ if (block.type !== "tool_result") {
61554
+ continue;
61555
+ }
61556
+ const toolUseId = typeof block.tool_use_id === "string" ? block.tool_use_id : null;
61557
+ if (toolUseId === null) {
61558
+ continue;
61559
+ }
61560
+ const path2 = this.pendingFileToolUses.get(toolUseId);
61561
+ this.pendingFileToolUses.delete(toolUseId);
61562
+ if (path2 !== void 0 && block.is_error !== true) {
61563
+ this.commit(sessionId, path2);
61564
+ }
61565
+ }
61566
+ }
61567
+ // The seeds to replay into a fresh CLI process, stalest observation first so
61568
+ // the most recent reads survive any CLI-side eviction.
61569
+ seeds(sessionId) {
61570
+ this.ensureLoaded(sessionId);
61571
+ return [...this.entriesByPath].map(([path2, mtime]) => ({ path: path2, mtime }));
61572
+ }
61573
+ // A conversation-lineage break: the next CLI session starts with no prior
61574
+ // context, so nothing the model "remembers reading" exists anymore.
61575
+ clear(sessionId) {
61576
+ this.ensureLoaded(sessionId);
61577
+ if (this.entriesByPath.size === 0) {
61578
+ return;
61579
+ }
61580
+ this.entriesByPath.clear();
61581
+ this.persist(sessionId);
61582
+ }
61583
+ ensureLoaded(sessionId) {
61584
+ if (this.loadedForSessionId === sessionId) {
61585
+ return;
61586
+ }
61587
+ this.loadedForSessionId = sessionId;
61588
+ this.entriesByPath.clear();
61589
+ this.pendingFileToolUses.clear();
61590
+ for (const entry of this.store.read(sessionId) ?? []) {
61591
+ this.entriesByPath.set(entry.path, entry.mtime);
61592
+ }
61593
+ }
61594
+ commit(sessionId, path2) {
61595
+ let mtime;
61596
+ try {
61597
+ mtime = Math.floor(statSync(path2).mtimeMs);
61598
+ } catch {
61599
+ if (this.entriesByPath.delete(path2)) {
61600
+ this.persist(sessionId);
61601
+ }
61602
+ return;
61603
+ }
61604
+ this.entriesByPath.delete(path2);
61605
+ this.entriesByPath.set(path2, mtime);
61606
+ while (this.entriesByPath.size > CLAUDE_READ_STATE_MAX_ENTRIES) {
61607
+ const oldest = this.entriesByPath.keys().next().value;
61608
+ if (oldest === void 0) {
61609
+ break;
61610
+ }
61611
+ this.entriesByPath.delete(oldest);
61612
+ }
61613
+ this.persist(sessionId);
61614
+ }
61615
+ persist(sessionId) {
61616
+ this.store.write({ sessionId, entries: this.seeds(sessionId) });
61617
+ }
61618
+ };
61619
+ function fileClaudeReadStateStore(path2 = CLAUDE_READ_STATE_PATH) {
61620
+ return {
61621
+ read(sessionId) {
61622
+ if (!existsSync2(path2)) {
61623
+ return null;
61624
+ }
61625
+ const record2 = parseReadStateRecord(readFileSync2(path2, "utf8"));
61626
+ if (!record2 || record2.sessionId !== sessionId) {
61627
+ return null;
61628
+ }
61629
+ return record2.entries;
61630
+ },
61631
+ write(record2) {
61632
+ mkdirSync2(dirname2(path2), { recursive: true });
61633
+ writeFileSync2(path2, `${JSON.stringify(record2)}
61634
+ `, "utf8");
61635
+ }
61636
+ };
61637
+ }
61638
+ function fileToolUse(block) {
61639
+ if (block.type !== "tool_use" || typeof block.id !== "string") {
61640
+ return null;
61641
+ }
61642
+ const input = block.input;
61643
+ if (typeof input !== "object" || input === null) {
61644
+ return null;
61645
+ }
61646
+ const filePath = input.file_path;
61647
+ if (typeof filePath !== "string" || filePath.length === 0) {
61648
+ return null;
61649
+ }
61650
+ switch (block.name) {
61651
+ case "Read": {
61652
+ const { offset, limit } = input;
61653
+ if (offset !== void 0 || limit !== void 0) {
61654
+ return null;
61655
+ }
61656
+ return { toolUseId: block.id, path: filePath };
61657
+ }
61658
+ case "Write":
61659
+ case "Edit":
61660
+ return { toolUseId: block.id, path: filePath };
61661
+ default:
61662
+ return null;
61663
+ }
61664
+ }
61665
+ function contentBlocks(content) {
61666
+ if (!Array.isArray(content)) {
61667
+ return [];
61668
+ }
61669
+ return content.filter(
61670
+ (block) => typeof block === "object" && block !== null
61671
+ );
61672
+ }
61673
+ function parseReadStateRecord(raw) {
61674
+ try {
61675
+ const value2 = JSON.parse(raw);
61676
+ if (value2 === null || typeof value2 !== "object" || !("sessionId" in value2) || !("entries" in value2) || typeof value2.sessionId !== "string" || !Array.isArray(value2.entries)) {
61677
+ return null;
61678
+ }
61679
+ const entries = [];
61680
+ for (const entry of value2.entries) {
61681
+ if (entry === null || typeof entry !== "object" || typeof entry.path !== "string" || typeof entry.mtime !== "number") {
61682
+ return null;
61683
+ }
61684
+ entries.push({
61685
+ path: entry.path,
61686
+ mtime: entry.mtime
61687
+ });
61688
+ }
61689
+ return { sessionId: value2.sessionId, entries };
61690
+ } catch {
61691
+ return null;
61692
+ }
61693
+ }
61694
+
61468
61695
  // ../../node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs
61469
61696
  import { createRequire as i_ } from "module";
61470
61697
  import { execFile as v6$ } from "child_process";
@@ -81236,6 +81463,7 @@ var CLAUDE_INTERRUPT_SETTLE_TIMEOUT_MS = 1e4;
81236
81463
  var CLAUDE_INTERRUPT_ACK_TIMEOUT_MS = 1e4;
81237
81464
  var CLAUDE_MCP_REGISTRATION_TIMEOUT_MS = 3e3;
81238
81465
  var CLAUDE_MCP_REGISTRATION_POLL_INTERVAL_MS = 100;
81466
+ var CLAUDE_READ_STATE_SEED_FAILURE_LIMIT = 3;
81239
81467
  var CLAUDE_STARTUP_PROFILE_HOOK_EVENTS = [
81240
81468
  "Setup",
81241
81469
  "SessionStart",
@@ -81452,6 +81680,32 @@ var ClaudeAgentBridgeSessionImpl = class {
81452
81680
  }
81453
81681
  );
81454
81682
  }
81683
+ async seedReadState(seeds) {
81684
+ if (seeds.length === 0 || this.state.kind !== "running") {
81685
+ return;
81686
+ }
81687
+ const query = this.state.query;
81688
+ const startedAt = Date.now();
81689
+ let seeded = 0;
81690
+ let failed = 0;
81691
+ for (const seed of seeds) {
81692
+ try {
81693
+ await query.seedReadState(seed.path, seed.mtime);
81694
+ seeded += 1;
81695
+ } catch (error51) {
81696
+ failed += 1;
81697
+ this.input.writeOutput?.(
81698
+ `agent_bridge_claude_read_state_seed_failed path=${seed.path} error=${error51 instanceof Error ? error51.message : String(error51)}`
81699
+ );
81700
+ if (failed >= CLAUDE_READ_STATE_SEED_FAILURE_LIMIT) {
81701
+ break;
81702
+ }
81703
+ }
81704
+ }
81705
+ this.input.writeOutput?.(
81706
+ `agent_bridge_claude_read_state_seeded seeded=${seeded} total=${seeds.length} duration_ms=${Date.now() - startedAt}`
81707
+ );
81708
+ }
81455
81709
  close() {
81456
81710
  const previousState = this.state;
81457
81711
  if (previousState.kind === "closed") {
@@ -81513,6 +81767,7 @@ var ClaudeAgentBridgeSessionImpl = class {
81513
81767
  this.input.writeOutput?.(
81514
81768
  `agent_bridge_claude_resume_fallback session_id=${resume}`
81515
81769
  );
81770
+ this.input.onResumeFallback?.();
81516
81771
  this.state = { kind: "idle" };
81517
81772
  return this.startSdkSession();
81518
81773
  }
@@ -82117,7 +82372,7 @@ function isClaudeAgentTurnResult(message) {
82117
82372
  }
82118
82373
  function toolUseIds(message) {
82119
82374
  if (message.type === "assistant") {
82120
- return contentBlocks(message.message.content).flatMap(
82375
+ return contentBlocks2(message.message.content).flatMap(
82121
82376
  (block2) => block2.type === "tool_use" && typeof block2.id === "string" ? [block2.id] : []
82122
82377
  );
82123
82378
  }
@@ -82135,11 +82390,11 @@ function toolResultIds(message) {
82135
82390
  if (message.type !== "user") {
82136
82391
  return [];
82137
82392
  }
82138
- return contentBlocks(message.message.content).flatMap(
82393
+ return contentBlocks2(message.message.content).flatMap(
82139
82394
  (block) => block.type === "tool_result" && typeof block.tool_use_id === "string" ? [block.tool_use_id] : []
82140
82395
  );
82141
82396
  }
82142
- function contentBlocks(content) {
82397
+ function contentBlocks2(content) {
82143
82398
  if (!Array.isArray(content)) {
82144
82399
  return [];
82145
82400
  }
@@ -82148,42 +82403,6 @@ function contentBlocks(content) {
82148
82403
  );
82149
82404
  }
82150
82405
 
82151
- // src/commands/agent-bridge/harness/claude-code/resume-store.ts
82152
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
82153
- import { dirname } from "path";
82154
- var AGENT_BRIDGE_RUNTIME_DIR = "/tmp/auto-bridge-runtime";
82155
- var CLAUDE_SESSION_RESUME_PATH = `${AGENT_BRIDGE_RUNTIME_DIR}/claude-session-id`;
82156
- function fileClaudeSessionResumeStore(path2 = CLAUDE_SESSION_RESUME_PATH) {
82157
- return {
82158
- read(sessionId) {
82159
- if (!existsSync2(path2)) {
82160
- return null;
82161
- }
82162
- const record2 = parseResumeRecord(readFileSync2(path2, "utf8"));
82163
- if (!record2 || record2.sessionId !== sessionId) {
82164
- return null;
82165
- }
82166
- return record2.agentId;
82167
- },
82168
- write(record2) {
82169
- mkdirSync2(dirname(path2), { recursive: true });
82170
- writeFileSync(path2, `${JSON.stringify(record2)}
82171
- `, "utf8");
82172
- }
82173
- };
82174
- }
82175
- function parseResumeRecord(raw) {
82176
- try {
82177
- const value2 = JSON.parse(raw);
82178
- if (value2 !== null && typeof value2 === "object" && "sessionId" in value2 && "agentId" in value2 && typeof value2.sessionId === "string" && typeof value2.agentId === "string" && value2.agentId.length > 0) {
82179
- return { sessionId: value2.sessionId, agentId: value2.agentId };
82180
- }
82181
- return null;
82182
- } catch {
82183
- return null;
82184
- }
82185
- }
82186
-
82187
82406
  // src/commands/agent-bridge/harness/claude-code/index.ts
82188
82407
  function createClaudeCodeCommandHandler(input) {
82189
82408
  return new ClaudeCodeCommandHandler(input);
@@ -82193,6 +82412,7 @@ var ClaudeCodeCommandHandler = class {
82193
82412
  this.input = input;
82194
82413
  this.claudeConfig = input.claude;
82195
82414
  this.outputBuffer = new AgentBridgeOutputBuffer(input);
82415
+ this.readState = input.readState ? new ClaudeReadStateTracker(input.readState) : null;
82196
82416
  }
82197
82417
  input;
82198
82418
  context = null;
@@ -82214,6 +82434,7 @@ var ClaudeCodeCommandHandler = class {
82214
82434
  pendingQuestions = /* @__PURE__ */ new Map();
82215
82435
  outputBuffer;
82216
82436
  projector = new ClaudeCodeProjector();
82437
+ readState;
82217
82438
  livenessTicker = null;
82218
82439
  // -----------------------------------------------------------------------------
82219
82440
  // Lifecycle (public API)
@@ -82590,6 +82811,7 @@ var ClaudeCodeCommandHandler = class {
82590
82811
  return;
82591
82812
  }
82592
82813
  this.persistAgentId(activeContext, message);
82814
+ this.trackReadState(activeContext, message);
82593
82815
  let projections;
82594
82816
  try {
82595
82817
  projections = this.projector.project(message);
@@ -82653,6 +82875,31 @@ var ClaudeCodeCommandHandler = class {
82653
82875
  );
82654
82876
  }
82655
82877
  }
82878
+ // Observes file-tool results into the read-state tracker and replays the
82879
+ // tracked seeds whenever a fresh CLI cache appears: a new process's `init`
82880
+ // (runtime restart, selection change, CLI-internal fork — all resume the
82881
+ // conversation but start with an empty readFileState) and compaction
82882
+ // boundaries (which can evict prior reads). Seeding is fire-and-forget:
82883
+ // a failed seed degrades to today's behavior, a fresh Read before writing.
82884
+ trackReadState(activeContext, message) {
82885
+ const tracker = this.readState;
82886
+ if (!tracker) {
82887
+ return;
82888
+ }
82889
+ if (message.type === "system" && (message.subtype === "init" || message.subtype === "compact_boundary")) {
82890
+ const seeds = tracker.seeds(activeContext.sessionId);
82891
+ if (seeds.length === 0) {
82892
+ return;
82893
+ }
82894
+ this.agentSession?.seedReadState(seeds).catch((error51) => {
82895
+ this.input.writeOutput?.(
82896
+ `agent_bridge_claude_read_state_seed_failed error=${error51 instanceof Error ? error51.message : String(error51)}`
82897
+ );
82898
+ });
82899
+ return;
82900
+ }
82901
+ tracker.observe(activeContext.sessionId, message);
82902
+ }
82656
82903
  storedResumeAgentId() {
82657
82904
  const store = this.input.sessionResume;
82658
82905
  const activeContext = this.context;
@@ -82682,10 +82929,18 @@ var ClaudeCodeCommandHandler = class {
82682
82929
  "Cannot restart Claude Code for a model/effort selection change without a session id to resume"
82683
82930
  );
82684
82931
  }
82932
+ if (!resumeAgentId && this.context) {
82933
+ this.readState?.clear(this.context.sessionId);
82934
+ }
82685
82935
  const session = claudeAgentBridgeRuntime.start({
82686
82936
  claude: this.claudeConfig,
82687
82937
  resumeAgentId,
82688
82938
  ...resumeRequired ? { allowResumeFallback: false } : {},
82939
+ onResumeFallback: () => {
82940
+ if (this.context) {
82941
+ this.readState?.clear(this.context.sessionId);
82942
+ }
82943
+ },
82689
82944
  canUseTool: this.canUseTool,
82690
82945
  onMessage: (message, meta3) => this.handleAgentMessage(message, meta3),
82691
82946
  onError: (error51) => this.handleAgentError(error51),
@@ -83098,25 +83353,25 @@ function normalizeChunk(chunk) {
83098
83353
  }
83099
83354
 
83100
83355
  // src/commands/agent-bridge/harness/codex/resume-store.ts
83101
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
83102
- import { dirname as dirname2 } from "path";
83356
+ import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
83357
+ import { dirname as dirname3 } from "path";
83103
83358
  var AGENT_BRIDGE_RUNTIME_DIR2 = "/tmp/auto-bridge-runtime";
83104
83359
  var CODEX_THREAD_RESUME_PATH = `${AGENT_BRIDGE_RUNTIME_DIR2}/codex-thread-id`;
83105
83360
  function fileCodexThreadResumeStore(path2 = CODEX_THREAD_RESUME_PATH) {
83106
83361
  return {
83107
83362
  read(sessionId) {
83108
- if (!existsSync3(path2)) {
83363
+ if (!existsSync4(path2)) {
83109
83364
  return null;
83110
83365
  }
83111
- const record2 = parseResumeRecord2(readFileSync3(path2, "utf8"));
83366
+ const record2 = parseResumeRecord2(readFileSync4(path2, "utf8"));
83112
83367
  if (!record2 || record2.sessionId !== sessionId) {
83113
83368
  return null;
83114
83369
  }
83115
83370
  return record2.threadId;
83116
83371
  },
83117
83372
  write(record2) {
83118
- mkdirSync3(dirname2(path2), { recursive: true });
83119
- writeFileSync2(path2, `${JSON.stringify(record2)}
83373
+ mkdirSync4(dirname3(path2), { recursive: true });
83374
+ writeFileSync3(path2, `${JSON.stringify(record2)}
83120
83375
  `, "utf8");
83121
83376
  }
83122
83377
  };
@@ -83135,8 +83390,26 @@ function parseResumeRecord2(raw) {
83135
83390
 
83136
83391
  // src/commands/agent-bridge/harness/codex/session.ts
83137
83392
  import { spawn } from "child_process";
83138
- import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync3 } from "fs";
83139
- import { join as join2 } from "path";
83393
+ import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync5 } from "fs";
83394
+ import { join as join3 } from "path";
83395
+
83396
+ // src/commands/agent-bridge/harness/codex/edit-capability.ts
83397
+ import { execFileSync } from "child_process";
83398
+ import {
83399
+ constants,
83400
+ accessSync,
83401
+ existsSync as existsSync5,
83402
+ lstatSync as lstatSync2,
83403
+ mkdtempSync,
83404
+ readFileSync as readFileSync5,
83405
+ realpathSync as realpathSync2,
83406
+ rmSync as rmSync2,
83407
+ symlinkSync as symlinkSync2,
83408
+ unlinkSync as unlinkSync2,
83409
+ writeFileSync as writeFileSync4
83410
+ } from "fs";
83411
+ import { tmpdir } from "os";
83412
+ import { delimiter, dirname as dirname4, join as join2 } from "path";
83140
83413
 
83141
83414
  // src/commands/agent-bridge/harness/codex/options.ts
83142
83415
  import { join } from "path";
@@ -83278,6 +83551,172 @@ function tomlString(value2) {
83278
83551
  return `"${value2.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
83279
83552
  }
83280
83553
 
83554
+ // src/commands/agent-bridge/harness/codex/edit-capability.ts
83555
+ var CODEX_APPLY_PATCH_ALIAS = "apply_patch";
83556
+ var CODEX_EDIT_PROBE = {
83557
+ fileName: "probe.txt",
83558
+ before: "codex-edit-probe\n",
83559
+ after: "codex-edit-probe-ok\n",
83560
+ patch: [
83561
+ "*** Begin Patch",
83562
+ "*** Update File: probe.txt",
83563
+ "@@",
83564
+ "-codex-edit-probe",
83565
+ "+codex-edit-probe-ok",
83566
+ "*** End Patch"
83567
+ ].join("\n")
83568
+ };
83569
+ var PROBE_TIMEOUT_MS = 15e3;
83570
+ var MAX_EVIDENCE_LENGTH = 300;
83571
+ var CODEX_PLATFORM_VENDOR_TARGETS = {
83572
+ linux: {
83573
+ x64: "x86_64-unknown-linux-musl",
83574
+ arm64: "aarch64-unknown-linux-musl"
83575
+ },
83576
+ darwin: {
83577
+ x64: "x86_64-apple-darwin",
83578
+ arm64: "aarch64-apple-darwin"
83579
+ }
83580
+ };
83581
+ function ensureCodexEditCapability(input) {
83582
+ if (input.command !== CODEX_EXECUTABLE_PATH) {
83583
+ input.writeOutput?.(
83584
+ "agent_bridge_codex_edit_capability status=skipped reason=command_override"
83585
+ );
83586
+ return;
83587
+ }
83588
+ const startedAt = Date.now();
83589
+ const layout = runStep(input, "resolve", () => resolveCodexVendorLayout());
83590
+ const status = runStep(
83591
+ input,
83592
+ "provision",
83593
+ () => provisionApplyPatchAlias(layout)
83594
+ );
83595
+ const alias = join2(layout.codexPathDir, CODEX_APPLY_PATCH_ALIAS);
83596
+ runStep(input, "verify", () => verifyApplyPatchAlias(alias));
83597
+ input.writeOutput?.(
83598
+ `agent_bridge_codex_edit_capability status=${status} alias=${alias} duration_ms=${Date.now() - startedAt}`
83599
+ );
83600
+ }
83601
+ function codexEditFallthroughMarker(item) {
83602
+ if (item.type !== "commandExecution" || item.exitCode !== 127) {
83603
+ return null;
83604
+ }
83605
+ const output = item.aggregatedOutput ?? "";
83606
+ if (!/apply_patch: (command )?not found/.test(output)) {
83607
+ return null;
83608
+ }
83609
+ return `agent_bridge_codex_edit_fallthrough item_id=${item.id} exit_code=127`;
83610
+ }
83611
+ function resolveCodexVendorLayout() {
83612
+ const wrapper = whichOnPath(CODEX_EXECUTABLE_PATH);
83613
+ if (!wrapper) {
83614
+ throw new Error("codex executable not found on PATH");
83615
+ }
83616
+ const target = CODEX_PLATFORM_VENDOR_TARGETS[process.platform]?.[process.arch];
83617
+ if (!target) {
83618
+ throw new Error(
83619
+ `unsupported platform for codex vendor layout: ${process.platform}/${process.arch}`
83620
+ );
83621
+ }
83622
+ const packageRoot = join2(dirname4(realpathSync2(wrapper)), "..");
83623
+ const platformPackage = `@openai/codex-${platformPackageSuffix()}`;
83624
+ const candidates = [
83625
+ join2(packageRoot, "node_modules", platformPackage, "vendor", target),
83626
+ join2(packageRoot, "vendor", target)
83627
+ ];
83628
+ for (const vendorDir of candidates) {
83629
+ const binary = join2(vendorDir, "bin", "codex");
83630
+ const codexPathDir = join2(vendorDir, "codex-path");
83631
+ if (existsSync5(binary) && existsSync5(codexPathDir)) {
83632
+ return { binary, codexPathDir };
83633
+ }
83634
+ }
83635
+ throw new Error(
83636
+ `codex vendor layout not found (wrapper=${wrapper} candidates=${candidates.join(",")})`
83637
+ );
83638
+ }
83639
+ function platformPackageSuffix() {
83640
+ const os = process.platform === "darwin" ? "darwin" : "linux";
83641
+ return `${os}-${process.arch}`;
83642
+ }
83643
+ function whichOnPath(command) {
83644
+ for (const dir of (process.env.PATH ?? "").split(delimiter)) {
83645
+ if (!dir) {
83646
+ continue;
83647
+ }
83648
+ const candidate = join2(dir, command);
83649
+ try {
83650
+ accessSync(candidate, constants.X_OK);
83651
+ return candidate;
83652
+ } catch {
83653
+ }
83654
+ }
83655
+ return null;
83656
+ }
83657
+ function provisionApplyPatchAlias(layout) {
83658
+ const alias = join2(layout.codexPathDir, CODEX_APPLY_PATCH_ALIAS);
83659
+ if (aliasResolvesToBinary(alias, layout.binary)) {
83660
+ return "present";
83661
+ }
83662
+ if (lstatExists(alias)) {
83663
+ unlinkSync2(alias);
83664
+ }
83665
+ symlinkSync2(layout.binary, alias);
83666
+ return "provisioned";
83667
+ }
83668
+ function aliasResolvesToBinary(alias, binary) {
83669
+ try {
83670
+ return realpathSync2(alias) === realpathSync2(binary);
83671
+ } catch {
83672
+ return false;
83673
+ }
83674
+ }
83675
+ function lstatExists(path2) {
83676
+ try {
83677
+ lstatSync2(path2);
83678
+ return true;
83679
+ } catch {
83680
+ return false;
83681
+ }
83682
+ }
83683
+ function verifyApplyPatchAlias(alias) {
83684
+ const scratch = mkdtempSync(join2(tmpdir(), "codex-edit-probe-"));
83685
+ try {
83686
+ const probeFile = join2(scratch, CODEX_EDIT_PROBE.fileName);
83687
+ writeFileSync4(probeFile, CODEX_EDIT_PROBE.before);
83688
+ execFileSync(alias, [CODEX_EDIT_PROBE.patch], {
83689
+ cwd: scratch,
83690
+ stdio: ["ignore", "pipe", "pipe"],
83691
+ timeout: PROBE_TIMEOUT_MS
83692
+ });
83693
+ const applied = readFileSync5(probeFile, "utf8");
83694
+ if (applied !== CODEX_EDIT_PROBE.after) {
83695
+ throw new Error("probe patch did not apply the expected content");
83696
+ }
83697
+ } finally {
83698
+ rmSync2(scratch, { recursive: true, force: true });
83699
+ }
83700
+ }
83701
+ function runStep(input, step, action) {
83702
+ try {
83703
+ return action();
83704
+ } catch (error51) {
83705
+ const detail = boundedEvidence(error51);
83706
+ input.writeOutput?.(
83707
+ `agent_bridge_codex_edit_capability status=failed step=${step} error=${detail}`
83708
+ );
83709
+ throw new Error(
83710
+ `Codex edit capability unavailable at ${step}: ${detail}. Codex 0.141.0 declares no apply_patch tool; without the codex-path alias, exec invocations the interceptor does not recognize fail with command-not-found (codex-runtime-tool-loss-diagnostics).`
83711
+ );
83712
+ }
83713
+ }
83714
+ function boundedEvidence(error51) {
83715
+ const message = error51 instanceof Error ? error51.message : String(error51);
83716
+ const flattened = message.replace(/\s+/g, " ").trim();
83717
+ return flattened.length > MAX_EVIDENCE_LENGTH ? `${flattened.slice(0, MAX_EVIDENCE_LENGTH)}\u2026` : flattened;
83718
+ }
83719
+
83281
83720
  // src/commands/agent-bridge/harness/codex/turn-retry.ts
83282
83721
  var MAX_CODEX_TURN_RETRY_ATTEMPTS = 3;
83283
83722
  var MAX_CODEX_TURN_RETRY_TOTAL_DELAY_MS = 3e4;
@@ -83511,12 +83950,16 @@ var CodexAgentBridgeSessionImpl = class {
83511
83950
  }
83512
83951
  async start() {
83513
83952
  const options = codexLaunchOptions(this.input.codex);
83514
- mkdirSync4(options.codexHome, { recursive: true });
83515
- writeFileSync3(join2(options.codexHome, "config.toml"), options.configToml);
83953
+ mkdirSync5(options.codexHome, { recursive: true });
83954
+ writeFileSync5(join3(options.codexHome, "config.toml"), options.configToml);
83516
83955
  const startedAt = Date.now();
83517
83956
  this.input.writeOutput?.(
83518
83957
  `agent_bridge_codex_startup_started codex_home=${options.codexHome}`
83519
83958
  );
83959
+ ensureCodexEditCapability({
83960
+ command: options.command,
83961
+ ...this.input.writeOutput ? { writeOutput: this.input.writeOutput } : {}
83962
+ });
83520
83963
  const proc = spawn(options.command, options.args, {
83521
83964
  env: options.env,
83522
83965
  stdio: ["pipe", "pipe", "pipe"]
@@ -83916,12 +84359,17 @@ var CodexAgentBridgeSessionImpl = class {
83916
84359
  this.pendingToolItemIds.add(notification.item.id);
83917
84360
  }
83918
84361
  return;
83919
- case "itemCompleted":
84362
+ case "itemCompleted": {
84363
+ const fallthrough = codexEditFallthroughMarker(notification.item);
84364
+ if (fallthrough) {
84365
+ this.input.writeOutput?.(fallthrough);
84366
+ }
83920
84367
  this.pendingToolItemIds.delete(notification.item.id);
83921
84368
  if (this.pendingToolItemIds.size === 0) {
83922
84369
  this.resolveSettlement();
83923
84370
  }
83924
84371
  return;
84372
+ }
83925
84373
  default:
83926
84374
  return;
83927
84375
  }
@@ -84406,6 +84854,7 @@ function createHarnessCommandHandler(input) {
84406
84854
  return createClaudeCodeCommandHandler({
84407
84855
  ...base,
84408
84856
  claude,
84857
+ readState: fileClaudeReadStateStore(),
84409
84858
  sessionResume: fileClaudeSessionResumeStore()
84410
84859
  });
84411
84860
  }
@@ -84627,7 +85076,7 @@ function bridgeUrlHost(bridgeUrl) {
84627
85076
  }
84628
85077
 
84629
85078
  // src/lib/entrypoint.ts
84630
- import { realpathSync as realpathSync2 } from "fs";
85079
+ import { realpathSync as realpathSync3 } from "fs";
84631
85080
  import { pathToFileURL } from "url";
84632
85081
  function isCliEntrypoint(input) {
84633
85082
  if (input.entrypoint.kind === "missing") {
@@ -84635,7 +85084,7 @@ function isCliEntrypoint(input) {
84635
85084
  }
84636
85085
  let resolvedEntrypoint;
84637
85086
  try {
84638
- resolvedEntrypoint = realpathSync2(input.entrypoint.path);
85087
+ resolvedEntrypoint = realpathSync3(input.entrypoint.path);
84639
85088
  } catch {
84640
85089
  return false;
84641
85090
  }