@autohq/cli 0.1.417 → 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.
package/dist/index.js CHANGED
@@ -1159,8 +1159,8 @@ var init_regexes = __esm({
1159
1159
  _emoji = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
1160
1160
  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])$/;
1161
1161
  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}|:))$/;
1162
- mac = (delimiter) => {
1163
- const escapedDelim = escapeRegex(delimiter ?? ":");
1162
+ mac = (delimiter2) => {
1163
+ const escapedDelim = escapeRegex(delimiter2 ?? ":");
1164
1164
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
1165
1165
  };
1166
1166
  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])$/;
@@ -20657,7 +20657,8 @@ var init_project_resources = __esm({
20657
20657
  name: external_exports.string().min(1),
20658
20658
  path: external_exports.string().min(1),
20659
20659
  file: external_exports.string().min(1),
20660
- line: external_exports.number().int().positive()
20660
+ line: external_exports.number().int().positive(),
20661
+ displayPath: external_exports.string().min(1).optional()
20661
20662
  });
20662
20663
  ProjectApplyRequestSchema = external_exports.object({
20663
20664
  delete: external_exports.array(ProjectDeleteResourceSchema).default([]),
@@ -36172,15 +36173,15 @@ async function* readSseEvents(body) {
36172
36173
  break;
36173
36174
  }
36174
36175
  buffer += decoder.decode(value, { stream: true });
36175
- let delimiter = buffer.indexOf("\n\n");
36176
- while (delimiter !== -1) {
36177
- const rawEvent = buffer.slice(0, delimiter);
36178
- buffer = buffer.slice(delimiter + 2);
36176
+ let delimiter2 = buffer.indexOf("\n\n");
36177
+ while (delimiter2 !== -1) {
36178
+ const rawEvent = buffer.slice(0, delimiter2);
36179
+ buffer = buffer.slice(delimiter2 + 2);
36179
36180
  const event2 = parseSseEvent(rawEvent);
36180
36181
  if (event2) {
36181
36182
  yield event2;
36182
36183
  }
36183
- delimiter = buffer.indexOf("\n\n");
36184
+ delimiter2 = buffer.indexOf("\n\n");
36184
36185
  }
36185
36186
  }
36186
36187
  buffer += decoder.decode();
@@ -38669,7 +38670,7 @@ var init_package = __esm({
38669
38670
  "package.json"() {
38670
38671
  package_default = {
38671
38672
  name: "@autohq/cli",
38672
- version: "0.1.417",
38673
+ version: "0.1.419",
38673
38674
  license: "SEE LICENSE IN README.md",
38674
38675
  publishConfig: {
38675
38676
  access: "public"
@@ -38734,13 +38735,13 @@ var init_version = __esm({
38734
38735
  });
38735
38736
 
38736
38737
  // src/commands/agents/authoring.ts
38737
- import { readFileSync as readFileSync4, readdirSync as readdirSync2, statSync } from "fs";
38738
+ import { readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
38738
38739
  import {
38739
38740
  basename as basename2,
38740
- dirname as dirname5,
38741
+ dirname as dirname7,
38741
38742
  extname,
38742
38743
  isAbsolute,
38743
- join as join5,
38744
+ join as join6,
38744
38745
  resolve
38745
38746
  } from "path";
38746
38747
  import { parseAllDocuments as parseYamlDocuments, stringify } from "yaml";
@@ -38792,8 +38793,8 @@ function renderAgentExplain(result) {
38792
38793
  return lines.join("\n");
38793
38794
  }
38794
38795
  function readLocalAgentAuthoringStatuses(input) {
38795
- const agentsDirectory = join5(
38796
- input?.directory ?? join5(process.cwd(), ".auto"),
38796
+ const agentsDirectory = join6(
38797
+ input?.directory ?? join6(process.cwd(), ".auto"),
38797
38798
  "agents"
38798
38799
  );
38799
38800
  const paths = agentAuthoringFiles(agentsDirectory);
@@ -38832,7 +38833,7 @@ function agentAuthoringFiles(directory) {
38832
38833
  }
38833
38834
  const files = [];
38834
38835
  for (const entry of entries) {
38835
- const path2 = join5(directory, entry.name);
38836
+ const path2 = join6(directory, entry.name);
38836
38837
  if (entry.isDirectory()) {
38837
38838
  files.push(...agentAuthoringFiles(path2));
38838
38839
  continue;
@@ -38852,12 +38853,12 @@ function resolveAgentAuthoringPath(input) {
38852
38853
  if (isAgentFile(candidate)) {
38853
38854
  return candidate;
38854
38855
  }
38855
- const agentsDirectory = join5(
38856
- input.directory ?? join5(process.cwd(), ".auto"),
38856
+ const agentsDirectory = join6(
38857
+ input.directory ?? join6(process.cwd(), ".auto"),
38857
38858
  "agents"
38858
38859
  );
38859
38860
  for (const extension of AGENT_FILE_EXTENSIONS) {
38860
- const path2 = join5(agentsDirectory, `${input.agent}${extension}`);
38861
+ const path2 = join6(agentsDirectory, `${input.agent}${extension}`);
38861
38862
  if (isAgentFile(path2)) {
38862
38863
  return path2;
38863
38864
  }
@@ -38915,7 +38916,7 @@ function readSingleDocument(path2) {
38915
38916
  return documents[0];
38916
38917
  }
38917
38918
  function readDocuments(path2) {
38918
- const source = readFileSync4(path2, "utf8");
38919
+ const source = readFileSync6(path2, "utf8");
38919
38920
  const documents = parseYamlDocuments(source);
38920
38921
  const parseError = documents.flatMap((document) => document.errors).at(0);
38921
38922
  if (parseError) {
@@ -38940,7 +38941,7 @@ function resolveImportPath(importPath, importerPath) {
38940
38941
  if (isAbsolute(importPath) || /^[A-Za-z]+:\/\//.test(importPath)) {
38941
38942
  throw new Error(`Agent import must be a relative path: ${importPath}`);
38942
38943
  }
38943
- const resolved = resolve(dirname5(importerPath), importPath);
38944
+ const resolved = resolve(dirname7(importerPath), importPath);
38944
38945
  if (!isAgentFile(resolved)) {
38945
38946
  throw new Error(
38946
38947
  `Agent import not found: ${importPath} from ${importerPath}`
@@ -39115,7 +39116,7 @@ function resolveFileBackedString(value, input) {
39115
39116
  `Invalid agent authoring file ${input.path}: ${input.field}.file must be a relative path`
39116
39117
  );
39117
39118
  }
39118
- return readFileSync4(resolve(dirname5(input.path), filePath), "utf8");
39119
+ return readFileSync6(resolve(dirname7(input.path), filePath), "utf8");
39119
39120
  }
39120
39121
  function removalDirectives(document, path2) {
39121
39122
  const raw = isRecord(document.remove) ? document.remove : {};
@@ -39266,7 +39267,7 @@ function importedEdgeCount(graph) {
39266
39267
  }
39267
39268
  function isAgentFile(path2) {
39268
39269
  try {
39269
- return statSync(path2).isFile();
39270
+ return statSync2(path2).isFile();
39270
39271
  } catch {
39271
39272
  return false;
39272
39273
  }
@@ -40892,6 +40893,7 @@ function readApplyDocument(path2, document, fileIndex, contextVariables) {
40892
40893
  resource,
40893
40894
  primaryResource: result.resource,
40894
40895
  draftLocations: result.sourceLocations,
40896
+ authoredTriggers: result.authoredTriggers,
40895
40897
  generatedLocation
40896
40898
  })
40897
40899
  };
@@ -40899,7 +40901,11 @@ function readApplyDocument(path2, document, fileIndex, contextVariables) {
40899
40901
  }
40900
40902
  function sourceLocationsForCompiledResource(input) {
40901
40903
  if (input.resource === input.primaryResource) {
40902
- return Object.values(input.draftLocations).map((location) => ({
40904
+ const draftLocations = projectCompiledTriggerSourceLocations(
40905
+ input.draftLocations,
40906
+ input.authoredTriggers
40907
+ );
40908
+ return Object.values(draftLocations).map((location) => ({
40903
40909
  ...location,
40904
40910
  kind: input.resource.kind,
40905
40911
  name: input.resource.metadata.name
@@ -40917,6 +40923,78 @@ function sourceLocationsForCompiledResource(input) {
40917
40923
  }
40918
40924
  ];
40919
40925
  }
40926
+ function projectCompiledTriggerSourceLocations(locations, authoredTriggers) {
40927
+ if (!Array.isArray(authoredTriggers)) {
40928
+ return locations;
40929
+ }
40930
+ const projected = Object.fromEntries(
40931
+ Object.entries(locations).filter(
40932
+ ([path2]) => !path2.startsWith("spec.triggers[")
40933
+ )
40934
+ );
40935
+ let compiledIndex = 0;
40936
+ for (const [authoredIndex, trigger] of authoredTriggers.entries()) {
40937
+ if (!isRecord2(trigger)) {
40938
+ continue;
40939
+ }
40940
+ const events = authoredTriggerEvents(trigger);
40941
+ const displayName = authoredTriggerDisplayName(trigger, events);
40942
+ const authoredPrefix = `spec.triggers[${authoredIndex}]`;
40943
+ const triggerLocations = Object.entries(locations).filter(
40944
+ ([path2]) => path2 === authoredPrefix || path2.startsWith(`${authoredPrefix}.`)
40945
+ );
40946
+ for (const [eventIndex] of events.entries()) {
40947
+ const compiledPrefix = `spec.triggers[${compiledIndex}]`;
40948
+ for (const [path2, location] of triggerLocations) {
40949
+ if (path2.startsWith(`${authoredPrefix}.events`)) {
40950
+ continue;
40951
+ }
40952
+ const suffix = path2.slice(authoredPrefix.length);
40953
+ projected[`${compiledPrefix}${suffix}`] = {
40954
+ ...location,
40955
+ path: `${compiledPrefix}${suffix}`,
40956
+ displayPath: `triggers.${displayName}${suffix}`
40957
+ };
40958
+ }
40959
+ const eventLocation = locations[`${authoredPrefix}.events[${eventIndex}]`] ?? locations[`${authoredPrefix}.event`] ?? locations[`${authoredPrefix}.events`];
40960
+ if (eventLocation) {
40961
+ projected[`${compiledPrefix}.event`] = {
40962
+ ...eventLocation,
40963
+ path: `${compiledPrefix}.event`,
40964
+ displayPath: `triggers.${displayName}.event`
40965
+ };
40966
+ }
40967
+ compiledIndex += 1;
40968
+ }
40969
+ }
40970
+ return projected;
40971
+ }
40972
+ function authoredTriggerEvents(trigger) {
40973
+ if (trigger.kind === "heartbeat") {
40974
+ return ["heartbeat"];
40975
+ }
40976
+ if (typeof trigger.event === "string") {
40977
+ return [trigger.event];
40978
+ }
40979
+ if (Array.isArray(trigger.events)) {
40980
+ return trigger.events.filter(
40981
+ (event) => typeof event === "string"
40982
+ );
40983
+ }
40984
+ return [];
40985
+ }
40986
+ function authoredTriggerDisplayName(trigger, events) {
40987
+ if (typeof trigger.name === "string") {
40988
+ return trigger.name;
40989
+ }
40990
+ if (events.length > 0) {
40991
+ return events.join(" + ");
40992
+ }
40993
+ if (typeof trigger.cron === "string") {
40994
+ return `cron ${trigger.cron}`;
40995
+ }
40996
+ return "trigger";
40997
+ }
40920
40998
  function validateAgentFragmentDocument(document, path2, context) {
40921
40999
  const normalizedPath = normalizeSourcePath(path2);
40922
41000
  if (context.stack.includes(normalizedPath)) {
@@ -40980,9 +41058,11 @@ function compileAgentDocumentValue(document, path2, fileIndex, contextVariables)
40980
41058
  variables: /* @__PURE__ */ new Map(),
40981
41059
  ...contextVariables && Object.keys(contextVariables).length > 0 ? { contextVariables: new Map(Object.entries(contextVariables)) } : {}
40982
41060
  });
41061
+ const authoredTriggers = structuredClone(draft.spec.triggers);
40983
41062
  return {
40984
41063
  ...compileAgentDraftResources(draft, path2),
40985
- sourceLocations: draft.sourceLocations
41064
+ sourceLocations: draft.sourceLocations,
41065
+ authoredTriggers
40986
41066
  };
40987
41067
  }
40988
41068
  function compileAgentDocument2(document, path2, context) {
@@ -41545,18 +41625,18 @@ var init_project_apply_files2 = __esm({
41545
41625
 
41546
41626
  // src/commands/apply/files.ts
41547
41627
  import {
41548
- existsSync as existsSync4,
41549
- readFileSync as readFileSync5,
41628
+ existsSync as existsSync6,
41629
+ readFileSync as readFileSync7,
41550
41630
  readdirSync as readdirSync3,
41551
- realpathSync,
41552
- statSync as statSync2
41631
+ realpathSync as realpathSync2,
41632
+ statSync as statSync3
41553
41633
  } from "fs";
41554
41634
  import {
41555
41635
  basename as basename3,
41556
- dirname as dirname6,
41636
+ dirname as dirname8,
41557
41637
  extname as extname3,
41558
41638
  isAbsolute as isAbsolute2,
41559
- join as join7,
41639
+ join as join8,
41560
41640
  relative,
41561
41641
  resolve as resolve2
41562
41642
  } from "path";
@@ -41587,7 +41667,7 @@ function readProjectApplyBundleInput(options) {
41587
41667
  }
41588
41668
  };
41589
41669
  }
41590
- const directory = resolve2(options.directory ?? join7(process.cwd(), ".auto"));
41670
+ const directory = resolve2(options.directory ?? join8(process.cwd(), ".auto"));
41591
41671
  const projectRoot = applyProjectRoot(directory);
41592
41672
  const files = withManagedTemplateFiles(sourceFiles(directory, projectRoot));
41593
41673
  const resourceRoot = sourcePathRelative(projectRoot, directory);
@@ -41624,7 +41704,7 @@ function sourceFiles(root, projectRoot) {
41624
41704
  return [];
41625
41705
  }
41626
41706
  return entries.flatMap((entry) => {
41627
- const path2 = join7(root, entry.name);
41707
+ const path2 = join8(root, entry.name);
41628
41708
  if (entry.isDirectory()) {
41629
41709
  return sourceFiles(path2, projectRoot);
41630
41710
  }
@@ -41637,7 +41717,7 @@ function sourceFiles(root, projectRoot) {
41637
41717
  function sourceFile(path2, projectRoot) {
41638
41718
  return {
41639
41719
  path: sourcePathRelative(projectRoot, path2),
41640
- contentBase64: readFileSync5(path2).toString("base64")
41720
+ contentBase64: readFileSync7(path2).toString("base64")
41641
41721
  };
41642
41722
  }
41643
41723
  function applyBundle(files) {
@@ -41678,24 +41758,24 @@ function filesystemAssetReader(projectRoot) {
41678
41758
  }
41679
41759
  return {
41680
41760
  path: path2,
41681
- bytes: readFileSync5(path2)
41761
+ bytes: readFileSync7(path2)
41682
41762
  };
41683
41763
  };
41684
41764
  }
41685
41765
  function applyProjectRoot(directory) {
41686
41766
  const resolved = resolve2(directory);
41687
- return basename3(resolved) === ".auto" ? dirname6(resolved) : resolved;
41767
+ return basename3(resolved) === ".auto" ? dirname8(resolved) : resolved;
41688
41768
  }
41689
41769
  function applyFileProjectRoot(file2) {
41690
- let dir = dirname6(resolve2(file2));
41770
+ let dir = dirname8(resolve2(file2));
41691
41771
  while (true) {
41692
41772
  if (basename3(dir) === ".auto") {
41693
- return dirname6(dir);
41773
+ return dirname8(dir);
41694
41774
  }
41695
41775
  if (directoryHasAutoRoot(dir)) {
41696
41776
  return dir;
41697
41777
  }
41698
- const parent = dirname6(dir);
41778
+ const parent = dirname8(dir);
41699
41779
  if (parent === dir) {
41700
41780
  return process.cwd();
41701
41781
  }
@@ -41704,14 +41784,14 @@ function applyFileProjectRoot(file2) {
41704
41784
  }
41705
41785
  function applyFileSourceRoot(file2, projectRoot) {
41706
41786
  const autoRoot = resolve2(projectRoot, ".auto");
41707
- return file2 === autoRoot || isInside(file2, autoRoot) ? autoRoot : dirname6(file2);
41787
+ return file2 === autoRoot || isInside(file2, autoRoot) ? autoRoot : dirname8(file2);
41708
41788
  }
41709
41789
  function directoryHasAutoRoot(directory) {
41710
41790
  const autoRoot = resolve2(directory, ".auto");
41711
- if (!existsSync4(autoRoot)) {
41791
+ if (!existsSync6(autoRoot)) {
41712
41792
  return false;
41713
41793
  }
41714
- return statSync2(autoRoot).isDirectory();
41794
+ return statSync3(autoRoot).isDirectory();
41715
41795
  }
41716
41796
  function displayResourceRoot(directory) {
41717
41797
  return basename3(directory) === ".auto" ? ".auto" : directory;
@@ -41734,11 +41814,11 @@ function validateAgentAvatarAsset(input) {
41734
41814
  `Invalid identity avatar asset for "${input.resourceName}": asset path must be under .auto/assets`
41735
41815
  );
41736
41816
  }
41737
- const projectRoot = realpathSync(input.projectRoot);
41817
+ const projectRoot = realpathSync2(input.projectRoot);
41738
41818
  const assetPath = resolve2(projectRoot, input.asset);
41739
41819
  let assetsRoot;
41740
41820
  try {
41741
- assetsRoot = realpathSync(resolve2(projectRoot, ".auto", "assets"));
41821
+ assetsRoot = realpathSync2(resolve2(projectRoot, ".auto", "assets"));
41742
41822
  } catch {
41743
41823
  if (input.allowMissing) {
41744
41824
  return null;
@@ -41750,8 +41830,8 @@ function validateAgentAvatarAsset(input) {
41750
41830
  let resolvedAssetPath;
41751
41831
  let stat;
41752
41832
  try {
41753
- resolvedAssetPath = realpathSync(assetPath);
41754
- stat = statSync2(resolvedAssetPath);
41833
+ resolvedAssetPath = realpathSync2(assetPath);
41834
+ stat = statSync3(resolvedAssetPath);
41755
41835
  } catch {
41756
41836
  if (input.allowMissing) {
41757
41837
  return null;
@@ -42316,14 +42396,14 @@ var init_resources3 = __esm({
42316
42396
  // src/commands/edit/actions.ts
42317
42397
  import { spawn as spawn3 } from "child_process";
42318
42398
  import {
42319
- mkdirSync as mkdirSync5,
42320
- mkdtempSync as mkdtempSync2,
42321
- readFileSync as readFileSync6,
42322
- rmSync as rmSync2,
42323
- writeFileSync as writeFileSync6
42399
+ mkdirSync as mkdirSync6,
42400
+ mkdtempSync as mkdtempSync3,
42401
+ readFileSync as readFileSync8,
42402
+ rmSync as rmSync3,
42403
+ writeFileSync as writeFileSync8
42324
42404
  } from "fs";
42325
- import { tmpdir as tmpdir2 } from "os";
42326
- import { join as join8 } from "path";
42405
+ import { tmpdir as tmpdir3 } from "os";
42406
+ import { join as join9 } from "path";
42327
42407
  import { parseAllDocuments as parseYamlDocuments3, stringify as stringify4 } from "yaml";
42328
42408
  async function editResource(input) {
42329
42409
  const reference = parseProjectResourceReference(input.resource);
@@ -42343,15 +42423,15 @@ async function editResource(input) {
42343
42423
  const document = editableAgentFacade(current);
42344
42424
  const source = `${stringify4(document).trimEnd()}
42345
42425
  `;
42346
- const tempRoot = mkdtempSync2(join8(tmpdir2(), "auto-edit-"));
42347
- const agentsDir = join8(tempRoot, ".auto", "agents");
42348
- mkdirSync5(agentsDir, { recursive: true });
42349
- const filePath = join8(agentsDir, `${reference.name}.yaml`);
42350
- writeFileSync6(filePath, source, "utf8");
42426
+ const tempRoot = mkdtempSync3(join9(tmpdir3(), "auto-edit-"));
42427
+ const agentsDir = join9(tempRoot, ".auto", "agents");
42428
+ mkdirSync6(agentsDir, { recursive: true });
42429
+ const filePath = join9(agentsDir, `${reference.name}.yaml`);
42430
+ writeFileSync8(filePath, source, "utf8");
42351
42431
  let removeTempFile = false;
42352
42432
  try {
42353
42433
  await runEditor(editor, filePath);
42354
- const editedSource = readFileSync6(filePath, "utf8");
42434
+ const editedSource = readFileSync8(filePath, "utf8");
42355
42435
  if (editedSource === source) {
42356
42436
  input.writeOutput("No changes; skipped apply.");
42357
42437
  removeTempFile = true;
@@ -42378,7 +42458,7 @@ async function editResource(input) {
42378
42458
  Edited file retained at ${filePath}`);
42379
42459
  } finally {
42380
42460
  if (removeTempFile) {
42381
- rmSync2(tempRoot, { recursive: true, force: true });
42461
+ rmSync3(tempRoot, { recursive: true, force: true });
42382
42462
  }
42383
42463
  }
42384
42464
  }
@@ -42417,7 +42497,7 @@ async function runEditor(editor, filePath) {
42417
42497
  });
42418
42498
  }
42419
42499
  function assertEditedResourceIdentity(filePath, expected) {
42420
- const source = readFileSync6(filePath, "utf8");
42500
+ const source = readFileSync8(filePath, "utf8");
42421
42501
  let parsedDocuments;
42422
42502
  try {
42423
42503
  parsedDocuments = parseYamlDocuments3(source);
@@ -47906,8 +47986,8 @@ __export(launcher_exports, {
47906
47986
  launch: () => launch
47907
47987
  });
47908
47988
  import { spawnSync } from "child_process";
47909
- import { existsSync as existsSync6 } from "fs";
47910
- import { dirname as dirname7, resolve as resolve3 } from "path";
47989
+ import { existsSync as existsSync8 } from "fs";
47990
+ import { dirname as dirname9, resolve as resolve3 } from "path";
47911
47991
  import { fileURLToPath } from "url";
47912
47992
  import {
47913
47993
  QueryClient,
@@ -48087,7 +48167,7 @@ function resolveSplashVersion() {
48087
48167
  return resolveLatestReleaseVersionFromCheckout() ?? cliVersion;
48088
48168
  }
48089
48169
  function resolveLatestReleaseVersionFromCheckout() {
48090
- const repoRoot = findRepoRoot(dirname7(fileURLToPath(import.meta.url)));
48170
+ const repoRoot = findRepoRoot(dirname9(fileURLToPath(import.meta.url)));
48091
48171
  if (!repoRoot) {
48092
48172
  return null;
48093
48173
  }
@@ -48104,10 +48184,10 @@ function resolveLatestReleaseVersionFromCheckout() {
48104
48184
  function findRepoRoot(startDirectory) {
48105
48185
  let directory = startDirectory;
48106
48186
  while (true) {
48107
- if (existsSync6(resolve3(directory, ".git")) && existsSync6(resolve3(directory, "apps/cli/package.json"))) {
48187
+ if (existsSync8(resolve3(directory, ".git")) && existsSync8(resolve3(directory, "apps/cli/package.json"))) {
48108
48188
  return directory;
48109
48189
  }
48110
- const parent = dirname7(directory);
48190
+ const parent = dirname9(directory);
48111
48191
  if (parent === directory) {
48112
48192
  return null;
48113
48193
  }
@@ -51919,6 +51999,233 @@ function uiChunk(chunk) {
51919
51999
  };
51920
52000
  }
51921
52001
 
52002
+ // src/commands/agent-bridge/harness/claude-code/read-state.ts
52003
+ import {
52004
+ existsSync as existsSync2,
52005
+ mkdirSync as mkdirSync3,
52006
+ readFileSync as readFileSync3,
52007
+ statSync,
52008
+ writeFileSync as writeFileSync3
52009
+ } from "fs";
52010
+ import { dirname as dirname4 } from "path";
52011
+
52012
+ // src/commands/agent-bridge/harness/claude-code/resume-store.ts
52013
+ import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
52014
+ import { dirname as dirname3 } from "path";
52015
+ var AGENT_BRIDGE_RUNTIME_DIR = "/tmp/auto-bridge-runtime";
52016
+ var CLAUDE_SESSION_RESUME_PATH = `${AGENT_BRIDGE_RUNTIME_DIR}/claude-session-id`;
52017
+ function fileClaudeSessionResumeStore(path2 = CLAUDE_SESSION_RESUME_PATH) {
52018
+ return {
52019
+ read(sessionId) {
52020
+ if (!existsSync(path2)) {
52021
+ return null;
52022
+ }
52023
+ const record2 = parseResumeRecord(readFileSync2(path2, "utf8"));
52024
+ if (!record2 || record2.sessionId !== sessionId) {
52025
+ return null;
52026
+ }
52027
+ return record2.agentId;
52028
+ },
52029
+ write(record2) {
52030
+ mkdirSync2(dirname3(path2), { recursive: true });
52031
+ writeFileSync2(path2, `${JSON.stringify(record2)}
52032
+ `, "utf8");
52033
+ }
52034
+ };
52035
+ }
52036
+ function parseResumeRecord(raw) {
52037
+ try {
52038
+ const value = JSON.parse(raw);
52039
+ if (value !== null && typeof value === "object" && "sessionId" in value && "agentId" in value && typeof value.sessionId === "string" && typeof value.agentId === "string" && value.agentId.length > 0) {
52040
+ return { sessionId: value.sessionId, agentId: value.agentId };
52041
+ }
52042
+ return null;
52043
+ } catch {
52044
+ return null;
52045
+ }
52046
+ }
52047
+
52048
+ // src/commands/agent-bridge/harness/claude-code/read-state.ts
52049
+ var CLAUDE_READ_STATE_PATH = `${AGENT_BRIDGE_RUNTIME_DIR}/claude-read-state`;
52050
+ var CLAUDE_READ_STATE_MAX_ENTRIES = 256;
52051
+ var ClaudeReadStateTracker = class {
52052
+ constructor(store) {
52053
+ this.store = store;
52054
+ }
52055
+ store;
52056
+ // Most-recently-observed entries last (Map preserves insertion order, and
52057
+ // touches re-insert), so eviction drops the stalest observation first.
52058
+ entriesByPath = /* @__PURE__ */ new Map();
52059
+ // tool_use ids of in-flight file-tool calls, mapped to the file they target.
52060
+ // Cleared at each turn's terminal result so interrupted calls cannot leak.
52061
+ pendingFileToolUses = /* @__PURE__ */ new Map();
52062
+ loadedForSessionId = null;
52063
+ // Feed every live SDK message through here. Successful Read/Write/Edit
52064
+ // results commit a path+mtime observation; everything else is ignored.
52065
+ observe(sessionId, message) {
52066
+ this.ensureLoaded(sessionId);
52067
+ if (message.type === "result") {
52068
+ this.pendingFileToolUses.clear();
52069
+ return;
52070
+ }
52071
+ if (message.type === "assistant" && message.parent_tool_use_id === null) {
52072
+ for (const block of contentBlocks(message.message.content)) {
52073
+ const use = fileToolUse(block);
52074
+ if (use) {
52075
+ this.pendingFileToolUses.set(use.toolUseId, use.path);
52076
+ }
52077
+ }
52078
+ return;
52079
+ }
52080
+ if (message.type !== "user" || message.parent_tool_use_id !== null) {
52081
+ return;
52082
+ }
52083
+ if ("isReplay" in message && message.isReplay === true) {
52084
+ return;
52085
+ }
52086
+ for (const block of contentBlocks(message.message.content)) {
52087
+ if (block.type !== "tool_result") {
52088
+ continue;
52089
+ }
52090
+ const toolUseId = typeof block.tool_use_id === "string" ? block.tool_use_id : null;
52091
+ if (toolUseId === null) {
52092
+ continue;
52093
+ }
52094
+ const path2 = this.pendingFileToolUses.get(toolUseId);
52095
+ this.pendingFileToolUses.delete(toolUseId);
52096
+ if (path2 !== void 0 && block.is_error !== true) {
52097
+ this.commit(sessionId, path2);
52098
+ }
52099
+ }
52100
+ }
52101
+ // The seeds to replay into a fresh CLI process, stalest observation first so
52102
+ // the most recent reads survive any CLI-side eviction.
52103
+ seeds(sessionId) {
52104
+ this.ensureLoaded(sessionId);
52105
+ return [...this.entriesByPath].map(([path2, mtime]) => ({ path: path2, mtime }));
52106
+ }
52107
+ // A conversation-lineage break: the next CLI session starts with no prior
52108
+ // context, so nothing the model "remembers reading" exists anymore.
52109
+ clear(sessionId) {
52110
+ this.ensureLoaded(sessionId);
52111
+ if (this.entriesByPath.size === 0) {
52112
+ return;
52113
+ }
52114
+ this.entriesByPath.clear();
52115
+ this.persist(sessionId);
52116
+ }
52117
+ ensureLoaded(sessionId) {
52118
+ if (this.loadedForSessionId === sessionId) {
52119
+ return;
52120
+ }
52121
+ this.loadedForSessionId = sessionId;
52122
+ this.entriesByPath.clear();
52123
+ this.pendingFileToolUses.clear();
52124
+ for (const entry of this.store.read(sessionId) ?? []) {
52125
+ this.entriesByPath.set(entry.path, entry.mtime);
52126
+ }
52127
+ }
52128
+ commit(sessionId, path2) {
52129
+ let mtime;
52130
+ try {
52131
+ mtime = Math.floor(statSync(path2).mtimeMs);
52132
+ } catch {
52133
+ if (this.entriesByPath.delete(path2)) {
52134
+ this.persist(sessionId);
52135
+ }
52136
+ return;
52137
+ }
52138
+ this.entriesByPath.delete(path2);
52139
+ this.entriesByPath.set(path2, mtime);
52140
+ while (this.entriesByPath.size > CLAUDE_READ_STATE_MAX_ENTRIES) {
52141
+ const oldest = this.entriesByPath.keys().next().value;
52142
+ if (oldest === void 0) {
52143
+ break;
52144
+ }
52145
+ this.entriesByPath.delete(oldest);
52146
+ }
52147
+ this.persist(sessionId);
52148
+ }
52149
+ persist(sessionId) {
52150
+ this.store.write({ sessionId, entries: this.seeds(sessionId) });
52151
+ }
52152
+ };
52153
+ function fileClaudeReadStateStore(path2 = CLAUDE_READ_STATE_PATH) {
52154
+ return {
52155
+ read(sessionId) {
52156
+ if (!existsSync2(path2)) {
52157
+ return null;
52158
+ }
52159
+ const record2 = parseReadStateRecord(readFileSync3(path2, "utf8"));
52160
+ if (!record2 || record2.sessionId !== sessionId) {
52161
+ return null;
52162
+ }
52163
+ return record2.entries;
52164
+ },
52165
+ write(record2) {
52166
+ mkdirSync3(dirname4(path2), { recursive: true });
52167
+ writeFileSync3(path2, `${JSON.stringify(record2)}
52168
+ `, "utf8");
52169
+ }
52170
+ };
52171
+ }
52172
+ function fileToolUse(block) {
52173
+ if (block.type !== "tool_use" || typeof block.id !== "string") {
52174
+ return null;
52175
+ }
52176
+ const input = block.input;
52177
+ if (typeof input !== "object" || input === null) {
52178
+ return null;
52179
+ }
52180
+ const filePath = input.file_path;
52181
+ if (typeof filePath !== "string" || filePath.length === 0) {
52182
+ return null;
52183
+ }
52184
+ switch (block.name) {
52185
+ case "Read": {
52186
+ const { offset, limit } = input;
52187
+ if (offset !== void 0 || limit !== void 0) {
52188
+ return null;
52189
+ }
52190
+ return { toolUseId: block.id, path: filePath };
52191
+ }
52192
+ case "Write":
52193
+ case "Edit":
52194
+ return { toolUseId: block.id, path: filePath };
52195
+ default:
52196
+ return null;
52197
+ }
52198
+ }
52199
+ function contentBlocks(content) {
52200
+ if (!Array.isArray(content)) {
52201
+ return [];
52202
+ }
52203
+ return content.filter(
52204
+ (block) => typeof block === "object" && block !== null
52205
+ );
52206
+ }
52207
+ function parseReadStateRecord(raw) {
52208
+ try {
52209
+ const value = JSON.parse(raw);
52210
+ if (value === null || typeof value !== "object" || !("sessionId" in value) || !("entries" in value) || typeof value.sessionId !== "string" || !Array.isArray(value.entries)) {
52211
+ return null;
52212
+ }
52213
+ const entries = [];
52214
+ for (const entry of value.entries) {
52215
+ if (entry === null || typeof entry !== "object" || typeof entry.path !== "string" || typeof entry.mtime !== "number") {
52216
+ return null;
52217
+ }
52218
+ entries.push({
52219
+ path: entry.path,
52220
+ mtime: entry.mtime
52221
+ });
52222
+ }
52223
+ return { sessionId: value.sessionId, entries };
52224
+ } catch {
52225
+ return null;
52226
+ }
52227
+ }
52228
+
51922
52229
  // src/commands/agent-bridge/harness/claude-code/session.ts
51923
52230
  import {
51924
52231
  startup as startupClaudeAgent
@@ -52118,6 +52425,7 @@ var CLAUDE_INTERRUPT_SETTLE_TIMEOUT_MS = 1e4;
52118
52425
  var CLAUDE_INTERRUPT_ACK_TIMEOUT_MS = 1e4;
52119
52426
  var CLAUDE_MCP_REGISTRATION_TIMEOUT_MS = 3e3;
52120
52427
  var CLAUDE_MCP_REGISTRATION_POLL_INTERVAL_MS = 100;
52428
+ var CLAUDE_READ_STATE_SEED_FAILURE_LIMIT = 3;
52121
52429
  var CLAUDE_STARTUP_PROFILE_HOOK_EVENTS = [
52122
52430
  "Setup",
52123
52431
  "SessionStart",
@@ -52334,6 +52642,32 @@ var ClaudeAgentBridgeSessionImpl = class {
52334
52642
  }
52335
52643
  );
52336
52644
  }
52645
+ async seedReadState(seeds) {
52646
+ if (seeds.length === 0 || this.state.kind !== "running") {
52647
+ return;
52648
+ }
52649
+ const query = this.state.query;
52650
+ const startedAt = Date.now();
52651
+ let seeded = 0;
52652
+ let failed = 0;
52653
+ for (const seed of seeds) {
52654
+ try {
52655
+ await query.seedReadState(seed.path, seed.mtime);
52656
+ seeded += 1;
52657
+ } catch (error51) {
52658
+ failed += 1;
52659
+ this.input.writeOutput?.(
52660
+ `agent_bridge_claude_read_state_seed_failed path=${seed.path} error=${error51 instanceof Error ? error51.message : String(error51)}`
52661
+ );
52662
+ if (failed >= CLAUDE_READ_STATE_SEED_FAILURE_LIMIT) {
52663
+ break;
52664
+ }
52665
+ }
52666
+ }
52667
+ this.input.writeOutput?.(
52668
+ `agent_bridge_claude_read_state_seeded seeded=${seeded} total=${seeds.length} duration_ms=${Date.now() - startedAt}`
52669
+ );
52670
+ }
52337
52671
  close() {
52338
52672
  const previousState = this.state;
52339
52673
  if (previousState.kind === "closed") {
@@ -52395,6 +52729,7 @@ var ClaudeAgentBridgeSessionImpl = class {
52395
52729
  this.input.writeOutput?.(
52396
52730
  `agent_bridge_claude_resume_fallback session_id=${resume}`
52397
52731
  );
52732
+ this.input.onResumeFallback?.();
52398
52733
  this.state = { kind: "idle" };
52399
52734
  return this.startSdkSession();
52400
52735
  }
@@ -52999,7 +53334,7 @@ function isClaudeAgentTurnResult(message) {
52999
53334
  }
53000
53335
  function toolUseIds(message) {
53001
53336
  if (message.type === "assistant") {
53002
- return contentBlocks(message.message.content).flatMap(
53337
+ return contentBlocks2(message.message.content).flatMap(
53003
53338
  (block2) => block2.type === "tool_use" && typeof block2.id === "string" ? [block2.id] : []
53004
53339
  );
53005
53340
  }
@@ -53017,11 +53352,11 @@ function toolResultIds(message) {
53017
53352
  if (message.type !== "user") {
53018
53353
  return [];
53019
53354
  }
53020
- return contentBlocks(message.message.content).flatMap(
53355
+ return contentBlocks2(message.message.content).flatMap(
53021
53356
  (block) => block.type === "tool_result" && typeof block.tool_use_id === "string" ? [block.tool_use_id] : []
53022
53357
  );
53023
53358
  }
53024
- function contentBlocks(content) {
53359
+ function contentBlocks2(content) {
53025
53360
  if (!Array.isArray(content)) {
53026
53361
  return [];
53027
53362
  }
@@ -53030,42 +53365,6 @@ function contentBlocks(content) {
53030
53365
  );
53031
53366
  }
53032
53367
 
53033
- // src/commands/agent-bridge/harness/claude-code/resume-store.ts
53034
- import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
53035
- import { dirname as dirname3 } from "path";
53036
- var AGENT_BRIDGE_RUNTIME_DIR = "/tmp/auto-bridge-runtime";
53037
- var CLAUDE_SESSION_RESUME_PATH = `${AGENT_BRIDGE_RUNTIME_DIR}/claude-session-id`;
53038
- function fileClaudeSessionResumeStore(path2 = CLAUDE_SESSION_RESUME_PATH) {
53039
- return {
53040
- read(sessionId) {
53041
- if (!existsSync(path2)) {
53042
- return null;
53043
- }
53044
- const record2 = parseResumeRecord(readFileSync2(path2, "utf8"));
53045
- if (!record2 || record2.sessionId !== sessionId) {
53046
- return null;
53047
- }
53048
- return record2.agentId;
53049
- },
53050
- write(record2) {
53051
- mkdirSync2(dirname3(path2), { recursive: true });
53052
- writeFileSync2(path2, `${JSON.stringify(record2)}
53053
- `, "utf8");
53054
- }
53055
- };
53056
- }
53057
- function parseResumeRecord(raw) {
53058
- try {
53059
- const value = JSON.parse(raw);
53060
- if (value !== null && typeof value === "object" && "sessionId" in value && "agentId" in value && typeof value.sessionId === "string" && typeof value.agentId === "string" && value.agentId.length > 0) {
53061
- return { sessionId: value.sessionId, agentId: value.agentId };
53062
- }
53063
- return null;
53064
- } catch {
53065
- return null;
53066
- }
53067
- }
53068
-
53069
53368
  // src/commands/agent-bridge/harness/claude-code/index.ts
53070
53369
  function createClaudeCodeCommandHandler(input) {
53071
53370
  return new ClaudeCodeCommandHandler(input);
@@ -53075,6 +53374,7 @@ var ClaudeCodeCommandHandler = class {
53075
53374
  this.input = input;
53076
53375
  this.claudeConfig = input.claude;
53077
53376
  this.outputBuffer = new AgentBridgeOutputBuffer(input);
53377
+ this.readState = input.readState ? new ClaudeReadStateTracker(input.readState) : null;
53078
53378
  }
53079
53379
  input;
53080
53380
  context = null;
@@ -53096,6 +53396,7 @@ var ClaudeCodeCommandHandler = class {
53096
53396
  pendingQuestions = /* @__PURE__ */ new Map();
53097
53397
  outputBuffer;
53098
53398
  projector = new ClaudeCodeProjector();
53399
+ readState;
53099
53400
  livenessTicker = null;
53100
53401
  // -----------------------------------------------------------------------------
53101
53402
  // Lifecycle (public API)
@@ -53472,6 +53773,7 @@ var ClaudeCodeCommandHandler = class {
53472
53773
  return;
53473
53774
  }
53474
53775
  this.persistAgentId(activeContext, message);
53776
+ this.trackReadState(activeContext, message);
53475
53777
  let projections;
53476
53778
  try {
53477
53779
  projections = this.projector.project(message);
@@ -53535,6 +53837,31 @@ var ClaudeCodeCommandHandler = class {
53535
53837
  );
53536
53838
  }
53537
53839
  }
53840
+ // Observes file-tool results into the read-state tracker and replays the
53841
+ // tracked seeds whenever a fresh CLI cache appears: a new process's `init`
53842
+ // (runtime restart, selection change, CLI-internal fork — all resume the
53843
+ // conversation but start with an empty readFileState) and compaction
53844
+ // boundaries (which can evict prior reads). Seeding is fire-and-forget:
53845
+ // a failed seed degrades to today's behavior, a fresh Read before writing.
53846
+ trackReadState(activeContext, message) {
53847
+ const tracker = this.readState;
53848
+ if (!tracker) {
53849
+ return;
53850
+ }
53851
+ if (message.type === "system" && (message.subtype === "init" || message.subtype === "compact_boundary")) {
53852
+ const seeds = tracker.seeds(activeContext.sessionId);
53853
+ if (seeds.length === 0) {
53854
+ return;
53855
+ }
53856
+ this.agentSession?.seedReadState(seeds).catch((error51) => {
53857
+ this.input.writeOutput?.(
53858
+ `agent_bridge_claude_read_state_seed_failed error=${error51 instanceof Error ? error51.message : String(error51)}`
53859
+ );
53860
+ });
53861
+ return;
53862
+ }
53863
+ tracker.observe(activeContext.sessionId, message);
53864
+ }
53538
53865
  storedResumeAgentId() {
53539
53866
  const store = this.input.sessionResume;
53540
53867
  const activeContext = this.context;
@@ -53564,10 +53891,18 @@ var ClaudeCodeCommandHandler = class {
53564
53891
  "Cannot restart Claude Code for a model/effort selection change without a session id to resume"
53565
53892
  );
53566
53893
  }
53894
+ if (!resumeAgentId && this.context) {
53895
+ this.readState?.clear(this.context.sessionId);
53896
+ }
53567
53897
  const session = claudeAgentBridgeRuntime.start({
53568
53898
  claude: this.claudeConfig,
53569
53899
  resumeAgentId,
53570
53900
  ...resumeRequired ? { allowResumeFallback: false } : {},
53901
+ onResumeFallback: () => {
53902
+ if (this.context) {
53903
+ this.readState?.clear(this.context.sessionId);
53904
+ }
53905
+ },
53571
53906
  canUseTool: this.canUseTool,
53572
53907
  onMessage: (message, meta3) => this.handleAgentMessage(message, meta3),
53573
53908
  onError: (error51) => this.handleAgentError(error51),
@@ -53984,25 +54319,25 @@ function normalizeChunk(chunk) {
53984
54319
  }
53985
54320
 
53986
54321
  // src/commands/agent-bridge/harness/codex/resume-store.ts
53987
- import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
53988
- import { dirname as dirname4 } from "path";
54322
+ import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
54323
+ import { dirname as dirname5 } from "path";
53989
54324
  var AGENT_BRIDGE_RUNTIME_DIR2 = "/tmp/auto-bridge-runtime";
53990
54325
  var CODEX_THREAD_RESUME_PATH = `${AGENT_BRIDGE_RUNTIME_DIR2}/codex-thread-id`;
53991
54326
  function fileCodexThreadResumeStore(path2 = CODEX_THREAD_RESUME_PATH) {
53992
54327
  return {
53993
54328
  read(sessionId) {
53994
- if (!existsSync2(path2)) {
54329
+ if (!existsSync3(path2)) {
53995
54330
  return null;
53996
54331
  }
53997
- const record2 = parseResumeRecord2(readFileSync3(path2, "utf8"));
54332
+ const record2 = parseResumeRecord2(readFileSync4(path2, "utf8"));
53998
54333
  if (!record2 || record2.sessionId !== sessionId) {
53999
54334
  return null;
54000
54335
  }
54001
54336
  return record2.threadId;
54002
54337
  },
54003
54338
  write(record2) {
54004
- mkdirSync3(dirname4(path2), { recursive: true });
54005
- writeFileSync3(path2, `${JSON.stringify(record2)}
54339
+ mkdirSync4(dirname5(path2), { recursive: true });
54340
+ writeFileSync4(path2, `${JSON.stringify(record2)}
54006
54341
  `, "utf8");
54007
54342
  }
54008
54343
  };
@@ -54022,8 +54357,26 @@ function parseResumeRecord2(raw) {
54022
54357
  // src/commands/agent-bridge/harness/codex/session.ts
54023
54358
  init_src();
54024
54359
  import { spawn as spawn2 } from "child_process";
54025
- import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
54026
- import { join as join4 } from "path";
54360
+ import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync6 } from "fs";
54361
+ import { join as join5 } from "path";
54362
+
54363
+ // src/commands/agent-bridge/harness/codex/edit-capability.ts
54364
+ import { execFileSync } from "child_process";
54365
+ import {
54366
+ constants,
54367
+ accessSync,
54368
+ existsSync as existsSync4,
54369
+ lstatSync,
54370
+ mkdtempSync,
54371
+ readFileSync as readFileSync5,
54372
+ realpathSync,
54373
+ rmSync as rmSync2,
54374
+ symlinkSync,
54375
+ unlinkSync,
54376
+ writeFileSync as writeFileSync5
54377
+ } from "fs";
54378
+ import { tmpdir } from "os";
54379
+ import { delimiter, dirname as dirname6, join as join4 } from "path";
54027
54380
 
54028
54381
  // src/commands/agent-bridge/harness/codex/options.ts
54029
54382
  import { join as join3 } from "path";
@@ -54165,6 +54518,172 @@ function tomlString(value) {
54165
54518
  return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
54166
54519
  }
54167
54520
 
54521
+ // src/commands/agent-bridge/harness/codex/edit-capability.ts
54522
+ var CODEX_APPLY_PATCH_ALIAS = "apply_patch";
54523
+ var CODEX_EDIT_PROBE = {
54524
+ fileName: "probe.txt",
54525
+ before: "codex-edit-probe\n",
54526
+ after: "codex-edit-probe-ok\n",
54527
+ patch: [
54528
+ "*** Begin Patch",
54529
+ "*** Update File: probe.txt",
54530
+ "@@",
54531
+ "-codex-edit-probe",
54532
+ "+codex-edit-probe-ok",
54533
+ "*** End Patch"
54534
+ ].join("\n")
54535
+ };
54536
+ var PROBE_TIMEOUT_MS = 15e3;
54537
+ var MAX_EVIDENCE_LENGTH = 300;
54538
+ var CODEX_PLATFORM_VENDOR_TARGETS = {
54539
+ linux: {
54540
+ x64: "x86_64-unknown-linux-musl",
54541
+ arm64: "aarch64-unknown-linux-musl"
54542
+ },
54543
+ darwin: {
54544
+ x64: "x86_64-apple-darwin",
54545
+ arm64: "aarch64-apple-darwin"
54546
+ }
54547
+ };
54548
+ function ensureCodexEditCapability(input) {
54549
+ if (input.command !== CODEX_EXECUTABLE_PATH) {
54550
+ input.writeOutput?.(
54551
+ "agent_bridge_codex_edit_capability status=skipped reason=command_override"
54552
+ );
54553
+ return;
54554
+ }
54555
+ const startedAt = Date.now();
54556
+ const layout = runStep(input, "resolve", () => resolveCodexVendorLayout());
54557
+ const status = runStep(
54558
+ input,
54559
+ "provision",
54560
+ () => provisionApplyPatchAlias(layout)
54561
+ );
54562
+ const alias = join4(layout.codexPathDir, CODEX_APPLY_PATCH_ALIAS);
54563
+ runStep(input, "verify", () => verifyApplyPatchAlias(alias));
54564
+ input.writeOutput?.(
54565
+ `agent_bridge_codex_edit_capability status=${status} alias=${alias} duration_ms=${Date.now() - startedAt}`
54566
+ );
54567
+ }
54568
+ function codexEditFallthroughMarker(item) {
54569
+ if (item.type !== "commandExecution" || item.exitCode !== 127) {
54570
+ return null;
54571
+ }
54572
+ const output = item.aggregatedOutput ?? "";
54573
+ if (!/apply_patch: (command )?not found/.test(output)) {
54574
+ return null;
54575
+ }
54576
+ return `agent_bridge_codex_edit_fallthrough item_id=${item.id} exit_code=127`;
54577
+ }
54578
+ function resolveCodexVendorLayout() {
54579
+ const wrapper = whichOnPath(CODEX_EXECUTABLE_PATH);
54580
+ if (!wrapper) {
54581
+ throw new Error("codex executable not found on PATH");
54582
+ }
54583
+ const target = CODEX_PLATFORM_VENDOR_TARGETS[process.platform]?.[process.arch];
54584
+ if (!target) {
54585
+ throw new Error(
54586
+ `unsupported platform for codex vendor layout: ${process.platform}/${process.arch}`
54587
+ );
54588
+ }
54589
+ const packageRoot = join4(dirname6(realpathSync(wrapper)), "..");
54590
+ const platformPackage = `@openai/codex-${platformPackageSuffix()}`;
54591
+ const candidates = [
54592
+ join4(packageRoot, "node_modules", platformPackage, "vendor", target),
54593
+ join4(packageRoot, "vendor", target)
54594
+ ];
54595
+ for (const vendorDir of candidates) {
54596
+ const binary = join4(vendorDir, "bin", "codex");
54597
+ const codexPathDir = join4(vendorDir, "codex-path");
54598
+ if (existsSync4(binary) && existsSync4(codexPathDir)) {
54599
+ return { binary, codexPathDir };
54600
+ }
54601
+ }
54602
+ throw new Error(
54603
+ `codex vendor layout not found (wrapper=${wrapper} candidates=${candidates.join(",")})`
54604
+ );
54605
+ }
54606
+ function platformPackageSuffix() {
54607
+ const os = process.platform === "darwin" ? "darwin" : "linux";
54608
+ return `${os}-${process.arch}`;
54609
+ }
54610
+ function whichOnPath(command) {
54611
+ for (const dir of (process.env.PATH ?? "").split(delimiter)) {
54612
+ if (!dir) {
54613
+ continue;
54614
+ }
54615
+ const candidate = join4(dir, command);
54616
+ try {
54617
+ accessSync(candidate, constants.X_OK);
54618
+ return candidate;
54619
+ } catch {
54620
+ }
54621
+ }
54622
+ return null;
54623
+ }
54624
+ function provisionApplyPatchAlias(layout) {
54625
+ const alias = join4(layout.codexPathDir, CODEX_APPLY_PATCH_ALIAS);
54626
+ if (aliasResolvesToBinary(alias, layout.binary)) {
54627
+ return "present";
54628
+ }
54629
+ if (lstatExists(alias)) {
54630
+ unlinkSync(alias);
54631
+ }
54632
+ symlinkSync(layout.binary, alias);
54633
+ return "provisioned";
54634
+ }
54635
+ function aliasResolvesToBinary(alias, binary) {
54636
+ try {
54637
+ return realpathSync(alias) === realpathSync(binary);
54638
+ } catch {
54639
+ return false;
54640
+ }
54641
+ }
54642
+ function lstatExists(path2) {
54643
+ try {
54644
+ lstatSync(path2);
54645
+ return true;
54646
+ } catch {
54647
+ return false;
54648
+ }
54649
+ }
54650
+ function verifyApplyPatchAlias(alias) {
54651
+ const scratch = mkdtempSync(join4(tmpdir(), "codex-edit-probe-"));
54652
+ try {
54653
+ const probeFile = join4(scratch, CODEX_EDIT_PROBE.fileName);
54654
+ writeFileSync5(probeFile, CODEX_EDIT_PROBE.before);
54655
+ execFileSync(alias, [CODEX_EDIT_PROBE.patch], {
54656
+ cwd: scratch,
54657
+ stdio: ["ignore", "pipe", "pipe"],
54658
+ timeout: PROBE_TIMEOUT_MS
54659
+ });
54660
+ const applied = readFileSync5(probeFile, "utf8");
54661
+ if (applied !== CODEX_EDIT_PROBE.after) {
54662
+ throw new Error("probe patch did not apply the expected content");
54663
+ }
54664
+ } finally {
54665
+ rmSync2(scratch, { recursive: true, force: true });
54666
+ }
54667
+ }
54668
+ function runStep(input, step, action) {
54669
+ try {
54670
+ return action();
54671
+ } catch (error51) {
54672
+ const detail = boundedEvidence(error51);
54673
+ input.writeOutput?.(
54674
+ `agent_bridge_codex_edit_capability status=failed step=${step} error=${detail}`
54675
+ );
54676
+ throw new Error(
54677
+ `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).`
54678
+ );
54679
+ }
54680
+ }
54681
+ function boundedEvidence(error51) {
54682
+ const message = error51 instanceof Error ? error51.message : String(error51);
54683
+ const flattened = message.replace(/\s+/g, " ").trim();
54684
+ return flattened.length > MAX_EVIDENCE_LENGTH ? `${flattened.slice(0, MAX_EVIDENCE_LENGTH)}\u2026` : flattened;
54685
+ }
54686
+
54168
54687
  // src/commands/agent-bridge/harness/codex/turn-retry.ts
54169
54688
  var MAX_CODEX_TURN_RETRY_ATTEMPTS = 3;
54170
54689
  var MAX_CODEX_TURN_RETRY_TOTAL_DELAY_MS = 3e4;
@@ -54398,12 +54917,16 @@ var CodexAgentBridgeSessionImpl = class {
54398
54917
  }
54399
54918
  async start() {
54400
54919
  const options = codexLaunchOptions(this.input.codex);
54401
- mkdirSync4(options.codexHome, { recursive: true });
54402
- writeFileSync4(join4(options.codexHome, "config.toml"), options.configToml);
54920
+ mkdirSync5(options.codexHome, { recursive: true });
54921
+ writeFileSync6(join5(options.codexHome, "config.toml"), options.configToml);
54403
54922
  const startedAt = Date.now();
54404
54923
  this.input.writeOutput?.(
54405
54924
  `agent_bridge_codex_startup_started codex_home=${options.codexHome}`
54406
54925
  );
54926
+ ensureCodexEditCapability({
54927
+ command: options.command,
54928
+ ...this.input.writeOutput ? { writeOutput: this.input.writeOutput } : {}
54929
+ });
54407
54930
  const proc = spawn2(options.command, options.args, {
54408
54931
  env: options.env,
54409
54932
  stdio: ["pipe", "pipe", "pipe"]
@@ -54803,12 +55326,17 @@ var CodexAgentBridgeSessionImpl = class {
54803
55326
  this.pendingToolItemIds.add(notification.item.id);
54804
55327
  }
54805
55328
  return;
54806
- case "itemCompleted":
55329
+ case "itemCompleted": {
55330
+ const fallthrough = codexEditFallthroughMarker(notification.item);
55331
+ if (fallthrough) {
55332
+ this.input.writeOutput?.(fallthrough);
55333
+ }
54807
55334
  this.pendingToolItemIds.delete(notification.item.id);
54808
55335
  if (this.pendingToolItemIds.size === 0) {
54809
55336
  this.resolveSettlement();
54810
55337
  }
54811
55338
  return;
55339
+ }
54812
55340
  default:
54813
55341
  return;
54814
55342
  }
@@ -55293,6 +55821,7 @@ function createHarnessCommandHandler(input) {
55293
55821
  return createClaudeCodeCommandHandler({
55294
55822
  ...base,
55295
55823
  claude,
55824
+ readState: fileClaudeReadStateStore(),
55296
55825
  sessionResume: fileClaudeSessionResumeStore()
55297
55826
  });
55298
55827
  }
@@ -55592,9 +56121,9 @@ function statusAgents(input) {
55592
56121
  // src/commands/agents/connect.ts
55593
56122
  init_resources2();
55594
56123
  init_browser();
55595
- import { existsSync as existsSync3, mkdtempSync, writeFileSync as writeFileSync5 } from "fs";
55596
- import { homedir as homedir3, tmpdir } from "os";
55597
- import { join as join6 } from "path";
56124
+ import { existsSync as existsSync5, mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync7 } from "fs";
56125
+ import { homedir as homedir3, tmpdir as tmpdir2 } from "os";
56126
+ import { join as join7 } from "path";
55598
56127
 
55599
56128
  // src/lib/stdio/secret.ts
55600
56129
  async function questionSecret(context, prompt) {
@@ -55785,7 +56314,7 @@ async function promptForIconUploads(input, options) {
55785
56314
  }
55786
56315
  }
55787
56316
  function stagedLocationLabel(stagedPath) {
55788
- return stagedPath.startsWith(`${join6(homedir3(), "Downloads")}/`) ? "Downloads" : "the printed path";
56317
+ return stagedPath.startsWith(`${join7(homedir3(), "Downloads")}/`) ? "Downloads" : "the printed path";
55789
56318
  }
55790
56319
  async function stageAvatarImage(input) {
55791
56320
  try {
@@ -55797,10 +56326,10 @@ async function stageAvatarImage(input) {
55797
56326
  }
55798
56327
  const contentType = response.headers.get("content-type") ?? "";
55799
56328
  const extension = contentType.includes("jpeg") ? ".jpg" : ".png";
55800
- const downloads = join6(homedir3(), "Downloads");
55801
- const directory = existsSync3(downloads) ? downloads : mkdtempSync(join6(tmpdir(), "auto-avatar-"));
55802
- const path2 = join6(directory, `${input.agent}-avatar${extension}`);
55803
- writeFileSync5(path2, Buffer.from(await response.arrayBuffer()));
56329
+ const downloads = join7(homedir3(), "Downloads");
56330
+ const directory = existsSync5(downloads) ? downloads : mkdtempSync2(join7(tmpdir2(), "auto-avatar-"));
56331
+ const path2 = join7(directory, `${input.agent}-avatar${extension}`);
56332
+ writeFileSync7(path2, Buffer.from(await response.arrayBuffer()));
55804
56333
  return path2;
55805
56334
  } catch {
55806
56335
  return void 0;
@@ -57299,19 +57828,19 @@ init_src();
57299
57828
  // src/commands/logs/actions.ts
57300
57829
  import {
57301
57830
  closeSync,
57302
- existsSync as existsSync5,
57831
+ existsSync as existsSync7,
57303
57832
  openSync,
57304
- readFileSync as readFileSync7,
57833
+ readFileSync as readFileSync9,
57305
57834
  readSync,
57306
- statSync as statSync3
57835
+ statSync as statSync4
57307
57836
  } from "fs";
57308
57837
  var DEFAULT_POLL_INTERVAL_MS = 1e3;
57309
57838
  async function tailRuntimeLog(input) {
57310
- if (!existsSync5(input.path)) {
57839
+ if (!existsSync7(input.path)) {
57311
57840
  input.writeError(`No runtime log at ${input.path}`);
57312
57841
  return;
57313
57842
  }
57314
- const content = readFileSync7(input.path, "utf8");
57843
+ const content = readFileSync9(input.path, "utf8");
57315
57844
  for (const line of selectLastLines(content, input.lines)) {
57316
57845
  input.writeOutput(line);
57317
57846
  }
@@ -57338,7 +57867,7 @@ async function followRuntimeLog(input) {
57338
57867
  }
57339
57868
  let size;
57340
57869
  try {
57341
- size = statSync3(input.path).size;
57870
+ size = statSync4(input.path).size;
57342
57871
  } catch {
57343
57872
  continue;
57344
57873
  }
@@ -60423,7 +60952,7 @@ function createProgram(options = {}) {
60423
60952
  }
60424
60953
 
60425
60954
  // src/lib/entrypoint.ts
60426
- import { realpathSync as realpathSync2 } from "fs";
60955
+ import { realpathSync as realpathSync3 } from "fs";
60427
60956
  import { pathToFileURL } from "url";
60428
60957
  function isCliEntrypoint(input) {
60429
60958
  if (input.entrypoint.kind === "missing") {
@@ -60431,7 +60960,7 @@ function isCliEntrypoint(input) {
60431
60960
  }
60432
60961
  let resolvedEntrypoint;
60433
60962
  try {
60434
- resolvedEntrypoint = realpathSync2(input.entrypoint.path);
60963
+ resolvedEntrypoint = realpathSync3(input.entrypoint.path);
60435
60964
  } catch {
60436
60965
  return false;
60437
60966
  }