@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.
- package/dist/agent-bridge.js +506 -57
- package/dist/index.js +577 -128
- package/package.json +1 -1
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 = (
|
|
1163
|
-
const escapedDelim = escapeRegex(
|
|
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])$/;
|
|
@@ -36173,15 +36173,15 @@ async function* readSseEvents(body) {
|
|
|
36173
36173
|
break;
|
|
36174
36174
|
}
|
|
36175
36175
|
buffer += decoder.decode(value, { stream: true });
|
|
36176
|
-
let
|
|
36177
|
-
while (
|
|
36178
|
-
const rawEvent = buffer.slice(0,
|
|
36179
|
-
buffer = buffer.slice(
|
|
36176
|
+
let delimiter2 = buffer.indexOf("\n\n");
|
|
36177
|
+
while (delimiter2 !== -1) {
|
|
36178
|
+
const rawEvent = buffer.slice(0, delimiter2);
|
|
36179
|
+
buffer = buffer.slice(delimiter2 + 2);
|
|
36180
36180
|
const event2 = parseSseEvent(rawEvent);
|
|
36181
36181
|
if (event2) {
|
|
36182
36182
|
yield event2;
|
|
36183
36183
|
}
|
|
36184
|
-
|
|
36184
|
+
delimiter2 = buffer.indexOf("\n\n");
|
|
36185
36185
|
}
|
|
36186
36186
|
}
|
|
36187
36187
|
buffer += decoder.decode();
|
|
@@ -38670,7 +38670,7 @@ var init_package = __esm({
|
|
|
38670
38670
|
"package.json"() {
|
|
38671
38671
|
package_default = {
|
|
38672
38672
|
name: "@autohq/cli",
|
|
38673
|
-
version: "0.1.
|
|
38673
|
+
version: "0.1.419",
|
|
38674
38674
|
license: "SEE LICENSE IN README.md",
|
|
38675
38675
|
publishConfig: {
|
|
38676
38676
|
access: "public"
|
|
@@ -38735,13 +38735,13 @@ var init_version = __esm({
|
|
|
38735
38735
|
});
|
|
38736
38736
|
|
|
38737
38737
|
// src/commands/agents/authoring.ts
|
|
38738
|
-
import { readFileSync as
|
|
38738
|
+
import { readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
38739
38739
|
import {
|
|
38740
38740
|
basename as basename2,
|
|
38741
|
-
dirname as
|
|
38741
|
+
dirname as dirname7,
|
|
38742
38742
|
extname,
|
|
38743
38743
|
isAbsolute,
|
|
38744
|
-
join as
|
|
38744
|
+
join as join6,
|
|
38745
38745
|
resolve
|
|
38746
38746
|
} from "path";
|
|
38747
38747
|
import { parseAllDocuments as parseYamlDocuments, stringify } from "yaml";
|
|
@@ -38793,8 +38793,8 @@ function renderAgentExplain(result) {
|
|
|
38793
38793
|
return lines.join("\n");
|
|
38794
38794
|
}
|
|
38795
38795
|
function readLocalAgentAuthoringStatuses(input) {
|
|
38796
|
-
const agentsDirectory =
|
|
38797
|
-
input?.directory ??
|
|
38796
|
+
const agentsDirectory = join6(
|
|
38797
|
+
input?.directory ?? join6(process.cwd(), ".auto"),
|
|
38798
38798
|
"agents"
|
|
38799
38799
|
);
|
|
38800
38800
|
const paths = agentAuthoringFiles(agentsDirectory);
|
|
@@ -38833,7 +38833,7 @@ function agentAuthoringFiles(directory) {
|
|
|
38833
38833
|
}
|
|
38834
38834
|
const files = [];
|
|
38835
38835
|
for (const entry of entries) {
|
|
38836
|
-
const path2 =
|
|
38836
|
+
const path2 = join6(directory, entry.name);
|
|
38837
38837
|
if (entry.isDirectory()) {
|
|
38838
38838
|
files.push(...agentAuthoringFiles(path2));
|
|
38839
38839
|
continue;
|
|
@@ -38853,12 +38853,12 @@ function resolveAgentAuthoringPath(input) {
|
|
|
38853
38853
|
if (isAgentFile(candidate)) {
|
|
38854
38854
|
return candidate;
|
|
38855
38855
|
}
|
|
38856
|
-
const agentsDirectory =
|
|
38857
|
-
input.directory ??
|
|
38856
|
+
const agentsDirectory = join6(
|
|
38857
|
+
input.directory ?? join6(process.cwd(), ".auto"),
|
|
38858
38858
|
"agents"
|
|
38859
38859
|
);
|
|
38860
38860
|
for (const extension of AGENT_FILE_EXTENSIONS) {
|
|
38861
|
-
const path2 =
|
|
38861
|
+
const path2 = join6(agentsDirectory, `${input.agent}${extension}`);
|
|
38862
38862
|
if (isAgentFile(path2)) {
|
|
38863
38863
|
return path2;
|
|
38864
38864
|
}
|
|
@@ -38916,7 +38916,7 @@ function readSingleDocument(path2) {
|
|
|
38916
38916
|
return documents[0];
|
|
38917
38917
|
}
|
|
38918
38918
|
function readDocuments(path2) {
|
|
38919
|
-
const source =
|
|
38919
|
+
const source = readFileSync6(path2, "utf8");
|
|
38920
38920
|
const documents = parseYamlDocuments(source);
|
|
38921
38921
|
const parseError = documents.flatMap((document) => document.errors).at(0);
|
|
38922
38922
|
if (parseError) {
|
|
@@ -38941,7 +38941,7 @@ function resolveImportPath(importPath, importerPath) {
|
|
|
38941
38941
|
if (isAbsolute(importPath) || /^[A-Za-z]+:\/\//.test(importPath)) {
|
|
38942
38942
|
throw new Error(`Agent import must be a relative path: ${importPath}`);
|
|
38943
38943
|
}
|
|
38944
|
-
const resolved = resolve(
|
|
38944
|
+
const resolved = resolve(dirname7(importerPath), importPath);
|
|
38945
38945
|
if (!isAgentFile(resolved)) {
|
|
38946
38946
|
throw new Error(
|
|
38947
38947
|
`Agent import not found: ${importPath} from ${importerPath}`
|
|
@@ -39116,7 +39116,7 @@ function resolveFileBackedString(value, input) {
|
|
|
39116
39116
|
`Invalid agent authoring file ${input.path}: ${input.field}.file must be a relative path`
|
|
39117
39117
|
);
|
|
39118
39118
|
}
|
|
39119
|
-
return
|
|
39119
|
+
return readFileSync6(resolve(dirname7(input.path), filePath), "utf8");
|
|
39120
39120
|
}
|
|
39121
39121
|
function removalDirectives(document, path2) {
|
|
39122
39122
|
const raw = isRecord(document.remove) ? document.remove : {};
|
|
@@ -39267,7 +39267,7 @@ function importedEdgeCount(graph) {
|
|
|
39267
39267
|
}
|
|
39268
39268
|
function isAgentFile(path2) {
|
|
39269
39269
|
try {
|
|
39270
|
-
return
|
|
39270
|
+
return statSync2(path2).isFile();
|
|
39271
39271
|
} catch {
|
|
39272
39272
|
return false;
|
|
39273
39273
|
}
|
|
@@ -41625,18 +41625,18 @@ var init_project_apply_files2 = __esm({
|
|
|
41625
41625
|
|
|
41626
41626
|
// src/commands/apply/files.ts
|
|
41627
41627
|
import {
|
|
41628
|
-
existsSync as
|
|
41629
|
-
readFileSync as
|
|
41628
|
+
existsSync as existsSync6,
|
|
41629
|
+
readFileSync as readFileSync7,
|
|
41630
41630
|
readdirSync as readdirSync3,
|
|
41631
|
-
realpathSync,
|
|
41632
|
-
statSync as
|
|
41631
|
+
realpathSync as realpathSync2,
|
|
41632
|
+
statSync as statSync3
|
|
41633
41633
|
} from "fs";
|
|
41634
41634
|
import {
|
|
41635
41635
|
basename as basename3,
|
|
41636
|
-
dirname as
|
|
41636
|
+
dirname as dirname8,
|
|
41637
41637
|
extname as extname3,
|
|
41638
41638
|
isAbsolute as isAbsolute2,
|
|
41639
|
-
join as
|
|
41639
|
+
join as join8,
|
|
41640
41640
|
relative,
|
|
41641
41641
|
resolve as resolve2
|
|
41642
41642
|
} from "path";
|
|
@@ -41667,7 +41667,7 @@ function readProjectApplyBundleInput(options) {
|
|
|
41667
41667
|
}
|
|
41668
41668
|
};
|
|
41669
41669
|
}
|
|
41670
|
-
const directory = resolve2(options.directory ??
|
|
41670
|
+
const directory = resolve2(options.directory ?? join8(process.cwd(), ".auto"));
|
|
41671
41671
|
const projectRoot = applyProjectRoot(directory);
|
|
41672
41672
|
const files = withManagedTemplateFiles(sourceFiles(directory, projectRoot));
|
|
41673
41673
|
const resourceRoot = sourcePathRelative(projectRoot, directory);
|
|
@@ -41704,7 +41704,7 @@ function sourceFiles(root, projectRoot) {
|
|
|
41704
41704
|
return [];
|
|
41705
41705
|
}
|
|
41706
41706
|
return entries.flatMap((entry) => {
|
|
41707
|
-
const path2 =
|
|
41707
|
+
const path2 = join8(root, entry.name);
|
|
41708
41708
|
if (entry.isDirectory()) {
|
|
41709
41709
|
return sourceFiles(path2, projectRoot);
|
|
41710
41710
|
}
|
|
@@ -41717,7 +41717,7 @@ function sourceFiles(root, projectRoot) {
|
|
|
41717
41717
|
function sourceFile(path2, projectRoot) {
|
|
41718
41718
|
return {
|
|
41719
41719
|
path: sourcePathRelative(projectRoot, path2),
|
|
41720
|
-
contentBase64:
|
|
41720
|
+
contentBase64: readFileSync7(path2).toString("base64")
|
|
41721
41721
|
};
|
|
41722
41722
|
}
|
|
41723
41723
|
function applyBundle(files) {
|
|
@@ -41758,24 +41758,24 @@ function filesystemAssetReader(projectRoot) {
|
|
|
41758
41758
|
}
|
|
41759
41759
|
return {
|
|
41760
41760
|
path: path2,
|
|
41761
|
-
bytes:
|
|
41761
|
+
bytes: readFileSync7(path2)
|
|
41762
41762
|
};
|
|
41763
41763
|
};
|
|
41764
41764
|
}
|
|
41765
41765
|
function applyProjectRoot(directory) {
|
|
41766
41766
|
const resolved = resolve2(directory);
|
|
41767
|
-
return basename3(resolved) === ".auto" ?
|
|
41767
|
+
return basename3(resolved) === ".auto" ? dirname8(resolved) : resolved;
|
|
41768
41768
|
}
|
|
41769
41769
|
function applyFileProjectRoot(file2) {
|
|
41770
|
-
let dir =
|
|
41770
|
+
let dir = dirname8(resolve2(file2));
|
|
41771
41771
|
while (true) {
|
|
41772
41772
|
if (basename3(dir) === ".auto") {
|
|
41773
|
-
return
|
|
41773
|
+
return dirname8(dir);
|
|
41774
41774
|
}
|
|
41775
41775
|
if (directoryHasAutoRoot(dir)) {
|
|
41776
41776
|
return dir;
|
|
41777
41777
|
}
|
|
41778
|
-
const parent =
|
|
41778
|
+
const parent = dirname8(dir);
|
|
41779
41779
|
if (parent === dir) {
|
|
41780
41780
|
return process.cwd();
|
|
41781
41781
|
}
|
|
@@ -41784,14 +41784,14 @@ function applyFileProjectRoot(file2) {
|
|
|
41784
41784
|
}
|
|
41785
41785
|
function applyFileSourceRoot(file2, projectRoot) {
|
|
41786
41786
|
const autoRoot = resolve2(projectRoot, ".auto");
|
|
41787
|
-
return file2 === autoRoot || isInside(file2, autoRoot) ? autoRoot :
|
|
41787
|
+
return file2 === autoRoot || isInside(file2, autoRoot) ? autoRoot : dirname8(file2);
|
|
41788
41788
|
}
|
|
41789
41789
|
function directoryHasAutoRoot(directory) {
|
|
41790
41790
|
const autoRoot = resolve2(directory, ".auto");
|
|
41791
|
-
if (!
|
|
41791
|
+
if (!existsSync6(autoRoot)) {
|
|
41792
41792
|
return false;
|
|
41793
41793
|
}
|
|
41794
|
-
return
|
|
41794
|
+
return statSync3(autoRoot).isDirectory();
|
|
41795
41795
|
}
|
|
41796
41796
|
function displayResourceRoot(directory) {
|
|
41797
41797
|
return basename3(directory) === ".auto" ? ".auto" : directory;
|
|
@@ -41814,11 +41814,11 @@ function validateAgentAvatarAsset(input) {
|
|
|
41814
41814
|
`Invalid identity avatar asset for "${input.resourceName}": asset path must be under .auto/assets`
|
|
41815
41815
|
);
|
|
41816
41816
|
}
|
|
41817
|
-
const projectRoot =
|
|
41817
|
+
const projectRoot = realpathSync2(input.projectRoot);
|
|
41818
41818
|
const assetPath = resolve2(projectRoot, input.asset);
|
|
41819
41819
|
let assetsRoot;
|
|
41820
41820
|
try {
|
|
41821
|
-
assetsRoot =
|
|
41821
|
+
assetsRoot = realpathSync2(resolve2(projectRoot, ".auto", "assets"));
|
|
41822
41822
|
} catch {
|
|
41823
41823
|
if (input.allowMissing) {
|
|
41824
41824
|
return null;
|
|
@@ -41830,8 +41830,8 @@ function validateAgentAvatarAsset(input) {
|
|
|
41830
41830
|
let resolvedAssetPath;
|
|
41831
41831
|
let stat;
|
|
41832
41832
|
try {
|
|
41833
|
-
resolvedAssetPath =
|
|
41834
|
-
stat =
|
|
41833
|
+
resolvedAssetPath = realpathSync2(assetPath);
|
|
41834
|
+
stat = statSync3(resolvedAssetPath);
|
|
41835
41835
|
} catch {
|
|
41836
41836
|
if (input.allowMissing) {
|
|
41837
41837
|
return null;
|
|
@@ -42396,14 +42396,14 @@ var init_resources3 = __esm({
|
|
|
42396
42396
|
// src/commands/edit/actions.ts
|
|
42397
42397
|
import { spawn as spawn3 } from "child_process";
|
|
42398
42398
|
import {
|
|
42399
|
-
mkdirSync as
|
|
42400
|
-
mkdtempSync as
|
|
42401
|
-
readFileSync as
|
|
42402
|
-
rmSync as
|
|
42403
|
-
writeFileSync as
|
|
42399
|
+
mkdirSync as mkdirSync6,
|
|
42400
|
+
mkdtempSync as mkdtempSync3,
|
|
42401
|
+
readFileSync as readFileSync8,
|
|
42402
|
+
rmSync as rmSync3,
|
|
42403
|
+
writeFileSync as writeFileSync8
|
|
42404
42404
|
} from "fs";
|
|
42405
|
-
import { tmpdir as
|
|
42406
|
-
import { join as
|
|
42405
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
42406
|
+
import { join as join9 } from "path";
|
|
42407
42407
|
import { parseAllDocuments as parseYamlDocuments3, stringify as stringify4 } from "yaml";
|
|
42408
42408
|
async function editResource(input) {
|
|
42409
42409
|
const reference = parseProjectResourceReference(input.resource);
|
|
@@ -42423,15 +42423,15 @@ async function editResource(input) {
|
|
|
42423
42423
|
const document = editableAgentFacade(current);
|
|
42424
42424
|
const source = `${stringify4(document).trimEnd()}
|
|
42425
42425
|
`;
|
|
42426
|
-
const tempRoot =
|
|
42427
|
-
const agentsDir =
|
|
42428
|
-
|
|
42429
|
-
const filePath =
|
|
42430
|
-
|
|
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");
|
|
42431
42431
|
let removeTempFile = false;
|
|
42432
42432
|
try {
|
|
42433
42433
|
await runEditor(editor, filePath);
|
|
42434
|
-
const editedSource =
|
|
42434
|
+
const editedSource = readFileSync8(filePath, "utf8");
|
|
42435
42435
|
if (editedSource === source) {
|
|
42436
42436
|
input.writeOutput("No changes; skipped apply.");
|
|
42437
42437
|
removeTempFile = true;
|
|
@@ -42458,7 +42458,7 @@ async function editResource(input) {
|
|
|
42458
42458
|
Edited file retained at ${filePath}`);
|
|
42459
42459
|
} finally {
|
|
42460
42460
|
if (removeTempFile) {
|
|
42461
|
-
|
|
42461
|
+
rmSync3(tempRoot, { recursive: true, force: true });
|
|
42462
42462
|
}
|
|
42463
42463
|
}
|
|
42464
42464
|
}
|
|
@@ -42497,7 +42497,7 @@ async function runEditor(editor, filePath) {
|
|
|
42497
42497
|
});
|
|
42498
42498
|
}
|
|
42499
42499
|
function assertEditedResourceIdentity(filePath, expected) {
|
|
42500
|
-
const source =
|
|
42500
|
+
const source = readFileSync8(filePath, "utf8");
|
|
42501
42501
|
let parsedDocuments;
|
|
42502
42502
|
try {
|
|
42503
42503
|
parsedDocuments = parseYamlDocuments3(source);
|
|
@@ -47986,8 +47986,8 @@ __export(launcher_exports, {
|
|
|
47986
47986
|
launch: () => launch
|
|
47987
47987
|
});
|
|
47988
47988
|
import { spawnSync } from "child_process";
|
|
47989
|
-
import { existsSync as
|
|
47990
|
-
import { dirname as
|
|
47989
|
+
import { existsSync as existsSync8 } from "fs";
|
|
47990
|
+
import { dirname as dirname9, resolve as resolve3 } from "path";
|
|
47991
47991
|
import { fileURLToPath } from "url";
|
|
47992
47992
|
import {
|
|
47993
47993
|
QueryClient,
|
|
@@ -48167,7 +48167,7 @@ function resolveSplashVersion() {
|
|
|
48167
48167
|
return resolveLatestReleaseVersionFromCheckout() ?? cliVersion;
|
|
48168
48168
|
}
|
|
48169
48169
|
function resolveLatestReleaseVersionFromCheckout() {
|
|
48170
|
-
const repoRoot = findRepoRoot(
|
|
48170
|
+
const repoRoot = findRepoRoot(dirname9(fileURLToPath(import.meta.url)));
|
|
48171
48171
|
if (!repoRoot) {
|
|
48172
48172
|
return null;
|
|
48173
48173
|
}
|
|
@@ -48184,10 +48184,10 @@ function resolveLatestReleaseVersionFromCheckout() {
|
|
|
48184
48184
|
function findRepoRoot(startDirectory) {
|
|
48185
48185
|
let directory = startDirectory;
|
|
48186
48186
|
while (true) {
|
|
48187
|
-
if (
|
|
48187
|
+
if (existsSync8(resolve3(directory, ".git")) && existsSync8(resolve3(directory, "apps/cli/package.json"))) {
|
|
48188
48188
|
return directory;
|
|
48189
48189
|
}
|
|
48190
|
-
const parent =
|
|
48190
|
+
const parent = dirname9(directory);
|
|
48191
48191
|
if (parent === directory) {
|
|
48192
48192
|
return null;
|
|
48193
48193
|
}
|
|
@@ -51999,6 +51999,233 @@ function uiChunk(chunk) {
|
|
|
51999
51999
|
};
|
|
52000
52000
|
}
|
|
52001
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
|
+
|
|
52002
52229
|
// src/commands/agent-bridge/harness/claude-code/session.ts
|
|
52003
52230
|
import {
|
|
52004
52231
|
startup as startupClaudeAgent
|
|
@@ -52198,6 +52425,7 @@ var CLAUDE_INTERRUPT_SETTLE_TIMEOUT_MS = 1e4;
|
|
|
52198
52425
|
var CLAUDE_INTERRUPT_ACK_TIMEOUT_MS = 1e4;
|
|
52199
52426
|
var CLAUDE_MCP_REGISTRATION_TIMEOUT_MS = 3e3;
|
|
52200
52427
|
var CLAUDE_MCP_REGISTRATION_POLL_INTERVAL_MS = 100;
|
|
52428
|
+
var CLAUDE_READ_STATE_SEED_FAILURE_LIMIT = 3;
|
|
52201
52429
|
var CLAUDE_STARTUP_PROFILE_HOOK_EVENTS = [
|
|
52202
52430
|
"Setup",
|
|
52203
52431
|
"SessionStart",
|
|
@@ -52414,6 +52642,32 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
52414
52642
|
}
|
|
52415
52643
|
);
|
|
52416
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
|
+
}
|
|
52417
52671
|
close() {
|
|
52418
52672
|
const previousState = this.state;
|
|
52419
52673
|
if (previousState.kind === "closed") {
|
|
@@ -52475,6 +52729,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
52475
52729
|
this.input.writeOutput?.(
|
|
52476
52730
|
`agent_bridge_claude_resume_fallback session_id=${resume}`
|
|
52477
52731
|
);
|
|
52732
|
+
this.input.onResumeFallback?.();
|
|
52478
52733
|
this.state = { kind: "idle" };
|
|
52479
52734
|
return this.startSdkSession();
|
|
52480
52735
|
}
|
|
@@ -53079,7 +53334,7 @@ function isClaudeAgentTurnResult(message) {
|
|
|
53079
53334
|
}
|
|
53080
53335
|
function toolUseIds(message) {
|
|
53081
53336
|
if (message.type === "assistant") {
|
|
53082
|
-
return
|
|
53337
|
+
return contentBlocks2(message.message.content).flatMap(
|
|
53083
53338
|
(block2) => block2.type === "tool_use" && typeof block2.id === "string" ? [block2.id] : []
|
|
53084
53339
|
);
|
|
53085
53340
|
}
|
|
@@ -53097,11 +53352,11 @@ function toolResultIds(message) {
|
|
|
53097
53352
|
if (message.type !== "user") {
|
|
53098
53353
|
return [];
|
|
53099
53354
|
}
|
|
53100
|
-
return
|
|
53355
|
+
return contentBlocks2(message.message.content).flatMap(
|
|
53101
53356
|
(block) => block.type === "tool_result" && typeof block.tool_use_id === "string" ? [block.tool_use_id] : []
|
|
53102
53357
|
);
|
|
53103
53358
|
}
|
|
53104
|
-
function
|
|
53359
|
+
function contentBlocks2(content) {
|
|
53105
53360
|
if (!Array.isArray(content)) {
|
|
53106
53361
|
return [];
|
|
53107
53362
|
}
|
|
@@ -53110,42 +53365,6 @@ function contentBlocks(content) {
|
|
|
53110
53365
|
);
|
|
53111
53366
|
}
|
|
53112
53367
|
|
|
53113
|
-
// src/commands/agent-bridge/harness/claude-code/resume-store.ts
|
|
53114
|
-
import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
53115
|
-
import { dirname as dirname3 } from "path";
|
|
53116
|
-
var AGENT_BRIDGE_RUNTIME_DIR = "/tmp/auto-bridge-runtime";
|
|
53117
|
-
var CLAUDE_SESSION_RESUME_PATH = `${AGENT_BRIDGE_RUNTIME_DIR}/claude-session-id`;
|
|
53118
|
-
function fileClaudeSessionResumeStore(path2 = CLAUDE_SESSION_RESUME_PATH) {
|
|
53119
|
-
return {
|
|
53120
|
-
read(sessionId) {
|
|
53121
|
-
if (!existsSync(path2)) {
|
|
53122
|
-
return null;
|
|
53123
|
-
}
|
|
53124
|
-
const record2 = parseResumeRecord(readFileSync2(path2, "utf8"));
|
|
53125
|
-
if (!record2 || record2.sessionId !== sessionId) {
|
|
53126
|
-
return null;
|
|
53127
|
-
}
|
|
53128
|
-
return record2.agentId;
|
|
53129
|
-
},
|
|
53130
|
-
write(record2) {
|
|
53131
|
-
mkdirSync2(dirname3(path2), { recursive: true });
|
|
53132
|
-
writeFileSync2(path2, `${JSON.stringify(record2)}
|
|
53133
|
-
`, "utf8");
|
|
53134
|
-
}
|
|
53135
|
-
};
|
|
53136
|
-
}
|
|
53137
|
-
function parseResumeRecord(raw) {
|
|
53138
|
-
try {
|
|
53139
|
-
const value = JSON.parse(raw);
|
|
53140
|
-
if (value !== null && typeof value === "object" && "sessionId" in value && "agentId" in value && typeof value.sessionId === "string" && typeof value.agentId === "string" && value.agentId.length > 0) {
|
|
53141
|
-
return { sessionId: value.sessionId, agentId: value.agentId };
|
|
53142
|
-
}
|
|
53143
|
-
return null;
|
|
53144
|
-
} catch {
|
|
53145
|
-
return null;
|
|
53146
|
-
}
|
|
53147
|
-
}
|
|
53148
|
-
|
|
53149
53368
|
// src/commands/agent-bridge/harness/claude-code/index.ts
|
|
53150
53369
|
function createClaudeCodeCommandHandler(input) {
|
|
53151
53370
|
return new ClaudeCodeCommandHandler(input);
|
|
@@ -53155,6 +53374,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
53155
53374
|
this.input = input;
|
|
53156
53375
|
this.claudeConfig = input.claude;
|
|
53157
53376
|
this.outputBuffer = new AgentBridgeOutputBuffer(input);
|
|
53377
|
+
this.readState = input.readState ? new ClaudeReadStateTracker(input.readState) : null;
|
|
53158
53378
|
}
|
|
53159
53379
|
input;
|
|
53160
53380
|
context = null;
|
|
@@ -53176,6 +53396,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
53176
53396
|
pendingQuestions = /* @__PURE__ */ new Map();
|
|
53177
53397
|
outputBuffer;
|
|
53178
53398
|
projector = new ClaudeCodeProjector();
|
|
53399
|
+
readState;
|
|
53179
53400
|
livenessTicker = null;
|
|
53180
53401
|
// -----------------------------------------------------------------------------
|
|
53181
53402
|
// Lifecycle (public API)
|
|
@@ -53552,6 +53773,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
53552
53773
|
return;
|
|
53553
53774
|
}
|
|
53554
53775
|
this.persistAgentId(activeContext, message);
|
|
53776
|
+
this.trackReadState(activeContext, message);
|
|
53555
53777
|
let projections;
|
|
53556
53778
|
try {
|
|
53557
53779
|
projections = this.projector.project(message);
|
|
@@ -53615,6 +53837,31 @@ var ClaudeCodeCommandHandler = class {
|
|
|
53615
53837
|
);
|
|
53616
53838
|
}
|
|
53617
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
|
+
}
|
|
53618
53865
|
storedResumeAgentId() {
|
|
53619
53866
|
const store = this.input.sessionResume;
|
|
53620
53867
|
const activeContext = this.context;
|
|
@@ -53644,10 +53891,18 @@ var ClaudeCodeCommandHandler = class {
|
|
|
53644
53891
|
"Cannot restart Claude Code for a model/effort selection change without a session id to resume"
|
|
53645
53892
|
);
|
|
53646
53893
|
}
|
|
53894
|
+
if (!resumeAgentId && this.context) {
|
|
53895
|
+
this.readState?.clear(this.context.sessionId);
|
|
53896
|
+
}
|
|
53647
53897
|
const session = claudeAgentBridgeRuntime.start({
|
|
53648
53898
|
claude: this.claudeConfig,
|
|
53649
53899
|
resumeAgentId,
|
|
53650
53900
|
...resumeRequired ? { allowResumeFallback: false } : {},
|
|
53901
|
+
onResumeFallback: () => {
|
|
53902
|
+
if (this.context) {
|
|
53903
|
+
this.readState?.clear(this.context.sessionId);
|
|
53904
|
+
}
|
|
53905
|
+
},
|
|
53651
53906
|
canUseTool: this.canUseTool,
|
|
53652
53907
|
onMessage: (message, meta3) => this.handleAgentMessage(message, meta3),
|
|
53653
53908
|
onError: (error51) => this.handleAgentError(error51),
|
|
@@ -54064,25 +54319,25 @@ function normalizeChunk(chunk) {
|
|
|
54064
54319
|
}
|
|
54065
54320
|
|
|
54066
54321
|
// src/commands/agent-bridge/harness/codex/resume-store.ts
|
|
54067
|
-
import { existsSync as
|
|
54068
|
-
import { dirname as
|
|
54322
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
54323
|
+
import { dirname as dirname5 } from "path";
|
|
54069
54324
|
var AGENT_BRIDGE_RUNTIME_DIR2 = "/tmp/auto-bridge-runtime";
|
|
54070
54325
|
var CODEX_THREAD_RESUME_PATH = `${AGENT_BRIDGE_RUNTIME_DIR2}/codex-thread-id`;
|
|
54071
54326
|
function fileCodexThreadResumeStore(path2 = CODEX_THREAD_RESUME_PATH) {
|
|
54072
54327
|
return {
|
|
54073
54328
|
read(sessionId) {
|
|
54074
|
-
if (!
|
|
54329
|
+
if (!existsSync3(path2)) {
|
|
54075
54330
|
return null;
|
|
54076
54331
|
}
|
|
54077
|
-
const record2 = parseResumeRecord2(
|
|
54332
|
+
const record2 = parseResumeRecord2(readFileSync4(path2, "utf8"));
|
|
54078
54333
|
if (!record2 || record2.sessionId !== sessionId) {
|
|
54079
54334
|
return null;
|
|
54080
54335
|
}
|
|
54081
54336
|
return record2.threadId;
|
|
54082
54337
|
},
|
|
54083
54338
|
write(record2) {
|
|
54084
|
-
|
|
54085
|
-
|
|
54339
|
+
mkdirSync4(dirname5(path2), { recursive: true });
|
|
54340
|
+
writeFileSync4(path2, `${JSON.stringify(record2)}
|
|
54086
54341
|
`, "utf8");
|
|
54087
54342
|
}
|
|
54088
54343
|
};
|
|
@@ -54102,8 +54357,26 @@ function parseResumeRecord2(raw) {
|
|
|
54102
54357
|
// src/commands/agent-bridge/harness/codex/session.ts
|
|
54103
54358
|
init_src();
|
|
54104
54359
|
import { spawn as spawn2 } from "child_process";
|
|
54105
|
-
import { mkdirSync as
|
|
54106
|
-
import { join as
|
|
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";
|
|
54107
54380
|
|
|
54108
54381
|
// src/commands/agent-bridge/harness/codex/options.ts
|
|
54109
54382
|
import { join as join3 } from "path";
|
|
@@ -54245,6 +54518,172 @@ function tomlString(value) {
|
|
|
54245
54518
|
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
54246
54519
|
}
|
|
54247
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
|
+
|
|
54248
54687
|
// src/commands/agent-bridge/harness/codex/turn-retry.ts
|
|
54249
54688
|
var MAX_CODEX_TURN_RETRY_ATTEMPTS = 3;
|
|
54250
54689
|
var MAX_CODEX_TURN_RETRY_TOTAL_DELAY_MS = 3e4;
|
|
@@ -54478,12 +54917,16 @@ var CodexAgentBridgeSessionImpl = class {
|
|
|
54478
54917
|
}
|
|
54479
54918
|
async start() {
|
|
54480
54919
|
const options = codexLaunchOptions(this.input.codex);
|
|
54481
|
-
|
|
54482
|
-
|
|
54920
|
+
mkdirSync5(options.codexHome, { recursive: true });
|
|
54921
|
+
writeFileSync6(join5(options.codexHome, "config.toml"), options.configToml);
|
|
54483
54922
|
const startedAt = Date.now();
|
|
54484
54923
|
this.input.writeOutput?.(
|
|
54485
54924
|
`agent_bridge_codex_startup_started codex_home=${options.codexHome}`
|
|
54486
54925
|
);
|
|
54926
|
+
ensureCodexEditCapability({
|
|
54927
|
+
command: options.command,
|
|
54928
|
+
...this.input.writeOutput ? { writeOutput: this.input.writeOutput } : {}
|
|
54929
|
+
});
|
|
54487
54930
|
const proc = spawn2(options.command, options.args, {
|
|
54488
54931
|
env: options.env,
|
|
54489
54932
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -54883,12 +55326,17 @@ var CodexAgentBridgeSessionImpl = class {
|
|
|
54883
55326
|
this.pendingToolItemIds.add(notification.item.id);
|
|
54884
55327
|
}
|
|
54885
55328
|
return;
|
|
54886
|
-
case "itemCompleted":
|
|
55329
|
+
case "itemCompleted": {
|
|
55330
|
+
const fallthrough = codexEditFallthroughMarker(notification.item);
|
|
55331
|
+
if (fallthrough) {
|
|
55332
|
+
this.input.writeOutput?.(fallthrough);
|
|
55333
|
+
}
|
|
54887
55334
|
this.pendingToolItemIds.delete(notification.item.id);
|
|
54888
55335
|
if (this.pendingToolItemIds.size === 0) {
|
|
54889
55336
|
this.resolveSettlement();
|
|
54890
55337
|
}
|
|
54891
55338
|
return;
|
|
55339
|
+
}
|
|
54892
55340
|
default:
|
|
54893
55341
|
return;
|
|
54894
55342
|
}
|
|
@@ -55373,6 +55821,7 @@ function createHarnessCommandHandler(input) {
|
|
|
55373
55821
|
return createClaudeCodeCommandHandler({
|
|
55374
55822
|
...base,
|
|
55375
55823
|
claude,
|
|
55824
|
+
readState: fileClaudeReadStateStore(),
|
|
55376
55825
|
sessionResume: fileClaudeSessionResumeStore()
|
|
55377
55826
|
});
|
|
55378
55827
|
}
|
|
@@ -55672,9 +56121,9 @@ function statusAgents(input) {
|
|
|
55672
56121
|
// src/commands/agents/connect.ts
|
|
55673
56122
|
init_resources2();
|
|
55674
56123
|
init_browser();
|
|
55675
|
-
import { existsSync as
|
|
55676
|
-
import { homedir as homedir3, tmpdir } from "os";
|
|
55677
|
-
import { join as
|
|
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";
|
|
55678
56127
|
|
|
55679
56128
|
// src/lib/stdio/secret.ts
|
|
55680
56129
|
async function questionSecret(context, prompt) {
|
|
@@ -55865,7 +56314,7 @@ async function promptForIconUploads(input, options) {
|
|
|
55865
56314
|
}
|
|
55866
56315
|
}
|
|
55867
56316
|
function stagedLocationLabel(stagedPath) {
|
|
55868
|
-
return stagedPath.startsWith(`${
|
|
56317
|
+
return stagedPath.startsWith(`${join7(homedir3(), "Downloads")}/`) ? "Downloads" : "the printed path";
|
|
55869
56318
|
}
|
|
55870
56319
|
async function stageAvatarImage(input) {
|
|
55871
56320
|
try {
|
|
@@ -55877,10 +56326,10 @@ async function stageAvatarImage(input) {
|
|
|
55877
56326
|
}
|
|
55878
56327
|
const contentType = response.headers.get("content-type") ?? "";
|
|
55879
56328
|
const extension = contentType.includes("jpeg") ? ".jpg" : ".png";
|
|
55880
|
-
const downloads =
|
|
55881
|
-
const directory =
|
|
55882
|
-
const path2 =
|
|
55883
|
-
|
|
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()));
|
|
55884
56333
|
return path2;
|
|
55885
56334
|
} catch {
|
|
55886
56335
|
return void 0;
|
|
@@ -57379,19 +57828,19 @@ init_src();
|
|
|
57379
57828
|
// src/commands/logs/actions.ts
|
|
57380
57829
|
import {
|
|
57381
57830
|
closeSync,
|
|
57382
|
-
existsSync as
|
|
57831
|
+
existsSync as existsSync7,
|
|
57383
57832
|
openSync,
|
|
57384
|
-
readFileSync as
|
|
57833
|
+
readFileSync as readFileSync9,
|
|
57385
57834
|
readSync,
|
|
57386
|
-
statSync as
|
|
57835
|
+
statSync as statSync4
|
|
57387
57836
|
} from "fs";
|
|
57388
57837
|
var DEFAULT_POLL_INTERVAL_MS = 1e3;
|
|
57389
57838
|
async function tailRuntimeLog(input) {
|
|
57390
|
-
if (!
|
|
57839
|
+
if (!existsSync7(input.path)) {
|
|
57391
57840
|
input.writeError(`No runtime log at ${input.path}`);
|
|
57392
57841
|
return;
|
|
57393
57842
|
}
|
|
57394
|
-
const content =
|
|
57843
|
+
const content = readFileSync9(input.path, "utf8");
|
|
57395
57844
|
for (const line of selectLastLines(content, input.lines)) {
|
|
57396
57845
|
input.writeOutput(line);
|
|
57397
57846
|
}
|
|
@@ -57418,7 +57867,7 @@ async function followRuntimeLog(input) {
|
|
|
57418
57867
|
}
|
|
57419
57868
|
let size;
|
|
57420
57869
|
try {
|
|
57421
|
-
size =
|
|
57870
|
+
size = statSync4(input.path).size;
|
|
57422
57871
|
} catch {
|
|
57423
57872
|
continue;
|
|
57424
57873
|
}
|
|
@@ -60503,7 +60952,7 @@ function createProgram(options = {}) {
|
|
|
60503
60952
|
}
|
|
60504
60953
|
|
|
60505
60954
|
// src/lib/entrypoint.ts
|
|
60506
|
-
import { realpathSync as
|
|
60955
|
+
import { realpathSync as realpathSync3 } from "fs";
|
|
60507
60956
|
import { pathToFileURL } from "url";
|
|
60508
60957
|
function isCliEntrypoint(input) {
|
|
60509
60958
|
if (input.entrypoint.kind === "missing") {
|
|
@@ -60511,7 +60960,7 @@ function isCliEntrypoint(input) {
|
|
|
60511
60960
|
}
|
|
60512
60961
|
let resolvedEntrypoint;
|
|
60513
60962
|
try {
|
|
60514
|
-
resolvedEntrypoint =
|
|
60963
|
+
resolvedEntrypoint = realpathSync3(input.entrypoint.path);
|
|
60515
60964
|
} catch {
|
|
60516
60965
|
return false;
|
|
60517
60966
|
}
|