@codexhost/cli-linux-arm64 0.6.2 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/THIRD_PARTY_NOTICES.txt +4 -0
- package/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +18 -14
- package/app/host-runtime.mjs +665 -356
- package/app/plugins/antigravity/plugin.mjs +45 -198
- package/app/plugins/claude-code/plugin.mjs +223 -49
- package/app/plugins/codebuddy/assets/icon.svg +1 -0
- package/app/plugins/codebuddy/manifest.json +13 -0
- package/app/plugins/codebuddy/plugin.mjs +23045 -0
- package/app/plugins/cursor-cli/assets/icon.svg +1 -0
- package/app/plugins/cursor-cli/manifest.json +13 -0
- package/app/plugins/cursor-cli/plugin.mjs +22579 -0
- package/app/plugins/enabled.json +3 -1
- package/app/plugins/pi/plugin.mjs +0 -12
- package/app/renderer-extension.js +212 -62
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- package/licenses/Agent-Client-Protocol-SDK-LICENSE.txt +191 -0
- package/package.json +1 -1
package/app/host-runtime.mjs
CHANGED
|
@@ -2278,7 +2278,7 @@ var require_websocket = __commonJS({
|
|
|
2278
2278
|
var http = __require("http");
|
|
2279
2279
|
var net5 = __require("net");
|
|
2280
2280
|
var tls = __require("tls");
|
|
2281
|
-
var { randomBytes: randomBytes3, createHash:
|
|
2281
|
+
var { randomBytes: randomBytes3, createHash: createHash9 } = __require("crypto");
|
|
2282
2282
|
var { Duplex: Duplex2, Readable } = __require("stream");
|
|
2283
2283
|
var { URL: URL2 } = __require("url");
|
|
2284
2284
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -2946,7 +2946,7 @@ var require_websocket = __commonJS({
|
|
|
2946
2946
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
2947
2947
|
return;
|
|
2948
2948
|
}
|
|
2949
|
-
const digest2 =
|
|
2949
|
+
const digest2 = createHash9("sha1").update(key + GUID).digest("base64");
|
|
2950
2950
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
2951
2951
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
2952
2952
|
return;
|
|
@@ -3315,7 +3315,7 @@ var require_websocket_server = __commonJS({
|
|
|
3315
3315
|
var EventEmitter = __require("events");
|
|
3316
3316
|
var http = __require("http");
|
|
3317
3317
|
var { Duplex: Duplex2 } = __require("stream");
|
|
3318
|
-
var { createHash:
|
|
3318
|
+
var { createHash: createHash9 } = __require("crypto");
|
|
3319
3319
|
var extension2 = require_extension();
|
|
3320
3320
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
3321
3321
|
var subprotocol2 = require_subprotocol();
|
|
@@ -3622,7 +3622,7 @@ var require_websocket_server = __commonJS({
|
|
|
3622
3622
|
);
|
|
3623
3623
|
}
|
|
3624
3624
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
3625
|
-
const digest2 =
|
|
3625
|
+
const digest2 = createHash9("sha1").update(key + GUID).digest("base64");
|
|
3626
3626
|
const headers = [
|
|
3627
3627
|
"HTTP/1.1 101 Switching Protocols",
|
|
3628
3628
|
"Upgrade: websocket",
|
|
@@ -4267,7 +4267,7 @@ async function runDelegationCli(input) {
|
|
|
4267
4267
|
|
|
4268
4268
|
// packages/host-runtime/src/run-host-runtime.ts
|
|
4269
4269
|
import { randomBytes } from "node:crypto";
|
|
4270
|
-
import
|
|
4270
|
+
import path21 from "node:path";
|
|
4271
4271
|
import { homedir } from "node:os";
|
|
4272
4272
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
4273
4273
|
|
|
@@ -4613,9 +4613,85 @@ function selectInstallerReleaseArtifact(release, target) {
|
|
|
4613
4613
|
});
|
|
4614
4614
|
}
|
|
4615
4615
|
|
|
4616
|
+
// packages/update-manager/dist/github-cli-release.js
|
|
4617
|
+
import { execFile } from "node:child_process";
|
|
4618
|
+
import path2 from "node:path";
|
|
4619
|
+
var GITHUB_LATEST_RELEASE_ENDPOINT = "repos/BytePioneer-AI/codex-host/releases/latest";
|
|
4620
|
+
var MAX_RELEASE_RESPONSE_BYTES = 1024 * 1024;
|
|
4621
|
+
var GITHUB_CLI_TIMEOUT_MS = 5e3;
|
|
4622
|
+
function defaultExecutableCandidates(environment, platform) {
|
|
4623
|
+
if (environment.CODEXHOST_GH_COMMAND)
|
|
4624
|
+
return [environment.CODEXHOST_GH_COMMAND];
|
|
4625
|
+
const candidates = ["gh"];
|
|
4626
|
+
if (platform === "darwin") {
|
|
4627
|
+
candidates.push("/opt/homebrew/bin/gh", "/usr/local/bin/gh");
|
|
4628
|
+
} else if (platform === "win32") {
|
|
4629
|
+
const programFiles = environment.ProgramFiles ?? environment.PROGRAMFILES;
|
|
4630
|
+
const localAppData = environment.LOCALAPPDATA;
|
|
4631
|
+
if (programFiles)
|
|
4632
|
+
candidates.push(path2.win32.join(programFiles, "GitHub CLI", "gh.exe"));
|
|
4633
|
+
if (localAppData) {
|
|
4634
|
+
candidates.push(path2.win32.join(localAppData, "Programs", "GitHub CLI", "gh.exe"));
|
|
4635
|
+
}
|
|
4636
|
+
} else {
|
|
4637
|
+
candidates.push("/usr/local/bin/gh", "/usr/bin/gh", "/snap/bin/gh");
|
|
4638
|
+
}
|
|
4639
|
+
return [...new Set(candidates.filter((candidate) => Boolean(candidate)))];
|
|
4640
|
+
}
|
|
4641
|
+
function runGitHubCli(executable2, arguments_2, options2) {
|
|
4642
|
+
return new Promise((resolve, reject) => {
|
|
4643
|
+
execFile(executable2, [...arguments_2], {
|
|
4644
|
+
encoding: "utf8",
|
|
4645
|
+
env: options2.environment,
|
|
4646
|
+
maxBuffer: MAX_RELEASE_RESPONSE_BYTES,
|
|
4647
|
+
timeout: GITHUB_CLI_TIMEOUT_MS,
|
|
4648
|
+
windowsHide: true,
|
|
4649
|
+
...options2.signal ? { signal: options2.signal } : {}
|
|
4650
|
+
}, (error51, stdout) => {
|
|
4651
|
+
if (error51)
|
|
4652
|
+
reject(error51);
|
|
4653
|
+
else
|
|
4654
|
+
resolve(stdout);
|
|
4655
|
+
});
|
|
4656
|
+
});
|
|
4657
|
+
}
|
|
4658
|
+
async function fetchLatestGitHubReleaseWithGitHubCli(options2 = {}) {
|
|
4659
|
+
const environment = options2.environment ?? process.env;
|
|
4660
|
+
const platform = options2.platform ?? process.platform;
|
|
4661
|
+
const candidates = options2.executableCandidates ?? defaultExecutableCandidates(environment, platform);
|
|
4662
|
+
const run = options2.run ?? runGitHubCli;
|
|
4663
|
+
const arguments_2 = [
|
|
4664
|
+
"api",
|
|
4665
|
+
"--hostname",
|
|
4666
|
+
"github.com",
|
|
4667
|
+
"--method",
|
|
4668
|
+
"GET",
|
|
4669
|
+
"--header",
|
|
4670
|
+
"Accept: application/vnd.github+json",
|
|
4671
|
+
"--header",
|
|
4672
|
+
"X-GitHub-Api-Version: 2022-11-28",
|
|
4673
|
+
GITHUB_LATEST_RELEASE_ENDPOINT
|
|
4674
|
+
];
|
|
4675
|
+
for (const executable2 of candidates) {
|
|
4676
|
+
options2.signal?.throwIfAborted();
|
|
4677
|
+
try {
|
|
4678
|
+
return parseLatestGitHubRelease(JSON.parse(await run(executable2, arguments_2, {
|
|
4679
|
+
environment,
|
|
4680
|
+
...options2.signal ? { signal: options2.signal } : {}
|
|
4681
|
+
})));
|
|
4682
|
+
} catch (error51) {
|
|
4683
|
+
options2.signal?.throwIfAborted();
|
|
4684
|
+
const code = error51?.code;
|
|
4685
|
+
if (code !== "ENOENT" && code !== "EACCES")
|
|
4686
|
+
return null;
|
|
4687
|
+
}
|
|
4688
|
+
}
|
|
4689
|
+
return null;
|
|
4690
|
+
}
|
|
4691
|
+
|
|
4616
4692
|
// packages/update-manager/dist/operation-state.js
|
|
4617
4693
|
import { lstat as lstat2, mkdir, open, readFile as readFile2, readdir, rm, writeFile } from "node:fs/promises";
|
|
4618
|
-
import
|
|
4694
|
+
import path3 from "node:path";
|
|
4619
4695
|
var LOCK_FILE = "active-update-v1.lock";
|
|
4620
4696
|
var STATUS_FILE = "status-v1.json";
|
|
4621
4697
|
var TERMINAL_PHASES = /* @__PURE__ */ new Set(["succeeded", "failed"]);
|
|
@@ -4630,12 +4706,12 @@ async function regularFile(filePath) {
|
|
|
4630
4706
|
}
|
|
4631
4707
|
}
|
|
4632
4708
|
async function isUpdateOperationActive(stateDirectory) {
|
|
4633
|
-
if (!
|
|
4709
|
+
if (!path3.isAbsolute(stateDirectory))
|
|
4634
4710
|
throw new Error("update state directory must be absolute");
|
|
4635
|
-
return regularFile(
|
|
4711
|
+
return regularFile(path3.join(stateDirectory, LOCK_FILE));
|
|
4636
4712
|
}
|
|
4637
4713
|
async function discoverLatestUpdateStatus(stateDirectory) {
|
|
4638
|
-
if (!
|
|
4714
|
+
if (!path3.isAbsolute(stateDirectory))
|
|
4639
4715
|
throw new Error("update state directory must be absolute");
|
|
4640
4716
|
let entries;
|
|
4641
4717
|
try {
|
|
@@ -4649,7 +4725,7 @@ async function discoverLatestUpdateStatus(stateDirectory) {
|
|
|
4649
4725
|
for (const entry of entries) {
|
|
4650
4726
|
if (!entry.isDirectory() || entry.isSymbolicLink() || !entry.name.startsWith("update-"))
|
|
4651
4727
|
continue;
|
|
4652
|
-
const statusPath =
|
|
4728
|
+
const statusPath = path3.join(stateDirectory, entry.name, STATUS_FILE);
|
|
4653
4729
|
if (!await regularFile(statusPath))
|
|
4654
4730
|
continue;
|
|
4655
4731
|
try {
|
|
@@ -4677,8 +4753,8 @@ async function cleanupTerminalUpdateState(stateDirectory, options2 = {}) {
|
|
|
4677
4753
|
for (const entry of entries) {
|
|
4678
4754
|
if (!entry.isDirectory() || entry.isSymbolicLink() || !entry.name.startsWith("update-"))
|
|
4679
4755
|
continue;
|
|
4680
|
-
const directory =
|
|
4681
|
-
const statusPath =
|
|
4756
|
+
const directory = path3.join(stateDirectory, entry.name);
|
|
4757
|
+
const statusPath = path3.join(directory, STATUS_FILE);
|
|
4682
4758
|
try {
|
|
4683
4759
|
const status = parseUpdateStatus(JSON.parse(await readFile2(statusPath, "utf8")));
|
|
4684
4760
|
if (TERMINAL_PHASES.has(status.phase) && now - status.updatedAt > retentionSeconds) {
|
|
@@ -4689,10 +4765,10 @@ async function cleanupTerminalUpdateState(stateDirectory, options2 = {}) {
|
|
|
4689
4765
|
}
|
|
4690
4766
|
}
|
|
4691
4767
|
async function acquireUpdateOperationLock(stateDirectory) {
|
|
4692
|
-
if (!
|
|
4768
|
+
if (!path3.isAbsolute(stateDirectory))
|
|
4693
4769
|
throw new Error("update state directory must be absolute");
|
|
4694
4770
|
await mkdir(stateDirectory, { recursive: true, mode: 448 });
|
|
4695
|
-
const lockPath =
|
|
4771
|
+
const lockPath = path3.join(stateDirectory, LOCK_FILE);
|
|
4696
4772
|
let handle;
|
|
4697
4773
|
try {
|
|
4698
4774
|
handle = await open(lockPath, "wx", 384);
|
|
@@ -4711,9 +4787,9 @@ async function acquireUpdateOperationLock(stateDirectory) {
|
|
|
4711
4787
|
async setStatusPath(statusPath) {
|
|
4712
4788
|
if (released)
|
|
4713
4789
|
throw new Error("update operation lock is released");
|
|
4714
|
-
if (!
|
|
4790
|
+
if (!path3.isAbsolute(statusPath))
|
|
4715
4791
|
throw new Error("update status path must be absolute");
|
|
4716
|
-
await writeFile(lockPath, `${JSON.stringify({ ownerPid: process.pid, statusPath:
|
|
4792
|
+
await writeFile(lockPath, `${JSON.stringify({ ownerPid: process.pid, statusPath: path3.normalize(statusPath) })}
|
|
4717
4793
|
`, { encoding: "utf8", mode: 384 });
|
|
4718
4794
|
},
|
|
4719
4795
|
async release() {
|
|
@@ -4735,7 +4811,7 @@ function processIsAlive(processId) {
|
|
|
4735
4811
|
}
|
|
4736
4812
|
}
|
|
4737
4813
|
async function recoverUpdateOperationLock(stateDirectory) {
|
|
4738
|
-
const lockPath =
|
|
4814
|
+
const lockPath = path3.join(stateDirectory, LOCK_FILE);
|
|
4739
4815
|
if (!await regularFile(lockPath))
|
|
4740
4816
|
return;
|
|
4741
4817
|
let ownerPid;
|
|
@@ -4747,7 +4823,7 @@ async function recoverUpdateOperationLock(stateDirectory) {
|
|
|
4747
4823
|
} catch {
|
|
4748
4824
|
return;
|
|
4749
4825
|
}
|
|
4750
|
-
if (typeof statusPath !== "string" || !
|
|
4826
|
+
if (typeof statusPath !== "string" || !path3.isAbsolute(statusPath))
|
|
4751
4827
|
return;
|
|
4752
4828
|
try {
|
|
4753
4829
|
const status = parseUpdateStatus(JSON.parse(await readFile2(statusPath, "utf8")));
|
|
@@ -4762,7 +4838,7 @@ async function recoverUpdateOperationLock(stateDirectory) {
|
|
|
4762
4838
|
import { spawn } from "node:child_process";
|
|
4763
4839
|
import { randomUUID } from "node:crypto";
|
|
4764
4840
|
import { chmod, copyFile, lstat as lstat4, mkdir as mkdir2, readFile as readFile3, rename, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
|
|
4765
|
-
import
|
|
4841
|
+
import path4 from "node:path";
|
|
4766
4842
|
|
|
4767
4843
|
// packages/update-manager/dist/artifact.js
|
|
4768
4844
|
import { createHash } from "node:crypto";
|
|
@@ -4883,9 +4959,9 @@ async function replaceStatusFile(temporaryPath, statusPath) {
|
|
|
4883
4959
|
}
|
|
4884
4960
|
}
|
|
4885
4961
|
function requireAbsolutePath(value2, label) {
|
|
4886
|
-
if (!
|
|
4962
|
+
if (!path4.isAbsolute(value2))
|
|
4887
4963
|
throw new Error(`${label} must be an absolute path`);
|
|
4888
|
-
return
|
|
4964
|
+
return path4.normalize(value2);
|
|
4889
4965
|
}
|
|
4890
4966
|
async function requireRegularFile(value2, label) {
|
|
4891
4967
|
const filePath = requireAbsolutePath(value2, label);
|
|
@@ -4928,7 +5004,7 @@ function createBackgroundUpdateManager(dependencies2 = {}) {
|
|
|
4928
5004
|
const now = dependencies2.now ?? Date.now;
|
|
4929
5005
|
const preparedRequests = /* @__PURE__ */ new Set();
|
|
4930
5006
|
async function writeStatusSnapshot(statusPath, status) {
|
|
4931
|
-
const temporaryPath =
|
|
5007
|
+
const temporaryPath = path4.join(path4.dirname(statusPath), `.update-status-${randomId()}.tmp`);
|
|
4932
5008
|
try {
|
|
4933
5009
|
await writeFile2(temporaryPath, `${JSON.stringify(status)}
|
|
4934
5010
|
`, {
|
|
@@ -4988,15 +5064,15 @@ function createBackgroundUpdateManager(dependencies2 = {}) {
|
|
|
4988
5064
|
const updaterExecutable = await requireRegularFile(options2.updaterExecutable, "Updater executable");
|
|
4989
5065
|
const stateDirectory = requireAbsolutePath(options2.stateDirectory, "update state directory");
|
|
4990
5066
|
await mkdir2(stateDirectory, { recursive: true, mode: 448 });
|
|
4991
|
-
const workDirectory =
|
|
5067
|
+
const workDirectory = path4.join(stateDirectory, `update-${version2}-${randomId()}`);
|
|
4992
5068
|
await mkdir2(workDirectory, { recursive: false, mode: 448 });
|
|
4993
5069
|
const executableSuffix = platform === "win32" ? ".exe" : "";
|
|
4994
|
-
const helperPath =
|
|
5070
|
+
const helperPath = path4.join(workDirectory, `codexhost-updater${executableSuffix}`);
|
|
4995
5071
|
await copyFile(updaterExecutable, helperPath);
|
|
4996
5072
|
if (platform !== "win32")
|
|
4997
5073
|
await chmod(helperPath, 448);
|
|
4998
|
-
const requestPath =
|
|
4999
|
-
const statusPath =
|
|
5074
|
+
const requestPath = path4.join(workDirectory, "request-v1.json");
|
|
5075
|
+
const statusPath = path4.join(workDirectory, "status-v1.json");
|
|
5000
5076
|
await writePrivateJson(statusPath, preparedStatus(version2, installation, now()));
|
|
5001
5077
|
await options2.onPrepared?.({ version: version2, installation, statusPath });
|
|
5002
5078
|
return {
|
|
@@ -5012,8 +5088,8 @@ function createBackgroundUpdateManager(dependencies2 = {}) {
|
|
|
5012
5088
|
}
|
|
5013
5089
|
async function prepareArtifact(common, installation, sourceValue, fileName) {
|
|
5014
5090
|
const source = validateArtifact(sourceValue);
|
|
5015
|
-
const temporaryPath =
|
|
5016
|
-
const artifactPath =
|
|
5091
|
+
const temporaryPath = path4.join(common.workDirectory, `.${fileName}.download`);
|
|
5092
|
+
const artifactPath = path4.join(common.workDirectory, fileName);
|
|
5017
5093
|
const progress = progressReporter(common.statusPath, common.version, installation, source.size);
|
|
5018
5094
|
try {
|
|
5019
5095
|
const result = await download(source, temporaryPath, progress.update);
|
|
@@ -5087,7 +5163,7 @@ function createBackgroundUpdateManager(dependencies2 = {}) {
|
|
|
5087
5163
|
throw new Error("macOS DMG updates require macOS");
|
|
5088
5164
|
const common = await prepareCommon(options2, "macos-dmg");
|
|
5089
5165
|
const appPath = requireAbsolutePath(options2.appPath, "macOS application path");
|
|
5090
|
-
if (
|
|
5166
|
+
if (path4.extname(appPath) !== ".app") {
|
|
5091
5167
|
throw new Error("macOS application path must end in .app");
|
|
5092
5168
|
}
|
|
5093
5169
|
const artifact = await prepareArtifact(common, "macos-dmg", options2.artifact, "update.dmg");
|
|
@@ -5886,10 +5962,10 @@ function mergeDefs(...defs) {
|
|
|
5886
5962
|
function cloneDef(schema) {
|
|
5887
5963
|
return mergeDefs(schema._zod.def);
|
|
5888
5964
|
}
|
|
5889
|
-
function getElementAtPath(obj,
|
|
5890
|
-
if (!
|
|
5965
|
+
function getElementAtPath(obj, path26) {
|
|
5966
|
+
if (!path26)
|
|
5891
5967
|
return obj;
|
|
5892
|
-
return
|
|
5968
|
+
return path26.reduce((acc, key) => acc?.[key], obj);
|
|
5893
5969
|
}
|
|
5894
5970
|
function promiseAllObject(promisesObj) {
|
|
5895
5971
|
const keys = Object.keys(promisesObj);
|
|
@@ -6298,11 +6374,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
6298
6374
|
}
|
|
6299
6375
|
return false;
|
|
6300
6376
|
}
|
|
6301
|
-
function prefixIssues(
|
|
6377
|
+
function prefixIssues(path26, issues) {
|
|
6302
6378
|
return issues.map((iss) => {
|
|
6303
6379
|
var _a3;
|
|
6304
6380
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
6305
|
-
iss.path.unshift(
|
|
6381
|
+
iss.path.unshift(path26);
|
|
6306
6382
|
return iss;
|
|
6307
6383
|
});
|
|
6308
6384
|
}
|
|
@@ -6449,16 +6525,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
6449
6525
|
}
|
|
6450
6526
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
6451
6527
|
const fieldErrors = { _errors: [] };
|
|
6452
|
-
const processError = (error52,
|
|
6528
|
+
const processError = (error52, path26 = []) => {
|
|
6453
6529
|
for (const issue2 of error52.issues) {
|
|
6454
6530
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
6455
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
6531
|
+
issue2.errors.map((issues) => processError({ issues }, [...path26, ...issue2.path]));
|
|
6456
6532
|
} else if (issue2.code === "invalid_key") {
|
|
6457
|
-
processError({ issues: issue2.issues }, [...
|
|
6533
|
+
processError({ issues: issue2.issues }, [...path26, ...issue2.path]);
|
|
6458
6534
|
} else if (issue2.code === "invalid_element") {
|
|
6459
|
-
processError({ issues: issue2.issues }, [...
|
|
6535
|
+
processError({ issues: issue2.issues }, [...path26, ...issue2.path]);
|
|
6460
6536
|
} else {
|
|
6461
|
-
const fullpath = [...
|
|
6537
|
+
const fullpath = [...path26, ...issue2.path];
|
|
6462
6538
|
if (fullpath.length === 0) {
|
|
6463
6539
|
fieldErrors._errors.push(mapper(issue2));
|
|
6464
6540
|
} else {
|
|
@@ -6485,17 +6561,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
6485
6561
|
}
|
|
6486
6562
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
6487
6563
|
const result = { errors: [] };
|
|
6488
|
-
const processError = (error52,
|
|
6564
|
+
const processError = (error52, path26 = []) => {
|
|
6489
6565
|
var _a3, _b;
|
|
6490
6566
|
for (const issue2 of error52.issues) {
|
|
6491
6567
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
6492
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
6568
|
+
issue2.errors.map((issues) => processError({ issues }, [...path26, ...issue2.path]));
|
|
6493
6569
|
} else if (issue2.code === "invalid_key") {
|
|
6494
|
-
processError({ issues: issue2.issues }, [...
|
|
6570
|
+
processError({ issues: issue2.issues }, [...path26, ...issue2.path]);
|
|
6495
6571
|
} else if (issue2.code === "invalid_element") {
|
|
6496
|
-
processError({ issues: issue2.issues }, [...
|
|
6572
|
+
processError({ issues: issue2.issues }, [...path26, ...issue2.path]);
|
|
6497
6573
|
} else {
|
|
6498
|
-
const fullpath = [...
|
|
6574
|
+
const fullpath = [...path26, ...issue2.path];
|
|
6499
6575
|
if (fullpath.length === 0) {
|
|
6500
6576
|
result.errors.push(mapper(issue2));
|
|
6501
6577
|
continue;
|
|
@@ -6527,8 +6603,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
6527
6603
|
}
|
|
6528
6604
|
function toDotPath(_path) {
|
|
6529
6605
|
const segs = [];
|
|
6530
|
-
const
|
|
6531
|
-
for (const seg of
|
|
6606
|
+
const path26 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
6607
|
+
for (const seg of path26) {
|
|
6532
6608
|
if (typeof seg === "number")
|
|
6533
6609
|
segs.push(`[${seg}]`);
|
|
6534
6610
|
else if (typeof seg === "symbol")
|
|
@@ -19220,13 +19296,13 @@ function resolveRef(ref, ctx) {
|
|
|
19220
19296
|
if (!ref.startsWith("#")) {
|
|
19221
19297
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
19222
19298
|
}
|
|
19223
|
-
const
|
|
19224
|
-
if (
|
|
19299
|
+
const path26 = ref.slice(1).split("/").filter(Boolean);
|
|
19300
|
+
if (path26.length === 0) {
|
|
19225
19301
|
return ctx.rootSchema;
|
|
19226
19302
|
}
|
|
19227
19303
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
19228
|
-
if (
|
|
19229
|
-
const key =
|
|
19304
|
+
if (path26[0] === defsKey) {
|
|
19305
|
+
const key = path26[1];
|
|
19230
19306
|
if (!key || !ctx.defs[key]) {
|
|
19231
19307
|
throw new Error(`Reference not found: ${ref}`);
|
|
19232
19308
|
}
|
|
@@ -20649,7 +20725,7 @@ import { execFileSync } from "node:child_process";
|
|
|
20649
20725
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
20650
20726
|
import { constants } from "node:fs";
|
|
20651
20727
|
import { copyFile as copyFile2, mkdir as mkdir3, open as open3, readFile as readFile4, readdir as readdir2, rename as rename2, rm as rm3, stat } from "node:fs/promises";
|
|
20652
|
-
import
|
|
20728
|
+
import path5 from "node:path";
|
|
20653
20729
|
|
|
20654
20730
|
// packages/mapping-store/dist/records.js
|
|
20655
20731
|
var nonBlankTextSchema6 = external_exports.string().refine((value2) => value2.trim().length > 0, {
|
|
@@ -20900,12 +20976,12 @@ var MappingStore = class {
|
|
|
20900
20976
|
#initialized = false;
|
|
20901
20977
|
#lockHandle = null;
|
|
20902
20978
|
constructor(options2) {
|
|
20903
|
-
this.#directory =
|
|
20904
|
-
this.#threadsDirectory =
|
|
20905
|
-
this.#delegationsDirectory =
|
|
20906
|
-
this.#backupsDirectory =
|
|
20907
|
-
this.#quarantineDirectory =
|
|
20908
|
-
this.#lockPath =
|
|
20979
|
+
this.#directory = path5.resolve(options2.directory);
|
|
20980
|
+
this.#threadsDirectory = path5.join(this.#directory, "threads");
|
|
20981
|
+
this.#delegationsDirectory = path5.join(this.#directory, "delegations");
|
|
20982
|
+
this.#backupsDirectory = path5.join(this.#directory, "backups");
|
|
20983
|
+
this.#quarantineDirectory = path5.join(this.#directory, "quarantine");
|
|
20984
|
+
this.#lockPath = path5.join(this.#directory, "store.lock");
|
|
20909
20985
|
this.#instanceId = options2.instanceId ?? randomUUID2();
|
|
20910
20986
|
this.#now = options2.now ?? (() => /* @__PURE__ */ new Date());
|
|
20911
20987
|
this.#beforeReplace = options2.beforeReplace;
|
|
@@ -20924,8 +21000,8 @@ var MappingStore = class {
|
|
|
20924
21000
|
await this.#cleanupResidue();
|
|
20925
21001
|
const names = (await readdir2(this.#threadsDirectory)).filter((name) => name.endsWith(".json"));
|
|
20926
21002
|
for (const name of names) {
|
|
20927
|
-
const primary =
|
|
20928
|
-
const backup =
|
|
21003
|
+
const primary = path5.join(this.#threadsDirectory, name);
|
|
21004
|
+
const backup = path5.join(this.#backupsDirectory, name);
|
|
20929
21005
|
let record3 = null;
|
|
20930
21006
|
try {
|
|
20931
21007
|
record3 = await this.#readRecord(primary, name);
|
|
@@ -20934,7 +21010,7 @@ var MappingStore = class {
|
|
|
20934
21010
|
record3 = await this.#readRecord(backup, name);
|
|
20935
21011
|
await this.#replaceFile(primary, record3, false);
|
|
20936
21012
|
} catch (backupError) {
|
|
20937
|
-
const quarantine =
|
|
21013
|
+
const quarantine = path5.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid`);
|
|
20938
21014
|
await rename2(primary, quarantine).catch(() => void 0);
|
|
20939
21015
|
void primaryError;
|
|
20940
21016
|
void backupError;
|
|
@@ -20950,14 +21026,14 @@ var MappingStore = class {
|
|
|
20950
21026
|
}
|
|
20951
21027
|
const delegationNames = (await readdir2(this.#delegationsDirectory)).filter((name) => name.endsWith(".json"));
|
|
20952
21028
|
for (const name of delegationNames) {
|
|
20953
|
-
const file2 =
|
|
21029
|
+
const file2 = path5.join(this.#delegationsDirectory, name);
|
|
20954
21030
|
try {
|
|
20955
21031
|
const parsed = storedDelegationRecordV1Schema.parse(JSON.parse(await readFile4(file2, "utf8")));
|
|
20956
21032
|
if (`${parsed.delegationId}.json` !== name)
|
|
20957
21033
|
throw new Error("filename mismatch");
|
|
20958
21034
|
this.#delegations.set(parsed.delegationId, parsed);
|
|
20959
21035
|
} catch {
|
|
20960
|
-
const quarantine =
|
|
21036
|
+
const quarantine = path5.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid-delegation`);
|
|
20961
21037
|
await rename2(file2, quarantine).catch(() => void 0);
|
|
20962
21038
|
}
|
|
20963
21039
|
}
|
|
@@ -21115,10 +21191,35 @@ var MappingStore = class {
|
|
|
21115
21191
|
turnMappings: this.#mergeMappings(current.turnMappings, input.turnMappings ?? [])
|
|
21116
21192
|
}));
|
|
21117
21193
|
}
|
|
21194
|
+
// Keep native ref, Turn mappings and the indexed create request in one serialized
|
|
21195
|
+
// record mutation; separate setters could leave a child pointing at mixed Sessions.
|
|
21196
|
+
async rebindSubagentSession(input) {
|
|
21197
|
+
return this.#update(input.hostThreadId, (current) => {
|
|
21198
|
+
const parent = this.#records.get(input.parentHostThreadId);
|
|
21199
|
+
if (current.state !== "ready" || !current.nativeSessionRef || current.subagent?.parentHostThreadId !== input.parentHostThreadId || parent?.state !== "ready" || parent.harnessId !== current.harnessId || input.previousNativeSessionRef.harnessId !== current.harnessId || input.nativeSessionRef.harnessId !== current.harnessId || !sameJson(parent.nativeSessionRef, input.nativeSessionRef))
|
|
21200
|
+
throw new MappingStoreError("MAPPING_CONFLICT", "Subagent replacement must belong to its current parent Session");
|
|
21201
|
+
if (sameJson(current.nativeSessionRef, input.nativeSessionRef) && current.createRequestId === input.createRequestId)
|
|
21202
|
+
return null;
|
|
21203
|
+
if (!sameJson(current.nativeSessionRef, input.previousNativeSessionRef)) {
|
|
21204
|
+
throw new MappingStoreError("MAPPING_CONFLICT", "Subagent replacement source Session is stale");
|
|
21205
|
+
}
|
|
21206
|
+
const nativeSessionId = input.nativeSessionRef.nativeSessionId;
|
|
21207
|
+
return {
|
|
21208
|
+
...current,
|
|
21209
|
+
createRequestId: input.createRequestId,
|
|
21210
|
+
nativeSessionRef: input.nativeSessionRef,
|
|
21211
|
+
turnMappings: current.turnMappings.map((mapping) => ({
|
|
21212
|
+
...mapping,
|
|
21213
|
+
nativeTurnRef: { ...mapping.nativeTurnRef, nativeSessionId },
|
|
21214
|
+
...mapping.nativeCheckpointRef ? { nativeCheckpointRef: { ...mapping.nativeCheckpointRef, nativeSessionId } } : {}
|
|
21215
|
+
}))
|
|
21216
|
+
};
|
|
21217
|
+
});
|
|
21218
|
+
}
|
|
21118
21219
|
async replaceReadySession(input) {
|
|
21119
21220
|
return this.#update(input.hostThreadId, (current) => {
|
|
21120
|
-
if (current.state !== "ready" || !current.nativeSessionRef || !current.forkSource || current.forkSource.hostThreadId !== input.forkSource.hostThreadId || current.nativeSessionRef.nativeSessionId === input.nativeSessionRef.nativeSessionId || input.turnMappings.length < 1 || input.turnMappings.length >= current.turnMappings.length || input.turnMappings.some(({ hostTurnId }, index) => hostTurnId !== current.turnMappings[index]?.hostTurnId)) {
|
|
21121
|
-
throw new MappingStoreError("MAPPING_CONFLICT", "Ready Session replacement must retain an exact shorter derived prefix");
|
|
21221
|
+
if (current.state !== "ready" || !current.nativeSessionRef || current.revision !== input.expectedRevision || !sameJson(current.nativeSessionRef, input.expectedNativeSessionRef) || !current.forkSource || current.forkSource.hostThreadId !== input.forkSource.hostThreadId || current.nativeSessionRef.nativeSessionId === input.nativeSessionRef.nativeSessionId || input.turnMappings.length < 1 || input.turnMappings.length >= current.turnMappings.length || input.turnMappings.some(({ hostTurnId }, index) => hostTurnId !== current.turnMappings[index]?.hostTurnId)) {
|
|
21222
|
+
throw new MappingStoreError("MAPPING_CONFLICT", "Ready Session replacement must match the expected record and retain an exact shorter derived prefix");
|
|
21122
21223
|
}
|
|
21123
21224
|
return {
|
|
21124
21225
|
...current,
|
|
@@ -21130,8 +21231,8 @@ var MappingStore = class {
|
|
|
21130
21231
|
}
|
|
21131
21232
|
async replaceReadySessionAfterLastTurn(input) {
|
|
21132
21233
|
return this.#update(input.hostThreadId, (current) => {
|
|
21133
|
-
if (current.state !== "ready" || !current.nativeSessionRef || input.turnMappings.length !== current.turnMappings.length - 1 || input.turnMappings.some(({ hostTurnId }, index) => hostTurnId !== current.turnMappings[index]?.hostTurnId)) {
|
|
21134
|
-
throw new MappingStoreError("MAPPING_CONFLICT", "Last-Turn Session replacement must retain the exact shorter Host Turn prefix");
|
|
21234
|
+
if (current.state !== "ready" || !current.nativeSessionRef || current.revision !== input.expectedRevision || !sameJson(current.nativeSessionRef, input.expectedNativeSessionRef) || input.turnMappings.length !== current.turnMappings.length - 1 || input.turnMappings.some(({ hostTurnId }, index) => hostTurnId !== current.turnMappings[index]?.hostTurnId)) {
|
|
21235
|
+
throw new MappingStoreError("MAPPING_CONFLICT", "Last-Turn Session replacement must match the expected record and retain the exact shorter Host Turn prefix");
|
|
21135
21236
|
}
|
|
21136
21237
|
return {
|
|
21137
21238
|
...current,
|
|
@@ -21352,10 +21453,10 @@ var MappingStore = class {
|
|
|
21352
21453
|
readdir2(this.#directory)
|
|
21353
21454
|
]);
|
|
21354
21455
|
await Promise.all([
|
|
21355
|
-
...threadNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(
|
|
21356
|
-
...delegationNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(
|
|
21456
|
+
...threadNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(path5.join(this.#threadsDirectory, name), { force: true })),
|
|
21457
|
+
...delegationNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(path5.join(this.#delegationsDirectory, name), { force: true })),
|
|
21357
21458
|
// Renamed aside by #acquireLock; nothing reads them back, and they accumulate one per run.
|
|
21358
|
-
...rootNames.filter((name) => name.startsWith(`${
|
|
21459
|
+
...rootNames.filter((name) => name.startsWith(`${path5.basename(this.#lockPath)}.stale-`)).map((name) => rm3(path5.join(this.#directory, name), { force: true }))
|
|
21359
21460
|
]);
|
|
21360
21461
|
}
|
|
21361
21462
|
async #acquireLock() {
|
|
@@ -21456,13 +21557,13 @@ var MappingStore = class {
|
|
|
21456
21557
|
await next;
|
|
21457
21558
|
}
|
|
21458
21559
|
#recordPath(hostThreadId) {
|
|
21459
|
-
return
|
|
21560
|
+
return path5.join(this.#threadsDirectory, `${hostThreadId}.json`);
|
|
21460
21561
|
}
|
|
21461
21562
|
#delegationPath(delegationId) {
|
|
21462
|
-
return
|
|
21563
|
+
return path5.join(this.#delegationsDirectory, `${delegationId}.json`);
|
|
21463
21564
|
}
|
|
21464
21565
|
#backupPath(hostThreadId) {
|
|
21465
|
-
return
|
|
21566
|
+
return path5.join(this.#backupsDirectory, `${hostThreadId}.json`);
|
|
21466
21567
|
}
|
|
21467
21568
|
#requireInitialized() {
|
|
21468
21569
|
if (!this.#initialized) {
|
|
@@ -22215,8 +22316,8 @@ function projectFileChangeKind(kind) {
|
|
|
22215
22316
|
return { type: kind };
|
|
22216
22317
|
}
|
|
22217
22318
|
function projectFileChanges(changes) {
|
|
22218
|
-
return changes.map(({ path:
|
|
22219
|
-
path:
|
|
22319
|
+
return changes.map(({ path: path26, kind, unifiedDiff }) => ({
|
|
22320
|
+
path: path26,
|
|
22220
22321
|
kind: projectFileChangeKind(kind),
|
|
22221
22322
|
diff: unifiedDiff
|
|
22222
22323
|
}));
|
|
@@ -22531,9 +22632,9 @@ function projectHistoricalTurn(input) {
|
|
|
22531
22632
|
return [];
|
|
22532
22633
|
}
|
|
22533
22634
|
return item.type === "reasoning" ? [
|
|
22534
|
-
projectItem(item, outcome, cwd, true, ""),
|
|
22635
|
+
projectItem(item, outcome, cwd, true, input.threadId ?? ""),
|
|
22535
22636
|
projectReasoningTranscriptItem(item, outcome, cwd)
|
|
22536
|
-
] : [projectItem(item, outcome, cwd, true, "")];
|
|
22637
|
+
] : [projectItem(item, outcome, cwd, true, input.threadId ?? "")];
|
|
22537
22638
|
})
|
|
22538
22639
|
],
|
|
22539
22640
|
error: error51,
|
|
@@ -23165,13 +23266,13 @@ function decodeThreadForkRequest(request) {
|
|
|
23165
23266
|
if (runtimeWorkspaceRoots !== void 0 && runtimeWorkspaceRoots !== null && (!Array.isArray(runtimeWorkspaceRoots) || runtimeWorkspaceRoots.some((root) => typeof root !== "string" || root.length === 0))) {
|
|
23166
23267
|
throw new Error("thread/fork params.runtimeWorkspaceRoots must be text paths or null");
|
|
23167
23268
|
}
|
|
23168
|
-
const
|
|
23269
|
+
const path26 = optionalText(params, "path", { allowEmpty: true });
|
|
23169
23270
|
const ephemeral = optionalBoolean(params, "ephemeral");
|
|
23170
23271
|
return {
|
|
23171
23272
|
threadId: threadId3,
|
|
23172
23273
|
...lastTurnText ? { lastTurnId: hostTurnIdSchema.parse(lastTurnText) } : {},
|
|
23173
23274
|
...beforeTurnText ? { beforeTurnId: hostTurnIdSchema.parse(beforeTurnText) } : {},
|
|
23174
|
-
...
|
|
23275
|
+
...path26 ? { path: path26 } : {},
|
|
23175
23276
|
...optionalField(params, "model"),
|
|
23176
23277
|
...optionalField(params, "modelProvider"),
|
|
23177
23278
|
...optionalField(params, "cwd"),
|
|
@@ -24182,18 +24283,149 @@ async function inspectHarnessAccounts(adapters, descriptors, timeoutMs = 12e3) {
|
|
|
24182
24283
|
}
|
|
24183
24284
|
|
|
24184
24285
|
// packages/host-runtime/src/app-server-host.ts
|
|
24185
|
-
import { createHash as
|
|
24286
|
+
import { createHash as createHash6, randomUUID as randomUUID9 } from "node:crypto";
|
|
24186
24287
|
import { rm as rm4 } from "node:fs/promises";
|
|
24187
24288
|
import os2 from "node:os";
|
|
24188
|
-
import
|
|
24289
|
+
import path12 from "node:path";
|
|
24189
24290
|
|
|
24190
24291
|
// packages/host-runtime/src/external-thread-fork.ts
|
|
24191
24292
|
import nodePath from "node:path";
|
|
24192
24293
|
|
|
24193
24294
|
// packages/host-runtime/src/external-thread-repository.ts
|
|
24194
|
-
import { randomUUID as
|
|
24295
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
24195
24296
|
import os from "node:os";
|
|
24196
|
-
import
|
|
24297
|
+
import path6 from "node:path";
|
|
24298
|
+
|
|
24299
|
+
// packages/host-runtime/src/external-subagent-threads.ts
|
|
24300
|
+
import { createHash as createHash3, randomUUID as randomUUID3 } from "node:crypto";
|
|
24301
|
+
function childCreateRequest(parent, nativeRef, id2) {
|
|
24302
|
+
const key = createHash3("sha256").update(JSON.stringify([parent.hostThreadId, parent.harnessId, nativeRef.nativeSessionId, id2])).digest("hex");
|
|
24303
|
+
return `subagent:${key}`;
|
|
24304
|
+
}
|
|
24305
|
+
function subagentMaterializer(store, parent, previousParent) {
|
|
24306
|
+
if (previousParent && (previousParent.hostThreadId !== parent.hostThreadId || previousParent.harnessId !== parent.harnessId)) {
|
|
24307
|
+
throw new Error("Subagent Session replacement must stay in the same Host Thread");
|
|
24308
|
+
}
|
|
24309
|
+
const previousRef = previousParent?.nativeSessionRef;
|
|
24310
|
+
let legacy;
|
|
24311
|
+
const legacyRecords = () => legacy ??= store.listThreads().then((records) => {
|
|
24312
|
+
const byRequest = /* @__PURE__ */ new Map();
|
|
24313
|
+
const children = /* @__PURE__ */ new Map();
|
|
24314
|
+
for (const record3 of records) {
|
|
24315
|
+
if (!record3.subagent || record3.harnessId !== parent.harnessId || !record3.nativeSessionRef)
|
|
24316
|
+
continue;
|
|
24317
|
+
const owner = {
|
|
24318
|
+
hostThreadId: record3.subagent.parentHostThreadId,
|
|
24319
|
+
harnessId: record3.harnessId
|
|
24320
|
+
};
|
|
24321
|
+
const key = childCreateRequest(
|
|
24322
|
+
owner,
|
|
24323
|
+
record3.nativeSessionRef,
|
|
24324
|
+
record3.subagent.nativeSubagentId
|
|
24325
|
+
);
|
|
24326
|
+
if (!byRequest.has(key) || record3.state === "ready") byRequest.set(key, record3);
|
|
24327
|
+
const siblings = children.get(owner.hostThreadId) ?? [];
|
|
24328
|
+
siblings.push(record3);
|
|
24329
|
+
children.set(owner.hostThreadId, siblings);
|
|
24330
|
+
}
|
|
24331
|
+
return { byRequest, children };
|
|
24332
|
+
});
|
|
24333
|
+
const rebind = async (existing, owner, visited = /* @__PURE__ */ new Set()) => {
|
|
24334
|
+
if (!previousRef || !owner.nativeSessionRef || !existing.subagent || visited.has(existing.hostThreadId)) {
|
|
24335
|
+
throw new Error("Invalid retained Subagent Session tree");
|
|
24336
|
+
}
|
|
24337
|
+
visited.add(existing.hostThreadId);
|
|
24338
|
+
const rebound = await store.rebindSubagentSession({
|
|
24339
|
+
hostThreadId: existing.hostThreadId,
|
|
24340
|
+
parentHostThreadId: owner.hostThreadId,
|
|
24341
|
+
previousNativeSessionRef: previousRef,
|
|
24342
|
+
nativeSessionRef: owner.nativeSessionRef,
|
|
24343
|
+
createRequestId: childCreateRequest(
|
|
24344
|
+
owner,
|
|
24345
|
+
owner.nativeSessionRef,
|
|
24346
|
+
existing.subagent.nativeSubagentId
|
|
24347
|
+
)
|
|
24348
|
+
});
|
|
24349
|
+
for (const descendant of (await legacyRecords()).children.get(existing.hostThreadId) ?? []) {
|
|
24350
|
+
if (descendant.state === "ready" && descendant.nativeSessionRef?.nativeSessionId === previousRef.nativeSessionId) {
|
|
24351
|
+
await rebind(descendant, rebound, visited);
|
|
24352
|
+
}
|
|
24353
|
+
}
|
|
24354
|
+
return rebound;
|
|
24355
|
+
};
|
|
24356
|
+
return async (child) => {
|
|
24357
|
+
if (!child.nativeSubagentId || !parent.nativeSessionRef || parent.state !== "ready")
|
|
24358
|
+
return null;
|
|
24359
|
+
const nativeRef = parent.nativeSessionRef;
|
|
24360
|
+
const createRequestId = childCreateRequest(parent, nativeRef, child.nativeSubagentId);
|
|
24361
|
+
const previousRequest = previousRef && previousRef.nativeSessionId !== nativeRef.nativeSessionId ? childCreateRequest(parent, previousRef, child.nativeSubagentId) : void 0;
|
|
24362
|
+
let existing = await store.getThreadByCreateRequest(createRequestId);
|
|
24363
|
+
if (!existing && previousRequest)
|
|
24364
|
+
existing = await store.getThreadByCreateRequest(previousRequest);
|
|
24365
|
+
if (!existing) {
|
|
24366
|
+
const { byRequest } = await legacyRecords();
|
|
24367
|
+
existing = byRequest.get(createRequestId) ?? (previousRequest ? byRequest.get(previousRequest) : void 0) ?? null;
|
|
24368
|
+
}
|
|
24369
|
+
if (existing?.state === "ready") {
|
|
24370
|
+
if (existing.nativeSessionRef?.nativeSessionId === nativeRef.nativeSessionId) return existing;
|
|
24371
|
+
if (!previousRef) throw new Error("Subagent belongs to a different Native Session");
|
|
24372
|
+
return rebind(existing, parent);
|
|
24373
|
+
}
|
|
24374
|
+
const provisional = existing ?? await store.createProvisional({
|
|
24375
|
+
hostThreadId: hostThreadIdSchema.parse(randomUUID3()),
|
|
24376
|
+
createRequestId,
|
|
24377
|
+
harnessId: parent.harnessId,
|
|
24378
|
+
cwd: parent.cwd,
|
|
24379
|
+
title: child.description,
|
|
24380
|
+
transportModelId: parent.transportModelId,
|
|
24381
|
+
ephemeral: parent.ephemeral,
|
|
24382
|
+
historyMode: "paginated",
|
|
24383
|
+
subagent: {
|
|
24384
|
+
parentHostThreadId: parent.hostThreadId,
|
|
24385
|
+
nativeSubagentId: child.nativeSubagentId,
|
|
24386
|
+
...child.role ? { role: child.role } : {}
|
|
24387
|
+
}
|
|
24388
|
+
});
|
|
24389
|
+
return provisional.state === "ready" ? provisional : store.commitReady({
|
|
24390
|
+
hostThreadId: provisional.hostThreadId,
|
|
24391
|
+
nativeSessionRef: nativeRef
|
|
24392
|
+
});
|
|
24393
|
+
};
|
|
24394
|
+
}
|
|
24395
|
+
async function materializeExternalSubagent(store, parent, child) {
|
|
24396
|
+
return subagentMaterializer(store, parent)(child);
|
|
24397
|
+
}
|
|
24398
|
+
async function projectExternalSnapshot(store, record3, snapshot, previousParent) {
|
|
24399
|
+
const materialize = subagentMaterializer(store, record3, previousParent);
|
|
24400
|
+
const turns = [];
|
|
24401
|
+
for (const [index, turn] of snapshot.turns.entries()) {
|
|
24402
|
+
const mapping = record3.turnMappings[index];
|
|
24403
|
+
if (!mapping) throw new Error("External Snapshot mapping is incomplete");
|
|
24404
|
+
const items = await Promise.all(
|
|
24405
|
+
turn.items.map(async (entry) => {
|
|
24406
|
+
if (entry.item.type !== "subagentDelegation") return entry;
|
|
24407
|
+
const subagents = await Promise.all(
|
|
24408
|
+
entry.item.subagents.map(async (child) => {
|
|
24409
|
+
const stored = await materialize(child);
|
|
24410
|
+
return stored ? { ...child, subagentId: stored.hostThreadId } : child;
|
|
24411
|
+
})
|
|
24412
|
+
);
|
|
24413
|
+
return { ...entry, item: { ...entry.item, subagents } };
|
|
24414
|
+
})
|
|
24415
|
+
);
|
|
24416
|
+
turns.push(
|
|
24417
|
+
projectHistoricalTurn({
|
|
24418
|
+
threadId: record3.hostThreadId,
|
|
24419
|
+
turnId: mapping.hostTurnId,
|
|
24420
|
+
cwd: record3.cwd,
|
|
24421
|
+
snapshot: { ...turn, items }
|
|
24422
|
+
})
|
|
24423
|
+
);
|
|
24424
|
+
}
|
|
24425
|
+
return turns;
|
|
24426
|
+
}
|
|
24427
|
+
|
|
24428
|
+
// packages/host-runtime/src/external-thread-repository.ts
|
|
24197
24429
|
function nativeTurnKey2(ref) {
|
|
24198
24430
|
return `${ref.harnessId}\0${ref.nativeSessionId}\0${ref.nativeTurnKey}\0${ref.formatVersion}`;
|
|
24199
24431
|
}
|
|
@@ -24202,8 +24434,8 @@ function sameMapping(left, right) {
|
|
|
24202
24434
|
}
|
|
24203
24435
|
function defaultMappingStoreDirectory(environment) {
|
|
24204
24436
|
const dataDirectory = environment.CODEXHOST_DATA_DIR;
|
|
24205
|
-
return
|
|
24206
|
-
dataDirectory ?
|
|
24437
|
+
return path6.join(
|
|
24438
|
+
dataDirectory ? path6.resolve(dataDirectory) : path6.join(os.homedir(), ".codexhost"),
|
|
24207
24439
|
"mapping-store"
|
|
24208
24440
|
);
|
|
24209
24441
|
}
|
|
@@ -24228,6 +24460,9 @@ var ExternalThreadRepository = class {
|
|
|
24228
24460
|
list() {
|
|
24229
24461
|
return this.store.listThreads();
|
|
24230
24462
|
}
|
|
24463
|
+
materializeSubagent(parent, child) {
|
|
24464
|
+
return materializeExternalSubagent(this.store, parent, child);
|
|
24465
|
+
}
|
|
24231
24466
|
findByCreateRequest(createRequestId) {
|
|
24232
24467
|
return this.store.getThreadByCreateRequest(createRequestId);
|
|
24233
24468
|
}
|
|
@@ -24297,7 +24532,7 @@ var ExternalThreadRepository = class {
|
|
|
24297
24532
|
throw new Error("Derived Snapshot identity does not belong to its Native Session");
|
|
24298
24533
|
}
|
|
24299
24534
|
return {
|
|
24300
|
-
hostTurnId: hostTurnIdSchema.parse(
|
|
24535
|
+
hostTurnId: hostTurnIdSchema.parse(randomUUID4()),
|
|
24301
24536
|
nativeTurnRef: turn.nativeTurnRef,
|
|
24302
24537
|
...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
|
|
24303
24538
|
};
|
|
@@ -24309,15 +24544,7 @@ var ExternalThreadRepository = class {
|
|
|
24309
24544
|
});
|
|
24310
24545
|
return {
|
|
24311
24546
|
record: nextRecord,
|
|
24312
|
-
turns:
|
|
24313
|
-
const mapping = mappings[index];
|
|
24314
|
-
if (!mapping) throw new Error("Derived Snapshot mapping is incomplete");
|
|
24315
|
-
return projectHistoricalTurn({
|
|
24316
|
-
turnId: mapping.hostTurnId,
|
|
24317
|
-
cwd: record3.cwd,
|
|
24318
|
-
snapshot: turn
|
|
24319
|
-
});
|
|
24320
|
-
})
|
|
24547
|
+
turns: await projectExternalSnapshot(this.store, nextRecord, snapshot)
|
|
24321
24548
|
};
|
|
24322
24549
|
}
|
|
24323
24550
|
async commitForkRollback(derived, source, nativeSessionRef, snapshot) {
|
|
@@ -24351,6 +24578,8 @@ var ExternalThreadRepository = class {
|
|
|
24351
24578
|
});
|
|
24352
24579
|
const nextRecord = await this.store.replaceReadySession({
|
|
24353
24580
|
hostThreadId: derived.hostThreadId,
|
|
24581
|
+
expectedRevision: derived.revision,
|
|
24582
|
+
expectedNativeSessionRef: derived.nativeSessionRef,
|
|
24354
24583
|
nativeSessionRef,
|
|
24355
24584
|
turnMappings: mappings,
|
|
24356
24585
|
forkSource: {
|
|
@@ -24360,15 +24589,7 @@ var ExternalThreadRepository = class {
|
|
|
24360
24589
|
});
|
|
24361
24590
|
return {
|
|
24362
24591
|
record: nextRecord,
|
|
24363
|
-
turns:
|
|
24364
|
-
const mapping = mappings[index];
|
|
24365
|
-
if (!mapping) throw new Error("External rollback Snapshot mapping is incomplete");
|
|
24366
|
-
return projectHistoricalTurn({
|
|
24367
|
-
turnId: mapping.hostTurnId,
|
|
24368
|
-
cwd: derived.cwd,
|
|
24369
|
-
snapshot: turn
|
|
24370
|
-
});
|
|
24371
|
-
})
|
|
24592
|
+
turns: await projectExternalSnapshot(this.store, nextRecord, snapshot, derived)
|
|
24372
24593
|
};
|
|
24373
24594
|
}
|
|
24374
24595
|
async commitLastTurnRollback(current, nativeSessionRef, snapshot) {
|
|
@@ -24388,30 +24609,26 @@ var ExternalThreadRepository = class {
|
|
|
24388
24609
|
});
|
|
24389
24610
|
const nextRecord = await this.store.replaceReadySessionAfterLastTurn({
|
|
24390
24611
|
hostThreadId: current.hostThreadId,
|
|
24612
|
+
expectedRevision: current.revision,
|
|
24613
|
+
expectedNativeSessionRef: current.nativeSessionRef,
|
|
24391
24614
|
nativeSessionRef,
|
|
24392
24615
|
turnMappings: mappings
|
|
24393
24616
|
});
|
|
24394
24617
|
return {
|
|
24395
24618
|
record: nextRecord,
|
|
24396
|
-
turns:
|
|
24397
|
-
const mapping = mappings[index];
|
|
24398
|
-
if (!mapping) throw new Error("Last-Turn rollback Snapshot mapping is incomplete");
|
|
24399
|
-
return projectHistoricalTurn({
|
|
24400
|
-
turnId: mapping.hostTurnId,
|
|
24401
|
-
cwd: current.cwd,
|
|
24402
|
-
snapshot: turn
|
|
24403
|
-
});
|
|
24404
|
-
})
|
|
24619
|
+
turns: await projectExternalSnapshot(this.store, nextRecord, snapshot, current)
|
|
24405
24620
|
};
|
|
24406
24621
|
}
|
|
24407
24622
|
async sessionTreeId(record3) {
|
|
24408
24623
|
let current = record3;
|
|
24409
24624
|
const visited = /* @__PURE__ */ new Set();
|
|
24410
|
-
while (current.forkSource) {
|
|
24625
|
+
while (current.subagent || current.forkSource) {
|
|
24411
24626
|
if (visited.has(current.hostThreadId))
|
|
24412
24627
|
throw new Error("External Thread Fork tree contains a cycle");
|
|
24413
24628
|
visited.add(current.hostThreadId);
|
|
24414
|
-
const
|
|
24629
|
+
const parentId = current.subagent?.parentHostThreadId ?? current.forkSource?.hostThreadId;
|
|
24630
|
+
if (!parentId) break;
|
|
24631
|
+
const source = await this.find(parentId);
|
|
24415
24632
|
if (!source) break;
|
|
24416
24633
|
current = source;
|
|
24417
24634
|
}
|
|
@@ -24435,7 +24652,7 @@ var ExternalThreadRepository = class {
|
|
|
24435
24652
|
const aligned = snapshot.turns.map((turn) => {
|
|
24436
24653
|
const existing = mappingsByNative.get(nativeTurnKey2(turn.nativeTurnRef));
|
|
24437
24654
|
const mapping = existing ?? {
|
|
24438
|
-
hostTurnId: hostTurnIdSchema.parse(
|
|
24655
|
+
hostTurnId: hostTurnIdSchema.parse(randomUUID4()),
|
|
24439
24656
|
nativeTurnRef: turn.nativeTurnRef,
|
|
24440
24657
|
...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
|
|
24441
24658
|
};
|
|
@@ -24456,16 +24673,14 @@ var ExternalThreadRepository = class {
|
|
|
24456
24673
|
const nextRecord = mappingsChanged ? await this.store.reconcileTurnMappings(record3.hostThreadId, orderedMappings) : record3;
|
|
24457
24674
|
return {
|
|
24458
24675
|
record: nextRecord,
|
|
24459
|
-
turns:
|
|
24460
|
-
({ mapping, snapshot: turn }) => projectHistoricalTurn({ turnId: mapping.hostTurnId, cwd: record3.cwd, snapshot: turn })
|
|
24461
|
-
)
|
|
24676
|
+
turns: await projectExternalSnapshot(this.store, nextRecord, snapshot)
|
|
24462
24677
|
};
|
|
24463
24678
|
}
|
|
24464
24679
|
};
|
|
24465
24680
|
function createExternalThreadRecordInput(input) {
|
|
24466
24681
|
return {
|
|
24467
|
-
hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(
|
|
24468
|
-
createRequestId: input.createRequestId ??
|
|
24682
|
+
hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(randomUUID4()),
|
|
24683
|
+
createRequestId: input.createRequestId ?? randomUUID4(),
|
|
24469
24684
|
harnessId: input.harnessId,
|
|
24470
24685
|
cwd: input.cwd,
|
|
24471
24686
|
...input.title ? { title: input.title } : {},
|
|
@@ -25112,13 +25327,14 @@ async function restoreCurrentConfiguration(session, configuration) {
|
|
|
25112
25327
|
}
|
|
25113
25328
|
async function executeCurrentLastTurnRollback(input) {
|
|
25114
25329
|
const { current, adapters, repository, runtime } = input;
|
|
25115
|
-
|
|
25330
|
+
const currentRecord = current.record;
|
|
25331
|
+
if (currentRecord.turnMappings.length === 0) {
|
|
25116
25332
|
return {
|
|
25117
25333
|
ok: false,
|
|
25118
25334
|
error: { code: -32076, message: "External Thread has no Turn to roll back" }
|
|
25119
25335
|
};
|
|
25120
25336
|
}
|
|
25121
|
-
const currentNativeRef =
|
|
25337
|
+
const currentNativeRef = currentRecord.nativeSessionRef;
|
|
25122
25338
|
const adapter = adapters.get(current.harnessId);
|
|
25123
25339
|
if (!currentNativeRef || !adapter) {
|
|
25124
25340
|
return {
|
|
@@ -25166,7 +25382,7 @@ async function executeCurrentLastTurnRollback(input) {
|
|
|
25166
25382
|
await session.close().catch(() => void 0);
|
|
25167
25383
|
return { ok: false, error: mapExternalThreadHarnessError(snapshot.error, "read") };
|
|
25168
25384
|
}
|
|
25169
|
-
if (snapshot.value.turns.length !==
|
|
25385
|
+
if (snapshot.value.turns.length !== currentRecord.turnMappings.length - 1) {
|
|
25170
25386
|
await session.close().catch(() => void 0);
|
|
25171
25387
|
return {
|
|
25172
25388
|
ok: false,
|
|
@@ -25184,7 +25400,7 @@ async function executeCurrentLastTurnRollback(input) {
|
|
|
25184
25400
|
let aligned;
|
|
25185
25401
|
try {
|
|
25186
25402
|
aligned = await repository.commitLastTurnRollback(
|
|
25187
|
-
|
|
25403
|
+
currentRecord,
|
|
25188
25404
|
finalNativeRef,
|
|
25189
25405
|
snapshot.value
|
|
25190
25406
|
);
|
|
@@ -25232,7 +25448,8 @@ async function executeExternalThreadRollback(input) {
|
|
|
25232
25448
|
...input.environment ? { environment: input.environment } : {}
|
|
25233
25449
|
});
|
|
25234
25450
|
}
|
|
25235
|
-
const
|
|
25451
|
+
const derivedRecord = derived.record;
|
|
25452
|
+
const forkSource = derivedRecord.forkSource;
|
|
25236
25453
|
if (!forkSource) {
|
|
25237
25454
|
return {
|
|
25238
25455
|
ok: false,
|
|
@@ -25263,10 +25480,11 @@ async function executeExternalThreadRollback(input) {
|
|
|
25263
25480
|
const sourceRefreshError = await runtime.refresh(source);
|
|
25264
25481
|
if (sourceRefreshError) return { ok: false, error: sourceRefreshError };
|
|
25265
25482
|
}
|
|
25266
|
-
const
|
|
25483
|
+
const sourceRecord = source.record;
|
|
25484
|
+
const sourceBoundaryIndex = sourceRecord.turnMappings.findIndex(
|
|
25267
25485
|
({ hostTurnId }) => hostTurnId === forkSource.hostTurnId
|
|
25268
25486
|
);
|
|
25269
|
-
if (sourceBoundaryIndex < 0 ||
|
|
25487
|
+
if (sourceBoundaryIndex < 0 || derivedRecord.turnMappings.length !== sourceBoundaryIndex + 1) {
|
|
25270
25488
|
return {
|
|
25271
25489
|
ok: false,
|
|
25272
25490
|
error: {
|
|
@@ -25275,19 +25493,19 @@ async function executeExternalThreadRollback(input) {
|
|
|
25275
25493
|
}
|
|
25276
25494
|
};
|
|
25277
25495
|
}
|
|
25278
|
-
const excludedActiveTurnCount = source.running ||
|
|
25279
|
-
const retainedCount =
|
|
25280
|
-
if (retainedCount ===
|
|
25496
|
+
const excludedActiveTurnCount = source.running || sourceRecord.turnMappings.length > derivedRecord.turnMappings.length ? 1 : 0;
|
|
25497
|
+
const retainedCount = derivedRecord.turnMappings.length - rollback.numTurns + excludedActiveTurnCount;
|
|
25498
|
+
if (retainedCount === derivedRecord.turnMappings.length) {
|
|
25281
25499
|
return { ok: true, thread: derived.thread };
|
|
25282
25500
|
}
|
|
25283
|
-
const boundary =
|
|
25501
|
+
const boundary = sourceRecord.turnMappings[retainedCount - 1];
|
|
25284
25502
|
if (retainedCount < 1 || !boundary?.nativeCheckpointRef) {
|
|
25285
25503
|
return {
|
|
25286
25504
|
ok: false,
|
|
25287
25505
|
error: { code: -32080, message: "External Fork Checkpoint is unavailable" }
|
|
25288
25506
|
};
|
|
25289
25507
|
}
|
|
25290
|
-
const sourceNativeRef =
|
|
25508
|
+
const sourceNativeRef = sourceRecord.nativeSessionRef;
|
|
25291
25509
|
const adapter = adapters.get(source.harnessId);
|
|
25292
25510
|
if (!sourceNativeRef || !adapter) {
|
|
25293
25511
|
return {
|
|
@@ -25315,7 +25533,7 @@ async function executeExternalThreadRollback(input) {
|
|
|
25315
25533
|
}
|
|
25316
25534
|
const session = opened.value;
|
|
25317
25535
|
const finalNativeRef = session.initialState.nativeRef;
|
|
25318
|
-
if (!finalNativeRef || finalNativeRef.nativeSessionId === sourceNativeRef.nativeSessionId || finalNativeRef.nativeSessionId ===
|
|
25536
|
+
if (!finalNativeRef || finalNativeRef.nativeSessionId === sourceNativeRef.nativeSessionId || finalNativeRef.nativeSessionId === derivedRecord.nativeSessionRef?.nativeSessionId) {
|
|
25319
25537
|
await session.close().catch(() => void 0);
|
|
25320
25538
|
return {
|
|
25321
25539
|
ok: false,
|
|
@@ -25337,8 +25555,8 @@ async function executeExternalThreadRollback(input) {
|
|
|
25337
25555
|
let aligned;
|
|
25338
25556
|
try {
|
|
25339
25557
|
aligned = await repository.commitForkRollback(
|
|
25340
|
-
|
|
25341
|
-
|
|
25558
|
+
derivedRecord,
|
|
25559
|
+
sourceRecord,
|
|
25342
25560
|
finalNativeRef,
|
|
25343
25561
|
snapshot.value
|
|
25344
25562
|
);
|
|
@@ -25583,9 +25801,43 @@ var ExternalThreadRuntime = class {
|
|
|
25583
25801
|
} catch (error51) {
|
|
25584
25802
|
this.#diagnose(error51);
|
|
25585
25803
|
}
|
|
25804
|
+
await this.#retireSubagents(current.id);
|
|
25586
25805
|
this.#threads.delete(current.id);
|
|
25587
25806
|
return this.register(input);
|
|
25588
25807
|
}
|
|
25808
|
+
async #retireSubagents(parentId) {
|
|
25809
|
+
const ancestors = /* @__PURE__ */ new Map();
|
|
25810
|
+
const descendant = async (record3) => {
|
|
25811
|
+
const visited = /* @__PURE__ */ new Set();
|
|
25812
|
+
let ownerId = record3?.subagent?.parentHostThreadId;
|
|
25813
|
+
while (ownerId && !visited.has(ownerId)) {
|
|
25814
|
+
if (ownerId === parentId) return true;
|
|
25815
|
+
visited.add(ownerId);
|
|
25816
|
+
let ancestor = ancestors.get(ownerId);
|
|
25817
|
+
if (!ancestor) {
|
|
25818
|
+
ancestor = this.#repository.find(ownerId);
|
|
25819
|
+
ancestors.set(ownerId, ancestor);
|
|
25820
|
+
}
|
|
25821
|
+
ownerId = (await ancestor)?.subagent?.parentHostThreadId;
|
|
25822
|
+
}
|
|
25823
|
+
return false;
|
|
25824
|
+
};
|
|
25825
|
+
for (const [id2, restoring] of [...this.#restores]) {
|
|
25826
|
+
if (await descendant(await this.#repository.find(id2))) {
|
|
25827
|
+
await restoring.catch(this.#diagnose);
|
|
25828
|
+
}
|
|
25829
|
+
}
|
|
25830
|
+
for (const child of this.#threads.values()) {
|
|
25831
|
+
if (!await descendant(child.record)) continue;
|
|
25832
|
+
this.#threads.delete(child.id);
|
|
25833
|
+
try {
|
|
25834
|
+
await child.session.close();
|
|
25835
|
+
await child.outputTask;
|
|
25836
|
+
} catch (error51) {
|
|
25837
|
+
this.#diagnose(error51);
|
|
25838
|
+
}
|
|
25839
|
+
}
|
|
25840
|
+
}
|
|
25589
25841
|
async locate(threadId3) {
|
|
25590
25842
|
const loaded = this.#threads.get(threadId3);
|
|
25591
25843
|
if (loaded) return { kind: "external", record: loaded.record, thread: loaded };
|
|
@@ -25696,6 +25948,10 @@ var ExternalThreadRuntime = class {
|
|
|
25696
25948
|
nativeSubagentId: subagent.nativeSubagentId,
|
|
25697
25949
|
cwd: record3.cwd
|
|
25698
25950
|
});
|
|
25951
|
+
const latest = await this.#repository.find(record3.hostThreadId);
|
|
25952
|
+
if (latest?.state === "ready" && latest.nativeSessionRef && JSON.stringify(latest.nativeSessionRef) !== JSON.stringify(parent)) {
|
|
25953
|
+
return this.#restore(latest);
|
|
25954
|
+
}
|
|
25699
25955
|
if (!snapshot.ok) {
|
|
25700
25956
|
throw new ExternalThreadOpenError(mapExternalThreadHarnessError(snapshot.error, "read"));
|
|
25701
25957
|
}
|
|
@@ -25972,11 +26228,11 @@ var ExternalTurnSteering = class {
|
|
|
25972
26228
|
};
|
|
25973
26229
|
|
|
25974
26230
|
// packages/host-runtime/src/harness-delegation-coordinator.ts
|
|
25975
|
-
import { createHash as
|
|
25976
|
-
import
|
|
26231
|
+
import { createHash as createHash5, randomUUID as randomUUID5 } from "node:crypto";
|
|
26232
|
+
import path7 from "node:path";
|
|
25977
26233
|
|
|
25978
26234
|
// packages/host-runtime/src/delegation-snapshot.ts
|
|
25979
|
-
import { createHash as
|
|
26235
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
25980
26236
|
var CURSOR_PREFIX = "codexhost:thread-messages:v1:";
|
|
25981
26237
|
var DEFAULT_MESSAGE_LIMIT = 25;
|
|
25982
26238
|
var MAX_MESSAGE_LIMIT = 100;
|
|
@@ -26030,7 +26286,7 @@ function allVisibleMessages(turns) {
|
|
|
26030
26286
|
return messages;
|
|
26031
26287
|
}
|
|
26032
26288
|
function cursorFingerprint(threadId3) {
|
|
26033
|
-
return
|
|
26289
|
+
return createHash4("sha256").update(threadId3).digest("hex");
|
|
26034
26290
|
}
|
|
26035
26291
|
function encodeCursor(threadId3, offset) {
|
|
26036
26292
|
const payload = JSON.stringify({ version: 1, fingerprint: cursorFingerprint(threadId3), offset });
|
|
@@ -26125,10 +26381,10 @@ function terminal(status) {
|
|
|
26125
26381
|
return status === "completed" || status === "failed" || status === "interrupted";
|
|
26126
26382
|
}
|
|
26127
26383
|
function taskDigest(input) {
|
|
26128
|
-
return
|
|
26384
|
+
return createHash5("sha256").update(
|
|
26129
26385
|
JSON.stringify({
|
|
26130
26386
|
task: input.task,
|
|
26131
|
-
cwd:
|
|
26387
|
+
cwd: path7.resolve(input.cwd),
|
|
26132
26388
|
modelId: input.model?.id ?? null,
|
|
26133
26389
|
thinkingOptionId: input.thinkingOptionId ?? null
|
|
26134
26390
|
})
|
|
@@ -26199,7 +26455,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
26199
26455
|
return {
|
|
26200
26456
|
harnessId: input.harnessId,
|
|
26201
26457
|
inspection: await adapter.inspect({
|
|
26202
|
-
...input.cwd ? { cwd:
|
|
26458
|
+
...input.cwd ? { cwd: path7.resolve(input.cwd) } : {},
|
|
26203
26459
|
...input.refresh !== void 0 ? { refresh: input.refresh } : {}
|
|
26204
26460
|
})
|
|
26205
26461
|
};
|
|
@@ -26213,7 +26469,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
26213
26469
|
const result = await this.#startOfficial({ ...input, parentThreadId, cwd: selectedCwd });
|
|
26214
26470
|
return { ...result, parentThreadId, cwd: result.cwd ?? selectedCwd };
|
|
26215
26471
|
}
|
|
26216
|
-
const startInput = { ...input, parentThreadId, cwd:
|
|
26472
|
+
const startInput = { ...input, parentThreadId, cwd: path7.resolve(selectedCwd) };
|
|
26217
26473
|
if (!this.#adapters.has(input.harnessId)) {
|
|
26218
26474
|
throw new DelegationControlError(
|
|
26219
26475
|
"HARNESS_NOT_FOUND",
|
|
@@ -26253,10 +26509,10 @@ var HarnessDelegationCoordinator = class {
|
|
|
26253
26509
|
});
|
|
26254
26510
|
this.#validateConfiguration(inspected.inspection, input.model, input.thinkingOptionId);
|
|
26255
26511
|
}
|
|
26256
|
-
const delegationId = hostThreadIdSchema.parse(
|
|
26257
|
-
const childThreadId = hostThreadIdSchema.parse(
|
|
26258
|
-
const turnId = hostTurnIdSchema.parse(
|
|
26259
|
-
const createRequestId = input.requestId ? `delegation:${input.requestId}` :
|
|
26512
|
+
const delegationId = hostThreadIdSchema.parse(randomUUID5());
|
|
26513
|
+
const childThreadId = hostThreadIdSchema.parse(randomUUID5());
|
|
26514
|
+
const turnId = hostTurnIdSchema.parse(randomUUID5());
|
|
26515
|
+
const createRequestId = input.requestId ? `delegation:${input.requestId}` : randomUUID5();
|
|
26260
26516
|
let record3 = await this.#repository.createProvisional(
|
|
26261
26517
|
createExternalThreadRecordInput({
|
|
26262
26518
|
hostThreadId: childThreadId,
|
|
@@ -26381,7 +26637,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
26381
26637
|
if (thread.running || thread.activeTurnId) {
|
|
26382
26638
|
throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
|
|
26383
26639
|
}
|
|
26384
|
-
const turnId = hostTurnIdSchema.parse(
|
|
26640
|
+
const turnId = hostTurnIdSchema.parse(randomUUID5());
|
|
26385
26641
|
try {
|
|
26386
26642
|
await this.#startExternalTurn(thread, input.message, turnId);
|
|
26387
26643
|
} catch (error51) {
|
|
@@ -26626,7 +26882,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
26626
26882
|
|
|
26627
26883
|
// packages/host-runtime/src/harness-plugin-loader.ts
|
|
26628
26884
|
import { readdir as readdir3, realpath as realpath2 } from "node:fs/promises";
|
|
26629
|
-
import
|
|
26885
|
+
import path9 from "node:path";
|
|
26630
26886
|
import { pathToFileURL } from "node:url";
|
|
26631
26887
|
|
|
26632
26888
|
// packages/host-runtime/src/harness-plugin-registry.ts
|
|
@@ -26664,16 +26920,16 @@ var HarnessPluginRegistry = class {
|
|
|
26664
26920
|
|
|
26665
26921
|
// packages/host-runtime/src/plugin-files.ts
|
|
26666
26922
|
import { open as open4, realpath, stat as stat2 } from "node:fs/promises";
|
|
26667
|
-
import
|
|
26923
|
+
import path8 from "node:path";
|
|
26668
26924
|
function inside(root, candidate) {
|
|
26669
|
-
const relative =
|
|
26670
|
-
return relative !== "" && !
|
|
26925
|
+
const relative = path8.relative(root, candidate);
|
|
26926
|
+
return relative !== "" && !path8.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path8.sep}`);
|
|
26671
26927
|
}
|
|
26672
26928
|
async function pluginResourcePath(root, relative) {
|
|
26673
|
-
if (
|
|
26929
|
+
if (path8.isAbsolute(relative) || !inside(root, path8.resolve(root, relative))) {
|
|
26674
26930
|
throw new Error("Plugin resource escapes its root");
|
|
26675
26931
|
}
|
|
26676
|
-
const resolved = await realpath(
|
|
26932
|
+
const resolved = await realpath(path8.resolve(root, relative));
|
|
26677
26933
|
if (!inside(root, resolved) || !(await stat2(resolved)).isFile()) {
|
|
26678
26934
|
throw new Error("Plugin resource must be a regular file inside its root");
|
|
26679
26935
|
}
|
|
@@ -26818,7 +27074,7 @@ async function loadHarnessPlugins(options2) {
|
|
|
26818
27074
|
const enabledIds = /* @__PURE__ */ new Set();
|
|
26819
27075
|
const roots = /* @__PURE__ */ new Set();
|
|
26820
27076
|
for (const configuredRoot of options2.roots) {
|
|
26821
|
-
if (!
|
|
27077
|
+
if (!path9.isAbsolute(configuredRoot)) {
|
|
26822
27078
|
diagnose({ code: "invalidRoot" });
|
|
26823
27079
|
continue;
|
|
26824
27080
|
}
|
|
@@ -26848,7 +27104,7 @@ async function loadHarnessPlugins(options2) {
|
|
|
26848
27104
|
for (const directory of directories) {
|
|
26849
27105
|
try {
|
|
26850
27106
|
const file2 = await pluginResourcePath(root, `${directory.name}/manifest.json`);
|
|
26851
|
-
const pluginRoot = await realpath2(
|
|
27107
|
+
const pluginRoot = await realpath2(path9.join(root, directory.name));
|
|
26852
27108
|
await pluginResourcePath(pluginRoot, "manifest.json");
|
|
26853
27109
|
const manifest = harnessPluginManifestSchema.parse(
|
|
26854
27110
|
JSON.parse(
|
|
@@ -26995,8 +27251,8 @@ function spawnOfficialAppServerConnection(input) {
|
|
|
26995
27251
|
|
|
26996
27252
|
// packages/host-runtime/src/account/account-repository.ts
|
|
26997
27253
|
import { mkdir as mkdir4, readFile as readFile5, rename as rename3, writeFile as writeFile3 } from "node:fs/promises";
|
|
26998
|
-
import
|
|
26999
|
-
import { randomUUID as
|
|
27254
|
+
import path10 from "node:path";
|
|
27255
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
27000
27256
|
function validateAccountId(accountId) {
|
|
27001
27257
|
if (!/^[A-Za-z0-9._~-]+$/u.test(accountId)) {
|
|
27002
27258
|
throw new Error("Codex Account ID must be non-empty and filename-safe");
|
|
@@ -27014,19 +27270,19 @@ var AccountRepository = class {
|
|
|
27014
27270
|
#mutationTail = Promise.resolve();
|
|
27015
27271
|
#writeTail = Promise.resolve();
|
|
27016
27272
|
constructor(input) {
|
|
27017
|
-
this.#file =
|
|
27273
|
+
this.#file = path10.join(path10.resolve(input.directory), "accounts.json");
|
|
27018
27274
|
this.#defaultAccount = {
|
|
27019
27275
|
...input.defaultAccount,
|
|
27020
27276
|
label: input.defaultAccount.label ?? input.defaultAccount.accountId
|
|
27021
27277
|
};
|
|
27022
27278
|
validateAccountId(this.#defaultAccount.accountId);
|
|
27023
|
-
if (!
|
|
27279
|
+
if (!path10.isAbsolute(this.#defaultAccount.codexHome)) {
|
|
27024
27280
|
throw new Error("Codex Account CODEX_HOME must be absolute");
|
|
27025
27281
|
}
|
|
27026
27282
|
}
|
|
27027
27283
|
async initialize() {
|
|
27028
27284
|
if (this.#initialized) return;
|
|
27029
|
-
await mkdir4(
|
|
27285
|
+
await mkdir4(path10.dirname(this.#file), { recursive: true });
|
|
27030
27286
|
let stored = null;
|
|
27031
27287
|
try {
|
|
27032
27288
|
stored = JSON.parse(await readFile5(this.#file, "utf8"));
|
|
@@ -27094,7 +27350,7 @@ var AccountRepository = class {
|
|
|
27094
27350
|
async upsert(input) {
|
|
27095
27351
|
this.#requireInitialized();
|
|
27096
27352
|
validateAccountId(input.accountId);
|
|
27097
|
-
if (!
|
|
27353
|
+
if (!path10.isAbsolute(input.codexHome))
|
|
27098
27354
|
throw new Error("Codex Account CODEX_HOME must be absolute");
|
|
27099
27355
|
return this.#mutate(async () => {
|
|
27100
27356
|
const previous = this.#accounts.get(input.accountId);
|
|
@@ -27103,7 +27359,7 @@ var AccountRepository = class {
|
|
|
27103
27359
|
const planType = input.planType === null ? void 0 : input.planType ?? previous?.planType;
|
|
27104
27360
|
const account = {
|
|
27105
27361
|
accountId: input.accountId,
|
|
27106
|
-
codexHome:
|
|
27362
|
+
codexHome: path10.normalize(input.codexHome),
|
|
27107
27363
|
...email3 ? { email: email3 } : {},
|
|
27108
27364
|
...planType ? { planType } : {},
|
|
27109
27365
|
label: input.label ?? previous?.label ?? input.accountId,
|
|
@@ -27117,7 +27373,7 @@ var AccountRepository = class {
|
|
|
27117
27373
|
}
|
|
27118
27374
|
#validateAccount(account) {
|
|
27119
27375
|
validateAccountId(account.accountId);
|
|
27120
|
-
if (!
|
|
27376
|
+
if (!path10.isAbsolute(account.codexHome)) throw new Error("Stored CODEX_HOME must be absolute");
|
|
27121
27377
|
if (account.email && (!account.email.includes("@") || account.email.length > 320)) {
|
|
27122
27378
|
throw new Error("Stored Codex Account email is invalid");
|
|
27123
27379
|
}
|
|
@@ -27138,7 +27394,7 @@ var AccountRepository = class {
|
|
|
27138
27394
|
accounts: [...this.#accounts.values()]
|
|
27139
27395
|
};
|
|
27140
27396
|
const operation = this.#writeTail.then(async () => {
|
|
27141
|
-
const temporary = `${this.#file}.${process.pid}.${
|
|
27397
|
+
const temporary = `${this.#file}.${process.pid}.${randomUUID6()}.tmp`;
|
|
27142
27398
|
await writeFile3(temporary, `${JSON.stringify(value2, null, 2)}
|
|
27143
27399
|
`, { mode: 384 });
|
|
27144
27400
|
await rename3(temporary, this.#file);
|
|
@@ -27161,19 +27417,19 @@ function isMissingFile(error51) {
|
|
|
27161
27417
|
|
|
27162
27418
|
// packages/host-runtime/src/account/thread-account-store.ts
|
|
27163
27419
|
import { mkdir as mkdir5, readFile as readFile6, rename as rename4, writeFile as writeFile4 } from "node:fs/promises";
|
|
27164
|
-
import { randomUUID as
|
|
27165
|
-
import
|
|
27420
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
27421
|
+
import path11 from "node:path";
|
|
27166
27422
|
var ThreadAccountStore = class {
|
|
27167
27423
|
#file;
|
|
27168
27424
|
#bindings = /* @__PURE__ */ new Map();
|
|
27169
27425
|
#initialized = false;
|
|
27170
27426
|
#writeTail = Promise.resolve();
|
|
27171
27427
|
constructor(input) {
|
|
27172
|
-
this.#file =
|
|
27428
|
+
this.#file = path11.join(path11.resolve(input.directory), "thread-accounts.json");
|
|
27173
27429
|
}
|
|
27174
27430
|
async initialize() {
|
|
27175
27431
|
if (this.#initialized) return;
|
|
27176
|
-
await mkdir5(
|
|
27432
|
+
await mkdir5(path11.dirname(this.#file), { recursive: true });
|
|
27177
27433
|
try {
|
|
27178
27434
|
const stored = JSON.parse(await readFile6(this.#file, "utf8"));
|
|
27179
27435
|
if (stored.formatVersion !== 1 || !stored.bindings || typeof stored.bindings !== "object") {
|
|
@@ -27232,7 +27488,7 @@ var ThreadAccountStore = class {
|
|
|
27232
27488
|
bindings: Object.fromEntries(this.#bindings)
|
|
27233
27489
|
};
|
|
27234
27490
|
const operation = this.#writeTail.then(async () => {
|
|
27235
|
-
const temporary = `${this.#file}.${process.pid}.${
|
|
27491
|
+
const temporary = `${this.#file}.${process.pid}.${randomUUID7()}.tmp`;
|
|
27236
27492
|
await writeFile4(temporary, `${JSON.stringify(value2, null, 2)}
|
|
27237
27493
|
`, { mode: 384 });
|
|
27238
27494
|
await rename4(temporary, this.#file);
|
|
@@ -27249,7 +27505,7 @@ function isMissingFile2(error51) {
|
|
|
27249
27505
|
import { mkdir as mkdir6 } from "node:fs/promises";
|
|
27250
27506
|
|
|
27251
27507
|
// packages/host-runtime/src/official-request-broker.ts
|
|
27252
|
-
import { randomUUID as
|
|
27508
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
27253
27509
|
var INTERNAL_REQUEST_PREFIX = "codexhost:official:";
|
|
27254
27510
|
var MAX_RETIRED_IDS = 1024;
|
|
27255
27511
|
function isRecord9(value2) {
|
|
@@ -27265,7 +27521,7 @@ var OfficialRequestBroker = class {
|
|
|
27265
27521
|
constructor(input) {
|
|
27266
27522
|
this.#send = input.send;
|
|
27267
27523
|
this.#timeoutMs = input.timeoutMs ?? 3e4;
|
|
27268
|
-
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${
|
|
27524
|
+
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID8()}`);
|
|
27269
27525
|
}
|
|
27270
27526
|
get pendingCount() {
|
|
27271
27527
|
return this.#pending.size;
|
|
@@ -27629,21 +27885,45 @@ function externalAnchor(entry) {
|
|
|
27629
27885
|
if (entry.source !== "external") throw new Error("Expected an External Thread list entry");
|
|
27630
27886
|
return { timestamp: entry.timestamp, threadId: threadId(entry.thread) };
|
|
27631
27887
|
}
|
|
27632
|
-
function includesExternalRecord(record3, query) {
|
|
27888
|
+
function includesExternalRecord(record3, query, byId) {
|
|
27633
27889
|
if (record3.state !== "ready" || !record3.nativeSessionRef) return false;
|
|
27634
|
-
|
|
27890
|
+
let current = record3;
|
|
27891
|
+
const owners = /* @__PURE__ */ new Set();
|
|
27892
|
+
while (current.subagent) {
|
|
27893
|
+
if (owners.has(current.hostThreadId)) return false;
|
|
27894
|
+
owners.add(current.hostThreadId);
|
|
27895
|
+
const parent = byId.get(current.subagent.parentHostThreadId);
|
|
27896
|
+
if (!parent || parent.state !== "ready" || parent.harnessId !== current.harnessId || parent.nativeSessionRef?.nativeSessionId !== current.nativeSessionRef?.nativeSessionId)
|
|
27897
|
+
return false;
|
|
27898
|
+
current = parent;
|
|
27899
|
+
}
|
|
27900
|
+
const sourceKind = record3.subagent ? "subAgentThreadSpawn" : "vscode";
|
|
27901
|
+
const scoped = query.parentThreadId !== null || query.ancestorThreadId !== null;
|
|
27902
|
+
if (record3.subagent && !scoped && !query.sourceKinds?.some((kind) => kind === "subAgent" || kind === "subAgentThreadSpawn"))
|
|
27903
|
+
return false;
|
|
27904
|
+
if (query.parentThreadId !== null && record3.subagent?.parentHostThreadId !== query.parentThreadId)
|
|
27905
|
+
return false;
|
|
27906
|
+
if (query.ancestorThreadId !== null) {
|
|
27907
|
+
let parentId = record3.subagent?.parentHostThreadId;
|
|
27908
|
+
const visited = /* @__PURE__ */ new Set([record3.hostThreadId]);
|
|
27909
|
+
while (parentId && parentId !== query.ancestorThreadId && !visited.has(parentId)) {
|
|
27910
|
+
visited.add(parentId);
|
|
27911
|
+
parentId = byId.get(parentId)?.subagent?.parentHostThreadId;
|
|
27912
|
+
}
|
|
27913
|
+
if (record3.hostThreadId === query.ancestorThreadId || parentId !== query.ancestorThreadId)
|
|
27914
|
+
return false;
|
|
27915
|
+
}
|
|
27635
27916
|
if (record3.archived !== query.archived) return false;
|
|
27636
27917
|
if (query.cwd !== null && !query.cwd.includes(record3.cwd)) return false;
|
|
27637
27918
|
if (query.modelProviders !== null && query.modelProviders.length > 0 && !query.modelProviders.includes("codexhost")) {
|
|
27638
27919
|
return false;
|
|
27639
27920
|
}
|
|
27640
|
-
if (query.sourceKinds !== null && query.sourceKinds.length > 0 && !query.sourceKinds.includes("
|
|
27921
|
+
if (query.sourceKinds !== null && query.sourceKinds.length > 0 && !query.sourceKinds.includes(sourceKind) && !(record3.subagent && query.sourceKinds.includes("subAgent"))) {
|
|
27641
27922
|
return false;
|
|
27642
27923
|
}
|
|
27643
27924
|
if (query.searchTerm !== null && !record3.title.toLowerCase().includes(query.searchTerm.toLowerCase())) {
|
|
27644
27925
|
return false;
|
|
27645
27926
|
}
|
|
27646
|
-
if (query.parentThreadId !== null || query.ancestorThreadId !== null) return false;
|
|
27647
27927
|
if (query.isPinned === true) return false;
|
|
27648
27928
|
return true;
|
|
27649
27929
|
}
|
|
@@ -27653,25 +27933,25 @@ function resolveExternalSessionTreeIds(records) {
|
|
|
27653
27933
|
const resolve = (start) => {
|
|
27654
27934
|
const cached2 = resolved.get(start.hostThreadId);
|
|
27655
27935
|
if (cached2) return cached2;
|
|
27656
|
-
const
|
|
27936
|
+
const path26 = [];
|
|
27657
27937
|
const visited = /* @__PURE__ */ new Set();
|
|
27658
27938
|
let current = start;
|
|
27659
27939
|
while (true) {
|
|
27660
27940
|
const known = resolved.get(current.hostThreadId);
|
|
27661
27941
|
if (known) {
|
|
27662
|
-
for (const record3 of
|
|
27942
|
+
for (const record3 of path26) resolved.set(record3.hostThreadId, known);
|
|
27663
27943
|
return known;
|
|
27664
27944
|
}
|
|
27665
27945
|
if (visited.has(current.hostThreadId)) {
|
|
27666
27946
|
throw new Error("External Thread Fork tree contains a cycle");
|
|
27667
27947
|
}
|
|
27668
27948
|
visited.add(current.hostThreadId);
|
|
27669
|
-
|
|
27670
|
-
const sourceId = current.forkSource?.hostThreadId;
|
|
27949
|
+
path26.push(current);
|
|
27950
|
+
const sourceId = current.subagent?.parentHostThreadId ?? current.forkSource?.hostThreadId;
|
|
27671
27951
|
const source = sourceId ? byId.get(sourceId) : void 0;
|
|
27672
27952
|
if (!source) {
|
|
27673
27953
|
const root = current.hostThreadId;
|
|
27674
|
-
for (const record3 of
|
|
27954
|
+
for (const record3 of path26) resolved.set(record3.hostThreadId, root);
|
|
27675
27955
|
return root;
|
|
27676
27956
|
}
|
|
27677
27957
|
current = source;
|
|
@@ -27683,7 +27963,8 @@ function resolveExternalSessionTreeIds(records) {
|
|
|
27683
27963
|
function listExternalThreadMetadata(input) {
|
|
27684
27964
|
if (!input.query.supportsExternal) return { data: [], hasMore: false };
|
|
27685
27965
|
const sessionIds = resolveExternalSessionTreeIds(input.records);
|
|
27686
|
-
const
|
|
27966
|
+
const byId = new Map(input.records.map((record3) => [record3.hostThreadId, record3]));
|
|
27967
|
+
const entries = input.records.filter((record3) => includesExternalRecord(record3, input.query, byId)).map((record3) => {
|
|
27687
27968
|
const runtime = input.runtimeFor(record3.hostThreadId);
|
|
27688
27969
|
const sessionId = sessionIds.get(record3.hostThreadId);
|
|
27689
27970
|
if (!sessionId) throw new Error("External Thread Session tree could not be resolved");
|
|
@@ -27765,6 +28046,7 @@ function threadId2(entry) {
|
|
|
27765
28046
|
return entry.thread.id;
|
|
27766
28047
|
}
|
|
27767
28048
|
async function aggregateOfficialAccountThreadListPage(input) {
|
|
28049
|
+
const pageLimit = typeof input.params.limit === "number" ? input.params.limit : input.query.limit;
|
|
27768
28050
|
const cursorValue2 = typeof input.params.cursor === "string" ? input.params.cursor : null;
|
|
27769
28051
|
const cursor = cursorValue2 ? decodeCursor2(cursorValue2) : { accounts: initialAccounts(input.accountIds) };
|
|
27770
28052
|
const sources = Object.entries(cursor.accounts).map(([accountId, state]) => ({
|
|
@@ -27801,7 +28083,7 @@ async function aggregateOfficialAccountThreadListPage(input) {
|
|
|
27801
28083
|
if (source.done) return null;
|
|
27802
28084
|
}
|
|
27803
28085
|
source.batchStart = source.cursor;
|
|
27804
|
-
const page = await request(source, source.cursor, Math.max(1,
|
|
28086
|
+
const page = await request(source, source.cursor, Math.max(1, pageLimit));
|
|
27805
28087
|
if (!source.requestedThisPage) {
|
|
27806
28088
|
source.backwardsCursor = page.backwardsCursor;
|
|
27807
28089
|
source.requestedThisPage = true;
|
|
@@ -27823,7 +28105,7 @@ async function aggregateOfficialAccountThreadListPage(input) {
|
|
|
27823
28105
|
};
|
|
27824
28106
|
const output = [];
|
|
27825
28107
|
const emitted = /* @__PURE__ */ new Set();
|
|
27826
|
-
while (output.length <
|
|
28108
|
+
while (output.length < pageLimit) {
|
|
27827
28109
|
const candidates = await Promise.all(
|
|
27828
28110
|
sources.map(async (source) => ({ source, entry: await ensure(source) }))
|
|
27829
28111
|
);
|
|
@@ -28357,18 +28639,18 @@ var AppServerHost = class {
|
|
|
28357
28639
|
};
|
|
28358
28640
|
this.#writer = new OrderedWriter(this.#options.desktopOutput);
|
|
28359
28641
|
const environment = this.#options.environment ?? process.env;
|
|
28360
|
-
const dataDirectory =
|
|
28361
|
-
environment.CODEXHOST_DATA_DIR ??
|
|
28642
|
+
const dataDirectory = path12.resolve(
|
|
28643
|
+
environment.CODEXHOST_DATA_DIR ?? path12.join(os2.homedir(), ".codexhost")
|
|
28362
28644
|
);
|
|
28363
28645
|
const accountRepository = options2.accountRepository ?? new AccountRepository({
|
|
28364
|
-
directory:
|
|
28646
|
+
directory: path12.join(dataDirectory, "codex-accounts"),
|
|
28365
28647
|
defaultAccount: {
|
|
28366
28648
|
accountId: "default",
|
|
28367
|
-
codexHome:
|
|
28649
|
+
codexHome: path12.resolve(environment.CODEX_HOME ?? path12.join(os2.homedir(), ".codex")),
|
|
28368
28650
|
label: "Default Codex Account"
|
|
28369
28651
|
}
|
|
28370
28652
|
});
|
|
28371
|
-
const threadAccountStore = options2.threadAccountStore ?? new ThreadAccountStore({ directory:
|
|
28653
|
+
const threadAccountStore = options2.threadAccountStore ?? new ThreadAccountStore({ directory: path12.join(dataDirectory, "codex-accounts") });
|
|
28372
28654
|
this.#accountRepository = accountRepository;
|
|
28373
28655
|
this.#threadAccountStore = threadAccountStore;
|
|
28374
28656
|
this.#accountDataDirectory = dataDirectory;
|
|
@@ -29183,7 +29465,7 @@ var AppServerHost = class {
|
|
|
29183
29465
|
throw new Error("Unknown Codex Account");
|
|
29184
29466
|
const runtime = await this.#codexRuntimePool.get(params2.accountId);
|
|
29185
29467
|
const response2 = await runtime.request("account/rateLimitResetCredit/consume", {
|
|
29186
|
-
idempotencyKey: params2.idempotencyKey ??
|
|
29468
|
+
idempotencyKey: params2.idempotencyKey ?? randomUUID9()
|
|
29187
29469
|
});
|
|
29188
29470
|
if (isRecord12(response2.error)) {
|
|
29189
29471
|
await this.#writer.json(rpcEnvelope(request, { error: response2.error }));
|
|
@@ -29230,10 +29512,10 @@ var AppServerHost = class {
|
|
|
29230
29512
|
}
|
|
29231
29513
|
if (request.method === "codexhost/account/create") {
|
|
29232
29514
|
const params2 = codexAccountCreateParamsSchema.parse(requestObject(request));
|
|
29233
|
-
const accountId =
|
|
29515
|
+
const accountId = randomUUID9();
|
|
29234
29516
|
const account = await this.#accountRepository.upsert({
|
|
29235
29517
|
accountId,
|
|
29236
|
-
codexHome:
|
|
29518
|
+
codexHome: path12.join(this.#accountDataDirectory, "codex-homes", accountId),
|
|
29237
29519
|
label: params2.label ?? `Codex Account ${accountId.slice(0, 8)}`
|
|
29238
29520
|
});
|
|
29239
29521
|
const activeAccountId = await this.#accountRepository.getActiveAccountId();
|
|
@@ -29289,12 +29571,12 @@ var AppServerHost = class {
|
|
|
29289
29571
|
for (const [key, session2] of this.#officialLoginSessions) {
|
|
29290
29572
|
if (session2.accountId === params2.accountId) this.#officialLoginSessions.delete(key);
|
|
29291
29573
|
}
|
|
29292
|
-
const managedCodexHome =
|
|
29574
|
+
const managedCodexHome = path12.join(
|
|
29293
29575
|
this.#accountDataDirectory,
|
|
29294
29576
|
"codex-homes",
|
|
29295
29577
|
params2.accountId
|
|
29296
29578
|
);
|
|
29297
|
-
if (
|
|
29579
|
+
if (path12.resolve(account.codexHome) === path12.resolve(managedCodexHome)) {
|
|
29298
29580
|
try {
|
|
29299
29581
|
await rm4(managedCodexHome, { recursive: true, force: true });
|
|
29300
29582
|
} catch (error51) {
|
|
@@ -29518,7 +29800,7 @@ var AppServerHost = class {
|
|
|
29518
29800
|
throw new DelegationControlError("INVALID_ARGUMENT", "Official Model Ref is invalid");
|
|
29519
29801
|
}
|
|
29520
29802
|
const nativeModelId = requestedModel ? decodeOfficialCodexModelRef(requestedModel) : void 0;
|
|
29521
|
-
const digest2 =
|
|
29803
|
+
const digest2 = createHash6("sha256").update(
|
|
29522
29804
|
JSON.stringify({
|
|
29523
29805
|
task: input.task,
|
|
29524
29806
|
cwd: input.cwd,
|
|
@@ -29621,7 +29903,7 @@ var AppServerHost = class {
|
|
|
29621
29903
|
throw error51;
|
|
29622
29904
|
}
|
|
29623
29905
|
this.#activeOfficialTurns.set(threadId3, turnId);
|
|
29624
|
-
const delegationId = hostThreadIdSchema.parse(
|
|
29906
|
+
const delegationId = hostThreadIdSchema.parse(randomUUID9());
|
|
29625
29907
|
try {
|
|
29626
29908
|
const source = await this.#repository.find(input.parentThreadId);
|
|
29627
29909
|
const pendingTerminal = this.#pendingOfficialTerminalStatuses.get(threadId3);
|
|
@@ -29785,7 +30067,7 @@ var AppServerHost = class {
|
|
|
29785
30067
|
async #listDelegationThreads(input) {
|
|
29786
30068
|
const [sortKey, sortDirection2] = input.sort.split("-");
|
|
29787
30069
|
const request = {
|
|
29788
|
-
id: `codexhost:delegation-list:${
|
|
30070
|
+
id: `codexhost:delegation-list:${randomUUID9()}`,
|
|
29789
30071
|
method: "thread/list",
|
|
29790
30072
|
params: {
|
|
29791
30073
|
cwd: input.cwd ? [input.cwd] : null,
|
|
@@ -29848,6 +30130,8 @@ var AppServerHost = class {
|
|
|
29848
30130
|
records,
|
|
29849
30131
|
runtimeFor: (threadId3) => {
|
|
29850
30132
|
const thread = this.#externalRuntime.get(threadId3);
|
|
30133
|
+
const subagentStatus = this.#subagentThreadStatuses.get(threadId3);
|
|
30134
|
+
if (subagentStatus) return { running: subagentStatus === "active" };
|
|
29851
30135
|
return thread ? { running: thread.running } : null;
|
|
29852
30136
|
},
|
|
29853
30137
|
requestOfficialPage: (params) => aggregateOfficialAccountThreadListPage({
|
|
@@ -30261,7 +30545,7 @@ var AppServerHost = class {
|
|
|
30261
30545
|
);
|
|
30262
30546
|
return;
|
|
30263
30547
|
}
|
|
30264
|
-
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(
|
|
30548
|
+
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID9());
|
|
30265
30549
|
const projection = {
|
|
30266
30550
|
projector: new CodexTurnProjector({
|
|
30267
30551
|
threadId: thread.id,
|
|
@@ -31120,7 +31404,7 @@ var AppServerHost = class {
|
|
|
31120
31404
|
if (thread.running || thread.activeTurnId || this.#pendingExternalCommandRequests.has(thread.id)) {
|
|
31121
31405
|
throw new ExternalSteerError(-32072, "External Thread already has an active Turn");
|
|
31122
31406
|
}
|
|
31123
|
-
const turnId = hostTurnIdSchema.parse(
|
|
31407
|
+
const turnId = hostTurnIdSchema.parse(randomUUID9());
|
|
31124
31408
|
const startedAtMs = Date.now();
|
|
31125
31409
|
const projection = {
|
|
31126
31410
|
projector: new CodexTurnProjector({
|
|
@@ -31296,7 +31580,7 @@ var AppServerHost = class {
|
|
|
31296
31580
|
if (event.type === "subagent.transcript.changed") {
|
|
31297
31581
|
const nativeSubagentId = event.nativeSubagentId;
|
|
31298
31582
|
const record3 = (await this.#repository.list()).find(
|
|
31299
|
-
(candidate) => candidate.subagent?.parentHostThreadId === thread.id && candidate.subagent.nativeSubagentId === nativeSubagentId
|
|
31583
|
+
(candidate) => candidate.subagent?.parentHostThreadId === thread.id && candidate.subagent.nativeSubagentId === nativeSubagentId && candidate.nativeSessionRef?.nativeSessionId === thread.record.nativeSessionRef?.nativeSessionId
|
|
31300
31584
|
);
|
|
31301
31585
|
if (record3) await this.#refreshOpenSubagentThread(record3.hostThreadId, false);
|
|
31302
31586
|
return;
|
|
@@ -31304,7 +31588,7 @@ var AppServerHost = class {
|
|
|
31304
31588
|
if (event.type === "subagent.state.changed") {
|
|
31305
31589
|
const nativeSubagentId = event.nativeSubagentId;
|
|
31306
31590
|
const record3 = (await this.#repository.list()).find(
|
|
31307
|
-
(candidate) => candidate.subagent?.parentHostThreadId === thread.id && candidate.subagent.nativeSubagentId === nativeSubagentId
|
|
31591
|
+
(candidate) => candidate.subagent?.parentHostThreadId === thread.id && candidate.subagent.nativeSubagentId === nativeSubagentId && candidate.nativeSessionRef?.nativeSessionId === thread.record.nativeSessionRef?.nativeSessionId
|
|
31308
31592
|
);
|
|
31309
31593
|
if (!record3) return;
|
|
31310
31594
|
const status = event.status === "pending" || event.status === "running" ? "active" : "idle";
|
|
@@ -31408,33 +31692,13 @@ var AppServerHost = class {
|
|
|
31408
31692
|
async #materializeSubagent(parent, subagent) {
|
|
31409
31693
|
if (!subagent.nativeSubagentId || !parent.record.nativeSessionRef) return subagent;
|
|
31410
31694
|
const status = subagent.status === "pending" || subagent.status === "running" ? "active" : "idle";
|
|
31411
|
-
const
|
|
31412
|
-
|
|
31413
|
-
|
|
31414
|
-
|
|
31415
|
-
|
|
31416
|
-
|
|
31417
|
-
await this.#setSubagentThreadStatus(existing.hostThreadId, status);
|
|
31418
|
-
return { ...subagent, subagentId: existing.hostThreadId };
|
|
31695
|
+
const record3 = await this.#repository.materializeSubagent(parent.record, subagent);
|
|
31696
|
+
if (!record3) return subagent;
|
|
31697
|
+
if (this.#subagentThreadStatuses.has(record3.hostThreadId)) {
|
|
31698
|
+
this.#trackRunningSubagent(parent.id, record3.hostThreadId, status);
|
|
31699
|
+
await this.#setSubagentThreadStatus(record3.hostThreadId, status);
|
|
31700
|
+
return { ...subagent, subagentId: record3.hostThreadId };
|
|
31419
31701
|
}
|
|
31420
|
-
const recordInput = createExternalThreadRecordInput({
|
|
31421
|
-
harnessId: parent.record.harnessId,
|
|
31422
|
-
cwd: parent.cwd,
|
|
31423
|
-
title: subagent.description,
|
|
31424
|
-
transportModelId: parent.transportModelId,
|
|
31425
|
-
ephemeral: false,
|
|
31426
|
-
historyMode: "paginated",
|
|
31427
|
-
subagent: {
|
|
31428
|
-
parentHostThreadId: parent.id,
|
|
31429
|
-
nativeSubagentId: subagent.nativeSubagentId,
|
|
31430
|
-
...subagent.role ? { role: subagent.role } : {}
|
|
31431
|
-
}
|
|
31432
|
-
});
|
|
31433
|
-
let record3 = await this.#repository.createProvisional(recordInput);
|
|
31434
|
-
record3 = await this.#repository.commitNative(
|
|
31435
|
-
record3.hostThreadId,
|
|
31436
|
-
parent.record.nativeSessionRef
|
|
31437
|
-
);
|
|
31438
31702
|
const thread = externalThreadValue({
|
|
31439
31703
|
record: record3,
|
|
31440
31704
|
turns: [],
|
|
@@ -31678,7 +31942,7 @@ var AppServerHost = class {
|
|
|
31678
31942
|
try {
|
|
31679
31943
|
result = projection.projector.projectQuestion(
|
|
31680
31944
|
interaction,
|
|
31681
|
-
hostItemIdSchema.parse(
|
|
31945
|
+
hostItemIdSchema.parse(randomUUID9())
|
|
31682
31946
|
);
|
|
31683
31947
|
} catch (error51) {
|
|
31684
31948
|
this.#diagnose(error51);
|
|
@@ -31834,7 +32098,7 @@ var AppServerHost = class {
|
|
|
31834
32098
|
};
|
|
31835
32099
|
|
|
31836
32100
|
// packages/host-runtime/src/codex-runtime/account-official-listeners.ts
|
|
31837
|
-
import
|
|
32101
|
+
import path13 from "node:path";
|
|
31838
32102
|
var AccountOfficialListeners = class {
|
|
31839
32103
|
constructor(createListener) {
|
|
31840
32104
|
this.createListener = createListener;
|
|
@@ -31845,7 +32109,7 @@ var AccountOfficialListeners = class {
|
|
|
31845
32109
|
#closed = false;
|
|
31846
32110
|
async endpoint(account) {
|
|
31847
32111
|
if (this.#closed) throw new Error("Account official listeners are closed");
|
|
31848
|
-
const key =
|
|
32112
|
+
const key = path13.resolve(account.codexHome);
|
|
31849
32113
|
const existing = this.#starting.get(key);
|
|
31850
32114
|
if (existing) return existing;
|
|
31851
32115
|
const listener = this.createListener(account);
|
|
@@ -31981,17 +32245,17 @@ var DelegationControlRegistry = class {
|
|
|
31981
32245
|
|
|
31982
32246
|
// packages/host-runtime/src/installed-harness-plugins.ts
|
|
31983
32247
|
import os3 from "node:os";
|
|
31984
|
-
import
|
|
32248
|
+
import path15 from "node:path";
|
|
31985
32249
|
import { fileURLToPath } from "node:url";
|
|
31986
32250
|
|
|
31987
32251
|
// packages/host-runtime/src/launcher-url-opener.ts
|
|
31988
32252
|
import { spawn as spawn3 } from "node:child_process";
|
|
31989
|
-
import
|
|
32253
|
+
import path14 from "node:path";
|
|
31990
32254
|
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "[::1]"]);
|
|
31991
32255
|
var OPEN_TIMEOUT_MS = 1e4;
|
|
31992
32256
|
function createLauncherUrlOpener(environment, spawnLauncher = (command, arguments_2, options2) => spawn3(command, arguments_2, options2)) {
|
|
31993
32257
|
const launcher = environment.CODEXHOST_LAUNCHER_EXECUTABLE;
|
|
31994
|
-
if (!launcher || !
|
|
32258
|
+
if (!launcher || !path14.isAbsolute(launcher)) return void 0;
|
|
31995
32259
|
const launcherEnvironment = Object.fromEntries(
|
|
31996
32260
|
Object.entries(environment).filter(([name]) => {
|
|
31997
32261
|
const normalized = name.toUpperCase();
|
|
@@ -32049,9 +32313,9 @@ function installedHarnessPluginOptions(environment, managedRemoteHost = false, h
|
|
|
32049
32313
|
const opener = managedRemoteHost ? void 0 : createLauncherUrlOpener(environment);
|
|
32050
32314
|
return {
|
|
32051
32315
|
pluginRoots: [
|
|
32052
|
-
|
|
32053
|
-
environment[HARNESS_PLUGIN_DIRECTORY_ENV] ??
|
|
32054
|
-
environment.CODEXHOST_DATA_DIR ?
|
|
32316
|
+
path15.join(path15.dirname(fileURLToPath(hostRuntimeUrl)), "plugins"),
|
|
32317
|
+
environment[HARNESS_PLUGIN_DIRECTORY_ENV] ?? path15.join(
|
|
32318
|
+
environment.CODEXHOST_DATA_DIR ? path15.resolve(environment.CODEXHOST_DATA_DIR) : path15.join(os3.homedir(), ".codexhost"),
|
|
32055
32319
|
"plugins"
|
|
32056
32320
|
)
|
|
32057
32321
|
],
|
|
@@ -32176,12 +32440,12 @@ async function startDelegationControlServer(input) {
|
|
|
32176
32440
|
}
|
|
32177
32441
|
|
|
32178
32442
|
// packages/host-runtime/src/delegation-skill.ts
|
|
32179
|
-
import { createHash as
|
|
32443
|
+
import { createHash as createHash7, randomUUID as randomUUID10 } from "node:crypto";
|
|
32180
32444
|
import { mkdir as mkdir7, open as open5, readFile as readFile7, rename as rename5, rm as rm5, stat as stat3 } from "node:fs/promises";
|
|
32181
32445
|
import os4 from "node:os";
|
|
32182
|
-
import
|
|
32446
|
+
import path16 from "node:path";
|
|
32183
32447
|
var SKILL_VERSION = 7;
|
|
32184
|
-
var SKILL_RELATIVE_PATH =
|
|
32448
|
+
var SKILL_RELATIVE_PATH = path16.join("skills", "codexhost-delegation", "SKILL.md");
|
|
32185
32449
|
var PREVIOUS_MANAGED_DIGESTS = [
|
|
32186
32450
|
"9d2f491850fb0b4084a31ba9b5e4a550b5e833747af322090d8ed0ff80b88c30",
|
|
32187
32451
|
"2bb0aebb9b06febbc6c0c0bcdb0b32506c7cdbf8dc3b734cc6b2a86621270e4e",
|
|
@@ -32236,9 +32500,9 @@ user’s request and the task:
|
|
|
32236
32500
|
Report the result returned by read or a completed wait, together with the target
|
|
32237
32501
|
agent, status, and a labeled task link. Keep internal tracking IDs in tool calls.
|
|
32238
32502
|
`;
|
|
32239
|
-
var CURRENT_DIGEST =
|
|
32503
|
+
var CURRENT_DIGEST = createHash7("sha256").update(CODEXHOST_DELEGATION_SKILL).digest("hex");
|
|
32240
32504
|
function digest(value2) {
|
|
32241
|
-
return
|
|
32505
|
+
return createHash7("sha256").update(value2).digest("hex");
|
|
32242
32506
|
}
|
|
32243
32507
|
function managedVersion(value2) {
|
|
32244
32508
|
const match = /^version:\s*(\d+)\s*$/mu.exec(value2);
|
|
@@ -32253,8 +32517,8 @@ async function readOptional(filePath) {
|
|
|
32253
32517
|
}
|
|
32254
32518
|
}
|
|
32255
32519
|
async function atomicWrite(filePath, content) {
|
|
32256
|
-
await mkdir7(
|
|
32257
|
-
const temporaryPath =
|
|
32520
|
+
await mkdir7(path16.dirname(filePath), { recursive: true, mode: 448 });
|
|
32521
|
+
const temporaryPath = path16.join(path16.dirname(filePath), `.SKILL.md.${randomUUID10()}.tmp`);
|
|
32258
32522
|
const handle = await open5(temporaryPath, "wx", 384);
|
|
32259
32523
|
try {
|
|
32260
32524
|
await handle.writeFile(content, "utf8");
|
|
@@ -32271,8 +32535,8 @@ async function atomicWrite(filePath, content) {
|
|
|
32271
32535
|
async function installDelegationSkills(input = {}) {
|
|
32272
32536
|
const home = input.homeDirectory ?? os4.homedir();
|
|
32273
32537
|
const destinations = [
|
|
32274
|
-
|
|
32275
|
-
|
|
32538
|
+
path16.join(home, ".agents", SKILL_RELATIVE_PATH),
|
|
32539
|
+
path16.join(home, ".claude", SKILL_RELATIVE_PATH)
|
|
32276
32540
|
];
|
|
32277
32541
|
const knownDigests = /* @__PURE__ */ new Set([
|
|
32278
32542
|
CURRENT_DIGEST,
|
|
@@ -32337,9 +32601,9 @@ async function installDelegationSkills(input = {}) {
|
|
|
32337
32601
|
}
|
|
32338
32602
|
|
|
32339
32603
|
// packages/host-runtime/src/remote-control-app-server.ts
|
|
32340
|
-
import { randomUUID as
|
|
32604
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
32341
32605
|
import { mkdir as mkdir8, open as open6, rename as rename6, rm as rm6 } from "node:fs/promises";
|
|
32342
|
-
import
|
|
32606
|
+
import path17 from "node:path";
|
|
32343
32607
|
|
|
32344
32608
|
// packages/host-runtime/src/remote-official-connection.ts
|
|
32345
32609
|
import net from "node:net";
|
|
@@ -32529,30 +32793,30 @@ var BRIDGE_READY_METHOD = "codexhost/remote-control-bridge/ready";
|
|
|
32529
32793
|
function absoluteEnvironmentPath2(environment, name, fallback, platform = process.platform) {
|
|
32530
32794
|
const value2 = environment[name] ?? fallback;
|
|
32531
32795
|
if (!value2) return null;
|
|
32532
|
-
if (
|
|
32533
|
-
return platform === "win32" &&
|
|
32796
|
+
if (path17.isAbsolute(value2)) return path17.normalize(value2);
|
|
32797
|
+
return platform === "win32" && path17.win32.isAbsolute(value2) ? path17.win32.normalize(value2) : null;
|
|
32534
32798
|
}
|
|
32535
32799
|
function nodeCompatibleWindowsPath(value2) {
|
|
32536
32800
|
if (value2.startsWith("\\\\?\\UNC\\")) return `\\\\${value2.slice(8)}`;
|
|
32537
32801
|
if (value2.startsWith("\\\\?\\")) return value2.slice(4);
|
|
32538
32802
|
return value2;
|
|
32539
32803
|
}
|
|
32540
|
-
function remoteControlBridgePipePath(processId = process.pid, instanceId =
|
|
32804
|
+
function remoteControlBridgePipePath(processId = process.pid, instanceId = randomUUID11()) {
|
|
32541
32805
|
const safeInstance = instanceId.replaceAll(/[^a-zA-Z0-9-]/gu, "");
|
|
32542
32806
|
if (!safeInstance) throw new Error("Remote Control bridge instance ID is invalid");
|
|
32543
32807
|
return `\\\\.\\pipe\\codexhost-remote-control-${processId}-${safeInstance}`;
|
|
32544
32808
|
}
|
|
32545
32809
|
function remoteControlBridgeDescriptorPath(environment) {
|
|
32546
32810
|
const root = environment.LOCALAPPDATA;
|
|
32547
|
-
if (!root || !
|
|
32548
|
-
return
|
|
32811
|
+
if (!root || !path17.isAbsolute(root)) return null;
|
|
32812
|
+
return path17.join(path17.normalize(root), "codexhost", REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE);
|
|
32549
32813
|
}
|
|
32550
32814
|
async function publishRemoteControlAppServerDescriptor(plan) {
|
|
32551
|
-
const directory =
|
|
32815
|
+
const directory = path17.dirname(plan.descriptorPath);
|
|
32552
32816
|
await mkdir8(directory, { recursive: true, mode: 448 });
|
|
32553
|
-
const temporaryPath =
|
|
32817
|
+
const temporaryPath = path17.join(
|
|
32554
32818
|
directory,
|
|
32555
|
-
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${
|
|
32819
|
+
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID11()}.tmp`
|
|
32556
32820
|
);
|
|
32557
32821
|
const handle = await open6(temporaryPath, "wx", 384);
|
|
32558
32822
|
try {
|
|
@@ -32643,14 +32907,14 @@ async function runRemoteControlAppServerBridge(input = {}) {
|
|
|
32643
32907
|
import { createServer as createServer2 } from "node:http";
|
|
32644
32908
|
import net2 from "node:net";
|
|
32645
32909
|
import { chmod as chmod3, lstat as lstat6, mkdir as mkdir10, rm as rm8 } from "node:fs/promises";
|
|
32646
|
-
import
|
|
32910
|
+
import path19 from "node:path";
|
|
32647
32911
|
import { PassThrough as PassThrough2 } from "node:stream";
|
|
32648
32912
|
|
|
32649
32913
|
// packages/host-runtime/src/remote-socket-lock.ts
|
|
32650
|
-
import { randomUUID as
|
|
32914
|
+
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
32651
32915
|
import { chmod as chmod2, lstat as lstat5, mkdir as mkdir9, open as open7, readFile as readFile8, readdir as readdir4, rename as rename7, rm as rm7 } from "node:fs/promises";
|
|
32652
32916
|
import { uptime } from "node:os";
|
|
32653
|
-
import
|
|
32917
|
+
import path18 from "node:path";
|
|
32654
32918
|
import { setTimeout as delay4 } from "node:timers/promises";
|
|
32655
32919
|
var LOCK_RETRY_COUNT = 200;
|
|
32656
32920
|
var LOCK_RETRY_DELAY_MS = 25;
|
|
@@ -32724,7 +32988,7 @@ async function readLockEntrySnapshot(filePath) {
|
|
|
32724
32988
|
source,
|
|
32725
32989
|
identity: { dev: metadata.dev, ino: metadata.ino },
|
|
32726
32990
|
mtimeMs: metadata.mtimeMs,
|
|
32727
|
-
record: record3 &&
|
|
32991
|
+
record: record3 && path18.basename(filePath) === lockEntryName(record3.ownerToken) ? record3 : null
|
|
32728
32992
|
};
|
|
32729
32993
|
}
|
|
32730
32994
|
function lockEntryIsAbandoned(snapshot) {
|
|
@@ -32745,7 +33009,7 @@ async function readLockEntryCatalog(lockDirectory) {
|
|
|
32745
33009
|
let unsettled = false;
|
|
32746
33010
|
for (const name of names) {
|
|
32747
33011
|
if (!name.startsWith(LOCK_ENTRY_PREFIX) || !name.endsWith(LOCK_ENTRY_SUFFIX)) continue;
|
|
32748
|
-
const snapshot = await readLockEntrySnapshot(
|
|
33012
|
+
const snapshot = await readLockEntrySnapshot(path18.join(lockDirectory, name));
|
|
32749
33013
|
if (snapshot === null) continue;
|
|
32750
33014
|
if (lockEntryIsAbandoned(snapshot)) {
|
|
32751
33015
|
if (!await removeAbandonedLockEntry(snapshot)) unsettled = true;
|
|
@@ -32773,7 +33037,7 @@ async function preparePrivateLockDirectory(lockDirectory) {
|
|
|
32773
33037
|
await chmod2(lockDirectory, 448);
|
|
32774
33038
|
}
|
|
32775
33039
|
async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
|
|
32776
|
-
const temporary =
|
|
33040
|
+
const temporary = path18.join(lockDirectory, `.tmp-${record3.ownerToken}-${randomUUID12()}`);
|
|
32777
33041
|
const handle = await open7(temporary, "wx", 384);
|
|
32778
33042
|
try {
|
|
32779
33043
|
await handle.writeFile(`${JSON.stringify(record3)}
|
|
@@ -32848,8 +33112,8 @@ async function withRemoteAppServerSocketInitializationLock(socketPath, action) {
|
|
|
32848
33112
|
const legacyPath = `${socketPath}.initializing`;
|
|
32849
33113
|
const lockDirectory = `${socketPath}.initializers`;
|
|
32850
33114
|
await preparePrivateLockDirectory(lockDirectory);
|
|
32851
|
-
const ownerToken =
|
|
32852
|
-
const entryPath =
|
|
33115
|
+
const ownerToken = randomUUID12();
|
|
33116
|
+
const entryPath = path18.join(lockDirectory, lockEntryName(ownerToken));
|
|
32853
33117
|
const baseRecord = {
|
|
32854
33118
|
version: 2,
|
|
32855
33119
|
ownerToken,
|
|
@@ -33023,14 +33287,14 @@ function remoteAppServerSocketPath(environment, listenUrl = "unix://") {
|
|
|
33023
33287
|
throw new Error("Remote app-server listener must use a Unix URL");
|
|
33024
33288
|
}
|
|
33025
33289
|
const explicit = listenUrl.slice("unix://".length);
|
|
33026
|
-
if (explicit.length > 0) return
|
|
33027
|
-
const codexHome = environment.CODEX_HOME ?? (environment.HOME ?
|
|
33290
|
+
if (explicit.length > 0) return path19.posix.resolve(decodeURIComponent(explicit));
|
|
33291
|
+
const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path19.posix.join(environment.HOME, ".codex") : void 0);
|
|
33028
33292
|
if (!codexHome)
|
|
33029
33293
|
throw new Error("CODEX_HOME or HOME is required for the remote app-server socket");
|
|
33030
|
-
return
|
|
33294
|
+
return path19.posix.join(codexHome, "app-server-control", "app-server-control.sock");
|
|
33031
33295
|
}
|
|
33032
33296
|
function officialListenerArgumentsForRemoteListener(arguments_2, socketPath) {
|
|
33033
|
-
if (!
|
|
33297
|
+
if (!path19.posix.isAbsolute(socketPath)) {
|
|
33034
33298
|
throw new Error("Shared official app-server socket path must be absolute");
|
|
33035
33299
|
}
|
|
33036
33300
|
if (remoteUnixListenerUrl(arguments_2) === null) {
|
|
@@ -33141,7 +33405,7 @@ async function removeStaleSocket(socketPath) {
|
|
|
33141
33405
|
await rm8(socketPath, { force: true });
|
|
33142
33406
|
}
|
|
33143
33407
|
async function prepareRemoteAppServerSocketDirectory(socketPath) {
|
|
33144
|
-
const socketDirectory =
|
|
33408
|
+
const socketDirectory = path19.dirname(socketPath);
|
|
33145
33409
|
const existing = await lstat6(socketDirectory).catch((error51) => {
|
|
33146
33410
|
if (error51.code === "ENOENT") return null;
|
|
33147
33411
|
throw error51;
|
|
@@ -33346,20 +33610,20 @@ function createRemoteAppServerWebSocketListener(input) {
|
|
|
33346
33610
|
|
|
33347
33611
|
// packages/host-runtime/src/remote-official-app-server.ts
|
|
33348
33612
|
import { spawn as spawn4 } from "node:child_process";
|
|
33349
|
-
import { randomUUID as
|
|
33613
|
+
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
33350
33614
|
import { lstat as lstat7, rm as rm9 } from "node:fs/promises";
|
|
33351
|
-
import
|
|
33615
|
+
import path20 from "node:path";
|
|
33352
33616
|
var DEFAULT_CLOSE_TIMEOUT_MS = 2e3;
|
|
33353
33617
|
var DEFAULT_LISTEN_TIMEOUT_MS = 1e4;
|
|
33354
|
-
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token =
|
|
33355
|
-
if (!
|
|
33618
|
+
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID13()) {
|
|
33619
|
+
if (!path20.posix.isAbsolute(desktopControlSocketPath)) {
|
|
33356
33620
|
throw new Error("Desktop control socket path must be absolute");
|
|
33357
33621
|
}
|
|
33358
33622
|
if (!/^[A-Za-z0-9-]+$/u.test(token) || !/[A-Za-z0-9]/u.test(token)) {
|
|
33359
33623
|
throw new Error("Shared official app-server socket token is invalid");
|
|
33360
33624
|
}
|
|
33361
33625
|
const compactToken = token.replaceAll("-", "").slice(0, 15);
|
|
33362
|
-
return
|
|
33626
|
+
return path20.posix.join(path20.posix.dirname(desktopControlSocketPath), `.c-${compactToken}.sock`);
|
|
33363
33627
|
}
|
|
33364
33628
|
function errorMessage5(error51) {
|
|
33365
33629
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
@@ -33650,7 +33914,16 @@ function createHostUpdateCoordinator(options2) {
|
|
|
33650
33914
|
});
|
|
33651
33915
|
return contextPromise;
|
|
33652
33916
|
};
|
|
33653
|
-
const fetchLatest = options2.fetchLatest ?? ((signal) =>
|
|
33917
|
+
const fetchLatest = options2.fetchLatest ?? (async (signal) => {
|
|
33918
|
+
const timeoutSignal = AbortSignal.timeout(15e3);
|
|
33919
|
+
const requestSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
33920
|
+
const authenticated = await fetchLatestGitHubReleaseWithGitHubCli({
|
|
33921
|
+
...options2.environment ? { environment: options2.environment } : {},
|
|
33922
|
+
platform,
|
|
33923
|
+
signal: requestSignal
|
|
33924
|
+
});
|
|
33925
|
+
return authenticated ?? fetchLatestGitHubRelease({ signal: requestSignal });
|
|
33926
|
+
});
|
|
33654
33927
|
let candidate = null;
|
|
33655
33928
|
async function latestStatus(context) {
|
|
33656
33929
|
const discovered = await discoverLatestUpdateStatus(context.common.stateDirectory);
|
|
@@ -33826,9 +34099,9 @@ function hasLauncherManagedUpdateRuntime(environment, hostRuntimePath) {
|
|
|
33826
34099
|
if (!environment[UPDATE_RUNTIME_ENV.launcherPid]) return false;
|
|
33827
34100
|
const npmPackageRoot = environment[UPDATE_RUNTIME_ENV.npmPackageRoot];
|
|
33828
34101
|
if (!npmPackageRoot || !hostRuntimePath) return true;
|
|
33829
|
-
if (!
|
|
33830
|
-
const runtimePackageRoot =
|
|
33831
|
-
return
|
|
34102
|
+
if (!path21.isAbsolute(npmPackageRoot) || !path21.isAbsolute(hostRuntimePath)) return false;
|
|
34103
|
+
const runtimePackageRoot = path21.dirname(path21.dirname(path21.normalize(hostRuntimePath)));
|
|
34104
|
+
return path21.relative(path21.normalize(npmPackageRoot), runtimePackageRoot) === "";
|
|
33832
34105
|
}
|
|
33833
34106
|
function requiredRuntimeConfiguration(environment) {
|
|
33834
34107
|
const stockCodexPath = environment[STOCK_CODEX_PATH_ENV];
|
|
@@ -33955,8 +34228,8 @@ async function runHostRuntime(input) {
|
|
|
33955
34228
|
});
|
|
33956
34229
|
try {
|
|
33957
34230
|
await officialListeners.endpoint({
|
|
33958
|
-
codexHome:
|
|
33959
|
-
delegationEnvironment.CODEX_HOME ??
|
|
34231
|
+
codexHome: path21.resolve(
|
|
34232
|
+
delegationEnvironment.CODEX_HOME ?? path21.join(homedir(), ".codex")
|
|
33960
34233
|
)
|
|
33961
34234
|
});
|
|
33962
34235
|
await listener.listen();
|
|
@@ -34057,7 +34330,7 @@ async function runHostRuntime(input) {
|
|
|
34057
34330
|
}
|
|
34058
34331
|
|
|
34059
34332
|
// packages/host-runtime/src/remote-host-install.ts
|
|
34060
|
-
import { createHash as
|
|
34333
|
+
import { createHash as createHash8, randomUUID as randomUUID14 } from "node:crypto";
|
|
34061
34334
|
import { constants as fsConstants } from "node:fs";
|
|
34062
34335
|
import {
|
|
34063
34336
|
access,
|
|
@@ -34072,7 +34345,7 @@ import {
|
|
|
34072
34345
|
stat as stat4,
|
|
34073
34346
|
writeFile as writeFile5
|
|
34074
34347
|
} from "node:fs/promises";
|
|
34075
|
-
import
|
|
34348
|
+
import path22 from "node:path";
|
|
34076
34349
|
var MANIFEST_FORMAT = 1;
|
|
34077
34350
|
var WRAPPER_MARKER = "# codexhost remote SSH wrapper v1";
|
|
34078
34351
|
var PROFILE_START = "# >>> codexhost remote SSH >>>";
|
|
@@ -34083,25 +34356,25 @@ function resolvePaths(options2) {
|
|
|
34083
34356
|
if (!configuredHome) {
|
|
34084
34357
|
throw new Error("A non-root HOME is required for remote Host installation");
|
|
34085
34358
|
}
|
|
34086
|
-
const home =
|
|
34087
|
-
if (!home || home ===
|
|
34359
|
+
const home = path22.resolve(configuredHome);
|
|
34360
|
+
if (!home || home === path22.parse(home).root) {
|
|
34088
34361
|
throw new Error("A non-root HOME is required for remote Host installation");
|
|
34089
34362
|
}
|
|
34090
|
-
const installRoot =
|
|
34091
|
-
const profilePath =
|
|
34092
|
-
options2.profilePath ??
|
|
34363
|
+
const installRoot = path22.resolve(options2.installRoot ?? path22.join(home, ".codexhost", "remote"));
|
|
34364
|
+
const profilePath = path22.resolve(
|
|
34365
|
+
options2.profilePath ?? path22.join(
|
|
34093
34366
|
home,
|
|
34094
|
-
|
|
34367
|
+
path22.basename(environment.SHELL ?? "") === "zsh" ? ".zshenv" : path22.basename(environment.SHELL ?? "") === "bash" ? ".bashrc" : ".profile"
|
|
34095
34368
|
)
|
|
34096
34369
|
);
|
|
34097
|
-
const binDirectory =
|
|
34370
|
+
const binDirectory = path22.join(installRoot, "bin");
|
|
34098
34371
|
return {
|
|
34099
34372
|
home,
|
|
34100
34373
|
installRoot,
|
|
34101
34374
|
binDirectory,
|
|
34102
|
-
wrapperPath:
|
|
34103
|
-
manifestPath:
|
|
34104
|
-
dataDirectory:
|
|
34375
|
+
wrapperPath: path22.join(binDirectory, "codex"),
|
|
34376
|
+
manifestPath: path22.join(installRoot, "manifest.json"),
|
|
34377
|
+
dataDirectory: path22.join(installRoot, "data"),
|
|
34105
34378
|
profilePath
|
|
34106
34379
|
};
|
|
34107
34380
|
}
|
|
@@ -34117,10 +34390,10 @@ async function existingText(filePath) {
|
|
|
34117
34390
|
}
|
|
34118
34391
|
}
|
|
34119
34392
|
async function fileSha256(filePath) {
|
|
34120
|
-
return
|
|
34393
|
+
return createHash8("sha256").update(await readFile9(filePath)).digest("hex");
|
|
34121
34394
|
}
|
|
34122
34395
|
async function executable(filePath, label) {
|
|
34123
|
-
const absolute =
|
|
34396
|
+
const absolute = path22.resolve(filePath);
|
|
34124
34397
|
try {
|
|
34125
34398
|
if (!(await stat4(absolute)).isFile()) throw new Error("not a regular file");
|
|
34126
34399
|
await access(absolute, fsConstants.X_OK);
|
|
@@ -34130,7 +34403,7 @@ async function executable(filePath, label) {
|
|
|
34130
34403
|
return absolute;
|
|
34131
34404
|
}
|
|
34132
34405
|
async function existingFile(filePath, label) {
|
|
34133
|
-
const absolute =
|
|
34406
|
+
const absolute = path22.resolve(filePath);
|
|
34134
34407
|
try {
|
|
34135
34408
|
const metadata = await stat4(absolute);
|
|
34136
34409
|
if (!metadata.isFile()) throw new Error("not a regular file");
|
|
@@ -34140,9 +34413,9 @@ async function existingFile(filePath, label) {
|
|
|
34140
34413
|
return absolute;
|
|
34141
34414
|
}
|
|
34142
34415
|
async function discoverExecutable(name, environment) {
|
|
34143
|
-
for (const directory of (environment.PATH ?? "").split(
|
|
34416
|
+
for (const directory of (environment.PATH ?? "").split(path22.delimiter)) {
|
|
34144
34417
|
if (!directory) continue;
|
|
34145
|
-
const candidate =
|
|
34418
|
+
const candidate = path22.resolve(directory, name);
|
|
34146
34419
|
try {
|
|
34147
34420
|
await access(candidate, fsConstants.X_OK);
|
|
34148
34421
|
return candidate;
|
|
@@ -34153,10 +34426,10 @@ async function discoverExecutable(name, environment) {
|
|
|
34153
34426
|
return null;
|
|
34154
34427
|
}
|
|
34155
34428
|
async function writeAtomic(filePath, contents, mode) {
|
|
34156
|
-
await mkdir11(
|
|
34157
|
-
const temporary =
|
|
34158
|
-
|
|
34159
|
-
`.${
|
|
34429
|
+
await mkdir11(path22.dirname(filePath), { recursive: true, mode: 448 });
|
|
34430
|
+
const temporary = path22.join(
|
|
34431
|
+
path22.dirname(filePath),
|
|
34432
|
+
`.${path22.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
|
|
34160
34433
|
);
|
|
34161
34434
|
try {
|
|
34162
34435
|
if (typeof contents === "string") {
|
|
@@ -34177,10 +34450,10 @@ async function writeAtomic(filePath, contents, mode) {
|
|
|
34177
34450
|
}
|
|
34178
34451
|
}
|
|
34179
34452
|
async function writeAtomicExecutable(filePath, sourcePath) {
|
|
34180
|
-
await mkdir11(
|
|
34181
|
-
const temporary =
|
|
34182
|
-
|
|
34183
|
-
`.${
|
|
34453
|
+
await mkdir11(path22.dirname(filePath), { recursive: true, mode: 448 });
|
|
34454
|
+
const temporary = path22.join(
|
|
34455
|
+
path22.dirname(filePath),
|
|
34456
|
+
`.${path22.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
|
|
34184
34457
|
);
|
|
34185
34458
|
try {
|
|
34186
34459
|
await copyFile3(sourcePath, temporary);
|
|
@@ -34221,8 +34494,8 @@ function removeManagedProfileBlock(contents) {
|
|
|
34221
34494
|
function installManagedProfileBlock(contents, manifest) {
|
|
34222
34495
|
const base = removeManagedProfileBlock(contents);
|
|
34223
34496
|
const environment = [
|
|
34224
|
-
`export CODEX_INSTALL_DIR=${shellQuote(
|
|
34225
|
-
`export PATH=${shellQuote(
|
|
34497
|
+
`export CODEX_INSTALL_DIR=${shellQuote(path22.dirname(manifest.wrapperPath))}`,
|
|
34498
|
+
`export PATH=${shellQuote(path22.dirname(manifest.wrapperPath))}:${shellQuote(path22.dirname(manifest.nodePath))}:${shellQuote(path22.dirname(manifest.stockCodexPath))}:"\${PATH:-/usr/local/bin:/usr/bin:/bin}"`,
|
|
34226
34499
|
`export CODEXHOST_STOCK_CODEX_PATH=${shellQuote(manifest.stockCodexPath)}`,
|
|
34227
34500
|
`export CODEXHOST_HOST_NODE_PATH=${shellQuote(manifest.nodePath)}`,
|
|
34228
34501
|
`export CODEXHOST_HOST_RUNTIME_PATH=${shellQuote(manifest.hostRuntimePath)}`,
|
|
@@ -34239,7 +34512,7 @@ function installManagedProfileBlock(contents, manifest) {
|
|
|
34239
34512
|
PROFILE_END,
|
|
34240
34513
|
""
|
|
34241
34514
|
].join("\n");
|
|
34242
|
-
if (
|
|
34515
|
+
if (path22.basename(manifest.profilePath) === ".bashrc") return `${block}${base}`;
|
|
34243
34516
|
const separator = base.length > 0 && !base.endsWith("\n") ? "\n" : "";
|
|
34244
34517
|
return `${base}${separator}${block}`;
|
|
34245
34518
|
}
|
|
@@ -34258,7 +34531,7 @@ ${WRAPPER_MARKER}
|
|
|
34258
34531
|
return "legacy-wrapper";
|
|
34259
34532
|
}
|
|
34260
34533
|
if (manifest.entrypointSha256 !== void 0) {
|
|
34261
|
-
return
|
|
34534
|
+
return createHash8("sha256").update(entrypoint).digest("hex") === manifest.entrypointSha256 ? "native" : "modified";
|
|
34262
34535
|
}
|
|
34263
34536
|
const shim = await readFile9(manifest.shimPath).catch((error51) => {
|
|
34264
34537
|
if (error51.code === "ENOENT") return null;
|
|
@@ -34304,9 +34577,9 @@ async function readManifest(filePath) {
|
|
|
34304
34577
|
];
|
|
34305
34578
|
const optionalPaths = ["claudeCommand", "profileBackupPath"];
|
|
34306
34579
|
if (manifest.format !== MANIFEST_FORMAT || Object.keys(manifest).some((key) => !allowed.has(key)) || requiredPaths.some(
|
|
34307
|
-
(key) => typeof manifest[key] !== "string" || !
|
|
34580
|
+
(key) => typeof manifest[key] !== "string" || !path22.isAbsolute(manifest[key])
|
|
34308
34581
|
) || optionalPaths.some(
|
|
34309
|
-
(key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !
|
|
34582
|
+
(key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !path22.isAbsolute(manifest[key]))
|
|
34310
34583
|
) || manifest.entrypointSha256 !== void 0 && (typeof manifest.entrypointSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(manifest.entrypointSha256))) {
|
|
34311
34584
|
throw new Error("Remote Host manifest has an unsupported format");
|
|
34312
34585
|
}
|
|
@@ -34535,7 +34808,7 @@ async function uninstallRemoteHost(options2) {
|
|
|
34535
34808
|
import { spawn as spawn5 } from "node:child_process";
|
|
34536
34809
|
import { stat as stat5 } from "node:fs/promises";
|
|
34537
34810
|
import net3 from "node:net";
|
|
34538
|
-
import
|
|
34811
|
+
import path23 from "node:path";
|
|
34539
34812
|
import { Duplex } from "node:stream";
|
|
34540
34813
|
var CODEXHOST_STATUS_METHOD = "codexhost/update/status";
|
|
34541
34814
|
var DIRECT_PROBE_TIMEOUT_MS = 5e3;
|
|
@@ -34554,9 +34827,9 @@ function classifyRemoteHostProbeResponse(response, socketPath) {
|
|
|
34554
34827
|
}
|
|
34555
34828
|
var lifecycleDependencyOverrides = {};
|
|
34556
34829
|
function socketPathFor(environment) {
|
|
34557
|
-
const codexHome = environment.CODEX_HOME ?? (environment.HOME ?
|
|
34830
|
+
const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path23.join(environment.HOME, ".codex") : void 0);
|
|
34558
34831
|
if (!codexHome) throw new Error("CODEX_HOME or HOME is required for remote Host lifecycle");
|
|
34559
|
-
return
|
|
34832
|
+
return path23.join(codexHome, "app-server-control", "app-server-control.sock");
|
|
34560
34833
|
}
|
|
34561
34834
|
async function defaultSocketExists(socketPath) {
|
|
34562
34835
|
const metadata = await stat5(socketPath).catch((error51) => {
|
|
@@ -34683,7 +34956,7 @@ function installedManifest(status) {
|
|
|
34683
34956
|
function managedEnvironment(manifest, environment) {
|
|
34684
34957
|
return {
|
|
34685
34958
|
...environment,
|
|
34686
|
-
CODEX_INSTALL_DIR:
|
|
34959
|
+
CODEX_INSTALL_DIR: path23.dirname(manifest.wrapperPath),
|
|
34687
34960
|
CODEXHOST_STOCK_CODEX_PATH: manifest.stockCodexPath,
|
|
34688
34961
|
CODEXHOST_HOST_NODE_PATH: manifest.nodePath,
|
|
34689
34962
|
CODEXHOST_HOST_RUNTIME_PATH: manifest.hostRuntimePath,
|
|
@@ -34691,7 +34964,7 @@ function managedEnvironment(manifest, environment) {
|
|
|
34691
34964
|
CODEXHOST_DEFAULT_AGENT: "codex",
|
|
34692
34965
|
CODEXHOST_REMOTE_SSH_MANAGED: "1",
|
|
34693
34966
|
...manifest.claudeCommand ? { CODEXHOST_CLAUDE_COMMAND: manifest.claudeCommand } : {},
|
|
34694
|
-
PATH: `${
|
|
34967
|
+
PATH: `${path23.dirname(manifest.wrapperPath)}${path23.delimiter}${path23.dirname(manifest.stockCodexPath)}${path23.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
|
|
34695
34968
|
};
|
|
34696
34969
|
}
|
|
34697
34970
|
async function defaultRunTerminator(manifest, socketPath, role, environment) {
|
|
@@ -34979,7 +35252,7 @@ var harnessBrokerServerFrameSchema = external_exports.union([
|
|
|
34979
35252
|
var harnessBrokerDescriptorSchema = external_exports.object({
|
|
34980
35253
|
schemaVersion: external_exports.literal(1),
|
|
34981
35254
|
protocolVersion: external_exports.literal(HARNESS_BROKER_PROTOCOL_VERSION),
|
|
34982
|
-
harnessId:
|
|
35255
|
+
harnessId: harnessPluginIdSchema,
|
|
34983
35256
|
generation: external_exports.string().uuid(),
|
|
34984
35257
|
ownerPid: external_exports.number().int().positive(),
|
|
34985
35258
|
socketPath: external_exports.string().min(1).max(512),
|
|
@@ -35030,33 +35303,48 @@ function consumeBrokerFrames(socket, onFrame, onError) {
|
|
|
35030
35303
|
|
|
35031
35304
|
// packages/harness-broker/dist/paths.js
|
|
35032
35305
|
import os5 from "node:os";
|
|
35033
|
-
import
|
|
35306
|
+
import path24 from "node:path";
|
|
35034
35307
|
var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
|
|
35035
35308
|
var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
|
|
35036
35309
|
var HARNESS_BROKER_SOCKET_FILE = "claude-code-broker-v1.sock";
|
|
35037
35310
|
function defaultHarnessBrokerDirectory(environment = process.env) {
|
|
35038
35311
|
const home = environment.HOME || os5.homedir();
|
|
35039
|
-
return
|
|
35312
|
+
return path24.join(home, ".codexhost", "harness-broker");
|
|
35040
35313
|
}
|
|
35041
|
-
function defaultHarnessBrokerDescriptorPath(environment = process.env) {
|
|
35042
|
-
|
|
35314
|
+
function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
|
|
35315
|
+
harnessPluginIdSchema.parse(harnessId);
|
|
35316
|
+
if (harnessId !== "claude-code")
|
|
35317
|
+
return path24.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
|
|
35318
|
+
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path24.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
|
|
35043
35319
|
}
|
|
35044
|
-
function defaultHarnessBrokerSocketPath(environment = process.env) {
|
|
35045
|
-
|
|
35320
|
+
function defaultHarnessBrokerSocketPath(environment = process.env, harnessId = "claude-code") {
|
|
35321
|
+
harnessPluginIdSchema.parse(harnessId);
|
|
35322
|
+
if (harnessId !== "claude-code")
|
|
35323
|
+
return path24.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
|
|
35324
|
+
return path24.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
|
|
35046
35325
|
}
|
|
35047
35326
|
|
|
35048
35327
|
// packages/harness-broker/dist/validation.js
|
|
35049
35328
|
var cwdSchema = external_exports.string().min(1).max(16384);
|
|
35329
|
+
var brokerEnvironmentSchema = external_exports.object({
|
|
35330
|
+
CODEXHOST_CLI_PATH: external_exports.string().max(16384).optional(),
|
|
35331
|
+
CODEXHOST_RUNTIME_ENDPOINT: external_exports.string().max(16384).optional(),
|
|
35332
|
+
CODEXHOST_RUNTIME_TOKEN: external_exports.string().max(16384).optional(),
|
|
35333
|
+
CODEXHOST_THREAD_ID: external_exports.string().max(256).optional()
|
|
35334
|
+
}).strict();
|
|
35050
35335
|
var createSchema = external_exports.object({
|
|
35051
35336
|
kind: external_exports.literal("create"),
|
|
35052
35337
|
cwd: cwdSchema,
|
|
35053
35338
|
executionPolicy: external_exports.enum(["default", "unattended-full-access"]).optional(),
|
|
35339
|
+
environment: brokerEnvironmentSchema.optional(),
|
|
35054
35340
|
model: harnessModelRefSchema.optional(),
|
|
35055
35341
|
thinkingOptionId: harnessThinkingOptionIdSchema.optional(),
|
|
35056
35342
|
permissionModeId: harnessPermissionModeIdSchema.optional()
|
|
35057
35343
|
}).strict();
|
|
35058
35344
|
var resumeSchema = external_exports.object({
|
|
35059
35345
|
kind: external_exports.literal("resume"),
|
|
35346
|
+
environment: brokerEnvironmentSchema.optional(),
|
|
35347
|
+
permissionModeId: harnessPermissionModeIdSchema.optional(),
|
|
35060
35348
|
model: harnessModelRefSchema.optional(),
|
|
35061
35349
|
thinkingOptionId: harnessThinkingOptionIdSchema.optional(),
|
|
35062
35350
|
nativeRef: nativeSessionRefSchema,
|
|
@@ -35065,12 +35353,14 @@ var resumeSchema = external_exports.object({
|
|
|
35065
35353
|
}).strict();
|
|
35066
35354
|
var forkSchema = external_exports.object({
|
|
35067
35355
|
kind: external_exports.literal("fork"),
|
|
35356
|
+
environment: brokerEnvironmentSchema.optional(),
|
|
35068
35357
|
sourceRef: nativeSessionRefSchema,
|
|
35069
35358
|
checkpoint: nativeCheckpointRefSchema,
|
|
35070
35359
|
cwd: cwdSchema
|
|
35071
35360
|
}).strict();
|
|
35072
35361
|
var rollbackSchema = external_exports.object({
|
|
35073
35362
|
kind: external_exports.literal("rollbackLastTurn"),
|
|
35363
|
+
environment: brokerEnvironmentSchema.optional(),
|
|
35074
35364
|
model: harnessModelRefSchema.optional(),
|
|
35075
35365
|
thinkingOptionId: harnessThinkingOptionIdSchema.optional(),
|
|
35076
35366
|
permissionModeId: harnessPermissionModeIdSchema.optional(),
|
|
@@ -35244,10 +35534,10 @@ var harnessOutputSchema = external_exports.custom((value2) => {
|
|
|
35244
35534
|
});
|
|
35245
35535
|
|
|
35246
35536
|
// packages/harness-broker/dist/server.js
|
|
35247
|
-
import { randomBytes as randomBytes2, randomUUID as
|
|
35537
|
+
import { randomBytes as randomBytes2, randomUUID as randomUUID15 } from "node:crypto";
|
|
35248
35538
|
import { chmod as chmod5, lstat as lstat9, mkdir as mkdir12, open as open8, readFile as readFile10, rename as rename9, rm as rm11 } from "node:fs/promises";
|
|
35249
35539
|
import net4, {} from "node:net";
|
|
35250
|
-
import
|
|
35540
|
+
import path25 from "node:path";
|
|
35251
35541
|
function harnessError(message, retryable = true) {
|
|
35252
35542
|
return { code: "unavailable", message, retryable, stage: "harnessBroker" };
|
|
35253
35543
|
}
|
|
@@ -35303,7 +35593,7 @@ async function assertNoLiveDescriptor(descriptorPath) {
|
|
|
35303
35593
|
}
|
|
35304
35594
|
}
|
|
35305
35595
|
async function publishDescriptor(descriptorPath, descriptor) {
|
|
35306
|
-
const temporary = `${descriptorPath}.${process.pid}.${
|
|
35596
|
+
const temporary = `${descriptorPath}.${process.pid}.${randomUUID15()}.tmp`;
|
|
35307
35597
|
const handle = await open8(temporary, "wx", 384);
|
|
35308
35598
|
try {
|
|
35309
35599
|
await handle.writeFile(`${JSON.stringify(descriptor)}
|
|
@@ -35369,25 +35659,23 @@ async function prepareUnixSocketPath(socketPath) {
|
|
|
35369
35659
|
}
|
|
35370
35660
|
}
|
|
35371
35661
|
async function startHarnessBrokerServer(input) {
|
|
35372
|
-
|
|
35373
|
-
|
|
35374
|
-
}
|
|
35375
|
-
if (process.platform !== "win32" && path24.dirname(input.descriptorPath) !== path24.dirname(input.socketPath)) {
|
|
35662
|
+
harnessPluginIdSchema.parse(input.adapter.harnessId);
|
|
35663
|
+
if (process.platform !== "win32" && path25.dirname(input.descriptorPath) !== path25.dirname(input.socketPath)) {
|
|
35376
35664
|
throw new Error("Harness broker descriptor and socket must share one private directory");
|
|
35377
35665
|
}
|
|
35378
35666
|
if (process.platform === "darwin" && Buffer.byteLength(input.socketPath) > 103) {
|
|
35379
35667
|
throw new Error("Harness broker Unix socket path is too long for macOS");
|
|
35380
35668
|
}
|
|
35381
|
-
await privateDirectory(
|
|
35669
|
+
await privateDirectory(path25.dirname(input.descriptorPath));
|
|
35382
35670
|
await assertNoLiveDescriptor(input.descriptorPath);
|
|
35383
35671
|
if (process.platform !== "win32")
|
|
35384
35672
|
await prepareUnixSocketPath(input.socketPath);
|
|
35385
|
-
const generation = input.generation ??
|
|
35673
|
+
const generation = input.generation ?? randomUUID15();
|
|
35386
35674
|
const token = input.token ?? randomBytes2(32).toString("hex");
|
|
35387
35675
|
const descriptor = {
|
|
35388
35676
|
schemaVersion: 1,
|
|
35389
35677
|
protocolVersion: HARNESS_BROKER_PROTOCOL_VERSION,
|
|
35390
|
-
harnessId:
|
|
35678
|
+
harnessId: input.adapter.harnessId,
|
|
35391
35679
|
generation,
|
|
35392
35680
|
ownerPid: process.pid,
|
|
35393
35681
|
socketPath: input.socketPath,
|
|
@@ -35400,7 +35688,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
35400
35688
|
let closed = false;
|
|
35401
35689
|
const server = net4.createServer((socket) => {
|
|
35402
35690
|
const state = {
|
|
35403
|
-
id:
|
|
35691
|
+
id: randomUUID15(),
|
|
35404
35692
|
socket,
|
|
35405
35693
|
authenticated: false,
|
|
35406
35694
|
inputSequence: 0,
|
|
@@ -35443,8 +35731,9 @@ async function startHarnessBrokerServer(input) {
|
|
|
35443
35731
|
if (output.kind === "event" && output.event.type === "session.state.changed") {
|
|
35444
35732
|
const state2 = output.event.state;
|
|
35445
35733
|
const observedNativeId = state2.nativeRef?.nativeSessionId;
|
|
35446
|
-
if (state2.nativeRef && record3.nativeRef && (record3.nativeRef.harnessId !== state2.nativeRef.harnessId || record3.nativeRef.nativeSessionId !== state2.nativeRef.nativeSessionId || record3.nativeRef.formatVersion !== state2.nativeRef.formatVersion)) {
|
|
35734
|
+
if (state2.nativeRef && (state2.nativeRef.harnessId !== input.adapter.harnessId || record3.nativeRef && (record3.nativeRef.harnessId !== state2.nativeRef.harnessId || record3.nativeRef.nativeSessionId !== state2.nativeRef.nativeSessionId || record3.nativeRef.formatVersion !== state2.nativeRef.formatVersion))) {
|
|
35447
35735
|
record3.faulted = true;
|
|
35736
|
+
releaseProvisionalWriter(record3);
|
|
35448
35737
|
await send({
|
|
35449
35738
|
kind: "output",
|
|
35450
35739
|
sessionId: record3.id,
|
|
@@ -35455,7 +35744,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
35455
35744
|
type: "session.faulted",
|
|
35456
35745
|
error: {
|
|
35457
35746
|
code: "protocolError",
|
|
35458
|
-
message: "Native
|
|
35747
|
+
message: "Native Harness Session identity changed after open",
|
|
35459
35748
|
retryable: false,
|
|
35460
35749
|
stage: "harnessBroker.identity"
|
|
35461
35750
|
}
|
|
@@ -35481,7 +35770,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
35481
35770
|
type: "session.faulted",
|
|
35482
35771
|
error: {
|
|
35483
35772
|
code: "sessionBusy",
|
|
35484
|
-
message: "Native
|
|
35773
|
+
message: "Native Harness Session already has an active writer",
|
|
35485
35774
|
retryable: true,
|
|
35486
35775
|
stage: "harnessBroker.identity"
|
|
35487
35776
|
}
|
|
@@ -35579,20 +35868,25 @@ async function startHarnessBrokerServer(input) {
|
|
|
35579
35868
|
if (request.method === "adapter.subagent.readSnapshot") {
|
|
35580
35869
|
const subagents = input.adapter.subagents;
|
|
35581
35870
|
if (!subagents)
|
|
35582
|
-
return { ok: false, error: harnessError("
|
|
35583
|
-
|
|
35871
|
+
return { ok: false, error: harnessError("Harness subagents are unavailable", false) };
|
|
35872
|
+
const params = subagentReadSnapshotSchema.parse(request.params);
|
|
35873
|
+
if (params.parent.harnessId !== input.adapter.harnessId)
|
|
35874
|
+
return { ok: false, error: protocolError("Subagent parent belongs to another Harness") };
|
|
35875
|
+
return subagents.readSnapshot(params);
|
|
35584
35876
|
}
|
|
35585
35877
|
if (request.method === "adapter.open") {
|
|
35586
35878
|
const openInput = brokerOpenInputSchema.parse(request.params);
|
|
35587
35879
|
const sourceRef = openInput.kind === "create" ? void 0 : openInput.kind === "resume" ? openInput.nativeRef : openInput.sourceRef;
|
|
35588
35880
|
const sourceNativeId = sourceRef?.nativeSessionId;
|
|
35881
|
+
if (sourceRef && sourceRef.harnessId !== input.adapter.harnessId)
|
|
35882
|
+
return { ok: false, error: protocolError("Native Session belongs to another Harness") };
|
|
35589
35883
|
const sourceKey = sourceNativeId ? nativeWriterKey(sourceNativeId) : void 0;
|
|
35590
35884
|
if (sourceKey && nativeWriters.has(sourceKey)) {
|
|
35591
35885
|
return {
|
|
35592
35886
|
ok: false,
|
|
35593
35887
|
error: {
|
|
35594
35888
|
code: "sessionBusy",
|
|
35595
|
-
message: "Native
|
|
35889
|
+
message: "Native Harness Session already has an active writer",
|
|
35596
35890
|
retryable: true,
|
|
35597
35891
|
stage: "harnessBroker.open"
|
|
35598
35892
|
}
|
|
@@ -35603,13 +35897,13 @@ async function startHarnessBrokerServer(input) {
|
|
|
35603
35897
|
ok: false,
|
|
35604
35898
|
error: {
|
|
35605
35899
|
code: "sessionBusy",
|
|
35606
|
-
message: "Native
|
|
35900
|
+
message: "Native Harness Session identity claim is already pending",
|
|
35607
35901
|
retryable: true,
|
|
35608
35902
|
stage: "harnessBroker.open"
|
|
35609
35903
|
}
|
|
35610
35904
|
};
|
|
35611
35905
|
}
|
|
35612
|
-
const openReservation =
|
|
35906
|
+
const openReservation = randomUUID15();
|
|
35613
35907
|
if (sourceKey)
|
|
35614
35908
|
nativeWriters.set(sourceKey, openReservation);
|
|
35615
35909
|
const provisionalReservation = openInput.kind === "create" ? openReservation : void 0;
|
|
@@ -35637,6 +35931,14 @@ async function startHarnessBrokerServer(input) {
|
|
|
35637
35931
|
return { ok: false, error: harnessError("Harness broker connection closed") };
|
|
35638
35932
|
}
|
|
35639
35933
|
const openedRef = opened.value.initialState.nativeRef;
|
|
35934
|
+
if (openedRef && openedRef.harnessId !== input.adapter.harnessId) {
|
|
35935
|
+
releaseOpenReservations();
|
|
35936
|
+
await opened.value.close().catch(() => void 0);
|
|
35937
|
+
return {
|
|
35938
|
+
ok: false,
|
|
35939
|
+
error: protocolError("Adapter opened a Session for another Harness")
|
|
35940
|
+
};
|
|
35941
|
+
}
|
|
35640
35942
|
if (sourceRef && (!openedRef || openedRef.harnessId !== sourceRef.harnessId || openedRef.formatVersion !== sourceRef.formatVersion || openInput.kind === "resume" && openedRef.nativeSessionId !== sourceRef.nativeSessionId)) {
|
|
35641
35943
|
releaseOpenReservations();
|
|
35642
35944
|
await opened.value.close().catch(() => void 0);
|
|
@@ -35644,7 +35946,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
35644
35946
|
ok: false,
|
|
35645
35947
|
error: {
|
|
35646
35948
|
code: "protocolError",
|
|
35647
|
-
message: "Native
|
|
35949
|
+
message: "Native Harness Session identity did not match the requested open",
|
|
35648
35950
|
retryable: false,
|
|
35649
35951
|
stage: "harnessBroker.open"
|
|
35650
35952
|
}
|
|
@@ -35660,7 +35962,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
35660
35962
|
ok: false,
|
|
35661
35963
|
error: {
|
|
35662
35964
|
code: "sessionBusy",
|
|
35663
|
-
message: "Native
|
|
35965
|
+
message: "Native Harness Session already has an active writer",
|
|
35664
35966
|
retryable: true,
|
|
35665
35967
|
stage: "harnessBroker.open"
|
|
35666
35968
|
}
|
|
@@ -35672,6 +35974,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
35672
35974
|
generation: 1,
|
|
35673
35975
|
owner: state.id,
|
|
35674
35976
|
cwd: openInput.cwd,
|
|
35977
|
+
...openInput.environment ? { environment: openInput.environment } : {},
|
|
35675
35978
|
...nativeId ? { nativeId } : {},
|
|
35676
35979
|
...opened.value.initialState.nativeRef ? { nativeRef: opened.value.initialState.nativeRef } : {},
|
|
35677
35980
|
...nativeKey ? { writerKey: nativeKey } : {},
|
|
@@ -35712,7 +36015,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
35712
36015
|
ok: false,
|
|
35713
36016
|
error: {
|
|
35714
36017
|
code: "sessionBusy",
|
|
35715
|
-
message: "Native
|
|
36018
|
+
message: "Native Harness Session identity has not been claimed yet",
|
|
35716
36019
|
retryable: true,
|
|
35717
36020
|
stage: "harnessBroker.identity"
|
|
35718
36021
|
}
|
|
@@ -35789,7 +36092,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
35789
36092
|
ok: false,
|
|
35790
36093
|
error: {
|
|
35791
36094
|
code: "sessionBusy",
|
|
35792
|
-
message: "Faulted
|
|
36095
|
+
message: "Faulted Harness Session has no authoritative native identity",
|
|
35793
36096
|
retryable: false,
|
|
35794
36097
|
stage: "harnessBroker.reopen"
|
|
35795
36098
|
}
|
|
@@ -35801,7 +36104,12 @@ async function startHarnessBrokerServer(input) {
|
|
|
35801
36104
|
record4.forwarderEpoch += 1;
|
|
35802
36105
|
await oldSession.close().catch(() => void 0);
|
|
35803
36106
|
await oldOutputTask.catch(() => void 0);
|
|
35804
|
-
const reopened = await input.adapter.open({
|
|
36107
|
+
const reopened = await input.adapter.open({
|
|
36108
|
+
kind: "resume",
|
|
36109
|
+
cwd: record4.cwd,
|
|
36110
|
+
nativeRef,
|
|
36111
|
+
...record4.environment ? { environment: record4.environment } : {}
|
|
36112
|
+
});
|
|
35805
36113
|
if (!reopened.ok)
|
|
35806
36114
|
return reopened;
|
|
35807
36115
|
const reopenedRef = reopened.value.initialState.nativeRef;
|
|
@@ -35811,7 +36119,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
35811
36119
|
ok: false,
|
|
35812
36120
|
error: {
|
|
35813
36121
|
code: "protocolError",
|
|
35814
|
-
message: "
|
|
36122
|
+
message: "Aqua Harness broker reopen changed the native Session identity",
|
|
35815
36123
|
retryable: false,
|
|
35816
36124
|
stage: "harnessBroker.reopen"
|
|
35817
36125
|
}
|
|
@@ -35875,7 +36183,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
35875
36183
|
}
|
|
35876
36184
|
state.authenticated = true;
|
|
35877
36185
|
state.inputSequence = 1;
|
|
35878
|
-
await send({ kind: "response", id:
|
|
36186
|
+
await send({ kind: "response", id: randomUUID15(), ok: true, value: { ready: true } });
|
|
35879
36187
|
return;
|
|
35880
36188
|
}
|
|
35881
36189
|
const parsed = harnessBrokerRequestSchema.safeParse(raw);
|
|
@@ -35948,15 +36256,16 @@ async function startHarnessBrokerServer(input) {
|
|
|
35948
36256
|
}
|
|
35949
36257
|
|
|
35950
36258
|
// packages/host-runtime/src/aqua-harness-broker.ts
|
|
35951
|
-
async function runClaudeAquaHarnessBroker(environment = process.env) {
|
|
36259
|
+
async function runClaudeAquaHarnessBroker(environment = process.env, requestedHarnessId = "claude-code") {
|
|
36260
|
+
const harnessId = harnessPluginIdSchema.parse(requestedHarnessId);
|
|
35952
36261
|
if (process.platform !== "darwin") {
|
|
35953
|
-
throw new Error("
|
|
36262
|
+
throw new Error("Aqua Harness broker is available only on macOS");
|
|
35954
36263
|
}
|
|
35955
36264
|
const { pluginRoots, pluginContext } = installedHarnessPluginOptions(environment);
|
|
35956
36265
|
const plugins = await loadHarnessPlugins({
|
|
35957
36266
|
roots: pluginRoots,
|
|
35958
36267
|
context: pluginContext,
|
|
35959
|
-
onlyIds: /* @__PURE__ */ new Set([
|
|
36268
|
+
onlyIds: /* @__PURE__ */ new Set([harnessId]),
|
|
35960
36269
|
warmup: false,
|
|
35961
36270
|
diagnose: (diagnostic) => process.stderr.write(`Harness plugin: ${JSON.stringify(diagnostic)}
|
|
35962
36271
|
`)
|
|
@@ -35969,19 +36278,19 @@ async function runClaudeAquaHarnessBroker(environment = process.env) {
|
|
|
35969
36278
|
let server;
|
|
35970
36279
|
try {
|
|
35971
36280
|
server = await startHarnessBrokerServer({
|
|
35972
|
-
descriptorPath: defaultHarnessBrokerDescriptorPath(environment),
|
|
35973
|
-
socketPath: defaultHarnessBrokerSocketPath(environment),
|
|
36281
|
+
descriptorPath: defaultHarnessBrokerDescriptorPath(environment, harnessId),
|
|
36282
|
+
socketPath: defaultHarnessBrokerSocketPath(environment, harnessId),
|
|
35974
36283
|
adapter
|
|
35975
36284
|
});
|
|
35976
36285
|
} catch (error51) {
|
|
35977
36286
|
await adapter.close().catch(() => void 0);
|
|
35978
36287
|
throw error51;
|
|
35979
36288
|
}
|
|
35980
|
-
process.title =
|
|
36289
|
+
process.title = `codexhost ${harnessId} Aqua harness broker`;
|
|
35981
36290
|
process.stdout.write(
|
|
35982
36291
|
`${JSON.stringify({
|
|
35983
36292
|
method: "codexhost/harness-broker/ready",
|
|
35984
|
-
params: { protocolVersion: 1, harnessId
|
|
36293
|
+
params: { protocolVersion: 1, harnessId }
|
|
35985
36294
|
})}
|
|
35986
36295
|
`
|
|
35987
36296
|
);
|
|
@@ -36004,7 +36313,7 @@ async function runClaudeAquaHarnessBroker(environment = process.env) {
|
|
|
36004
36313
|
|
|
36005
36314
|
// packages/host-runtime/src/release-main.ts
|
|
36006
36315
|
var arguments_ = process.argv.slice(2);
|
|
36007
|
-
process.exitCode = arguments_[0] === "--codexhost-delegation-cli" ? await runDelegationCli({ arguments: arguments_.slice(1), environment: process.env }) : arguments_[0] === "--codexhost-harness-broker" ? await runClaudeAquaHarnessBroker(process.env) : arguments_[0] === "--codexhost-remote" ? await runRemoteHostCli({ arguments: arguments_.slice(1), environment: process.env }) : arguments_[0] === "--codexhost-remote-control-bridge" ? await runRemoteControlAppServerBridge() : await runHostRuntime({
|
|
36316
|
+
process.exitCode = arguments_[0] === "--codexhost-delegation-cli" ? await runDelegationCli({ arguments: arguments_.slice(1), environment: process.env }) : arguments_[0] === "--codexhost-harness-broker" ? await runClaudeAquaHarnessBroker(process.env, arguments_[1] ?? "claude-code") : arguments_[0] === "--codexhost-remote" ? await runRemoteHostCli({ arguments: arguments_.slice(1), environment: process.env }) : arguments_[0] === "--codexhost-remote-control-bridge" ? await runRemoteControlAppServerBridge() : await runHostRuntime({
|
|
36008
36317
|
arguments: arguments_,
|
|
36009
36318
|
environment: process.env,
|
|
36010
36319
|
hostRuntimeUrl: import.meta.url
|