@liberseek/boft-cli-win32-arm64 0.6.7 → 0.6.8
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 +672 -363
- package/app/plugins/antigravity/plugin.mjs +45 -198
- package/app/plugins/claude-code/plugin.mjs +245 -58
- package/app/plugins/codebuddy/assets/icon.svg +1 -0
- package/app/plugins/codebuddy/manifest.json +13 -0
- package/app/plugins/codebuddy/plugin.mjs +23179 -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 +22713 -0
- package/app/plugins/enabled.json +3 -1
- package/app/plugins/opencode/plugin.mjs +24 -5
- package/app/plugins/pi/plugin.mjs +0 -12
- package/app/renderer-extension.js +264 -98
- package/bin/boft.exe +0 -0
- package/libexec/boft-node-repl.exe +0 -0
- package/libexec/boft-shim.exe +0 -0
- package/libexec/boft-updater.exe +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",
|
|
@@ -4283,7 +4283,7 @@ async function runDelegationCli(input) {
|
|
|
4283
4283
|
|
|
4284
4284
|
// packages/host-runtime/src/run-host-runtime.ts
|
|
4285
4285
|
import { randomBytes } from "node:crypto";
|
|
4286
|
-
import
|
|
4286
|
+
import path22 from "node:path";
|
|
4287
4287
|
import { homedir } from "node:os";
|
|
4288
4288
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
4289
4289
|
|
|
@@ -4629,9 +4629,85 @@ function selectInstallerReleaseArtifact(release, target) {
|
|
|
4629
4629
|
});
|
|
4630
4630
|
}
|
|
4631
4631
|
|
|
4632
|
+
// packages/update-manager/dist/github-cli-release.js
|
|
4633
|
+
import { execFile } from "node:child_process";
|
|
4634
|
+
import path2 from "node:path";
|
|
4635
|
+
var GITHUB_LATEST_RELEASE_ENDPOINT = "repos/BytePioneer-AI/codex-host/releases/latest";
|
|
4636
|
+
var MAX_RELEASE_RESPONSE_BYTES = 1024 * 1024;
|
|
4637
|
+
var GITHUB_CLI_TIMEOUT_MS = 5e3;
|
|
4638
|
+
function defaultExecutableCandidates(environment, platform) {
|
|
4639
|
+
if (environment.CODEXHOST_GH_COMMAND)
|
|
4640
|
+
return [environment.CODEXHOST_GH_COMMAND];
|
|
4641
|
+
const candidates = ["gh"];
|
|
4642
|
+
if (platform === "darwin") {
|
|
4643
|
+
candidates.push("/opt/homebrew/bin/gh", "/usr/local/bin/gh");
|
|
4644
|
+
} else if (platform === "win32") {
|
|
4645
|
+
const programFiles = environment.ProgramFiles ?? environment.PROGRAMFILES;
|
|
4646
|
+
const localAppData = environment.LOCALAPPDATA;
|
|
4647
|
+
if (programFiles)
|
|
4648
|
+
candidates.push(path2.win32.join(programFiles, "GitHub CLI", "gh.exe"));
|
|
4649
|
+
if (localAppData) {
|
|
4650
|
+
candidates.push(path2.win32.join(localAppData, "Programs", "GitHub CLI", "gh.exe"));
|
|
4651
|
+
}
|
|
4652
|
+
} else {
|
|
4653
|
+
candidates.push("/usr/local/bin/gh", "/usr/bin/gh", "/snap/bin/gh");
|
|
4654
|
+
}
|
|
4655
|
+
return [...new Set(candidates.filter((candidate) => Boolean(candidate)))];
|
|
4656
|
+
}
|
|
4657
|
+
function runGitHubCli(executable2, arguments_2, options2) {
|
|
4658
|
+
return new Promise((resolve, reject) => {
|
|
4659
|
+
execFile(executable2, [...arguments_2], {
|
|
4660
|
+
encoding: "utf8",
|
|
4661
|
+
env: options2.environment,
|
|
4662
|
+
maxBuffer: MAX_RELEASE_RESPONSE_BYTES,
|
|
4663
|
+
timeout: GITHUB_CLI_TIMEOUT_MS,
|
|
4664
|
+
windowsHide: true,
|
|
4665
|
+
...options2.signal ? { signal: options2.signal } : {}
|
|
4666
|
+
}, (error51, stdout) => {
|
|
4667
|
+
if (error51)
|
|
4668
|
+
reject(error51);
|
|
4669
|
+
else
|
|
4670
|
+
resolve(stdout);
|
|
4671
|
+
});
|
|
4672
|
+
});
|
|
4673
|
+
}
|
|
4674
|
+
async function fetchLatestGitHubReleaseWithGitHubCli(options2 = {}) {
|
|
4675
|
+
const environment = options2.environment ?? process.env;
|
|
4676
|
+
const platform = options2.platform ?? process.platform;
|
|
4677
|
+
const candidates = options2.executableCandidates ?? defaultExecutableCandidates(environment, platform);
|
|
4678
|
+
const run = options2.run ?? runGitHubCli;
|
|
4679
|
+
const arguments_2 = [
|
|
4680
|
+
"api",
|
|
4681
|
+
"--hostname",
|
|
4682
|
+
"github.com",
|
|
4683
|
+
"--method",
|
|
4684
|
+
"GET",
|
|
4685
|
+
"--header",
|
|
4686
|
+
"Accept: application/vnd.github+json",
|
|
4687
|
+
"--header",
|
|
4688
|
+
"X-GitHub-Api-Version: 2022-11-28",
|
|
4689
|
+
GITHUB_LATEST_RELEASE_ENDPOINT
|
|
4690
|
+
];
|
|
4691
|
+
for (const executable2 of candidates) {
|
|
4692
|
+
options2.signal?.throwIfAborted();
|
|
4693
|
+
try {
|
|
4694
|
+
return parseLatestGitHubRelease(JSON.parse(await run(executable2, arguments_2, {
|
|
4695
|
+
environment,
|
|
4696
|
+
...options2.signal ? { signal: options2.signal } : {}
|
|
4697
|
+
})));
|
|
4698
|
+
} catch (error51) {
|
|
4699
|
+
options2.signal?.throwIfAborted();
|
|
4700
|
+
const code = error51?.code;
|
|
4701
|
+
if (code !== "ENOENT" && code !== "EACCES")
|
|
4702
|
+
return null;
|
|
4703
|
+
}
|
|
4704
|
+
}
|
|
4705
|
+
return null;
|
|
4706
|
+
}
|
|
4707
|
+
|
|
4632
4708
|
// packages/update-manager/dist/operation-state.js
|
|
4633
4709
|
import { lstat as lstat2, mkdir, open, readFile as readFile2, readdir, rm, writeFile } from "node:fs/promises";
|
|
4634
|
-
import
|
|
4710
|
+
import path3 from "node:path";
|
|
4635
4711
|
var LOCK_FILE = "active-update-v1.lock";
|
|
4636
4712
|
var STATUS_FILE = "status-v1.json";
|
|
4637
4713
|
var TERMINAL_PHASES = /* @__PURE__ */ new Set(["succeeded", "failed"]);
|
|
@@ -4646,12 +4722,12 @@ async function regularFile(filePath) {
|
|
|
4646
4722
|
}
|
|
4647
4723
|
}
|
|
4648
4724
|
async function isUpdateOperationActive(stateDirectory) {
|
|
4649
|
-
if (!
|
|
4725
|
+
if (!path3.isAbsolute(stateDirectory))
|
|
4650
4726
|
throw new Error("update state directory must be absolute");
|
|
4651
|
-
return regularFile(
|
|
4727
|
+
return regularFile(path3.join(stateDirectory, LOCK_FILE));
|
|
4652
4728
|
}
|
|
4653
4729
|
async function discoverLatestUpdateStatus(stateDirectory) {
|
|
4654
|
-
if (!
|
|
4730
|
+
if (!path3.isAbsolute(stateDirectory))
|
|
4655
4731
|
throw new Error("update state directory must be absolute");
|
|
4656
4732
|
let entries;
|
|
4657
4733
|
try {
|
|
@@ -4665,7 +4741,7 @@ async function discoverLatestUpdateStatus(stateDirectory) {
|
|
|
4665
4741
|
for (const entry of entries) {
|
|
4666
4742
|
if (!entry.isDirectory() || entry.isSymbolicLink() || !entry.name.startsWith("update-"))
|
|
4667
4743
|
continue;
|
|
4668
|
-
const statusPath =
|
|
4744
|
+
const statusPath = path3.join(stateDirectory, entry.name, STATUS_FILE);
|
|
4669
4745
|
if (!await regularFile(statusPath))
|
|
4670
4746
|
continue;
|
|
4671
4747
|
try {
|
|
@@ -4693,8 +4769,8 @@ async function cleanupTerminalUpdateState(stateDirectory, options2 = {}) {
|
|
|
4693
4769
|
for (const entry of entries) {
|
|
4694
4770
|
if (!entry.isDirectory() || entry.isSymbolicLink() || !entry.name.startsWith("update-"))
|
|
4695
4771
|
continue;
|
|
4696
|
-
const directory =
|
|
4697
|
-
const statusPath =
|
|
4772
|
+
const directory = path3.join(stateDirectory, entry.name);
|
|
4773
|
+
const statusPath = path3.join(directory, STATUS_FILE);
|
|
4698
4774
|
try {
|
|
4699
4775
|
const status = parseUpdateStatus(JSON.parse(await readFile2(statusPath, "utf8")));
|
|
4700
4776
|
if (TERMINAL_PHASES.has(status.phase) && now - status.updatedAt > retentionSeconds) {
|
|
@@ -4705,10 +4781,10 @@ async function cleanupTerminalUpdateState(stateDirectory, options2 = {}) {
|
|
|
4705
4781
|
}
|
|
4706
4782
|
}
|
|
4707
4783
|
async function acquireUpdateOperationLock(stateDirectory) {
|
|
4708
|
-
if (!
|
|
4784
|
+
if (!path3.isAbsolute(stateDirectory))
|
|
4709
4785
|
throw new Error("update state directory must be absolute");
|
|
4710
4786
|
await mkdir(stateDirectory, { recursive: true, mode: 448 });
|
|
4711
|
-
const lockPath =
|
|
4787
|
+
const lockPath = path3.join(stateDirectory, LOCK_FILE);
|
|
4712
4788
|
let handle;
|
|
4713
4789
|
try {
|
|
4714
4790
|
handle = await open(lockPath, "wx", 384);
|
|
@@ -4727,9 +4803,9 @@ async function acquireUpdateOperationLock(stateDirectory) {
|
|
|
4727
4803
|
async setStatusPath(statusPath) {
|
|
4728
4804
|
if (released)
|
|
4729
4805
|
throw new Error("update operation lock is released");
|
|
4730
|
-
if (!
|
|
4806
|
+
if (!path3.isAbsolute(statusPath))
|
|
4731
4807
|
throw new Error("update status path must be absolute");
|
|
4732
|
-
await writeFile(lockPath, `${JSON.stringify({ ownerPid: process.pid, statusPath:
|
|
4808
|
+
await writeFile(lockPath, `${JSON.stringify({ ownerPid: process.pid, statusPath: path3.normalize(statusPath) })}
|
|
4733
4809
|
`, { encoding: "utf8", mode: 384 });
|
|
4734
4810
|
},
|
|
4735
4811
|
async release() {
|
|
@@ -4751,7 +4827,7 @@ function processIsAlive(processId) {
|
|
|
4751
4827
|
}
|
|
4752
4828
|
}
|
|
4753
4829
|
async function recoverUpdateOperationLock(stateDirectory) {
|
|
4754
|
-
const lockPath =
|
|
4830
|
+
const lockPath = path3.join(stateDirectory, LOCK_FILE);
|
|
4755
4831
|
if (!await regularFile(lockPath))
|
|
4756
4832
|
return;
|
|
4757
4833
|
let ownerPid;
|
|
@@ -4763,7 +4839,7 @@ async function recoverUpdateOperationLock(stateDirectory) {
|
|
|
4763
4839
|
} catch {
|
|
4764
4840
|
return;
|
|
4765
4841
|
}
|
|
4766
|
-
if (typeof statusPath !== "string" || !
|
|
4842
|
+
if (typeof statusPath !== "string" || !path3.isAbsolute(statusPath))
|
|
4767
4843
|
return;
|
|
4768
4844
|
try {
|
|
4769
4845
|
const status = parseUpdateStatus(JSON.parse(await readFile2(statusPath, "utf8")));
|
|
@@ -4778,7 +4854,7 @@ async function recoverUpdateOperationLock(stateDirectory) {
|
|
|
4778
4854
|
import { spawn } from "node:child_process";
|
|
4779
4855
|
import { randomUUID } from "node:crypto";
|
|
4780
4856
|
import { chmod, copyFile, lstat as lstat4, mkdir as mkdir2, readFile as readFile3, rename, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
|
|
4781
|
-
import
|
|
4857
|
+
import path4 from "node:path";
|
|
4782
4858
|
|
|
4783
4859
|
// packages/update-manager/dist/artifact.js
|
|
4784
4860
|
import { createHash } from "node:crypto";
|
|
@@ -4899,9 +4975,9 @@ async function replaceStatusFile(temporaryPath, statusPath) {
|
|
|
4899
4975
|
}
|
|
4900
4976
|
}
|
|
4901
4977
|
function requireAbsolutePath(value2, label) {
|
|
4902
|
-
if (!
|
|
4978
|
+
if (!path4.isAbsolute(value2))
|
|
4903
4979
|
throw new Error(`${label} must be an absolute path`);
|
|
4904
|
-
return
|
|
4980
|
+
return path4.normalize(value2);
|
|
4905
4981
|
}
|
|
4906
4982
|
async function requireRegularFile(value2, label) {
|
|
4907
4983
|
const filePath = requireAbsolutePath(value2, label);
|
|
@@ -4944,7 +5020,7 @@ function createBackgroundUpdateManager(dependencies2 = {}) {
|
|
|
4944
5020
|
const now = dependencies2.now ?? Date.now;
|
|
4945
5021
|
const preparedRequests = /* @__PURE__ */ new Set();
|
|
4946
5022
|
async function writeStatusSnapshot(statusPath, status) {
|
|
4947
|
-
const temporaryPath =
|
|
5023
|
+
const temporaryPath = path4.join(path4.dirname(statusPath), `.update-status-${randomId()}.tmp`);
|
|
4948
5024
|
try {
|
|
4949
5025
|
await writeFile2(temporaryPath, `${JSON.stringify(status)}
|
|
4950
5026
|
`, {
|
|
@@ -5004,15 +5080,15 @@ function createBackgroundUpdateManager(dependencies2 = {}) {
|
|
|
5004
5080
|
const updaterExecutable = await requireRegularFile(options2.updaterExecutable, "Updater executable");
|
|
5005
5081
|
const stateDirectory = requireAbsolutePath(options2.stateDirectory, "update state directory");
|
|
5006
5082
|
await mkdir2(stateDirectory, { recursive: true, mode: 448 });
|
|
5007
|
-
const workDirectory =
|
|
5083
|
+
const workDirectory = path4.join(stateDirectory, `update-${version2}-${randomId()}`);
|
|
5008
5084
|
await mkdir2(workDirectory, { recursive: false, mode: 448 });
|
|
5009
5085
|
const executableSuffix = platform === "win32" ? ".exe" : "";
|
|
5010
|
-
const helperPath =
|
|
5086
|
+
const helperPath = path4.join(workDirectory, `boft-updater${executableSuffix}`);
|
|
5011
5087
|
await copyFile(updaterExecutable, helperPath);
|
|
5012
5088
|
if (platform !== "win32")
|
|
5013
5089
|
await chmod(helperPath, 448);
|
|
5014
|
-
const requestPath =
|
|
5015
|
-
const statusPath =
|
|
5090
|
+
const requestPath = path4.join(workDirectory, "request-v1.json");
|
|
5091
|
+
const statusPath = path4.join(workDirectory, "status-v1.json");
|
|
5016
5092
|
await writePrivateJson(statusPath, preparedStatus(version2, installation, now()));
|
|
5017
5093
|
await options2.onPrepared?.({ version: version2, installation, statusPath });
|
|
5018
5094
|
return {
|
|
@@ -5028,8 +5104,8 @@ function createBackgroundUpdateManager(dependencies2 = {}) {
|
|
|
5028
5104
|
}
|
|
5029
5105
|
async function prepareArtifact(common, installation, sourceValue, fileName) {
|
|
5030
5106
|
const source = validateArtifact(sourceValue);
|
|
5031
|
-
const temporaryPath =
|
|
5032
|
-
const artifactPath =
|
|
5107
|
+
const temporaryPath = path4.join(common.workDirectory, `.${fileName}.download`);
|
|
5108
|
+
const artifactPath = path4.join(common.workDirectory, fileName);
|
|
5033
5109
|
const progress = progressReporter(common.statusPath, common.version, installation, source.size);
|
|
5034
5110
|
try {
|
|
5035
5111
|
const result = await download(source, temporaryPath, progress.update);
|
|
@@ -5103,7 +5179,7 @@ function createBackgroundUpdateManager(dependencies2 = {}) {
|
|
|
5103
5179
|
throw new Error("macOS DMG updates require macOS");
|
|
5104
5180
|
const common = await prepareCommon(options2, "macos-dmg");
|
|
5105
5181
|
const appPath = requireAbsolutePath(options2.appPath, "macOS application path");
|
|
5106
|
-
if (
|
|
5182
|
+
if (path4.extname(appPath) !== ".app") {
|
|
5107
5183
|
throw new Error("macOS application path must end in .app");
|
|
5108
5184
|
}
|
|
5109
5185
|
const artifact = await prepareArtifact(common, "macos-dmg", options2.artifact, "update.dmg");
|
|
@@ -5138,7 +5214,7 @@ function createBackgroundUpdateManager(dependencies2 = {}) {
|
|
|
5138
5214
|
|
|
5139
5215
|
// packages/host-runtime/src/account/codex-home-auth.ts
|
|
5140
5216
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
5141
|
-
import
|
|
5217
|
+
import path5 from "node:path";
|
|
5142
5218
|
var CODEX_API_AUTH_IDENTITY_FALLBACK = "BANK OF TOKEN";
|
|
5143
5219
|
function tomlUnquote(value2) {
|
|
5144
5220
|
const trimmed = value2.trim();
|
|
@@ -5284,10 +5360,10 @@ function inspectCodexApiUsageSource(input) {
|
|
|
5284
5360
|
return { baseUrl, apiKey };
|
|
5285
5361
|
}
|
|
5286
5362
|
async function inspectCodexHomeAuth(codexHome) {
|
|
5287
|
-
const root =
|
|
5363
|
+
const root = path5.resolve(codexHome);
|
|
5288
5364
|
const [configToml, authJson] = await Promise.all([
|
|
5289
|
-
readOptionalUtf8(
|
|
5290
|
-
readOptionalUtf8(
|
|
5365
|
+
readOptionalUtf8(path5.join(root, "config.toml")),
|
|
5366
|
+
readOptionalUtf8(path5.join(root, "auth.json"))
|
|
5291
5367
|
]);
|
|
5292
5368
|
return inspectCodexAuthDocuments({
|
|
5293
5369
|
...configToml ? { configToml } : {},
|
|
@@ -5295,10 +5371,10 @@ async function inspectCodexHomeAuth(codexHome) {
|
|
|
5295
5371
|
});
|
|
5296
5372
|
}
|
|
5297
5373
|
async function inspectCodexHomeApiUsageSource(codexHome, env = process.env) {
|
|
5298
|
-
const root =
|
|
5374
|
+
const root = path5.resolve(codexHome);
|
|
5299
5375
|
const [configToml, authJson] = await Promise.all([
|
|
5300
|
-
readOptionalUtf8(
|
|
5301
|
-
readOptionalUtf8(
|
|
5376
|
+
readOptionalUtf8(path5.join(root, "config.toml")),
|
|
5377
|
+
readOptionalUtf8(path5.join(root, "auth.json"))
|
|
5302
5378
|
]);
|
|
5303
5379
|
return inspectCodexApiUsageSource({
|
|
5304
5380
|
...configToml ? { configToml } : {},
|
|
@@ -6142,10 +6218,10 @@ function mergeDefs(...defs) {
|
|
|
6142
6218
|
function cloneDef(schema) {
|
|
6143
6219
|
return mergeDefs(schema._zod.def);
|
|
6144
6220
|
}
|
|
6145
|
-
function getElementAtPath(obj,
|
|
6146
|
-
if (!
|
|
6221
|
+
function getElementAtPath(obj, path27) {
|
|
6222
|
+
if (!path27)
|
|
6147
6223
|
return obj;
|
|
6148
|
-
return
|
|
6224
|
+
return path27.reduce((acc, key) => acc?.[key], obj);
|
|
6149
6225
|
}
|
|
6150
6226
|
function promiseAllObject(promisesObj) {
|
|
6151
6227
|
const keys = Object.keys(promisesObj);
|
|
@@ -6554,11 +6630,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
6554
6630
|
}
|
|
6555
6631
|
return false;
|
|
6556
6632
|
}
|
|
6557
|
-
function prefixIssues(
|
|
6633
|
+
function prefixIssues(path27, issues) {
|
|
6558
6634
|
return issues.map((iss) => {
|
|
6559
6635
|
var _a3;
|
|
6560
6636
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
6561
|
-
iss.path.unshift(
|
|
6637
|
+
iss.path.unshift(path27);
|
|
6562
6638
|
return iss;
|
|
6563
6639
|
});
|
|
6564
6640
|
}
|
|
@@ -6705,16 +6781,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
6705
6781
|
}
|
|
6706
6782
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
6707
6783
|
const fieldErrors = { _errors: [] };
|
|
6708
|
-
const processError = (error52,
|
|
6784
|
+
const processError = (error52, path27 = []) => {
|
|
6709
6785
|
for (const issue2 of error52.issues) {
|
|
6710
6786
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
6711
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
6787
|
+
issue2.errors.map((issues) => processError({ issues }, [...path27, ...issue2.path]));
|
|
6712
6788
|
} else if (issue2.code === "invalid_key") {
|
|
6713
|
-
processError({ issues: issue2.issues }, [...
|
|
6789
|
+
processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
|
|
6714
6790
|
} else if (issue2.code === "invalid_element") {
|
|
6715
|
-
processError({ issues: issue2.issues }, [...
|
|
6791
|
+
processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
|
|
6716
6792
|
} else {
|
|
6717
|
-
const fullpath = [...
|
|
6793
|
+
const fullpath = [...path27, ...issue2.path];
|
|
6718
6794
|
if (fullpath.length === 0) {
|
|
6719
6795
|
fieldErrors._errors.push(mapper(issue2));
|
|
6720
6796
|
} else {
|
|
@@ -6741,17 +6817,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
6741
6817
|
}
|
|
6742
6818
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
6743
6819
|
const result = { errors: [] };
|
|
6744
|
-
const processError = (error52,
|
|
6820
|
+
const processError = (error52, path27 = []) => {
|
|
6745
6821
|
var _a3, _b;
|
|
6746
6822
|
for (const issue2 of error52.issues) {
|
|
6747
6823
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
6748
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
6824
|
+
issue2.errors.map((issues) => processError({ issues }, [...path27, ...issue2.path]));
|
|
6749
6825
|
} else if (issue2.code === "invalid_key") {
|
|
6750
|
-
processError({ issues: issue2.issues }, [...
|
|
6826
|
+
processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
|
|
6751
6827
|
} else if (issue2.code === "invalid_element") {
|
|
6752
|
-
processError({ issues: issue2.issues }, [...
|
|
6828
|
+
processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
|
|
6753
6829
|
} else {
|
|
6754
|
-
const fullpath = [...
|
|
6830
|
+
const fullpath = [...path27, ...issue2.path];
|
|
6755
6831
|
if (fullpath.length === 0) {
|
|
6756
6832
|
result.errors.push(mapper(issue2));
|
|
6757
6833
|
continue;
|
|
@@ -6783,8 +6859,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
6783
6859
|
}
|
|
6784
6860
|
function toDotPath(_path) {
|
|
6785
6861
|
const segs = [];
|
|
6786
|
-
const
|
|
6787
|
-
for (const seg of
|
|
6862
|
+
const path27 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
6863
|
+
for (const seg of path27) {
|
|
6788
6864
|
if (typeof seg === "number")
|
|
6789
6865
|
segs.push(`[${seg}]`);
|
|
6790
6866
|
else if (typeof seg === "symbol")
|
|
@@ -19476,13 +19552,13 @@ function resolveRef(ref, ctx) {
|
|
|
19476
19552
|
if (!ref.startsWith("#")) {
|
|
19477
19553
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
19478
19554
|
}
|
|
19479
|
-
const
|
|
19480
|
-
if (
|
|
19555
|
+
const path27 = ref.slice(1).split("/").filter(Boolean);
|
|
19556
|
+
if (path27.length === 0) {
|
|
19481
19557
|
return ctx.rootSchema;
|
|
19482
19558
|
}
|
|
19483
19559
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
19484
|
-
if (
|
|
19485
|
-
const key =
|
|
19560
|
+
if (path27[0] === defsKey) {
|
|
19561
|
+
const key = path27[1];
|
|
19486
19562
|
if (!key || !ctx.defs[key]) {
|
|
19487
19563
|
throw new Error(`Reference not found: ${ref}`);
|
|
19488
19564
|
}
|
|
@@ -20935,7 +21011,7 @@ import { execFileSync } from "node:child_process";
|
|
|
20935
21011
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
20936
21012
|
import { constants } from "node:fs";
|
|
20937
21013
|
import { copyFile as copyFile2, mkdir as mkdir3, open as open3, readFile as readFile5, readdir as readdir2, rename as rename2, rm as rm3, stat } from "node:fs/promises";
|
|
20938
|
-
import
|
|
21014
|
+
import path6 from "node:path";
|
|
20939
21015
|
|
|
20940
21016
|
// packages/mapping-store/dist/records.js
|
|
20941
21017
|
var nonBlankTextSchema6 = external_exports.string().refine((value2) => value2.trim().length > 0, {
|
|
@@ -21188,12 +21264,12 @@ var MappingStore = class {
|
|
|
21188
21264
|
#initialized = false;
|
|
21189
21265
|
#lockHandle = null;
|
|
21190
21266
|
constructor(options2) {
|
|
21191
|
-
this.#directory =
|
|
21192
|
-
this.#threadsDirectory =
|
|
21193
|
-
this.#delegationsDirectory =
|
|
21194
|
-
this.#backupsDirectory =
|
|
21195
|
-
this.#quarantineDirectory =
|
|
21196
|
-
this.#lockPath =
|
|
21267
|
+
this.#directory = path6.resolve(options2.directory);
|
|
21268
|
+
this.#threadsDirectory = path6.join(this.#directory, "threads");
|
|
21269
|
+
this.#delegationsDirectory = path6.join(this.#directory, "delegations");
|
|
21270
|
+
this.#backupsDirectory = path6.join(this.#directory, "backups");
|
|
21271
|
+
this.#quarantineDirectory = path6.join(this.#directory, "quarantine");
|
|
21272
|
+
this.#lockPath = path6.join(this.#directory, "store.lock");
|
|
21197
21273
|
this.#instanceId = options2.instanceId ?? randomUUID2();
|
|
21198
21274
|
this.#now = options2.now ?? (() => /* @__PURE__ */ new Date());
|
|
21199
21275
|
this.#beforeReplace = options2.beforeReplace;
|
|
@@ -21212,8 +21288,8 @@ var MappingStore = class {
|
|
|
21212
21288
|
await this.#cleanupResidue();
|
|
21213
21289
|
const names = (await readdir2(this.#threadsDirectory)).filter((name) => name.endsWith(".json"));
|
|
21214
21290
|
for (const name of names) {
|
|
21215
|
-
const primary =
|
|
21216
|
-
const backup =
|
|
21291
|
+
const primary = path6.join(this.#threadsDirectory, name);
|
|
21292
|
+
const backup = path6.join(this.#backupsDirectory, name);
|
|
21217
21293
|
let record3 = null;
|
|
21218
21294
|
try {
|
|
21219
21295
|
record3 = await this.#readRecord(primary, name);
|
|
@@ -21222,7 +21298,7 @@ var MappingStore = class {
|
|
|
21222
21298
|
record3 = await this.#readRecord(backup, name);
|
|
21223
21299
|
await this.#replaceFile(primary, record3, false);
|
|
21224
21300
|
} catch (backupError) {
|
|
21225
|
-
const quarantine =
|
|
21301
|
+
const quarantine = path6.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid`);
|
|
21226
21302
|
await rename2(primary, quarantine).catch(() => void 0);
|
|
21227
21303
|
void primaryError;
|
|
21228
21304
|
void backupError;
|
|
@@ -21238,14 +21314,14 @@ var MappingStore = class {
|
|
|
21238
21314
|
}
|
|
21239
21315
|
const delegationNames = (await readdir2(this.#delegationsDirectory)).filter((name) => name.endsWith(".json"));
|
|
21240
21316
|
for (const name of delegationNames) {
|
|
21241
|
-
const file2 =
|
|
21317
|
+
const file2 = path6.join(this.#delegationsDirectory, name);
|
|
21242
21318
|
try {
|
|
21243
21319
|
const parsed = storedDelegationRecordV1Schema.parse(JSON.parse(await readFile5(file2, "utf8")));
|
|
21244
21320
|
if (`${parsed.delegationId}.json` !== name)
|
|
21245
21321
|
throw new Error("filename mismatch");
|
|
21246
21322
|
this.#delegations.set(parsed.delegationId, parsed);
|
|
21247
21323
|
} catch {
|
|
21248
|
-
const quarantine =
|
|
21324
|
+
const quarantine = path6.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid-delegation`);
|
|
21249
21325
|
await rename2(file2, quarantine).catch(() => void 0);
|
|
21250
21326
|
}
|
|
21251
21327
|
}
|
|
@@ -21404,10 +21480,35 @@ var MappingStore = class {
|
|
|
21404
21480
|
turnMappings: this.#mergeMappings(current.turnMappings, input.turnMappings ?? [])
|
|
21405
21481
|
}));
|
|
21406
21482
|
}
|
|
21483
|
+
// Keep native ref, Turn mappings and the indexed create request in one serialized
|
|
21484
|
+
// record mutation; separate setters could leave a child pointing at mixed Sessions.
|
|
21485
|
+
async rebindSubagentSession(input) {
|
|
21486
|
+
return this.#update(input.hostThreadId, (current) => {
|
|
21487
|
+
const parent = this.#records.get(input.parentHostThreadId);
|
|
21488
|
+
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))
|
|
21489
|
+
throw new MappingStoreError("MAPPING_CONFLICT", "Subagent replacement must belong to its current parent Session");
|
|
21490
|
+
if (sameJson(current.nativeSessionRef, input.nativeSessionRef) && current.createRequestId === input.createRequestId)
|
|
21491
|
+
return null;
|
|
21492
|
+
if (!sameJson(current.nativeSessionRef, input.previousNativeSessionRef)) {
|
|
21493
|
+
throw new MappingStoreError("MAPPING_CONFLICT", "Subagent replacement source Session is stale");
|
|
21494
|
+
}
|
|
21495
|
+
const nativeSessionId = input.nativeSessionRef.nativeSessionId;
|
|
21496
|
+
return {
|
|
21497
|
+
...current,
|
|
21498
|
+
createRequestId: input.createRequestId,
|
|
21499
|
+
nativeSessionRef: input.nativeSessionRef,
|
|
21500
|
+
turnMappings: current.turnMappings.map((mapping) => ({
|
|
21501
|
+
...mapping,
|
|
21502
|
+
nativeTurnRef: { ...mapping.nativeTurnRef, nativeSessionId },
|
|
21503
|
+
...mapping.nativeCheckpointRef ? { nativeCheckpointRef: { ...mapping.nativeCheckpointRef, nativeSessionId } } : {}
|
|
21504
|
+
}))
|
|
21505
|
+
};
|
|
21506
|
+
});
|
|
21507
|
+
}
|
|
21407
21508
|
async replaceReadySession(input) {
|
|
21408
21509
|
return this.#update(input.hostThreadId, (current) => {
|
|
21409
|
-
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)) {
|
|
21410
|
-
throw new MappingStoreError("MAPPING_CONFLICT", "Ready Session replacement must retain an exact shorter derived prefix");
|
|
21510
|
+
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)) {
|
|
21511
|
+
throw new MappingStoreError("MAPPING_CONFLICT", "Ready Session replacement must match the expected record and retain an exact shorter derived prefix");
|
|
21411
21512
|
}
|
|
21412
21513
|
return {
|
|
21413
21514
|
...current,
|
|
@@ -21419,8 +21520,8 @@ var MappingStore = class {
|
|
|
21419
21520
|
}
|
|
21420
21521
|
async replaceReadySessionAfterLastTurn(input) {
|
|
21421
21522
|
return this.#update(input.hostThreadId, (current) => {
|
|
21422
|
-
if (current.state !== "ready" || !current.nativeSessionRef || input.turnMappings.length !== current.turnMappings.length - 1 || input.turnMappings.some(({ hostTurnId }, index) => hostTurnId !== current.turnMappings[index]?.hostTurnId)) {
|
|
21423
|
-
throw new MappingStoreError("MAPPING_CONFLICT", "Last-Turn Session replacement must retain the exact shorter Host Turn prefix");
|
|
21523
|
+
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)) {
|
|
21524
|
+
throw new MappingStoreError("MAPPING_CONFLICT", "Last-Turn Session replacement must match the expected record and retain the exact shorter Host Turn prefix");
|
|
21424
21525
|
}
|
|
21425
21526
|
return {
|
|
21426
21527
|
...current,
|
|
@@ -21648,10 +21749,10 @@ var MappingStore = class {
|
|
|
21648
21749
|
readdir2(this.#directory)
|
|
21649
21750
|
]);
|
|
21650
21751
|
await Promise.all([
|
|
21651
|
-
...threadNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(
|
|
21652
|
-
...delegationNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(
|
|
21752
|
+
...threadNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(path6.join(this.#threadsDirectory, name), { force: true })),
|
|
21753
|
+
...delegationNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(path6.join(this.#delegationsDirectory, name), { force: true })),
|
|
21653
21754
|
// Renamed aside by #acquireLock; nothing reads them back, and they accumulate one per run.
|
|
21654
|
-
...rootNames.filter((name) => name.startsWith(`${
|
|
21755
|
+
...rootNames.filter((name) => name.startsWith(`${path6.basename(this.#lockPath)}.stale-`)).map((name) => rm3(path6.join(this.#directory, name), { force: true }))
|
|
21655
21756
|
]);
|
|
21656
21757
|
}
|
|
21657
21758
|
async #acquireLock() {
|
|
@@ -21752,13 +21853,13 @@ var MappingStore = class {
|
|
|
21752
21853
|
await next;
|
|
21753
21854
|
}
|
|
21754
21855
|
#recordPath(hostThreadId) {
|
|
21755
|
-
return
|
|
21856
|
+
return path6.join(this.#threadsDirectory, `${hostThreadId}.json`);
|
|
21756
21857
|
}
|
|
21757
21858
|
#delegationPath(delegationId) {
|
|
21758
|
-
return
|
|
21859
|
+
return path6.join(this.#delegationsDirectory, `${delegationId}.json`);
|
|
21759
21860
|
}
|
|
21760
21861
|
#backupPath(hostThreadId) {
|
|
21761
|
-
return
|
|
21862
|
+
return path6.join(this.#backupsDirectory, `${hostThreadId}.json`);
|
|
21762
21863
|
}
|
|
21763
21864
|
#requireInitialized() {
|
|
21764
21865
|
if (!this.#initialized) {
|
|
@@ -22519,8 +22620,8 @@ function projectFileChangeKind(kind) {
|
|
|
22519
22620
|
return { type: kind };
|
|
22520
22621
|
}
|
|
22521
22622
|
function projectFileChanges(changes) {
|
|
22522
|
-
return changes.map(({ path:
|
|
22523
|
-
path:
|
|
22623
|
+
return changes.map(({ path: path27, kind, unifiedDiff }) => ({
|
|
22624
|
+
path: path27,
|
|
22524
22625
|
kind: projectFileChangeKind(kind),
|
|
22525
22626
|
diff: unifiedDiff
|
|
22526
22627
|
}));
|
|
@@ -22843,9 +22944,9 @@ function projectHistoricalTurn(input) {
|
|
|
22843
22944
|
return [];
|
|
22844
22945
|
}
|
|
22845
22946
|
return item.type === "reasoning" ? [
|
|
22846
|
-
projectItem(item, outcome, cwd, true, ""),
|
|
22947
|
+
projectItem(item, outcome, cwd, true, input.threadId ?? ""),
|
|
22847
22948
|
projectReasoningTranscriptItem(item, outcome, cwd, item.durationMs ?? null)
|
|
22848
|
-
] : [projectItem(item, outcome, cwd, true, "")];
|
|
22949
|
+
] : [projectItem(item, outcome, cwd, true, input.threadId ?? "")];
|
|
22849
22950
|
})
|
|
22850
22951
|
],
|
|
22851
22952
|
error: error51,
|
|
@@ -23478,13 +23579,13 @@ function decodeThreadForkRequest(request) {
|
|
|
23478
23579
|
if (runtimeWorkspaceRoots !== void 0 && runtimeWorkspaceRoots !== null && (!Array.isArray(runtimeWorkspaceRoots) || runtimeWorkspaceRoots.some((root) => typeof root !== "string" || root.length === 0))) {
|
|
23479
23580
|
throw new Error("thread/fork params.runtimeWorkspaceRoots must be text paths or null");
|
|
23480
23581
|
}
|
|
23481
|
-
const
|
|
23582
|
+
const path27 = optionalText(params, "path", { allowEmpty: true });
|
|
23482
23583
|
const ephemeral = optionalBoolean(params, "ephemeral");
|
|
23483
23584
|
return {
|
|
23484
23585
|
threadId: threadId3,
|
|
23485
23586
|
...lastTurnText ? { lastTurnId: hostTurnIdSchema.parse(lastTurnText) } : {},
|
|
23486
23587
|
...beforeTurnText ? { beforeTurnId: hostTurnIdSchema.parse(beforeTurnText) } : {},
|
|
23487
|
-
...
|
|
23588
|
+
...path27 ? { path: path27 } : {},
|
|
23488
23589
|
...optionalField(params, "model"),
|
|
23489
23590
|
...optionalField(params, "modelProvider"),
|
|
23490
23591
|
...optionalField(params, "cwd"),
|
|
@@ -24495,18 +24596,149 @@ async function inspectHarnessAccounts(adapters, descriptors, timeoutMs = 12e3) {
|
|
|
24495
24596
|
}
|
|
24496
24597
|
|
|
24497
24598
|
// packages/host-runtime/src/app-server-host.ts
|
|
24498
|
-
import { createHash as
|
|
24599
|
+
import { createHash as createHash6, randomUUID as randomUUID9 } from "node:crypto";
|
|
24499
24600
|
import { rm as rm4 } from "node:fs/promises";
|
|
24500
24601
|
import os2 from "node:os";
|
|
24501
|
-
import
|
|
24602
|
+
import path13 from "node:path";
|
|
24502
24603
|
|
|
24503
24604
|
// packages/host-runtime/src/external-thread-fork.ts
|
|
24504
24605
|
import nodePath from "node:path";
|
|
24505
24606
|
|
|
24506
24607
|
// packages/host-runtime/src/external-thread-repository.ts
|
|
24507
|
-
import { randomUUID as
|
|
24608
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
24508
24609
|
import os from "node:os";
|
|
24509
|
-
import
|
|
24610
|
+
import path7 from "node:path";
|
|
24611
|
+
|
|
24612
|
+
// packages/host-runtime/src/external-subagent-threads.ts
|
|
24613
|
+
import { createHash as createHash3, randomUUID as randomUUID3 } from "node:crypto";
|
|
24614
|
+
function childCreateRequest(parent, nativeRef, id2) {
|
|
24615
|
+
const key = createHash3("sha256").update(JSON.stringify([parent.hostThreadId, parent.harnessId, nativeRef.nativeSessionId, id2])).digest("hex");
|
|
24616
|
+
return `subagent:${key}`;
|
|
24617
|
+
}
|
|
24618
|
+
function subagentMaterializer(store, parent, previousParent) {
|
|
24619
|
+
if (previousParent && (previousParent.hostThreadId !== parent.hostThreadId || previousParent.harnessId !== parent.harnessId)) {
|
|
24620
|
+
throw new Error("Subagent Session replacement must stay in the same Host Thread");
|
|
24621
|
+
}
|
|
24622
|
+
const previousRef = previousParent?.nativeSessionRef;
|
|
24623
|
+
let legacy;
|
|
24624
|
+
const legacyRecords = () => legacy ??= store.listThreads().then((records) => {
|
|
24625
|
+
const byRequest = /* @__PURE__ */ new Map();
|
|
24626
|
+
const children = /* @__PURE__ */ new Map();
|
|
24627
|
+
for (const record3 of records) {
|
|
24628
|
+
if (!record3.subagent || record3.harnessId !== parent.harnessId || !record3.nativeSessionRef)
|
|
24629
|
+
continue;
|
|
24630
|
+
const owner = {
|
|
24631
|
+
hostThreadId: record3.subagent.parentHostThreadId,
|
|
24632
|
+
harnessId: record3.harnessId
|
|
24633
|
+
};
|
|
24634
|
+
const key = childCreateRequest(
|
|
24635
|
+
owner,
|
|
24636
|
+
record3.nativeSessionRef,
|
|
24637
|
+
record3.subagent.nativeSubagentId
|
|
24638
|
+
);
|
|
24639
|
+
if (!byRequest.has(key) || record3.state === "ready") byRequest.set(key, record3);
|
|
24640
|
+
const siblings = children.get(owner.hostThreadId) ?? [];
|
|
24641
|
+
siblings.push(record3);
|
|
24642
|
+
children.set(owner.hostThreadId, siblings);
|
|
24643
|
+
}
|
|
24644
|
+
return { byRequest, children };
|
|
24645
|
+
});
|
|
24646
|
+
const rebind = async (existing, owner, visited = /* @__PURE__ */ new Set()) => {
|
|
24647
|
+
if (!previousRef || !owner.nativeSessionRef || !existing.subagent || visited.has(existing.hostThreadId)) {
|
|
24648
|
+
throw new Error("Invalid retained Subagent Session tree");
|
|
24649
|
+
}
|
|
24650
|
+
visited.add(existing.hostThreadId);
|
|
24651
|
+
const rebound = await store.rebindSubagentSession({
|
|
24652
|
+
hostThreadId: existing.hostThreadId,
|
|
24653
|
+
parentHostThreadId: owner.hostThreadId,
|
|
24654
|
+
previousNativeSessionRef: previousRef,
|
|
24655
|
+
nativeSessionRef: owner.nativeSessionRef,
|
|
24656
|
+
createRequestId: childCreateRequest(
|
|
24657
|
+
owner,
|
|
24658
|
+
owner.nativeSessionRef,
|
|
24659
|
+
existing.subagent.nativeSubagentId
|
|
24660
|
+
)
|
|
24661
|
+
});
|
|
24662
|
+
for (const descendant of (await legacyRecords()).children.get(existing.hostThreadId) ?? []) {
|
|
24663
|
+
if (descendant.state === "ready" && descendant.nativeSessionRef?.nativeSessionId === previousRef.nativeSessionId) {
|
|
24664
|
+
await rebind(descendant, rebound, visited);
|
|
24665
|
+
}
|
|
24666
|
+
}
|
|
24667
|
+
return rebound;
|
|
24668
|
+
};
|
|
24669
|
+
return async (child) => {
|
|
24670
|
+
if (!child.nativeSubagentId || !parent.nativeSessionRef || parent.state !== "ready")
|
|
24671
|
+
return null;
|
|
24672
|
+
const nativeRef = parent.nativeSessionRef;
|
|
24673
|
+
const createRequestId = childCreateRequest(parent, nativeRef, child.nativeSubagentId);
|
|
24674
|
+
const previousRequest = previousRef && previousRef.nativeSessionId !== nativeRef.nativeSessionId ? childCreateRequest(parent, previousRef, child.nativeSubagentId) : void 0;
|
|
24675
|
+
let existing = await store.getThreadByCreateRequest(createRequestId);
|
|
24676
|
+
if (!existing && previousRequest)
|
|
24677
|
+
existing = await store.getThreadByCreateRequest(previousRequest);
|
|
24678
|
+
if (!existing) {
|
|
24679
|
+
const { byRequest } = await legacyRecords();
|
|
24680
|
+
existing = byRequest.get(createRequestId) ?? (previousRequest ? byRequest.get(previousRequest) : void 0) ?? null;
|
|
24681
|
+
}
|
|
24682
|
+
if (existing?.state === "ready") {
|
|
24683
|
+
if (existing.nativeSessionRef?.nativeSessionId === nativeRef.nativeSessionId) return existing;
|
|
24684
|
+
if (!previousRef) throw new Error("Subagent belongs to a different Native Session");
|
|
24685
|
+
return rebind(existing, parent);
|
|
24686
|
+
}
|
|
24687
|
+
const provisional = existing ?? await store.createProvisional({
|
|
24688
|
+
hostThreadId: hostThreadIdSchema.parse(randomUUID3()),
|
|
24689
|
+
createRequestId,
|
|
24690
|
+
harnessId: parent.harnessId,
|
|
24691
|
+
cwd: parent.cwd,
|
|
24692
|
+
title: child.description,
|
|
24693
|
+
transportModelId: parent.transportModelId,
|
|
24694
|
+
ephemeral: parent.ephemeral,
|
|
24695
|
+
historyMode: "paginated",
|
|
24696
|
+
subagent: {
|
|
24697
|
+
parentHostThreadId: parent.hostThreadId,
|
|
24698
|
+
nativeSubagentId: child.nativeSubagentId,
|
|
24699
|
+
...child.role ? { role: child.role } : {}
|
|
24700
|
+
}
|
|
24701
|
+
});
|
|
24702
|
+
return provisional.state === "ready" ? provisional : store.commitReady({
|
|
24703
|
+
hostThreadId: provisional.hostThreadId,
|
|
24704
|
+
nativeSessionRef: nativeRef
|
|
24705
|
+
});
|
|
24706
|
+
};
|
|
24707
|
+
}
|
|
24708
|
+
async function materializeExternalSubagent(store, parent, child) {
|
|
24709
|
+
return subagentMaterializer(store, parent)(child);
|
|
24710
|
+
}
|
|
24711
|
+
async function projectExternalSnapshot(store, record3, snapshot, previousParent) {
|
|
24712
|
+
const materialize = subagentMaterializer(store, record3, previousParent);
|
|
24713
|
+
const turns = [];
|
|
24714
|
+
for (const [index, turn] of snapshot.turns.entries()) {
|
|
24715
|
+
const mapping = record3.turnMappings[index];
|
|
24716
|
+
if (!mapping) throw new Error("External Snapshot mapping is incomplete");
|
|
24717
|
+
const items = await Promise.all(
|
|
24718
|
+
turn.items.map(async (entry) => {
|
|
24719
|
+
if (entry.item.type !== "subagentDelegation") return entry;
|
|
24720
|
+
const subagents = await Promise.all(
|
|
24721
|
+
entry.item.subagents.map(async (child) => {
|
|
24722
|
+
const stored = await materialize(child);
|
|
24723
|
+
return stored ? { ...child, subagentId: stored.hostThreadId } : child;
|
|
24724
|
+
})
|
|
24725
|
+
);
|
|
24726
|
+
return { ...entry, item: { ...entry.item, subagents } };
|
|
24727
|
+
})
|
|
24728
|
+
);
|
|
24729
|
+
turns.push(
|
|
24730
|
+
projectHistoricalTurn({
|
|
24731
|
+
threadId: record3.hostThreadId,
|
|
24732
|
+
turnId: mapping.hostTurnId,
|
|
24733
|
+
cwd: record3.cwd,
|
|
24734
|
+
snapshot: { ...turn, items }
|
|
24735
|
+
})
|
|
24736
|
+
);
|
|
24737
|
+
}
|
|
24738
|
+
return turns;
|
|
24739
|
+
}
|
|
24740
|
+
|
|
24741
|
+
// packages/host-runtime/src/external-thread-repository.ts
|
|
24510
24742
|
function nativeTurnKey2(ref) {
|
|
24511
24743
|
return `${ref.harnessId}\0${ref.nativeSessionId}\0${ref.nativeTurnKey}\0${ref.formatVersion}`;
|
|
24512
24744
|
}
|
|
@@ -24515,8 +24747,8 @@ function sameMapping(left, right) {
|
|
|
24515
24747
|
}
|
|
24516
24748
|
function defaultMappingStoreDirectory(environment) {
|
|
24517
24749
|
const dataDirectory = environment.CODEXHOST_DATA_DIR;
|
|
24518
|
-
return
|
|
24519
|
-
dataDirectory ?
|
|
24750
|
+
return path7.join(
|
|
24751
|
+
dataDirectory ? path7.resolve(dataDirectory) : path7.join(os.homedir(), ".codexhost"),
|
|
24520
24752
|
"mapping-store"
|
|
24521
24753
|
);
|
|
24522
24754
|
}
|
|
@@ -24541,6 +24773,9 @@ var ExternalThreadRepository = class {
|
|
|
24541
24773
|
list() {
|
|
24542
24774
|
return this.store.listThreads();
|
|
24543
24775
|
}
|
|
24776
|
+
materializeSubagent(parent, child) {
|
|
24777
|
+
return materializeExternalSubagent(this.store, parent, child);
|
|
24778
|
+
}
|
|
24544
24779
|
findByCreateRequest(createRequestId) {
|
|
24545
24780
|
return this.store.getThreadByCreateRequest(createRequestId);
|
|
24546
24781
|
}
|
|
@@ -24617,7 +24852,7 @@ var ExternalThreadRepository = class {
|
|
|
24617
24852
|
throw new Error("Derived Snapshot identity does not belong to its Native Session");
|
|
24618
24853
|
}
|
|
24619
24854
|
return {
|
|
24620
|
-
hostTurnId: hostTurnIdSchema.parse(
|
|
24855
|
+
hostTurnId: hostTurnIdSchema.parse(randomUUID4()),
|
|
24621
24856
|
nativeTurnRef: turn.nativeTurnRef,
|
|
24622
24857
|
...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
|
|
24623
24858
|
};
|
|
@@ -24629,15 +24864,7 @@ var ExternalThreadRepository = class {
|
|
|
24629
24864
|
});
|
|
24630
24865
|
return {
|
|
24631
24866
|
record: nextRecord,
|
|
24632
|
-
turns:
|
|
24633
|
-
const mapping = mappings[index];
|
|
24634
|
-
if (!mapping) throw new Error("Derived Snapshot mapping is incomplete");
|
|
24635
|
-
return projectHistoricalTurn({
|
|
24636
|
-
turnId: mapping.hostTurnId,
|
|
24637
|
-
cwd: record3.cwd,
|
|
24638
|
-
snapshot: turn
|
|
24639
|
-
});
|
|
24640
|
-
})
|
|
24867
|
+
turns: await projectExternalSnapshot(this.store, nextRecord, snapshot)
|
|
24641
24868
|
};
|
|
24642
24869
|
}
|
|
24643
24870
|
async commitForkRollback(derived, source, nativeSessionRef, snapshot) {
|
|
@@ -24671,6 +24898,8 @@ var ExternalThreadRepository = class {
|
|
|
24671
24898
|
});
|
|
24672
24899
|
const nextRecord = await this.store.replaceReadySession({
|
|
24673
24900
|
hostThreadId: derived.hostThreadId,
|
|
24901
|
+
expectedRevision: derived.revision,
|
|
24902
|
+
expectedNativeSessionRef: derived.nativeSessionRef,
|
|
24674
24903
|
nativeSessionRef,
|
|
24675
24904
|
turnMappings: mappings,
|
|
24676
24905
|
forkSource: {
|
|
@@ -24680,15 +24909,7 @@ var ExternalThreadRepository = class {
|
|
|
24680
24909
|
});
|
|
24681
24910
|
return {
|
|
24682
24911
|
record: nextRecord,
|
|
24683
|
-
turns:
|
|
24684
|
-
const mapping = mappings[index];
|
|
24685
|
-
if (!mapping) throw new Error("External rollback Snapshot mapping is incomplete");
|
|
24686
|
-
return projectHistoricalTurn({
|
|
24687
|
-
turnId: mapping.hostTurnId,
|
|
24688
|
-
cwd: derived.cwd,
|
|
24689
|
-
snapshot: turn
|
|
24690
|
-
});
|
|
24691
|
-
})
|
|
24912
|
+
turns: await projectExternalSnapshot(this.store, nextRecord, snapshot, derived)
|
|
24692
24913
|
};
|
|
24693
24914
|
}
|
|
24694
24915
|
async commitLastTurnRollback(current, nativeSessionRef, snapshot) {
|
|
@@ -24708,30 +24929,26 @@ var ExternalThreadRepository = class {
|
|
|
24708
24929
|
});
|
|
24709
24930
|
const nextRecord = await this.store.replaceReadySessionAfterLastTurn({
|
|
24710
24931
|
hostThreadId: current.hostThreadId,
|
|
24932
|
+
expectedRevision: current.revision,
|
|
24933
|
+
expectedNativeSessionRef: current.nativeSessionRef,
|
|
24711
24934
|
nativeSessionRef,
|
|
24712
24935
|
turnMappings: mappings
|
|
24713
24936
|
});
|
|
24714
24937
|
return {
|
|
24715
24938
|
record: nextRecord,
|
|
24716
|
-
turns:
|
|
24717
|
-
const mapping = mappings[index];
|
|
24718
|
-
if (!mapping) throw new Error("Last-Turn rollback Snapshot mapping is incomplete");
|
|
24719
|
-
return projectHistoricalTurn({
|
|
24720
|
-
turnId: mapping.hostTurnId,
|
|
24721
|
-
cwd: current.cwd,
|
|
24722
|
-
snapshot: turn
|
|
24723
|
-
});
|
|
24724
|
-
})
|
|
24939
|
+
turns: await projectExternalSnapshot(this.store, nextRecord, snapshot, current)
|
|
24725
24940
|
};
|
|
24726
24941
|
}
|
|
24727
24942
|
async sessionTreeId(record3) {
|
|
24728
24943
|
let current = record3;
|
|
24729
24944
|
const visited = /* @__PURE__ */ new Set();
|
|
24730
|
-
while (current.forkSource) {
|
|
24945
|
+
while (current.subagent || current.forkSource) {
|
|
24731
24946
|
if (visited.has(current.hostThreadId))
|
|
24732
24947
|
throw new Error("External Thread Fork tree contains a cycle");
|
|
24733
24948
|
visited.add(current.hostThreadId);
|
|
24734
|
-
const
|
|
24949
|
+
const parentId = current.subagent?.parentHostThreadId ?? current.forkSource?.hostThreadId;
|
|
24950
|
+
if (!parentId) break;
|
|
24951
|
+
const source = await this.find(parentId);
|
|
24735
24952
|
if (!source) break;
|
|
24736
24953
|
current = source;
|
|
24737
24954
|
}
|
|
@@ -24755,7 +24972,7 @@ var ExternalThreadRepository = class {
|
|
|
24755
24972
|
const aligned = snapshot.turns.map((turn) => {
|
|
24756
24973
|
const existing = mappingsByNative.get(nativeTurnKey2(turn.nativeTurnRef));
|
|
24757
24974
|
const mapping = existing ?? {
|
|
24758
|
-
hostTurnId: hostTurnIdSchema.parse(
|
|
24975
|
+
hostTurnId: hostTurnIdSchema.parse(randomUUID4()),
|
|
24759
24976
|
nativeTurnRef: turn.nativeTurnRef,
|
|
24760
24977
|
...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
|
|
24761
24978
|
};
|
|
@@ -24776,16 +24993,14 @@ var ExternalThreadRepository = class {
|
|
|
24776
24993
|
const nextRecord = mappingsChanged ? await this.store.reconcileTurnMappings(record3.hostThreadId, orderedMappings) : record3;
|
|
24777
24994
|
return {
|
|
24778
24995
|
record: nextRecord,
|
|
24779
|
-
turns:
|
|
24780
|
-
({ mapping, snapshot: turn }) => projectHistoricalTurn({ turnId: mapping.hostTurnId, cwd: record3.cwd, snapshot: turn })
|
|
24781
|
-
)
|
|
24996
|
+
turns: await projectExternalSnapshot(this.store, nextRecord, snapshot)
|
|
24782
24997
|
};
|
|
24783
24998
|
}
|
|
24784
24999
|
};
|
|
24785
25000
|
function createExternalThreadRecordInput(input) {
|
|
24786
25001
|
return {
|
|
24787
|
-
hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(
|
|
24788
|
-
createRequestId: input.createRequestId ??
|
|
25002
|
+
hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(randomUUID4()),
|
|
25003
|
+
createRequestId: input.createRequestId ?? randomUUID4(),
|
|
24789
25004
|
harnessId: input.harnessId,
|
|
24790
25005
|
cwd: input.cwd,
|
|
24791
25006
|
...input.title ? { title: input.title } : {},
|
|
@@ -25463,13 +25678,14 @@ async function restoreCurrentConfiguration(session, configuration) {
|
|
|
25463
25678
|
}
|
|
25464
25679
|
async function executeCurrentLastTurnRollback(input) {
|
|
25465
25680
|
const { current, adapters, repository, runtime } = input;
|
|
25466
|
-
|
|
25681
|
+
const currentRecord = current.record;
|
|
25682
|
+
if (currentRecord.turnMappings.length === 0) {
|
|
25467
25683
|
return {
|
|
25468
25684
|
ok: false,
|
|
25469
25685
|
error: { code: -32076, message: "External Thread has no Turn to roll back" }
|
|
25470
25686
|
};
|
|
25471
25687
|
}
|
|
25472
|
-
const currentNativeRef =
|
|
25688
|
+
const currentNativeRef = currentRecord.nativeSessionRef;
|
|
25473
25689
|
const adapter = adapters.get(current.harnessId);
|
|
25474
25690
|
if (!currentNativeRef || !adapter) {
|
|
25475
25691
|
return {
|
|
@@ -25517,7 +25733,7 @@ async function executeCurrentLastTurnRollback(input) {
|
|
|
25517
25733
|
await session.close().catch(() => void 0);
|
|
25518
25734
|
return { ok: false, error: mapExternalThreadHarnessError(snapshot.error, "read") };
|
|
25519
25735
|
}
|
|
25520
|
-
if (snapshot.value.turns.length !==
|
|
25736
|
+
if (snapshot.value.turns.length !== currentRecord.turnMappings.length - 1) {
|
|
25521
25737
|
await session.close().catch(() => void 0);
|
|
25522
25738
|
return {
|
|
25523
25739
|
ok: false,
|
|
@@ -25535,7 +25751,7 @@ async function executeCurrentLastTurnRollback(input) {
|
|
|
25535
25751
|
let aligned;
|
|
25536
25752
|
try {
|
|
25537
25753
|
aligned = await repository.commitLastTurnRollback(
|
|
25538
|
-
|
|
25754
|
+
currentRecord,
|
|
25539
25755
|
finalNativeRef,
|
|
25540
25756
|
snapshot.value
|
|
25541
25757
|
);
|
|
@@ -25583,7 +25799,8 @@ async function executeExternalThreadRollback(input) {
|
|
|
25583
25799
|
...input.environment ? { environment: input.environment } : {}
|
|
25584
25800
|
});
|
|
25585
25801
|
}
|
|
25586
|
-
const
|
|
25802
|
+
const derivedRecord = derived.record;
|
|
25803
|
+
const forkSource = derivedRecord.forkSource;
|
|
25587
25804
|
if (!forkSource) {
|
|
25588
25805
|
return {
|
|
25589
25806
|
ok: false,
|
|
@@ -25614,10 +25831,11 @@ async function executeExternalThreadRollback(input) {
|
|
|
25614
25831
|
const sourceRefreshError = await runtime.refresh(source);
|
|
25615
25832
|
if (sourceRefreshError) return { ok: false, error: sourceRefreshError };
|
|
25616
25833
|
}
|
|
25617
|
-
const
|
|
25834
|
+
const sourceRecord = source.record;
|
|
25835
|
+
const sourceBoundaryIndex = sourceRecord.turnMappings.findIndex(
|
|
25618
25836
|
({ hostTurnId }) => hostTurnId === forkSource.hostTurnId
|
|
25619
25837
|
);
|
|
25620
|
-
if (sourceBoundaryIndex < 0 ||
|
|
25838
|
+
if (sourceBoundaryIndex < 0 || derivedRecord.turnMappings.length !== sourceBoundaryIndex + 1) {
|
|
25621
25839
|
return {
|
|
25622
25840
|
ok: false,
|
|
25623
25841
|
error: {
|
|
@@ -25626,19 +25844,19 @@ async function executeExternalThreadRollback(input) {
|
|
|
25626
25844
|
}
|
|
25627
25845
|
};
|
|
25628
25846
|
}
|
|
25629
|
-
const excludedActiveTurnCount = source.running ||
|
|
25630
|
-
const retainedCount =
|
|
25631
|
-
if (retainedCount ===
|
|
25847
|
+
const excludedActiveTurnCount = source.running || sourceRecord.turnMappings.length > derivedRecord.turnMappings.length ? 1 : 0;
|
|
25848
|
+
const retainedCount = derivedRecord.turnMappings.length - rollback.numTurns + excludedActiveTurnCount;
|
|
25849
|
+
if (retainedCount === derivedRecord.turnMappings.length) {
|
|
25632
25850
|
return { ok: true, thread: derived.thread };
|
|
25633
25851
|
}
|
|
25634
|
-
const boundary =
|
|
25852
|
+
const boundary = sourceRecord.turnMappings[retainedCount - 1];
|
|
25635
25853
|
if (retainedCount < 1 || !boundary?.nativeCheckpointRef) {
|
|
25636
25854
|
return {
|
|
25637
25855
|
ok: false,
|
|
25638
25856
|
error: { code: -32080, message: "External Fork Checkpoint is unavailable" }
|
|
25639
25857
|
};
|
|
25640
25858
|
}
|
|
25641
|
-
const sourceNativeRef =
|
|
25859
|
+
const sourceNativeRef = sourceRecord.nativeSessionRef;
|
|
25642
25860
|
const adapter = adapters.get(source.harnessId);
|
|
25643
25861
|
if (!sourceNativeRef || !adapter) {
|
|
25644
25862
|
return {
|
|
@@ -25666,7 +25884,7 @@ async function executeExternalThreadRollback(input) {
|
|
|
25666
25884
|
}
|
|
25667
25885
|
const session = opened.value;
|
|
25668
25886
|
const finalNativeRef = session.initialState.nativeRef;
|
|
25669
|
-
if (!finalNativeRef || finalNativeRef.nativeSessionId === sourceNativeRef.nativeSessionId || finalNativeRef.nativeSessionId ===
|
|
25887
|
+
if (!finalNativeRef || finalNativeRef.nativeSessionId === sourceNativeRef.nativeSessionId || finalNativeRef.nativeSessionId === derivedRecord.nativeSessionRef?.nativeSessionId) {
|
|
25670
25888
|
await session.close().catch(() => void 0);
|
|
25671
25889
|
return {
|
|
25672
25890
|
ok: false,
|
|
@@ -25688,8 +25906,8 @@ async function executeExternalThreadRollback(input) {
|
|
|
25688
25906
|
let aligned;
|
|
25689
25907
|
try {
|
|
25690
25908
|
aligned = await repository.commitForkRollback(
|
|
25691
|
-
|
|
25692
|
-
|
|
25909
|
+
derivedRecord,
|
|
25910
|
+
sourceRecord,
|
|
25693
25911
|
finalNativeRef,
|
|
25694
25912
|
snapshot.value
|
|
25695
25913
|
);
|
|
@@ -25934,9 +26152,43 @@ var ExternalThreadRuntime = class {
|
|
|
25934
26152
|
} catch (error51) {
|
|
25935
26153
|
this.#diagnose(error51);
|
|
25936
26154
|
}
|
|
26155
|
+
await this.#retireSubagents(current.id);
|
|
25937
26156
|
this.#threads.delete(current.id);
|
|
25938
26157
|
return this.register(input);
|
|
25939
26158
|
}
|
|
26159
|
+
async #retireSubagents(parentId) {
|
|
26160
|
+
const ancestors = /* @__PURE__ */ new Map();
|
|
26161
|
+
const descendant = async (record3) => {
|
|
26162
|
+
const visited = /* @__PURE__ */ new Set();
|
|
26163
|
+
let ownerId = record3?.subagent?.parentHostThreadId;
|
|
26164
|
+
while (ownerId && !visited.has(ownerId)) {
|
|
26165
|
+
if (ownerId === parentId) return true;
|
|
26166
|
+
visited.add(ownerId);
|
|
26167
|
+
let ancestor = ancestors.get(ownerId);
|
|
26168
|
+
if (!ancestor) {
|
|
26169
|
+
ancestor = this.#repository.find(ownerId);
|
|
26170
|
+
ancestors.set(ownerId, ancestor);
|
|
26171
|
+
}
|
|
26172
|
+
ownerId = (await ancestor)?.subagent?.parentHostThreadId;
|
|
26173
|
+
}
|
|
26174
|
+
return false;
|
|
26175
|
+
};
|
|
26176
|
+
for (const [id2, restoring] of [...this.#restores]) {
|
|
26177
|
+
if (await descendant(await this.#repository.find(id2))) {
|
|
26178
|
+
await restoring.catch(this.#diagnose);
|
|
26179
|
+
}
|
|
26180
|
+
}
|
|
26181
|
+
for (const child of this.#threads.values()) {
|
|
26182
|
+
if (!await descendant(child.record)) continue;
|
|
26183
|
+
this.#threads.delete(child.id);
|
|
26184
|
+
try {
|
|
26185
|
+
await child.session.close();
|
|
26186
|
+
await child.outputTask;
|
|
26187
|
+
} catch (error51) {
|
|
26188
|
+
this.#diagnose(error51);
|
|
26189
|
+
}
|
|
26190
|
+
}
|
|
26191
|
+
}
|
|
25940
26192
|
async locate(threadId3) {
|
|
25941
26193
|
const loaded = this.#threads.get(threadId3);
|
|
25942
26194
|
if (loaded) return { kind: "external", record: loaded.record, thread: loaded };
|
|
@@ -26047,6 +26299,10 @@ var ExternalThreadRuntime = class {
|
|
|
26047
26299
|
nativeSubagentId: subagent.nativeSubagentId,
|
|
26048
26300
|
cwd: record3.cwd
|
|
26049
26301
|
});
|
|
26302
|
+
const latest = await this.#repository.find(record3.hostThreadId);
|
|
26303
|
+
if (latest?.state === "ready" && latest.nativeSessionRef && JSON.stringify(latest.nativeSessionRef) !== JSON.stringify(parent)) {
|
|
26304
|
+
return this.#restore(latest);
|
|
26305
|
+
}
|
|
26050
26306
|
if (!snapshot.ok) {
|
|
26051
26307
|
throw new ExternalThreadOpenError(mapExternalThreadHarnessError(snapshot.error, "read"));
|
|
26052
26308
|
}
|
|
@@ -26323,11 +26579,11 @@ var ExternalTurnSteering = class {
|
|
|
26323
26579
|
};
|
|
26324
26580
|
|
|
26325
26581
|
// packages/host-runtime/src/harness-delegation-coordinator.ts
|
|
26326
|
-
import { createHash as
|
|
26327
|
-
import
|
|
26582
|
+
import { createHash as createHash5, randomUUID as randomUUID5 } from "node:crypto";
|
|
26583
|
+
import path8 from "node:path";
|
|
26328
26584
|
|
|
26329
26585
|
// packages/host-runtime/src/delegation-snapshot.ts
|
|
26330
|
-
import { createHash as
|
|
26586
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
26331
26587
|
var CURSOR_PREFIX = "codexhost:thread-messages:v1:";
|
|
26332
26588
|
var DEFAULT_MESSAGE_LIMIT = 25;
|
|
26333
26589
|
var MAX_MESSAGE_LIMIT = 100;
|
|
@@ -26381,7 +26637,7 @@ function allVisibleMessages(turns) {
|
|
|
26381
26637
|
return messages;
|
|
26382
26638
|
}
|
|
26383
26639
|
function cursorFingerprint(threadId3) {
|
|
26384
|
-
return
|
|
26640
|
+
return createHash4("sha256").update(threadId3).digest("hex");
|
|
26385
26641
|
}
|
|
26386
26642
|
function encodeCursor(threadId3, offset) {
|
|
26387
26643
|
const payload = JSON.stringify({ version: 1, fingerprint: cursorFingerprint(threadId3), offset });
|
|
@@ -26492,10 +26748,10 @@ function terminal(status) {
|
|
|
26492
26748
|
return status === "completed" || status === "failed" || status === "interrupted";
|
|
26493
26749
|
}
|
|
26494
26750
|
function taskDigest(input) {
|
|
26495
|
-
return
|
|
26751
|
+
return createHash5("sha256").update(
|
|
26496
26752
|
JSON.stringify({
|
|
26497
26753
|
task: input.task,
|
|
26498
|
-
cwd:
|
|
26754
|
+
cwd: path8.resolve(input.cwd),
|
|
26499
26755
|
modelId: input.model?.id ?? null,
|
|
26500
26756
|
thinkingOptionId: input.thinkingOptionId ?? null
|
|
26501
26757
|
})
|
|
@@ -26566,7 +26822,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
26566
26822
|
return {
|
|
26567
26823
|
harnessId: input.harnessId,
|
|
26568
26824
|
inspection: await adapter.inspect({
|
|
26569
|
-
...input.cwd ? { cwd:
|
|
26825
|
+
...input.cwd ? { cwd: path8.resolve(input.cwd) } : {},
|
|
26570
26826
|
...input.refresh !== void 0 ? { refresh: input.refresh } : {}
|
|
26571
26827
|
})
|
|
26572
26828
|
};
|
|
@@ -26580,7 +26836,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
26580
26836
|
const result = await this.#startOfficial({ ...input, parentThreadId, cwd: selectedCwd });
|
|
26581
26837
|
return { ...result, parentThreadId, cwd: result.cwd ?? selectedCwd };
|
|
26582
26838
|
}
|
|
26583
|
-
const startInput = { ...input, parentThreadId, cwd:
|
|
26839
|
+
const startInput = { ...input, parentThreadId, cwd: path8.resolve(selectedCwd) };
|
|
26584
26840
|
if (!this.#adapters.has(input.harnessId)) {
|
|
26585
26841
|
throw new DelegationControlError(
|
|
26586
26842
|
"HARNESS_NOT_FOUND",
|
|
@@ -26620,10 +26876,10 @@ var HarnessDelegationCoordinator = class {
|
|
|
26620
26876
|
});
|
|
26621
26877
|
this.#validateConfiguration(inspected.inspection, input.model, input.thinkingOptionId);
|
|
26622
26878
|
}
|
|
26623
|
-
const delegationId = hostThreadIdSchema.parse(
|
|
26624
|
-
const childThreadId = hostThreadIdSchema.parse(
|
|
26625
|
-
const turnId = hostTurnIdSchema.parse(
|
|
26626
|
-
const createRequestId = input.requestId ? `delegation:${input.requestId}` :
|
|
26879
|
+
const delegationId = hostThreadIdSchema.parse(randomUUID5());
|
|
26880
|
+
const childThreadId = hostThreadIdSchema.parse(randomUUID5());
|
|
26881
|
+
const turnId = hostTurnIdSchema.parse(randomUUID5());
|
|
26882
|
+
const createRequestId = input.requestId ? `delegation:${input.requestId}` : randomUUID5();
|
|
26627
26883
|
let record3 = await this.#repository.createProvisional(
|
|
26628
26884
|
createExternalThreadRecordInput({
|
|
26629
26885
|
hostThreadId: childThreadId,
|
|
@@ -26748,7 +27004,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
26748
27004
|
if (thread.running || thread.activeTurnId) {
|
|
26749
27005
|
throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
|
|
26750
27006
|
}
|
|
26751
|
-
const turnId = hostTurnIdSchema.parse(
|
|
27007
|
+
const turnId = hostTurnIdSchema.parse(randomUUID5());
|
|
26752
27008
|
try {
|
|
26753
27009
|
await this.#startExternalTurn(thread, input.message, turnId);
|
|
26754
27010
|
} catch (error51) {
|
|
@@ -26993,7 +27249,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
26993
27249
|
|
|
26994
27250
|
// packages/host-runtime/src/harness-plugin-loader.ts
|
|
26995
27251
|
import { readdir as readdir3, realpath as realpath2 } from "node:fs/promises";
|
|
26996
|
-
import
|
|
27252
|
+
import path10 from "node:path";
|
|
26997
27253
|
import { pathToFileURL } from "node:url";
|
|
26998
27254
|
|
|
26999
27255
|
// packages/host-runtime/src/harness-plugin-registry.ts
|
|
@@ -27031,16 +27287,16 @@ var HarnessPluginRegistry = class {
|
|
|
27031
27287
|
|
|
27032
27288
|
// packages/host-runtime/src/plugin-files.ts
|
|
27033
27289
|
import { open as open4, realpath, stat as stat2 } from "node:fs/promises";
|
|
27034
|
-
import
|
|
27290
|
+
import path9 from "node:path";
|
|
27035
27291
|
function inside(root, candidate) {
|
|
27036
|
-
const relative =
|
|
27037
|
-
return relative !== "" && !
|
|
27292
|
+
const relative = path9.relative(root, candidate);
|
|
27293
|
+
return relative !== "" && !path9.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path9.sep}`);
|
|
27038
27294
|
}
|
|
27039
27295
|
async function pluginResourcePath(root, relative) {
|
|
27040
|
-
if (
|
|
27296
|
+
if (path9.isAbsolute(relative) || !inside(root, path9.resolve(root, relative))) {
|
|
27041
27297
|
throw new Error("Plugin resource escapes its root");
|
|
27042
27298
|
}
|
|
27043
|
-
const resolved = await realpath(
|
|
27299
|
+
const resolved = await realpath(path9.resolve(root, relative));
|
|
27044
27300
|
if (!inside(root, resolved) || !(await stat2(resolved)).isFile()) {
|
|
27045
27301
|
throw new Error("Plugin resource must be a regular file inside its root");
|
|
27046
27302
|
}
|
|
@@ -27185,7 +27441,7 @@ async function loadHarnessPlugins(options2) {
|
|
|
27185
27441
|
const enabledIds = /* @__PURE__ */ new Set();
|
|
27186
27442
|
const roots = /* @__PURE__ */ new Set();
|
|
27187
27443
|
for (const configuredRoot of options2.roots) {
|
|
27188
|
-
if (!
|
|
27444
|
+
if (!path10.isAbsolute(configuredRoot)) {
|
|
27189
27445
|
diagnose({ code: "invalidRoot" });
|
|
27190
27446
|
continue;
|
|
27191
27447
|
}
|
|
@@ -27215,7 +27471,7 @@ async function loadHarnessPlugins(options2) {
|
|
|
27215
27471
|
for (const directory of directories) {
|
|
27216
27472
|
try {
|
|
27217
27473
|
const file2 = await pluginResourcePath(root, `${directory.name}/manifest.json`);
|
|
27218
|
-
const pluginRoot = await realpath2(
|
|
27474
|
+
const pluginRoot = await realpath2(path10.join(root, directory.name));
|
|
27219
27475
|
await pluginResourcePath(pluginRoot, "manifest.json");
|
|
27220
27476
|
const manifest = harnessPluginManifestSchema.parse(
|
|
27221
27477
|
JSON.parse(
|
|
@@ -27362,8 +27618,8 @@ function spawnOfficialAppServerConnection(input) {
|
|
|
27362
27618
|
|
|
27363
27619
|
// packages/host-runtime/src/account/account-repository.ts
|
|
27364
27620
|
import { mkdir as mkdir4, readFile as readFile6, rename as rename3, writeFile as writeFile3 } from "node:fs/promises";
|
|
27365
|
-
import
|
|
27366
|
-
import { randomUUID as
|
|
27621
|
+
import path11 from "node:path";
|
|
27622
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
27367
27623
|
function validateAccountId(accountId) {
|
|
27368
27624
|
if (!/^[A-Za-z0-9._~-]+$/u.test(accountId)) {
|
|
27369
27625
|
throw new Error("Codex Account ID must be non-empty and filename-safe");
|
|
@@ -27381,19 +27637,19 @@ var AccountRepository = class {
|
|
|
27381
27637
|
#mutationTail = Promise.resolve();
|
|
27382
27638
|
#writeTail = Promise.resolve();
|
|
27383
27639
|
constructor(input) {
|
|
27384
|
-
this.#file =
|
|
27640
|
+
this.#file = path11.join(path11.resolve(input.directory), "accounts.json");
|
|
27385
27641
|
this.#defaultAccount = {
|
|
27386
27642
|
...input.defaultAccount,
|
|
27387
27643
|
label: input.defaultAccount.label ?? input.defaultAccount.accountId
|
|
27388
27644
|
};
|
|
27389
27645
|
validateAccountId(this.#defaultAccount.accountId);
|
|
27390
|
-
if (!
|
|
27646
|
+
if (!path11.isAbsolute(this.#defaultAccount.codexHome)) {
|
|
27391
27647
|
throw new Error("Codex Account CODEX_HOME must be absolute");
|
|
27392
27648
|
}
|
|
27393
27649
|
}
|
|
27394
27650
|
async initialize() {
|
|
27395
27651
|
if (this.#initialized) return;
|
|
27396
|
-
await mkdir4(
|
|
27652
|
+
await mkdir4(path11.dirname(this.#file), { recursive: true });
|
|
27397
27653
|
let stored = null;
|
|
27398
27654
|
try {
|
|
27399
27655
|
stored = JSON.parse(await readFile6(this.#file, "utf8"));
|
|
@@ -27461,7 +27717,7 @@ var AccountRepository = class {
|
|
|
27461
27717
|
async upsert(input) {
|
|
27462
27718
|
this.#requireInitialized();
|
|
27463
27719
|
validateAccountId(input.accountId);
|
|
27464
|
-
if (!
|
|
27720
|
+
if (!path11.isAbsolute(input.codexHome))
|
|
27465
27721
|
throw new Error("Codex Account CODEX_HOME must be absolute");
|
|
27466
27722
|
return this.#mutate(async () => {
|
|
27467
27723
|
const previous = this.#accounts.get(input.accountId);
|
|
@@ -27470,7 +27726,7 @@ var AccountRepository = class {
|
|
|
27470
27726
|
const planType = input.planType === null ? void 0 : input.planType ?? previous?.planType;
|
|
27471
27727
|
const account = {
|
|
27472
27728
|
accountId: input.accountId,
|
|
27473
|
-
codexHome:
|
|
27729
|
+
codexHome: path11.normalize(input.codexHome),
|
|
27474
27730
|
...email3 ? { email: email3 } : {},
|
|
27475
27731
|
...planType ? { planType } : {},
|
|
27476
27732
|
label: input.label ?? previous?.label ?? input.accountId,
|
|
@@ -27484,7 +27740,7 @@ var AccountRepository = class {
|
|
|
27484
27740
|
}
|
|
27485
27741
|
#validateAccount(account) {
|
|
27486
27742
|
validateAccountId(account.accountId);
|
|
27487
|
-
if (!
|
|
27743
|
+
if (!path11.isAbsolute(account.codexHome)) throw new Error("Stored CODEX_HOME must be absolute");
|
|
27488
27744
|
if (account.email && (!account.email.includes("@") || account.email.length > 320)) {
|
|
27489
27745
|
throw new Error("Stored Codex Account email is invalid");
|
|
27490
27746
|
}
|
|
@@ -27505,7 +27761,7 @@ var AccountRepository = class {
|
|
|
27505
27761
|
accounts: [...this.#accounts.values()]
|
|
27506
27762
|
};
|
|
27507
27763
|
const operation = this.#writeTail.then(async () => {
|
|
27508
|
-
const temporary = `${this.#file}.${process.pid}.${
|
|
27764
|
+
const temporary = `${this.#file}.${process.pid}.${randomUUID6()}.tmp`;
|
|
27509
27765
|
await writeFile3(temporary, `${JSON.stringify(value2, null, 2)}
|
|
27510
27766
|
`, { mode: 384 });
|
|
27511
27767
|
await rename3(temporary, this.#file);
|
|
@@ -27528,19 +27784,19 @@ function isMissingFile(error51) {
|
|
|
27528
27784
|
|
|
27529
27785
|
// packages/host-runtime/src/account/thread-account-store.ts
|
|
27530
27786
|
import { mkdir as mkdir5, readFile as readFile7, rename as rename4, writeFile as writeFile4 } from "node:fs/promises";
|
|
27531
|
-
import { randomUUID as
|
|
27532
|
-
import
|
|
27787
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
27788
|
+
import path12 from "node:path";
|
|
27533
27789
|
var ThreadAccountStore = class {
|
|
27534
27790
|
#file;
|
|
27535
27791
|
#bindings = /* @__PURE__ */ new Map();
|
|
27536
27792
|
#initialized = false;
|
|
27537
27793
|
#writeTail = Promise.resolve();
|
|
27538
27794
|
constructor(input) {
|
|
27539
|
-
this.#file =
|
|
27795
|
+
this.#file = path12.join(path12.resolve(input.directory), "thread-accounts.json");
|
|
27540
27796
|
}
|
|
27541
27797
|
async initialize() {
|
|
27542
27798
|
if (this.#initialized) return;
|
|
27543
|
-
await mkdir5(
|
|
27799
|
+
await mkdir5(path12.dirname(this.#file), { recursive: true });
|
|
27544
27800
|
try {
|
|
27545
27801
|
const stored = JSON.parse(await readFile7(this.#file, "utf8"));
|
|
27546
27802
|
if (stored.formatVersion !== 1 || !stored.bindings || typeof stored.bindings !== "object") {
|
|
@@ -27599,7 +27855,7 @@ var ThreadAccountStore = class {
|
|
|
27599
27855
|
bindings: Object.fromEntries(this.#bindings)
|
|
27600
27856
|
};
|
|
27601
27857
|
const operation = this.#writeTail.then(async () => {
|
|
27602
|
-
const temporary = `${this.#file}.${process.pid}.${
|
|
27858
|
+
const temporary = `${this.#file}.${process.pid}.${randomUUID7()}.tmp`;
|
|
27603
27859
|
await writeFile4(temporary, `${JSON.stringify(value2, null, 2)}
|
|
27604
27860
|
`, { mode: 384 });
|
|
27605
27861
|
await rename4(temporary, this.#file);
|
|
@@ -27616,7 +27872,7 @@ function isMissingFile2(error51) {
|
|
|
27616
27872
|
import { mkdir as mkdir6 } from "node:fs/promises";
|
|
27617
27873
|
|
|
27618
27874
|
// packages/host-runtime/src/official-request-broker.ts
|
|
27619
|
-
import { randomUUID as
|
|
27875
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
27620
27876
|
var INTERNAL_REQUEST_PREFIX = "codexhost:official:";
|
|
27621
27877
|
var MAX_RETIRED_IDS = 1024;
|
|
27622
27878
|
function isRecord10(value2) {
|
|
@@ -27632,7 +27888,7 @@ var OfficialRequestBroker = class {
|
|
|
27632
27888
|
constructor(input) {
|
|
27633
27889
|
this.#send = input.send;
|
|
27634
27890
|
this.#timeoutMs = input.timeoutMs ?? 3e4;
|
|
27635
|
-
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${
|
|
27891
|
+
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID8()}`);
|
|
27636
27892
|
}
|
|
27637
27893
|
get pendingCount() {
|
|
27638
27894
|
return this.#pending.size;
|
|
@@ -27996,21 +28252,45 @@ function externalAnchor(entry) {
|
|
|
27996
28252
|
if (entry.source !== "external") throw new Error("Expected an External Thread list entry");
|
|
27997
28253
|
return { timestamp: entry.timestamp, threadId: threadId(entry.thread) };
|
|
27998
28254
|
}
|
|
27999
|
-
function includesExternalRecord(record3, query) {
|
|
28255
|
+
function includesExternalRecord(record3, query, byId) {
|
|
28000
28256
|
if (record3.state !== "ready" || !record3.nativeSessionRef) return false;
|
|
28001
|
-
|
|
28257
|
+
let current = record3;
|
|
28258
|
+
const owners = /* @__PURE__ */ new Set();
|
|
28259
|
+
while (current.subagent) {
|
|
28260
|
+
if (owners.has(current.hostThreadId)) return false;
|
|
28261
|
+
owners.add(current.hostThreadId);
|
|
28262
|
+
const parent = byId.get(current.subagent.parentHostThreadId);
|
|
28263
|
+
if (!parent || parent.state !== "ready" || parent.harnessId !== current.harnessId || parent.nativeSessionRef?.nativeSessionId !== current.nativeSessionRef?.nativeSessionId)
|
|
28264
|
+
return false;
|
|
28265
|
+
current = parent;
|
|
28266
|
+
}
|
|
28267
|
+
const sourceKind = record3.subagent ? "subAgentThreadSpawn" : "vscode";
|
|
28268
|
+
const scoped = query.parentThreadId !== null || query.ancestorThreadId !== null;
|
|
28269
|
+
if (record3.subagent && !scoped && !query.sourceKinds?.some((kind) => kind === "subAgent" || kind === "subAgentThreadSpawn"))
|
|
28270
|
+
return false;
|
|
28271
|
+
if (query.parentThreadId !== null && record3.subagent?.parentHostThreadId !== query.parentThreadId)
|
|
28272
|
+
return false;
|
|
28273
|
+
if (query.ancestorThreadId !== null) {
|
|
28274
|
+
let parentId = record3.subagent?.parentHostThreadId;
|
|
28275
|
+
const visited = /* @__PURE__ */ new Set([record3.hostThreadId]);
|
|
28276
|
+
while (parentId && parentId !== query.ancestorThreadId && !visited.has(parentId)) {
|
|
28277
|
+
visited.add(parentId);
|
|
28278
|
+
parentId = byId.get(parentId)?.subagent?.parentHostThreadId;
|
|
28279
|
+
}
|
|
28280
|
+
if (record3.hostThreadId === query.ancestorThreadId || parentId !== query.ancestorThreadId)
|
|
28281
|
+
return false;
|
|
28282
|
+
}
|
|
28002
28283
|
if (record3.archived !== query.archived) return false;
|
|
28003
28284
|
if (query.cwd !== null && !query.cwd.includes(record3.cwd)) return false;
|
|
28004
28285
|
if (query.modelProviders !== null && query.modelProviders.length > 0 && !query.modelProviders.includes("codexhost")) {
|
|
28005
28286
|
return false;
|
|
28006
28287
|
}
|
|
28007
|
-
if (query.sourceKinds !== null && query.sourceKinds.length > 0 && !query.sourceKinds.includes("
|
|
28288
|
+
if (query.sourceKinds !== null && query.sourceKinds.length > 0 && !query.sourceKinds.includes(sourceKind) && !(record3.subagent && query.sourceKinds.includes("subAgent"))) {
|
|
28008
28289
|
return false;
|
|
28009
28290
|
}
|
|
28010
28291
|
if (query.searchTerm !== null && !record3.title.toLowerCase().includes(query.searchTerm.toLowerCase())) {
|
|
28011
28292
|
return false;
|
|
28012
28293
|
}
|
|
28013
|
-
if (query.parentThreadId !== null || query.ancestorThreadId !== null) return false;
|
|
28014
28294
|
if (query.isPinned !== null && record3.isPinned !== query.isPinned) return false;
|
|
28015
28295
|
return true;
|
|
28016
28296
|
}
|
|
@@ -28020,25 +28300,25 @@ function resolveExternalSessionTreeIds(records) {
|
|
|
28020
28300
|
const resolve = (start) => {
|
|
28021
28301
|
const cached2 = resolved.get(start.hostThreadId);
|
|
28022
28302
|
if (cached2) return cached2;
|
|
28023
|
-
const
|
|
28303
|
+
const path27 = [];
|
|
28024
28304
|
const visited = /* @__PURE__ */ new Set();
|
|
28025
28305
|
let current = start;
|
|
28026
28306
|
while (true) {
|
|
28027
28307
|
const known = resolved.get(current.hostThreadId);
|
|
28028
28308
|
if (known) {
|
|
28029
|
-
for (const record3 of
|
|
28309
|
+
for (const record3 of path27) resolved.set(record3.hostThreadId, known);
|
|
28030
28310
|
return known;
|
|
28031
28311
|
}
|
|
28032
28312
|
if (visited.has(current.hostThreadId)) {
|
|
28033
28313
|
throw new Error("External Thread Fork tree contains a cycle");
|
|
28034
28314
|
}
|
|
28035
28315
|
visited.add(current.hostThreadId);
|
|
28036
|
-
|
|
28037
|
-
const sourceId = current.forkSource?.hostThreadId;
|
|
28316
|
+
path27.push(current);
|
|
28317
|
+
const sourceId = current.subagent?.parentHostThreadId ?? current.forkSource?.hostThreadId;
|
|
28038
28318
|
const source = sourceId ? byId.get(sourceId) : void 0;
|
|
28039
28319
|
if (!source) {
|
|
28040
28320
|
const root = current.hostThreadId;
|
|
28041
|
-
for (const record3 of
|
|
28321
|
+
for (const record3 of path27) resolved.set(record3.hostThreadId, root);
|
|
28042
28322
|
return root;
|
|
28043
28323
|
}
|
|
28044
28324
|
current = source;
|
|
@@ -28050,7 +28330,8 @@ function resolveExternalSessionTreeIds(records) {
|
|
|
28050
28330
|
function listExternalThreadMetadata(input) {
|
|
28051
28331
|
if (!input.query.supportsExternal) return { data: [], hasMore: false };
|
|
28052
28332
|
const sessionIds = resolveExternalSessionTreeIds(input.records);
|
|
28053
|
-
const
|
|
28333
|
+
const byId = new Map(input.records.map((record3) => [record3.hostThreadId, record3]));
|
|
28334
|
+
const entries = input.records.filter((record3) => includesExternalRecord(record3, input.query, byId)).map((record3) => {
|
|
28054
28335
|
const runtime = input.runtimeFor(record3.hostThreadId);
|
|
28055
28336
|
const sessionId = sessionIds.get(record3.hostThreadId);
|
|
28056
28337
|
if (!sessionId) throw new Error("External Thread Session tree could not be resolved");
|
|
@@ -28132,6 +28413,7 @@ function threadId2(entry) {
|
|
|
28132
28413
|
return entry.thread.id;
|
|
28133
28414
|
}
|
|
28134
28415
|
async function aggregateOfficialAccountThreadListPage(input) {
|
|
28416
|
+
const pageLimit = typeof input.params.limit === "number" ? input.params.limit : input.query.limit;
|
|
28135
28417
|
const cursorValue2 = typeof input.params.cursor === "string" ? input.params.cursor : null;
|
|
28136
28418
|
const cursor = cursorValue2 ? decodeCursor2(cursorValue2) : { accounts: initialAccounts(input.accountIds) };
|
|
28137
28419
|
const sources = Object.entries(cursor.accounts).map(([accountId, state]) => ({
|
|
@@ -28168,7 +28450,7 @@ async function aggregateOfficialAccountThreadListPage(input) {
|
|
|
28168
28450
|
if (source.done) return null;
|
|
28169
28451
|
}
|
|
28170
28452
|
source.batchStart = source.cursor;
|
|
28171
|
-
const page = await request(source, source.cursor, Math.max(1,
|
|
28453
|
+
const page = await request(source, source.cursor, Math.max(1, pageLimit));
|
|
28172
28454
|
if (!source.requestedThisPage) {
|
|
28173
28455
|
source.backwardsCursor = page.backwardsCursor;
|
|
28174
28456
|
source.requestedThisPage = true;
|
|
@@ -28190,7 +28472,7 @@ async function aggregateOfficialAccountThreadListPage(input) {
|
|
|
28190
28472
|
};
|
|
28191
28473
|
const output = [];
|
|
28192
28474
|
const emitted = /* @__PURE__ */ new Set();
|
|
28193
|
-
while (output.length <
|
|
28475
|
+
while (output.length < pageLimit) {
|
|
28194
28476
|
const candidates = await Promise.all(
|
|
28195
28477
|
sources.map(async (source) => ({ source, entry: await ensure(source) }))
|
|
28196
28478
|
);
|
|
@@ -28728,18 +29010,18 @@ var AppServerHost = class {
|
|
|
28728
29010
|
};
|
|
28729
29011
|
this.#writer = new OrderedWriter(this.#options.desktopOutput);
|
|
28730
29012
|
const environment = this.#options.environment ?? process.env;
|
|
28731
|
-
const dataDirectory =
|
|
28732
|
-
environment.CODEXHOST_DATA_DIR ??
|
|
29013
|
+
const dataDirectory = path13.resolve(
|
|
29014
|
+
environment.CODEXHOST_DATA_DIR ?? path13.join(os2.homedir(), ".codexhost")
|
|
28733
29015
|
);
|
|
28734
29016
|
const accountRepository = options2.accountRepository ?? new AccountRepository({
|
|
28735
|
-
directory:
|
|
29017
|
+
directory: path13.join(dataDirectory, "codex-accounts"),
|
|
28736
29018
|
defaultAccount: {
|
|
28737
29019
|
accountId: "default",
|
|
28738
|
-
codexHome:
|
|
29020
|
+
codexHome: path13.resolve(environment.CODEX_HOME ?? path13.join(os2.homedir(), ".codex")),
|
|
28739
29021
|
label: "Default Codex Account"
|
|
28740
29022
|
}
|
|
28741
29023
|
});
|
|
28742
|
-
const threadAccountStore = options2.threadAccountStore ?? new ThreadAccountStore({ directory:
|
|
29024
|
+
const threadAccountStore = options2.threadAccountStore ?? new ThreadAccountStore({ directory: path13.join(dataDirectory, "codex-accounts") });
|
|
28743
29025
|
this.#accountRepository = accountRepository;
|
|
28744
29026
|
this.#threadAccountStore = threadAccountStore;
|
|
28745
29027
|
this.#accountDataDirectory = dataDirectory;
|
|
@@ -29572,7 +29854,7 @@ var AppServerHost = class {
|
|
|
29572
29854
|
throw new Error("Unknown Codex Account");
|
|
29573
29855
|
const runtime = await this.#codexRuntimePool.get(params2.accountId);
|
|
29574
29856
|
const response2 = await runtime.request("account/rateLimitResetCredit/consume", {
|
|
29575
|
-
idempotencyKey: params2.idempotencyKey ??
|
|
29857
|
+
idempotencyKey: params2.idempotencyKey ?? randomUUID9()
|
|
29576
29858
|
});
|
|
29577
29859
|
if (isRecord13(response2.error)) {
|
|
29578
29860
|
await this.#writer.json(rpcEnvelope(request, { error: response2.error }));
|
|
@@ -29613,10 +29895,10 @@ var AppServerHost = class {
|
|
|
29613
29895
|
}
|
|
29614
29896
|
if (request.method === "codexhost/account/create") {
|
|
29615
29897
|
const params2 = codexAccountCreateParamsSchema.parse(requestObject(request));
|
|
29616
|
-
const accountId =
|
|
29898
|
+
const accountId = randomUUID9();
|
|
29617
29899
|
const account = await this.#accountRepository.upsert({
|
|
29618
29900
|
accountId,
|
|
29619
|
-
codexHome:
|
|
29901
|
+
codexHome: path13.join(this.#accountDataDirectory, "codex-homes", accountId),
|
|
29620
29902
|
label: params2.label ?? `Codex Account ${accountId.slice(0, 8)}`
|
|
29621
29903
|
});
|
|
29622
29904
|
const activeAccountId = await this.#accountRepository.getActiveAccountId();
|
|
@@ -29656,12 +29938,12 @@ var AppServerHost = class {
|
|
|
29656
29938
|
for (const [key, session2] of this.#officialLoginSessions) {
|
|
29657
29939
|
if (session2.accountId === params2.accountId) this.#officialLoginSessions.delete(key);
|
|
29658
29940
|
}
|
|
29659
|
-
const managedCodexHome =
|
|
29941
|
+
const managedCodexHome = path13.join(
|
|
29660
29942
|
this.#accountDataDirectory,
|
|
29661
29943
|
"codex-homes",
|
|
29662
29944
|
params2.accountId
|
|
29663
29945
|
);
|
|
29664
|
-
if (
|
|
29946
|
+
if (path13.resolve(account.codexHome) === path13.resolve(managedCodexHome)) {
|
|
29665
29947
|
try {
|
|
29666
29948
|
await rm4(managedCodexHome, { recursive: true, force: true });
|
|
29667
29949
|
} catch (error51) {
|
|
@@ -29900,7 +30182,7 @@ var AppServerHost = class {
|
|
|
29900
30182
|
throw new DelegationControlError("INVALID_ARGUMENT", "Official Model Ref is invalid");
|
|
29901
30183
|
}
|
|
29902
30184
|
const nativeModelId = requestedModel ? decodeOfficialCodexModelRef(requestedModel) : void 0;
|
|
29903
|
-
const digest2 =
|
|
30185
|
+
const digest2 = createHash6("sha256").update(
|
|
29904
30186
|
JSON.stringify({
|
|
29905
30187
|
task: input.task,
|
|
29906
30188
|
cwd: input.cwd,
|
|
@@ -30003,7 +30285,7 @@ var AppServerHost = class {
|
|
|
30003
30285
|
throw error51;
|
|
30004
30286
|
}
|
|
30005
30287
|
this.#activeOfficialTurns.set(threadId3, turnId);
|
|
30006
|
-
const delegationId = hostThreadIdSchema.parse(
|
|
30288
|
+
const delegationId = hostThreadIdSchema.parse(randomUUID9());
|
|
30007
30289
|
try {
|
|
30008
30290
|
const source = await this.#repository.find(input.parentThreadId);
|
|
30009
30291
|
const pendingTerminal = this.#pendingOfficialTerminalStatuses.get(threadId3);
|
|
@@ -30167,7 +30449,7 @@ var AppServerHost = class {
|
|
|
30167
30449
|
async #listDelegationThreads(input) {
|
|
30168
30450
|
const [sortKey, sortDirection2] = input.sort.split("-");
|
|
30169
30451
|
const request = {
|
|
30170
|
-
id: `codexhost:delegation-list:${
|
|
30452
|
+
id: `codexhost:delegation-list:${randomUUID9()}`,
|
|
30171
30453
|
method: "thread/list",
|
|
30172
30454
|
params: {
|
|
30173
30455
|
cwd: input.cwd ? [input.cwd] : null,
|
|
@@ -30230,6 +30512,8 @@ var AppServerHost = class {
|
|
|
30230
30512
|
records,
|
|
30231
30513
|
runtimeFor: (threadId3) => {
|
|
30232
30514
|
const thread = this.#externalRuntime.get(threadId3);
|
|
30515
|
+
const subagentStatus = this.#subagentThreadStatuses.get(threadId3);
|
|
30516
|
+
if (subagentStatus) return { running: subagentStatus === "active" };
|
|
30233
30517
|
return thread ? { running: thread.running } : null;
|
|
30234
30518
|
},
|
|
30235
30519
|
requestOfficialPage: (params) => aggregateOfficialAccountThreadListPage({
|
|
@@ -30681,7 +30965,7 @@ var AppServerHost = class {
|
|
|
30681
30965
|
);
|
|
30682
30966
|
return;
|
|
30683
30967
|
}
|
|
30684
|
-
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(
|
|
30968
|
+
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID9());
|
|
30685
30969
|
const projection = {
|
|
30686
30970
|
projector: new CodexTurnProjector({
|
|
30687
30971
|
threadId: thread.id,
|
|
@@ -31540,7 +31824,7 @@ var AppServerHost = class {
|
|
|
31540
31824
|
if (thread.running || thread.activeTurnId || this.#pendingExternalCommandRequests.has(thread.id)) {
|
|
31541
31825
|
throw new ExternalSteerError(-32072, "External Thread already has an active Turn");
|
|
31542
31826
|
}
|
|
31543
|
-
const turnId = hostTurnIdSchema.parse(
|
|
31827
|
+
const turnId = hostTurnIdSchema.parse(randomUUID9());
|
|
31544
31828
|
const startedAtMs = Date.now();
|
|
31545
31829
|
const projection = {
|
|
31546
31830
|
projector: new CodexTurnProjector({
|
|
@@ -31800,7 +32084,7 @@ var AppServerHost = class {
|
|
|
31800
32084
|
if (event.type === "subagent.transcript.changed") {
|
|
31801
32085
|
const nativeSubagentId = event.nativeSubagentId;
|
|
31802
32086
|
const record3 = (await this.#repository.list()).find(
|
|
31803
|
-
(candidate) => candidate.subagent?.parentHostThreadId === thread.id && candidate.subagent.nativeSubagentId === nativeSubagentId
|
|
32087
|
+
(candidate) => candidate.subagent?.parentHostThreadId === thread.id && candidate.subagent.nativeSubagentId === nativeSubagentId && candidate.nativeSessionRef?.nativeSessionId === thread.record.nativeSessionRef?.nativeSessionId
|
|
31804
32088
|
);
|
|
31805
32089
|
if (record3) await this.#refreshOpenSubagentThread(record3.hostThreadId, false);
|
|
31806
32090
|
return;
|
|
@@ -31808,7 +32092,7 @@ var AppServerHost = class {
|
|
|
31808
32092
|
if (event.type === "subagent.state.changed") {
|
|
31809
32093
|
const nativeSubagentId = event.nativeSubagentId;
|
|
31810
32094
|
const record3 = (await this.#repository.list()).find(
|
|
31811
|
-
(candidate) => candidate.subagent?.parentHostThreadId === thread.id && candidate.subagent.nativeSubagentId === nativeSubagentId
|
|
32095
|
+
(candidate) => candidate.subagent?.parentHostThreadId === thread.id && candidate.subagent.nativeSubagentId === nativeSubagentId && candidate.nativeSessionRef?.nativeSessionId === thread.record.nativeSessionRef?.nativeSessionId
|
|
31812
32096
|
);
|
|
31813
32097
|
if (!record3) return;
|
|
31814
32098
|
const status = event.status === "pending" || event.status === "running" ? "active" : "idle";
|
|
@@ -31914,33 +32198,13 @@ var AppServerHost = class {
|
|
|
31914
32198
|
async #materializeSubagent(parent, subagent) {
|
|
31915
32199
|
if (!subagent.nativeSubagentId || !parent.record.nativeSessionRef) return subagent;
|
|
31916
32200
|
const status = subagent.status === "pending" || subagent.status === "running" ? "active" : "idle";
|
|
31917
|
-
const
|
|
31918
|
-
|
|
31919
|
-
|
|
31920
|
-
|
|
31921
|
-
|
|
31922
|
-
|
|
31923
|
-
await this.#setSubagentThreadStatus(existing.hostThreadId, status);
|
|
31924
|
-
return { ...subagent, subagentId: existing.hostThreadId };
|
|
32201
|
+
const record3 = await this.#repository.materializeSubagent(parent.record, subagent);
|
|
32202
|
+
if (!record3) return subagent;
|
|
32203
|
+
if (this.#subagentThreadStatuses.has(record3.hostThreadId)) {
|
|
32204
|
+
this.#trackRunningSubagent(parent.id, record3.hostThreadId, status);
|
|
32205
|
+
await this.#setSubagentThreadStatus(record3.hostThreadId, status);
|
|
32206
|
+
return { ...subagent, subagentId: record3.hostThreadId };
|
|
31925
32207
|
}
|
|
31926
|
-
const recordInput = createExternalThreadRecordInput({
|
|
31927
|
-
harnessId: parent.record.harnessId,
|
|
31928
|
-
cwd: parent.cwd,
|
|
31929
|
-
title: subagent.description,
|
|
31930
|
-
transportModelId: parent.transportModelId,
|
|
31931
|
-
ephemeral: false,
|
|
31932
|
-
historyMode: "paginated",
|
|
31933
|
-
subagent: {
|
|
31934
|
-
parentHostThreadId: parent.id,
|
|
31935
|
-
nativeSubagentId: subagent.nativeSubagentId,
|
|
31936
|
-
...subagent.role ? { role: subagent.role } : {}
|
|
31937
|
-
}
|
|
31938
|
-
});
|
|
31939
|
-
let record3 = await this.#repository.createProvisional(recordInput);
|
|
31940
|
-
record3 = await this.#repository.commitNative(
|
|
31941
|
-
record3.hostThreadId,
|
|
31942
|
-
parent.record.nativeSessionRef
|
|
31943
|
-
);
|
|
31944
32208
|
const thread = externalThreadValue({
|
|
31945
32209
|
record: record3,
|
|
31946
32210
|
turns: [],
|
|
@@ -32186,7 +32450,7 @@ var AppServerHost = class {
|
|
|
32186
32450
|
try {
|
|
32187
32451
|
result = projection.projector.projectQuestion(
|
|
32188
32452
|
interaction,
|
|
32189
|
-
hostItemIdSchema.parse(
|
|
32453
|
+
hostItemIdSchema.parse(randomUUID9())
|
|
32190
32454
|
);
|
|
32191
32455
|
} catch (error51) {
|
|
32192
32456
|
this.#diagnose(error51);
|
|
@@ -32342,7 +32606,7 @@ var AppServerHost = class {
|
|
|
32342
32606
|
};
|
|
32343
32607
|
|
|
32344
32608
|
// packages/host-runtime/src/codex-runtime/account-official-listeners.ts
|
|
32345
|
-
import
|
|
32609
|
+
import path14 from "node:path";
|
|
32346
32610
|
var AccountOfficialListeners = class {
|
|
32347
32611
|
constructor(createListener) {
|
|
32348
32612
|
this.createListener = createListener;
|
|
@@ -32353,7 +32617,7 @@ var AccountOfficialListeners = class {
|
|
|
32353
32617
|
#closed = false;
|
|
32354
32618
|
async endpoint(account) {
|
|
32355
32619
|
if (this.#closed) throw new Error("Account official listeners are closed");
|
|
32356
|
-
const key =
|
|
32620
|
+
const key = path14.resolve(account.codexHome);
|
|
32357
32621
|
const existing = this.#starting.get(key);
|
|
32358
32622
|
if (existing) return existing;
|
|
32359
32623
|
const listener = this.createListener(account);
|
|
@@ -32489,17 +32753,17 @@ var DelegationControlRegistry = class {
|
|
|
32489
32753
|
|
|
32490
32754
|
// packages/host-runtime/src/installed-harness-plugins.ts
|
|
32491
32755
|
import os3 from "node:os";
|
|
32492
|
-
import
|
|
32756
|
+
import path16 from "node:path";
|
|
32493
32757
|
import { fileURLToPath } from "node:url";
|
|
32494
32758
|
|
|
32495
32759
|
// packages/host-runtime/src/launcher-url-opener.ts
|
|
32496
32760
|
import { spawn as spawn3 } from "node:child_process";
|
|
32497
|
-
import
|
|
32761
|
+
import path15 from "node:path";
|
|
32498
32762
|
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "[::1]"]);
|
|
32499
32763
|
var OPEN_TIMEOUT_MS = 1e4;
|
|
32500
32764
|
function createLauncherUrlOpener(environment, spawnLauncher = (command, arguments_2, options2) => spawn3(command, arguments_2, options2)) {
|
|
32501
32765
|
const launcher = environment.CODEXHOST_LAUNCHER_EXECUTABLE;
|
|
32502
|
-
if (!launcher || !
|
|
32766
|
+
if (!launcher || !path15.isAbsolute(launcher)) return void 0;
|
|
32503
32767
|
const launcherEnvironment = Object.fromEntries(
|
|
32504
32768
|
Object.entries(environment).filter(([name]) => {
|
|
32505
32769
|
const normalized = name.toUpperCase();
|
|
@@ -32557,9 +32821,9 @@ function installedHarnessPluginOptions(environment, managedRemoteHost = false, h
|
|
|
32557
32821
|
const opener = managedRemoteHost ? void 0 : createLauncherUrlOpener(environment);
|
|
32558
32822
|
return {
|
|
32559
32823
|
pluginRoots: [
|
|
32560
|
-
|
|
32561
|
-
environment[HARNESS_PLUGIN_DIRECTORY_ENV] ??
|
|
32562
|
-
environment.CODEXHOST_DATA_DIR ?
|
|
32824
|
+
path16.join(path16.dirname(fileURLToPath(hostRuntimeUrl)), "plugins"),
|
|
32825
|
+
environment[HARNESS_PLUGIN_DIRECTORY_ENV] ?? path16.join(
|
|
32826
|
+
environment.CODEXHOST_DATA_DIR ? path16.resolve(environment.CODEXHOST_DATA_DIR) : path16.join(os3.homedir(), ".codexhost"),
|
|
32563
32827
|
"plugins"
|
|
32564
32828
|
)
|
|
32565
32829
|
],
|
|
@@ -32684,12 +32948,12 @@ async function startDelegationControlServer(input) {
|
|
|
32684
32948
|
}
|
|
32685
32949
|
|
|
32686
32950
|
// packages/host-runtime/src/delegation-skill.ts
|
|
32687
|
-
import { createHash as
|
|
32951
|
+
import { createHash as createHash7, randomUUID as randomUUID10 } from "node:crypto";
|
|
32688
32952
|
import { mkdir as mkdir7, open as open5, readFile as readFile8, rename as rename5, rm as rm5, stat as stat3 } from "node:fs/promises";
|
|
32689
32953
|
import os4 from "node:os";
|
|
32690
|
-
import
|
|
32954
|
+
import path17 from "node:path";
|
|
32691
32955
|
var SKILL_VERSION = 7;
|
|
32692
|
-
var SKILL_RELATIVE_PATH =
|
|
32956
|
+
var SKILL_RELATIVE_PATH = path17.join("skills", "codexhost-delegation", "SKILL.md");
|
|
32693
32957
|
var PREVIOUS_MANAGED_DIGESTS = [
|
|
32694
32958
|
"9d2f491850fb0b4084a31ba9b5e4a550b5e833747af322090d8ed0ff80b88c30",
|
|
32695
32959
|
"2bb0aebb9b06febbc6c0c0bcdb0b32506c7cdbf8dc3b734cc6b2a86621270e4e",
|
|
@@ -32745,9 +33009,9 @@ user’s request and the task:
|
|
|
32745
33009
|
Report the result returned by read or a completed wait, together with the target
|
|
32746
33010
|
agent, status, and a labeled task link. Keep internal tracking IDs in tool calls.
|
|
32747
33011
|
`;
|
|
32748
|
-
var CURRENT_DIGEST =
|
|
33012
|
+
var CURRENT_DIGEST = createHash7("sha256").update(CODEXHOST_DELEGATION_SKILL).digest("hex");
|
|
32749
33013
|
function digest(value2) {
|
|
32750
|
-
return
|
|
33014
|
+
return createHash7("sha256").update(value2).digest("hex");
|
|
32751
33015
|
}
|
|
32752
33016
|
function managedVersion(value2) {
|
|
32753
33017
|
const match = /^version:\s*(\d+)\s*$/mu.exec(value2);
|
|
@@ -32762,8 +33026,8 @@ async function readOptional(filePath) {
|
|
|
32762
33026
|
}
|
|
32763
33027
|
}
|
|
32764
33028
|
async function atomicWrite(filePath, content) {
|
|
32765
|
-
await mkdir7(
|
|
32766
|
-
const temporaryPath =
|
|
33029
|
+
await mkdir7(path17.dirname(filePath), { recursive: true, mode: 448 });
|
|
33030
|
+
const temporaryPath = path17.join(path17.dirname(filePath), `.SKILL.md.${randomUUID10()}.tmp`);
|
|
32767
33031
|
const handle = await open5(temporaryPath, "wx", 384);
|
|
32768
33032
|
try {
|
|
32769
33033
|
await handle.writeFile(content, "utf8");
|
|
@@ -32780,8 +33044,8 @@ async function atomicWrite(filePath, content) {
|
|
|
32780
33044
|
async function installDelegationSkills(input = {}) {
|
|
32781
33045
|
const home = input.homeDirectory ?? os4.homedir();
|
|
32782
33046
|
const destinations = [
|
|
32783
|
-
|
|
32784
|
-
|
|
33047
|
+
path17.join(home, ".agents", SKILL_RELATIVE_PATH),
|
|
33048
|
+
path17.join(home, ".claude", SKILL_RELATIVE_PATH)
|
|
32785
33049
|
];
|
|
32786
33050
|
const knownDigests = /* @__PURE__ */ new Set([
|
|
32787
33051
|
CURRENT_DIGEST,
|
|
@@ -32846,9 +33110,9 @@ async function installDelegationSkills(input = {}) {
|
|
|
32846
33110
|
}
|
|
32847
33111
|
|
|
32848
33112
|
// packages/host-runtime/src/remote-control-app-server.ts
|
|
32849
|
-
import { randomUUID as
|
|
33113
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
32850
33114
|
import { mkdir as mkdir8, open as open6, rename as rename6, rm as rm6 } from "node:fs/promises";
|
|
32851
|
-
import
|
|
33115
|
+
import path18 from "node:path";
|
|
32852
33116
|
|
|
32853
33117
|
// packages/host-runtime/src/remote-official-connection.ts
|
|
32854
33118
|
import net from "node:net";
|
|
@@ -33038,30 +33302,30 @@ var BRIDGE_READY_METHOD = "codexhost/remote-control-bridge/ready";
|
|
|
33038
33302
|
function absoluteEnvironmentPath2(environment, name, fallback, platform = process.platform) {
|
|
33039
33303
|
const value2 = environment[name] ?? fallback;
|
|
33040
33304
|
if (!value2) return null;
|
|
33041
|
-
if (
|
|
33042
|
-
return platform === "win32" &&
|
|
33305
|
+
if (path18.isAbsolute(value2)) return path18.normalize(value2);
|
|
33306
|
+
return platform === "win32" && path18.win32.isAbsolute(value2) ? path18.win32.normalize(value2) : null;
|
|
33043
33307
|
}
|
|
33044
33308
|
function nodeCompatibleWindowsPath(value2) {
|
|
33045
33309
|
if (value2.startsWith("\\\\?\\UNC\\")) return `\\\\${value2.slice(8)}`;
|
|
33046
33310
|
if (value2.startsWith("\\\\?\\")) return value2.slice(4);
|
|
33047
33311
|
return value2;
|
|
33048
33312
|
}
|
|
33049
|
-
function remoteControlBridgePipePath(processId = process.pid, instanceId =
|
|
33313
|
+
function remoteControlBridgePipePath(processId = process.pid, instanceId = randomUUID11()) {
|
|
33050
33314
|
const safeInstance = instanceId.replaceAll(/[^a-zA-Z0-9-]/gu, "");
|
|
33051
33315
|
if (!safeInstance) throw new Error("Remote Control bridge instance ID is invalid");
|
|
33052
33316
|
return `\\\\.\\pipe\\codexhost-remote-control-${processId}-${safeInstance}`;
|
|
33053
33317
|
}
|
|
33054
33318
|
function remoteControlBridgeDescriptorPath(environment) {
|
|
33055
33319
|
const root = environment.LOCALAPPDATA;
|
|
33056
|
-
if (!root || !
|
|
33057
|
-
return
|
|
33320
|
+
if (!root || !path18.isAbsolute(root)) return null;
|
|
33321
|
+
return path18.join(path18.normalize(root), "codexhost", REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE);
|
|
33058
33322
|
}
|
|
33059
33323
|
async function publishRemoteControlAppServerDescriptor(plan) {
|
|
33060
|
-
const directory =
|
|
33324
|
+
const directory = path18.dirname(plan.descriptorPath);
|
|
33061
33325
|
await mkdir8(directory, { recursive: true, mode: 448 });
|
|
33062
|
-
const temporaryPath =
|
|
33326
|
+
const temporaryPath = path18.join(
|
|
33063
33327
|
directory,
|
|
33064
|
-
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${
|
|
33328
|
+
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID11()}.tmp`
|
|
33065
33329
|
);
|
|
33066
33330
|
const handle = await open6(temporaryPath, "wx", 384);
|
|
33067
33331
|
try {
|
|
@@ -33152,14 +33416,14 @@ async function runRemoteControlAppServerBridge(input = {}) {
|
|
|
33152
33416
|
import { createServer as createServer2 } from "node:http";
|
|
33153
33417
|
import net2 from "node:net";
|
|
33154
33418
|
import { chmod as chmod3, lstat as lstat6, mkdir as mkdir10, rm as rm8 } from "node:fs/promises";
|
|
33155
|
-
import
|
|
33419
|
+
import path20 from "node:path";
|
|
33156
33420
|
import { PassThrough as PassThrough2 } from "node:stream";
|
|
33157
33421
|
|
|
33158
33422
|
// packages/host-runtime/src/remote-socket-lock.ts
|
|
33159
|
-
import { randomUUID as
|
|
33423
|
+
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
33160
33424
|
import { chmod as chmod2, lstat as lstat5, mkdir as mkdir9, open as open7, readFile as readFile9, readdir as readdir4, rename as rename7, rm as rm7 } from "node:fs/promises";
|
|
33161
33425
|
import { uptime } from "node:os";
|
|
33162
|
-
import
|
|
33426
|
+
import path19 from "node:path";
|
|
33163
33427
|
import { setTimeout as delay4 } from "node:timers/promises";
|
|
33164
33428
|
var LOCK_RETRY_COUNT = 200;
|
|
33165
33429
|
var LOCK_RETRY_DELAY_MS = 25;
|
|
@@ -33233,7 +33497,7 @@ async function readLockEntrySnapshot(filePath) {
|
|
|
33233
33497
|
source,
|
|
33234
33498
|
identity: { dev: metadata.dev, ino: metadata.ino },
|
|
33235
33499
|
mtimeMs: metadata.mtimeMs,
|
|
33236
|
-
record: record3 &&
|
|
33500
|
+
record: record3 && path19.basename(filePath) === lockEntryName(record3.ownerToken) ? record3 : null
|
|
33237
33501
|
};
|
|
33238
33502
|
}
|
|
33239
33503
|
function lockEntryIsAbandoned(snapshot) {
|
|
@@ -33254,7 +33518,7 @@ async function readLockEntryCatalog(lockDirectory) {
|
|
|
33254
33518
|
let unsettled = false;
|
|
33255
33519
|
for (const name of names) {
|
|
33256
33520
|
if (!name.startsWith(LOCK_ENTRY_PREFIX) || !name.endsWith(LOCK_ENTRY_SUFFIX)) continue;
|
|
33257
|
-
const snapshot = await readLockEntrySnapshot(
|
|
33521
|
+
const snapshot = await readLockEntrySnapshot(path19.join(lockDirectory, name));
|
|
33258
33522
|
if (snapshot === null) continue;
|
|
33259
33523
|
if (lockEntryIsAbandoned(snapshot)) {
|
|
33260
33524
|
if (!await removeAbandonedLockEntry(snapshot)) unsettled = true;
|
|
@@ -33282,7 +33546,7 @@ async function preparePrivateLockDirectory(lockDirectory) {
|
|
|
33282
33546
|
await chmod2(lockDirectory, 448);
|
|
33283
33547
|
}
|
|
33284
33548
|
async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
|
|
33285
|
-
const temporary =
|
|
33549
|
+
const temporary = path19.join(lockDirectory, `.tmp-${record3.ownerToken}-${randomUUID12()}`);
|
|
33286
33550
|
const handle = await open7(temporary, "wx", 384);
|
|
33287
33551
|
try {
|
|
33288
33552
|
await handle.writeFile(`${JSON.stringify(record3)}
|
|
@@ -33357,8 +33621,8 @@ async function withRemoteAppServerSocketInitializationLock(socketPath, action) {
|
|
|
33357
33621
|
const legacyPath = `${socketPath}.initializing`;
|
|
33358
33622
|
const lockDirectory = `${socketPath}.initializers`;
|
|
33359
33623
|
await preparePrivateLockDirectory(lockDirectory);
|
|
33360
|
-
const ownerToken =
|
|
33361
|
-
const entryPath =
|
|
33624
|
+
const ownerToken = randomUUID12();
|
|
33625
|
+
const entryPath = path19.join(lockDirectory, lockEntryName(ownerToken));
|
|
33362
33626
|
const baseRecord = {
|
|
33363
33627
|
version: 2,
|
|
33364
33628
|
ownerToken,
|
|
@@ -33532,14 +33796,14 @@ function remoteAppServerSocketPath(environment, listenUrl = "unix://") {
|
|
|
33532
33796
|
throw new Error("Remote app-server listener must use a Unix URL");
|
|
33533
33797
|
}
|
|
33534
33798
|
const explicit = listenUrl.slice("unix://".length);
|
|
33535
|
-
if (explicit.length > 0) return
|
|
33536
|
-
const codexHome = environment.CODEX_HOME ?? (environment.HOME ?
|
|
33799
|
+
if (explicit.length > 0) return path20.posix.resolve(decodeURIComponent(explicit));
|
|
33800
|
+
const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path20.posix.join(environment.HOME, ".codex") : void 0);
|
|
33537
33801
|
if (!codexHome)
|
|
33538
33802
|
throw new Error("CODEX_HOME or HOME is required for the remote app-server socket");
|
|
33539
|
-
return
|
|
33803
|
+
return path20.posix.join(codexHome, "app-server-control", "app-server-control.sock");
|
|
33540
33804
|
}
|
|
33541
33805
|
function officialListenerArgumentsForRemoteListener(arguments_2, socketPath) {
|
|
33542
|
-
if (!
|
|
33806
|
+
if (!path20.posix.isAbsolute(socketPath)) {
|
|
33543
33807
|
throw new Error("Shared official app-server socket path must be absolute");
|
|
33544
33808
|
}
|
|
33545
33809
|
if (remoteUnixListenerUrl(arguments_2) === null) {
|
|
@@ -33650,7 +33914,7 @@ async function removeStaleSocket(socketPath) {
|
|
|
33650
33914
|
await rm8(socketPath, { force: true });
|
|
33651
33915
|
}
|
|
33652
33916
|
async function prepareRemoteAppServerSocketDirectory(socketPath) {
|
|
33653
|
-
const socketDirectory =
|
|
33917
|
+
const socketDirectory = path20.dirname(socketPath);
|
|
33654
33918
|
const existing = await lstat6(socketDirectory).catch((error51) => {
|
|
33655
33919
|
if (error51.code === "ENOENT") return null;
|
|
33656
33920
|
throw error51;
|
|
@@ -33855,20 +34119,20 @@ function createRemoteAppServerWebSocketListener(input) {
|
|
|
33855
34119
|
|
|
33856
34120
|
// packages/host-runtime/src/remote-official-app-server.ts
|
|
33857
34121
|
import { spawn as spawn4 } from "node:child_process";
|
|
33858
|
-
import { randomUUID as
|
|
34122
|
+
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
33859
34123
|
import { lstat as lstat7, rm as rm9 } from "node:fs/promises";
|
|
33860
|
-
import
|
|
34124
|
+
import path21 from "node:path";
|
|
33861
34125
|
var DEFAULT_CLOSE_TIMEOUT_MS = 2e3;
|
|
33862
34126
|
var DEFAULT_LISTEN_TIMEOUT_MS = 1e4;
|
|
33863
|
-
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token =
|
|
33864
|
-
if (!
|
|
34127
|
+
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID13()) {
|
|
34128
|
+
if (!path21.posix.isAbsolute(desktopControlSocketPath)) {
|
|
33865
34129
|
throw new Error("Desktop control socket path must be absolute");
|
|
33866
34130
|
}
|
|
33867
34131
|
if (!/^[A-Za-z0-9-]+$/u.test(token) || !/[A-Za-z0-9]/u.test(token)) {
|
|
33868
34132
|
throw new Error("Shared official app-server socket token is invalid");
|
|
33869
34133
|
}
|
|
33870
34134
|
const compactToken = token.replaceAll("-", "").slice(0, 15);
|
|
33871
|
-
return
|
|
34135
|
+
return path21.posix.join(path21.posix.dirname(desktopControlSocketPath), `.c-${compactToken}.sock`);
|
|
33872
34136
|
}
|
|
33873
34137
|
function errorMessage5(error51) {
|
|
33874
34138
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
@@ -34159,7 +34423,16 @@ function createHostUpdateCoordinator(options2) {
|
|
|
34159
34423
|
});
|
|
34160
34424
|
return contextPromise;
|
|
34161
34425
|
};
|
|
34162
|
-
const fetchLatest = options2.fetchLatest ?? ((signal) =>
|
|
34426
|
+
const fetchLatest = options2.fetchLatest ?? (async (signal) => {
|
|
34427
|
+
const timeoutSignal = AbortSignal.timeout(15e3);
|
|
34428
|
+
const requestSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
34429
|
+
const authenticated = await fetchLatestGitHubReleaseWithGitHubCli({
|
|
34430
|
+
...options2.environment ? { environment: options2.environment } : {},
|
|
34431
|
+
platform,
|
|
34432
|
+
signal: requestSignal
|
|
34433
|
+
});
|
|
34434
|
+
return authenticated ?? fetchLatestGitHubRelease({ signal: requestSignal });
|
|
34435
|
+
});
|
|
34163
34436
|
let candidate = null;
|
|
34164
34437
|
async function latestStatus(context) {
|
|
34165
34438
|
const discovered = await discoverLatestUpdateStatus(context.common.stateDirectory);
|
|
@@ -34335,9 +34608,9 @@ function hasLauncherManagedUpdateRuntime(environment, hostRuntimePath) {
|
|
|
34335
34608
|
if (!environment[UPDATE_RUNTIME_ENV.launcherPid]) return false;
|
|
34336
34609
|
const npmPackageRoot = environment[UPDATE_RUNTIME_ENV.npmPackageRoot];
|
|
34337
34610
|
if (!npmPackageRoot || !hostRuntimePath) return true;
|
|
34338
|
-
if (!
|
|
34339
|
-
const runtimePackageRoot =
|
|
34340
|
-
return
|
|
34611
|
+
if (!path22.isAbsolute(npmPackageRoot) || !path22.isAbsolute(hostRuntimePath)) return false;
|
|
34612
|
+
const runtimePackageRoot = path22.dirname(path22.dirname(path22.normalize(hostRuntimePath)));
|
|
34613
|
+
return path22.relative(path22.normalize(npmPackageRoot), runtimePackageRoot) === "";
|
|
34341
34614
|
}
|
|
34342
34615
|
function requiredRuntimeConfiguration(environment) {
|
|
34343
34616
|
const stockCodexPath = environment[STOCK_CODEX_PATH_ENV];
|
|
@@ -34464,8 +34737,8 @@ async function runHostRuntime(input) {
|
|
|
34464
34737
|
});
|
|
34465
34738
|
try {
|
|
34466
34739
|
await officialListeners.endpoint({
|
|
34467
|
-
codexHome:
|
|
34468
|
-
delegationEnvironment.CODEX_HOME ??
|
|
34740
|
+
codexHome: path22.resolve(
|
|
34741
|
+
delegationEnvironment.CODEX_HOME ?? path22.join(homedir(), ".codex")
|
|
34469
34742
|
)
|
|
34470
34743
|
});
|
|
34471
34744
|
await listener.listen();
|
|
@@ -34566,7 +34839,7 @@ async function runHostRuntime(input) {
|
|
|
34566
34839
|
}
|
|
34567
34840
|
|
|
34568
34841
|
// packages/host-runtime/src/remote-host-install.ts
|
|
34569
|
-
import { createHash as
|
|
34842
|
+
import { createHash as createHash8, randomUUID as randomUUID14 } from "node:crypto";
|
|
34570
34843
|
import { constants as fsConstants } from "node:fs";
|
|
34571
34844
|
import {
|
|
34572
34845
|
access,
|
|
@@ -34581,7 +34854,7 @@ import {
|
|
|
34581
34854
|
stat as stat4,
|
|
34582
34855
|
writeFile as writeFile5
|
|
34583
34856
|
} from "node:fs/promises";
|
|
34584
|
-
import
|
|
34857
|
+
import path23 from "node:path";
|
|
34585
34858
|
var MANIFEST_FORMAT = 1;
|
|
34586
34859
|
var WRAPPER_MARKER = "# codexhost remote SSH wrapper v1";
|
|
34587
34860
|
var PROFILE_START = "# >>> codexhost remote SSH >>>";
|
|
@@ -34592,25 +34865,25 @@ function resolvePaths(options2) {
|
|
|
34592
34865
|
if (!configuredHome) {
|
|
34593
34866
|
throw new Error("A non-root HOME is required for remote Host installation");
|
|
34594
34867
|
}
|
|
34595
|
-
const home =
|
|
34596
|
-
if (!home || home ===
|
|
34868
|
+
const home = path23.resolve(configuredHome);
|
|
34869
|
+
if (!home || home === path23.parse(home).root) {
|
|
34597
34870
|
throw new Error("A non-root HOME is required for remote Host installation");
|
|
34598
34871
|
}
|
|
34599
|
-
const installRoot =
|
|
34600
|
-
const profilePath =
|
|
34601
|
-
options2.profilePath ??
|
|
34872
|
+
const installRoot = path23.resolve(options2.installRoot ?? path23.join(home, ".codexhost", "remote"));
|
|
34873
|
+
const profilePath = path23.resolve(
|
|
34874
|
+
options2.profilePath ?? path23.join(
|
|
34602
34875
|
home,
|
|
34603
|
-
|
|
34876
|
+
path23.basename(environment.SHELL ?? "") === "zsh" ? ".zshenv" : path23.basename(environment.SHELL ?? "") === "bash" ? ".bashrc" : ".profile"
|
|
34604
34877
|
)
|
|
34605
34878
|
);
|
|
34606
|
-
const binDirectory =
|
|
34879
|
+
const binDirectory = path23.join(installRoot, "bin");
|
|
34607
34880
|
return {
|
|
34608
34881
|
home,
|
|
34609
34882
|
installRoot,
|
|
34610
34883
|
binDirectory,
|
|
34611
|
-
wrapperPath:
|
|
34612
|
-
manifestPath:
|
|
34613
|
-
dataDirectory:
|
|
34884
|
+
wrapperPath: path23.join(binDirectory, "codex"),
|
|
34885
|
+
manifestPath: path23.join(installRoot, "manifest.json"),
|
|
34886
|
+
dataDirectory: path23.join(installRoot, "data"),
|
|
34614
34887
|
profilePath
|
|
34615
34888
|
};
|
|
34616
34889
|
}
|
|
@@ -34626,10 +34899,10 @@ async function existingText(filePath) {
|
|
|
34626
34899
|
}
|
|
34627
34900
|
}
|
|
34628
34901
|
async function fileSha256(filePath) {
|
|
34629
|
-
return
|
|
34902
|
+
return createHash8("sha256").update(await readFile10(filePath)).digest("hex");
|
|
34630
34903
|
}
|
|
34631
34904
|
async function executable(filePath, label) {
|
|
34632
|
-
const absolute =
|
|
34905
|
+
const absolute = path23.resolve(filePath);
|
|
34633
34906
|
try {
|
|
34634
34907
|
if (!(await stat4(absolute)).isFile()) throw new Error("not a regular file");
|
|
34635
34908
|
await access(absolute, fsConstants.X_OK);
|
|
@@ -34639,7 +34912,7 @@ async function executable(filePath, label) {
|
|
|
34639
34912
|
return absolute;
|
|
34640
34913
|
}
|
|
34641
34914
|
async function existingFile(filePath, label) {
|
|
34642
|
-
const absolute =
|
|
34915
|
+
const absolute = path23.resolve(filePath);
|
|
34643
34916
|
try {
|
|
34644
34917
|
const metadata = await stat4(absolute);
|
|
34645
34918
|
if (!metadata.isFile()) throw new Error("not a regular file");
|
|
@@ -34649,9 +34922,9 @@ async function existingFile(filePath, label) {
|
|
|
34649
34922
|
return absolute;
|
|
34650
34923
|
}
|
|
34651
34924
|
async function discoverExecutable(name, environment) {
|
|
34652
|
-
for (const directory of (environment.PATH ?? "").split(
|
|
34925
|
+
for (const directory of (environment.PATH ?? "").split(path23.delimiter)) {
|
|
34653
34926
|
if (!directory) continue;
|
|
34654
|
-
const candidate =
|
|
34927
|
+
const candidate = path23.resolve(directory, name);
|
|
34655
34928
|
try {
|
|
34656
34929
|
await access(candidate, fsConstants.X_OK);
|
|
34657
34930
|
return candidate;
|
|
@@ -34662,10 +34935,10 @@ async function discoverExecutable(name, environment) {
|
|
|
34662
34935
|
return null;
|
|
34663
34936
|
}
|
|
34664
34937
|
async function writeAtomic(filePath, contents, mode) {
|
|
34665
|
-
await mkdir11(
|
|
34666
|
-
const temporary =
|
|
34667
|
-
|
|
34668
|
-
`.${
|
|
34938
|
+
await mkdir11(path23.dirname(filePath), { recursive: true, mode: 448 });
|
|
34939
|
+
const temporary = path23.join(
|
|
34940
|
+
path23.dirname(filePath),
|
|
34941
|
+
`.${path23.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
|
|
34669
34942
|
);
|
|
34670
34943
|
try {
|
|
34671
34944
|
if (typeof contents === "string") {
|
|
@@ -34686,10 +34959,10 @@ async function writeAtomic(filePath, contents, mode) {
|
|
|
34686
34959
|
}
|
|
34687
34960
|
}
|
|
34688
34961
|
async function writeAtomicExecutable(filePath, sourcePath) {
|
|
34689
|
-
await mkdir11(
|
|
34690
|
-
const temporary =
|
|
34691
|
-
|
|
34692
|
-
`.${
|
|
34962
|
+
await mkdir11(path23.dirname(filePath), { recursive: true, mode: 448 });
|
|
34963
|
+
const temporary = path23.join(
|
|
34964
|
+
path23.dirname(filePath),
|
|
34965
|
+
`.${path23.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
|
|
34693
34966
|
);
|
|
34694
34967
|
try {
|
|
34695
34968
|
await copyFile3(sourcePath, temporary);
|
|
@@ -34730,8 +35003,8 @@ function removeManagedProfileBlock(contents) {
|
|
|
34730
35003
|
function installManagedProfileBlock(contents, manifest) {
|
|
34731
35004
|
const base = removeManagedProfileBlock(contents);
|
|
34732
35005
|
const environment = [
|
|
34733
|
-
`export CODEX_INSTALL_DIR=${shellQuote(
|
|
34734
|
-
`export PATH=${shellQuote(
|
|
35006
|
+
`export CODEX_INSTALL_DIR=${shellQuote(path23.dirname(manifest.wrapperPath))}`,
|
|
35007
|
+
`export PATH=${shellQuote(path23.dirname(manifest.wrapperPath))}:${shellQuote(path23.dirname(manifest.nodePath))}:${shellQuote(path23.dirname(manifest.stockCodexPath))}:"\${PATH:-/usr/local/bin:/usr/bin:/bin}"`,
|
|
34735
35008
|
`export CODEXHOST_STOCK_CODEX_PATH=${shellQuote(manifest.stockCodexPath)}`,
|
|
34736
35009
|
`export CODEXHOST_HOST_NODE_PATH=${shellQuote(manifest.nodePath)}`,
|
|
34737
35010
|
`export CODEXHOST_HOST_RUNTIME_PATH=${shellQuote(manifest.hostRuntimePath)}`,
|
|
@@ -34748,7 +35021,7 @@ function installManagedProfileBlock(contents, manifest) {
|
|
|
34748
35021
|
PROFILE_END,
|
|
34749
35022
|
""
|
|
34750
35023
|
].join("\n");
|
|
34751
|
-
if (
|
|
35024
|
+
if (path23.basename(manifest.profilePath) === ".bashrc") return `${block}${base}`;
|
|
34752
35025
|
const separator = base.length > 0 && !base.endsWith("\n") ? "\n" : "";
|
|
34753
35026
|
return `${base}${separator}${block}`;
|
|
34754
35027
|
}
|
|
@@ -34767,7 +35040,7 @@ ${WRAPPER_MARKER}
|
|
|
34767
35040
|
return "legacy-wrapper";
|
|
34768
35041
|
}
|
|
34769
35042
|
if (manifest.entrypointSha256 !== void 0) {
|
|
34770
|
-
return
|
|
35043
|
+
return createHash8("sha256").update(entrypoint).digest("hex") === manifest.entrypointSha256 ? "native" : "modified";
|
|
34771
35044
|
}
|
|
34772
35045
|
const shim = await readFile10(manifest.shimPath).catch((error51) => {
|
|
34773
35046
|
if (error51.code === "ENOENT") return null;
|
|
@@ -34813,9 +35086,9 @@ async function readManifest(filePath) {
|
|
|
34813
35086
|
];
|
|
34814
35087
|
const optionalPaths = ["claudeCommand", "profileBackupPath"];
|
|
34815
35088
|
if (manifest.format !== MANIFEST_FORMAT || Object.keys(manifest).some((key) => !allowed.has(key)) || requiredPaths.some(
|
|
34816
|
-
(key) => typeof manifest[key] !== "string" || !
|
|
35089
|
+
(key) => typeof manifest[key] !== "string" || !path23.isAbsolute(manifest[key])
|
|
34817
35090
|
) || optionalPaths.some(
|
|
34818
|
-
(key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !
|
|
35091
|
+
(key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !path23.isAbsolute(manifest[key]))
|
|
34819
35092
|
) || manifest.entrypointSha256 !== void 0 && (typeof manifest.entrypointSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(manifest.entrypointSha256))) {
|
|
34820
35093
|
throw new Error("Remote Host manifest has an unsupported format");
|
|
34821
35094
|
}
|
|
@@ -35044,7 +35317,7 @@ async function uninstallRemoteHost(options2) {
|
|
|
35044
35317
|
import { spawn as spawn5 } from "node:child_process";
|
|
35045
35318
|
import { stat as stat5 } from "node:fs/promises";
|
|
35046
35319
|
import net3 from "node:net";
|
|
35047
|
-
import
|
|
35320
|
+
import path24 from "node:path";
|
|
35048
35321
|
import { Duplex } from "node:stream";
|
|
35049
35322
|
var CODEXHOST_STATUS_METHOD = "codexhost/update/status";
|
|
35050
35323
|
var DIRECT_PROBE_TIMEOUT_MS = 5e3;
|
|
@@ -35063,9 +35336,9 @@ function classifyRemoteHostProbeResponse(response, socketPath) {
|
|
|
35063
35336
|
}
|
|
35064
35337
|
var lifecycleDependencyOverrides = {};
|
|
35065
35338
|
function socketPathFor(environment) {
|
|
35066
|
-
const codexHome = environment.CODEX_HOME ?? (environment.HOME ?
|
|
35339
|
+
const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path24.join(environment.HOME, ".codex") : void 0);
|
|
35067
35340
|
if (!codexHome) throw new Error("CODEX_HOME or HOME is required for remote Host lifecycle");
|
|
35068
|
-
return
|
|
35341
|
+
return path24.join(codexHome, "app-server-control", "app-server-control.sock");
|
|
35069
35342
|
}
|
|
35070
35343
|
async function defaultSocketExists(socketPath) {
|
|
35071
35344
|
const metadata = await stat5(socketPath).catch((error51) => {
|
|
@@ -35195,7 +35468,7 @@ function installedManifest(status) {
|
|
|
35195
35468
|
function managedEnvironment(manifest, environment) {
|
|
35196
35469
|
return {
|
|
35197
35470
|
...environment,
|
|
35198
|
-
CODEX_INSTALL_DIR:
|
|
35471
|
+
CODEX_INSTALL_DIR: path24.dirname(manifest.wrapperPath),
|
|
35199
35472
|
CODEXHOST_STOCK_CODEX_PATH: manifest.stockCodexPath,
|
|
35200
35473
|
CODEXHOST_HOST_NODE_PATH: manifest.nodePath,
|
|
35201
35474
|
CODEXHOST_HOST_RUNTIME_PATH: manifest.hostRuntimePath,
|
|
@@ -35203,7 +35476,7 @@ function managedEnvironment(manifest, environment) {
|
|
|
35203
35476
|
CODEXHOST_DEFAULT_AGENT: "codex",
|
|
35204
35477
|
CODEXHOST_REMOTE_SSH_MANAGED: "1",
|
|
35205
35478
|
...manifest.claudeCommand ? { CODEXHOST_CLAUDE_COMMAND: manifest.claudeCommand } : {},
|
|
35206
|
-
PATH: `${
|
|
35479
|
+
PATH: `${path24.dirname(manifest.wrapperPath)}${path24.delimiter}${path24.dirname(manifest.stockCodexPath)}${path24.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
|
|
35207
35480
|
};
|
|
35208
35481
|
}
|
|
35209
35482
|
async function defaultRunTerminator(manifest, socketPath, role, environment) {
|
|
@@ -35494,7 +35767,7 @@ var harnessBrokerServerFrameSchema = external_exports.union([
|
|
|
35494
35767
|
var harnessBrokerDescriptorSchema = external_exports.object({
|
|
35495
35768
|
schemaVersion: external_exports.literal(1),
|
|
35496
35769
|
protocolVersion: external_exports.literal(HARNESS_BROKER_PROTOCOL_VERSION),
|
|
35497
|
-
harnessId:
|
|
35770
|
+
harnessId: harnessPluginIdSchema,
|
|
35498
35771
|
generation: external_exports.string().uuid(),
|
|
35499
35772
|
ownerPid: external_exports.number().int().positive(),
|
|
35500
35773
|
socketPath: external_exports.string().min(1).max(512),
|
|
@@ -35545,33 +35818,48 @@ function consumeBrokerFrames(socket, onFrame, onError) {
|
|
|
35545
35818
|
|
|
35546
35819
|
// packages/harness-broker/dist/paths.js
|
|
35547
35820
|
import os5 from "node:os";
|
|
35548
|
-
import
|
|
35821
|
+
import path25 from "node:path";
|
|
35549
35822
|
var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
|
|
35550
35823
|
var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
|
|
35551
35824
|
var HARNESS_BROKER_SOCKET_FILE = "claude-code-broker-v1.sock";
|
|
35552
35825
|
function defaultHarnessBrokerDirectory(environment = process.env) {
|
|
35553
35826
|
const home = environment.HOME || os5.homedir();
|
|
35554
|
-
return
|
|
35827
|
+
return path25.join(home, ".codexhost", "harness-broker");
|
|
35555
35828
|
}
|
|
35556
|
-
function defaultHarnessBrokerDescriptorPath(environment = process.env) {
|
|
35557
|
-
|
|
35829
|
+
function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
|
|
35830
|
+
harnessPluginIdSchema.parse(harnessId);
|
|
35831
|
+
if (harnessId !== "claude-code")
|
|
35832
|
+
return path25.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
|
|
35833
|
+
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path25.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
|
|
35558
35834
|
}
|
|
35559
|
-
function defaultHarnessBrokerSocketPath(environment = process.env) {
|
|
35560
|
-
|
|
35835
|
+
function defaultHarnessBrokerSocketPath(environment = process.env, harnessId = "claude-code") {
|
|
35836
|
+
harnessPluginIdSchema.parse(harnessId);
|
|
35837
|
+
if (harnessId !== "claude-code")
|
|
35838
|
+
return path25.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
|
|
35839
|
+
return path25.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
|
|
35561
35840
|
}
|
|
35562
35841
|
|
|
35563
35842
|
// packages/harness-broker/dist/validation.js
|
|
35564
35843
|
var cwdSchema = external_exports.string().min(1).max(16384);
|
|
35844
|
+
var brokerEnvironmentSchema = external_exports.object({
|
|
35845
|
+
CODEXHOST_CLI_PATH: external_exports.string().max(16384).optional(),
|
|
35846
|
+
CODEXHOST_RUNTIME_ENDPOINT: external_exports.string().max(16384).optional(),
|
|
35847
|
+
CODEXHOST_RUNTIME_TOKEN: external_exports.string().max(16384).optional(),
|
|
35848
|
+
CODEXHOST_THREAD_ID: external_exports.string().max(256).optional()
|
|
35849
|
+
}).strict();
|
|
35565
35850
|
var createSchema = external_exports.object({
|
|
35566
35851
|
kind: external_exports.literal("create"),
|
|
35567
35852
|
cwd: cwdSchema,
|
|
35568
35853
|
executionPolicy: external_exports.enum(["default", "unattended-full-access"]).optional(),
|
|
35854
|
+
environment: brokerEnvironmentSchema.optional(),
|
|
35569
35855
|
model: harnessModelRefSchema.optional(),
|
|
35570
35856
|
thinkingOptionId: harnessThinkingOptionIdSchema.optional(),
|
|
35571
35857
|
permissionModeId: harnessPermissionModeIdSchema.optional()
|
|
35572
35858
|
}).strict();
|
|
35573
35859
|
var resumeSchema = external_exports.object({
|
|
35574
35860
|
kind: external_exports.literal("resume"),
|
|
35861
|
+
environment: brokerEnvironmentSchema.optional(),
|
|
35862
|
+
permissionModeId: harnessPermissionModeIdSchema.optional(),
|
|
35575
35863
|
model: harnessModelRefSchema.optional(),
|
|
35576
35864
|
thinkingOptionId: harnessThinkingOptionIdSchema.optional(),
|
|
35577
35865
|
nativeRef: nativeSessionRefSchema,
|
|
@@ -35580,12 +35868,14 @@ var resumeSchema = external_exports.object({
|
|
|
35580
35868
|
}).strict();
|
|
35581
35869
|
var forkSchema = external_exports.object({
|
|
35582
35870
|
kind: external_exports.literal("fork"),
|
|
35871
|
+
environment: brokerEnvironmentSchema.optional(),
|
|
35583
35872
|
sourceRef: nativeSessionRefSchema,
|
|
35584
35873
|
checkpoint: nativeCheckpointRefSchema,
|
|
35585
35874
|
cwd: cwdSchema
|
|
35586
35875
|
}).strict();
|
|
35587
35876
|
var rollbackSchema = external_exports.object({
|
|
35588
35877
|
kind: external_exports.literal("rollbackLastTurn"),
|
|
35878
|
+
environment: brokerEnvironmentSchema.optional(),
|
|
35589
35879
|
model: harnessModelRefSchema.optional(),
|
|
35590
35880
|
thinkingOptionId: harnessThinkingOptionIdSchema.optional(),
|
|
35591
35881
|
permissionModeId: harnessPermissionModeIdSchema.optional(),
|
|
@@ -35780,10 +36070,10 @@ var harnessOutputSchema = external_exports.custom((value2) => {
|
|
|
35780
36070
|
});
|
|
35781
36071
|
|
|
35782
36072
|
// packages/harness-broker/dist/server.js
|
|
35783
|
-
import { randomBytes as randomBytes2, randomUUID as
|
|
36073
|
+
import { randomBytes as randomBytes2, randomUUID as randomUUID15 } from "node:crypto";
|
|
35784
36074
|
import { chmod as chmod5, lstat as lstat9, mkdir as mkdir12, open as open8, readFile as readFile11, rename as rename9, rm as rm11 } from "node:fs/promises";
|
|
35785
36075
|
import net4, {} from "node:net";
|
|
35786
|
-
import
|
|
36076
|
+
import path26 from "node:path";
|
|
35787
36077
|
function harnessError(message, retryable = true) {
|
|
35788
36078
|
return { code: "unavailable", message, retryable, stage: "harnessBroker" };
|
|
35789
36079
|
}
|
|
@@ -35839,7 +36129,7 @@ async function assertNoLiveDescriptor(descriptorPath) {
|
|
|
35839
36129
|
}
|
|
35840
36130
|
}
|
|
35841
36131
|
async function publishDescriptor(descriptorPath, descriptor) {
|
|
35842
|
-
const temporary = `${descriptorPath}.${process.pid}.${
|
|
36132
|
+
const temporary = `${descriptorPath}.${process.pid}.${randomUUID15()}.tmp`;
|
|
35843
36133
|
const handle = await open8(temporary, "wx", 384);
|
|
35844
36134
|
try {
|
|
35845
36135
|
await handle.writeFile(`${JSON.stringify(descriptor)}
|
|
@@ -35905,25 +36195,23 @@ async function prepareUnixSocketPath(socketPath) {
|
|
|
35905
36195
|
}
|
|
35906
36196
|
}
|
|
35907
36197
|
async function startHarnessBrokerServer(input) {
|
|
35908
|
-
|
|
35909
|
-
|
|
35910
|
-
}
|
|
35911
|
-
if (process.platform !== "win32" && path25.dirname(input.descriptorPath) !== path25.dirname(input.socketPath)) {
|
|
36198
|
+
harnessPluginIdSchema.parse(input.adapter.harnessId);
|
|
36199
|
+
if (process.platform !== "win32" && path26.dirname(input.descriptorPath) !== path26.dirname(input.socketPath)) {
|
|
35912
36200
|
throw new Error("Harness broker descriptor and socket must share one private directory");
|
|
35913
36201
|
}
|
|
35914
36202
|
if (process.platform === "darwin" && Buffer.byteLength(input.socketPath) > 103) {
|
|
35915
36203
|
throw new Error("Harness broker Unix socket path is too long for macOS");
|
|
35916
36204
|
}
|
|
35917
|
-
await privateDirectory(
|
|
36205
|
+
await privateDirectory(path26.dirname(input.descriptorPath));
|
|
35918
36206
|
await assertNoLiveDescriptor(input.descriptorPath);
|
|
35919
36207
|
if (process.platform !== "win32")
|
|
35920
36208
|
await prepareUnixSocketPath(input.socketPath);
|
|
35921
|
-
const generation = input.generation ??
|
|
36209
|
+
const generation = input.generation ?? randomUUID15();
|
|
35922
36210
|
const token = input.token ?? randomBytes2(32).toString("hex");
|
|
35923
36211
|
const descriptor = {
|
|
35924
36212
|
schemaVersion: 1,
|
|
35925
36213
|
protocolVersion: HARNESS_BROKER_PROTOCOL_VERSION,
|
|
35926
|
-
harnessId:
|
|
36214
|
+
harnessId: input.adapter.harnessId,
|
|
35927
36215
|
generation,
|
|
35928
36216
|
ownerPid: process.pid,
|
|
35929
36217
|
socketPath: input.socketPath,
|
|
@@ -35936,7 +36224,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
35936
36224
|
let closed = false;
|
|
35937
36225
|
const server = net4.createServer((socket) => {
|
|
35938
36226
|
const state = {
|
|
35939
|
-
id:
|
|
36227
|
+
id: randomUUID15(),
|
|
35940
36228
|
socket,
|
|
35941
36229
|
authenticated: false,
|
|
35942
36230
|
inputSequence: 0,
|
|
@@ -35979,8 +36267,9 @@ async function startHarnessBrokerServer(input) {
|
|
|
35979
36267
|
if (output.kind === "event" && output.event.type === "session.state.changed") {
|
|
35980
36268
|
const state2 = output.event.state;
|
|
35981
36269
|
const observedNativeId = state2.nativeRef?.nativeSessionId;
|
|
35982
|
-
if (state2.nativeRef && record3.nativeRef && (record3.nativeRef.harnessId !== state2.nativeRef.harnessId || record3.nativeRef.nativeSessionId !== state2.nativeRef.nativeSessionId || record3.nativeRef.formatVersion !== state2.nativeRef.formatVersion)) {
|
|
36270
|
+
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))) {
|
|
35983
36271
|
record3.faulted = true;
|
|
36272
|
+
releaseProvisionalWriter(record3);
|
|
35984
36273
|
await send({
|
|
35985
36274
|
kind: "output",
|
|
35986
36275
|
sessionId: record3.id,
|
|
@@ -35991,7 +36280,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
35991
36280
|
type: "session.faulted",
|
|
35992
36281
|
error: {
|
|
35993
36282
|
code: "protocolError",
|
|
35994
|
-
message: "Native
|
|
36283
|
+
message: "Native Harness Session identity changed after open",
|
|
35995
36284
|
retryable: false,
|
|
35996
36285
|
stage: "harnessBroker.identity"
|
|
35997
36286
|
}
|
|
@@ -36017,7 +36306,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
36017
36306
|
type: "session.faulted",
|
|
36018
36307
|
error: {
|
|
36019
36308
|
code: "sessionBusy",
|
|
36020
|
-
message: "Native
|
|
36309
|
+
message: "Native Harness Session already has an active writer",
|
|
36021
36310
|
retryable: true,
|
|
36022
36311
|
stage: "harnessBroker.identity"
|
|
36023
36312
|
}
|
|
@@ -36115,8 +36404,11 @@ async function startHarnessBrokerServer(input) {
|
|
|
36115
36404
|
if (request.method === "adapter.subagent.readSnapshot") {
|
|
36116
36405
|
const subagents = input.adapter.subagents;
|
|
36117
36406
|
if (!subagents)
|
|
36118
|
-
return { ok: false, error: harnessError("
|
|
36119
|
-
|
|
36407
|
+
return { ok: false, error: harnessError("Harness subagents are unavailable", false) };
|
|
36408
|
+
const params = subagentReadSnapshotSchema.parse(request.params);
|
|
36409
|
+
if (params.parent.harnessId !== input.adapter.harnessId)
|
|
36410
|
+
return { ok: false, error: protocolError("Subagent parent belongs to another Harness") };
|
|
36411
|
+
return subagents.readSnapshot(params);
|
|
36120
36412
|
}
|
|
36121
36413
|
if (request.method === "adapter.sessionImport.list") {
|
|
36122
36414
|
const { limit, offset } = brokerSessionImportListParamsSchema.parse(request.params);
|
|
@@ -36166,13 +36458,15 @@ async function startHarnessBrokerServer(input) {
|
|
|
36166
36458
|
const openInput = brokerOpenInputSchema.parse(request.params);
|
|
36167
36459
|
const sourceRef = openInput.kind === "create" ? void 0 : openInput.kind === "resume" ? openInput.nativeRef : openInput.sourceRef;
|
|
36168
36460
|
const sourceNativeId = sourceRef?.nativeSessionId;
|
|
36461
|
+
if (sourceRef && sourceRef.harnessId !== input.adapter.harnessId)
|
|
36462
|
+
return { ok: false, error: protocolError("Native Session belongs to another Harness") };
|
|
36169
36463
|
const sourceKey = sourceNativeId ? nativeWriterKey(sourceNativeId) : void 0;
|
|
36170
36464
|
if (sourceKey && nativeWriters.has(sourceKey)) {
|
|
36171
36465
|
return {
|
|
36172
36466
|
ok: false,
|
|
36173
36467
|
error: {
|
|
36174
36468
|
code: "sessionBusy",
|
|
36175
|
-
message: "Native
|
|
36469
|
+
message: "Native Harness Session already has an active writer",
|
|
36176
36470
|
retryable: true,
|
|
36177
36471
|
stage: "harnessBroker.open"
|
|
36178
36472
|
}
|
|
@@ -36183,13 +36477,13 @@ async function startHarnessBrokerServer(input) {
|
|
|
36183
36477
|
ok: false,
|
|
36184
36478
|
error: {
|
|
36185
36479
|
code: "sessionBusy",
|
|
36186
|
-
message: "Native
|
|
36480
|
+
message: "Native Harness Session identity claim is already pending",
|
|
36187
36481
|
retryable: true,
|
|
36188
36482
|
stage: "harnessBroker.open"
|
|
36189
36483
|
}
|
|
36190
36484
|
};
|
|
36191
36485
|
}
|
|
36192
|
-
const openReservation =
|
|
36486
|
+
const openReservation = randomUUID15();
|
|
36193
36487
|
if (sourceKey)
|
|
36194
36488
|
nativeWriters.set(sourceKey, openReservation);
|
|
36195
36489
|
const provisionalReservation = openInput.kind === "create" ? openReservation : void 0;
|
|
@@ -36217,6 +36511,14 @@ async function startHarnessBrokerServer(input) {
|
|
|
36217
36511
|
return { ok: false, error: harnessError("Harness broker connection closed") };
|
|
36218
36512
|
}
|
|
36219
36513
|
const openedRef = opened.value.initialState.nativeRef;
|
|
36514
|
+
if (openedRef && openedRef.harnessId !== input.adapter.harnessId) {
|
|
36515
|
+
releaseOpenReservations();
|
|
36516
|
+
await opened.value.close().catch(() => void 0);
|
|
36517
|
+
return {
|
|
36518
|
+
ok: false,
|
|
36519
|
+
error: protocolError("Adapter opened a Session for another Harness")
|
|
36520
|
+
};
|
|
36521
|
+
}
|
|
36220
36522
|
if (sourceRef && (!openedRef || openedRef.harnessId !== sourceRef.harnessId || openedRef.formatVersion !== sourceRef.formatVersion || openInput.kind === "resume" && openedRef.nativeSessionId !== sourceRef.nativeSessionId)) {
|
|
36221
36523
|
releaseOpenReservations();
|
|
36222
36524
|
await opened.value.close().catch(() => void 0);
|
|
@@ -36224,7 +36526,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
36224
36526
|
ok: false,
|
|
36225
36527
|
error: {
|
|
36226
36528
|
code: "protocolError",
|
|
36227
|
-
message: "Native
|
|
36529
|
+
message: "Native Harness Session identity did not match the requested open",
|
|
36228
36530
|
retryable: false,
|
|
36229
36531
|
stage: "harnessBroker.open"
|
|
36230
36532
|
}
|
|
@@ -36240,7 +36542,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
36240
36542
|
ok: false,
|
|
36241
36543
|
error: {
|
|
36242
36544
|
code: "sessionBusy",
|
|
36243
|
-
message: "Native
|
|
36545
|
+
message: "Native Harness Session already has an active writer",
|
|
36244
36546
|
retryable: true,
|
|
36245
36547
|
stage: "harnessBroker.open"
|
|
36246
36548
|
}
|
|
@@ -36252,6 +36554,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
36252
36554
|
generation: 1,
|
|
36253
36555
|
owner: state.id,
|
|
36254
36556
|
cwd: openInput.cwd,
|
|
36557
|
+
...openInput.environment ? { environment: openInput.environment } : {},
|
|
36255
36558
|
...nativeId ? { nativeId } : {},
|
|
36256
36559
|
...opened.value.initialState.nativeRef ? { nativeRef: opened.value.initialState.nativeRef } : {},
|
|
36257
36560
|
...nativeKey ? { writerKey: nativeKey } : {},
|
|
@@ -36292,7 +36595,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
36292
36595
|
ok: false,
|
|
36293
36596
|
error: {
|
|
36294
36597
|
code: "sessionBusy",
|
|
36295
|
-
message: "Native
|
|
36598
|
+
message: "Native Harness Session identity has not been claimed yet",
|
|
36296
36599
|
retryable: true,
|
|
36297
36600
|
stage: "harnessBroker.identity"
|
|
36298
36601
|
}
|
|
@@ -36369,7 +36672,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
36369
36672
|
ok: false,
|
|
36370
36673
|
error: {
|
|
36371
36674
|
code: "sessionBusy",
|
|
36372
|
-
message: "Faulted
|
|
36675
|
+
message: "Faulted Harness Session has no authoritative native identity",
|
|
36373
36676
|
retryable: false,
|
|
36374
36677
|
stage: "harnessBroker.reopen"
|
|
36375
36678
|
}
|
|
@@ -36381,7 +36684,12 @@ async function startHarnessBrokerServer(input) {
|
|
|
36381
36684
|
record4.forwarderEpoch += 1;
|
|
36382
36685
|
await oldSession.close().catch(() => void 0);
|
|
36383
36686
|
await oldOutputTask.catch(() => void 0);
|
|
36384
|
-
const reopened = await input.adapter.open({
|
|
36687
|
+
const reopened = await input.adapter.open({
|
|
36688
|
+
kind: "resume",
|
|
36689
|
+
cwd: record4.cwd,
|
|
36690
|
+
nativeRef,
|
|
36691
|
+
...record4.environment ? { environment: record4.environment } : {}
|
|
36692
|
+
});
|
|
36385
36693
|
if (!reopened.ok)
|
|
36386
36694
|
return reopened;
|
|
36387
36695
|
const reopenedRef = reopened.value.initialState.nativeRef;
|
|
@@ -36391,7 +36699,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
36391
36699
|
ok: false,
|
|
36392
36700
|
error: {
|
|
36393
36701
|
code: "protocolError",
|
|
36394
|
-
message: "
|
|
36702
|
+
message: "Aqua Harness broker reopen changed the native Session identity",
|
|
36395
36703
|
retryable: false,
|
|
36396
36704
|
stage: "harnessBroker.reopen"
|
|
36397
36705
|
}
|
|
@@ -36455,7 +36763,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
36455
36763
|
}
|
|
36456
36764
|
state.authenticated = true;
|
|
36457
36765
|
state.inputSequence = 1;
|
|
36458
|
-
await send({ kind: "response", id:
|
|
36766
|
+
await send({ kind: "response", id: randomUUID15(), ok: true, value: { ready: true } });
|
|
36459
36767
|
return;
|
|
36460
36768
|
}
|
|
36461
36769
|
const parsed = harnessBrokerRequestSchema.safeParse(raw);
|
|
@@ -36528,15 +36836,16 @@ async function startHarnessBrokerServer(input) {
|
|
|
36528
36836
|
}
|
|
36529
36837
|
|
|
36530
36838
|
// packages/host-runtime/src/aqua-harness-broker.ts
|
|
36531
|
-
async function runClaudeAquaHarnessBroker(environment = process.env) {
|
|
36839
|
+
async function runClaudeAquaHarnessBroker(environment = process.env, requestedHarnessId = "claude-code") {
|
|
36840
|
+
const harnessId = harnessPluginIdSchema.parse(requestedHarnessId);
|
|
36532
36841
|
if (process.platform !== "darwin") {
|
|
36533
|
-
throw new Error("
|
|
36842
|
+
throw new Error("Aqua Harness broker is available only on macOS");
|
|
36534
36843
|
}
|
|
36535
36844
|
const { pluginRoots, pluginContext } = installedHarnessPluginOptions(environment);
|
|
36536
36845
|
const plugins = await loadHarnessPlugins({
|
|
36537
36846
|
roots: pluginRoots,
|
|
36538
36847
|
context: pluginContext,
|
|
36539
|
-
onlyIds: /* @__PURE__ */ new Set([
|
|
36848
|
+
onlyIds: /* @__PURE__ */ new Set([harnessId]),
|
|
36540
36849
|
warmup: false,
|
|
36541
36850
|
diagnose: (diagnostic) => process.stderr.write(`Harness plugin: ${JSON.stringify(diagnostic)}
|
|
36542
36851
|
`)
|
|
@@ -36549,19 +36858,19 @@ async function runClaudeAquaHarnessBroker(environment = process.env) {
|
|
|
36549
36858
|
let server;
|
|
36550
36859
|
try {
|
|
36551
36860
|
server = await startHarnessBrokerServer({
|
|
36552
|
-
descriptorPath: defaultHarnessBrokerDescriptorPath(environment),
|
|
36553
|
-
socketPath: defaultHarnessBrokerSocketPath(environment),
|
|
36861
|
+
descriptorPath: defaultHarnessBrokerDescriptorPath(environment, harnessId),
|
|
36862
|
+
socketPath: defaultHarnessBrokerSocketPath(environment, harnessId),
|
|
36554
36863
|
adapter
|
|
36555
36864
|
});
|
|
36556
36865
|
} catch (error51) {
|
|
36557
36866
|
await adapter.close().catch(() => void 0);
|
|
36558
36867
|
throw error51;
|
|
36559
36868
|
}
|
|
36560
|
-
process.title =
|
|
36869
|
+
process.title = `codexhost ${harnessId} Aqua harness broker`;
|
|
36561
36870
|
process.stdout.write(
|
|
36562
36871
|
`${JSON.stringify({
|
|
36563
36872
|
method: "codexhost/harness-broker/ready",
|
|
36564
|
-
params: { protocolVersion: 1, harnessId
|
|
36873
|
+
params: { protocolVersion: 1, harnessId }
|
|
36565
36874
|
})}
|
|
36566
36875
|
`
|
|
36567
36876
|
);
|
|
@@ -36584,7 +36893,7 @@ async function runClaudeAquaHarnessBroker(environment = process.env) {
|
|
|
36584
36893
|
|
|
36585
36894
|
// packages/host-runtime/src/release-main.ts
|
|
36586
36895
|
var arguments_ = process.argv.slice(2);
|
|
36587
|
-
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({
|
|
36896
|
+
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({
|
|
36588
36897
|
arguments: arguments_,
|
|
36589
36898
|
environment: process.env,
|
|
36590
36899
|
hostRuntimeUrl: import.meta.url
|