@liberseek/boft-cli-win32-arm64 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/THIRD_PARTY_NOTICES.txt +0 -4
- package/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +256 -179
- package/app/host-runtime.mjs +646 -323
- package/app/plugins/antigravity/plugin.mjs +123 -1
- package/app/plugins/claude-code/plugin.mjs +252 -46
- package/app/plugins/codebuddy/plugin.mjs +2287 -879
- package/app/plugins/cursor-cli/plugin.mjs +35756 -10755
- package/app/plugins/deepseek-harness/plugin.mjs +70 -0
- package/app/plugins/enabled.json +1 -0
- package/app/plugins/grok/plugin.mjs +193 -82
- package/app/plugins/hermes/plugin.mjs +2444 -94
- package/app/plugins/kiro-cli/plugin.mjs +70 -0
- package/app/plugins/muse/plugin.mjs +70 -0
- package/app/plugins/omp/plugin.mjs +92 -4
- package/app/plugins/opencode/plugin.mjs +70 -0
- package/app/plugins/pi/plugin.mjs +2139 -973
- package/app/plugins/qoder/plugin.mjs +71 -9
- package/app/plugins/qoder-cn/plugin.mjs +71 -9
- package/app/plugins/workbuddy/assets/icon.svg +29 -0
- package/app/plugins/workbuddy/manifest.json +14 -0
- package/app/plugins/workbuddy/plugin.mjs +25007 -0
- package/app/renderer-extension.js +2874 -1408
- 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/package.json +1 -1
- package/licenses/opencodex-LICENSE.txt +0 -21
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: randomBytes4, createHash:
|
|
2281
|
+
var { randomBytes: randomBytes4, createHash: createHash11 } = __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 = createHash11("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: createHash11 } = __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 = createHash11("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 as randomBytes2 } from "node:crypto";
|
|
4286
|
-
import
|
|
4286
|
+
import path23 from "node:path";
|
|
4287
4287
|
import { homedir as homedir2 } from "node:os";
|
|
4288
4288
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
4289
4289
|
|
|
@@ -5978,10 +5978,10 @@ function mergeDefs(...defs) {
|
|
|
5978
5978
|
function cloneDef(schema) {
|
|
5979
5979
|
return mergeDefs(schema._zod.def);
|
|
5980
5980
|
}
|
|
5981
|
-
function getElementAtPath(obj,
|
|
5982
|
-
if (!
|
|
5981
|
+
function getElementAtPath(obj, path28) {
|
|
5982
|
+
if (!path28)
|
|
5983
5983
|
return obj;
|
|
5984
|
-
return
|
|
5984
|
+
return path28.reduce((acc, key) => acc?.[key], obj);
|
|
5985
5985
|
}
|
|
5986
5986
|
function promiseAllObject(promisesObj) {
|
|
5987
5987
|
const keys = Object.keys(promisesObj);
|
|
@@ -6390,11 +6390,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
6390
6390
|
}
|
|
6391
6391
|
return false;
|
|
6392
6392
|
}
|
|
6393
|
-
function prefixIssues(
|
|
6393
|
+
function prefixIssues(path28, issues) {
|
|
6394
6394
|
return issues.map((iss) => {
|
|
6395
6395
|
var _a3;
|
|
6396
6396
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
6397
|
-
iss.path.unshift(
|
|
6397
|
+
iss.path.unshift(path28);
|
|
6398
6398
|
return iss;
|
|
6399
6399
|
});
|
|
6400
6400
|
}
|
|
@@ -6541,16 +6541,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
6541
6541
|
}
|
|
6542
6542
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
6543
6543
|
const fieldErrors = { _errors: [] };
|
|
6544
|
-
const processError = (error52,
|
|
6544
|
+
const processError = (error52, path28 = []) => {
|
|
6545
6545
|
for (const issue2 of error52.issues) {
|
|
6546
6546
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
6547
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
6547
|
+
issue2.errors.map((issues) => processError({ issues }, [...path28, ...issue2.path]));
|
|
6548
6548
|
} else if (issue2.code === "invalid_key") {
|
|
6549
|
-
processError({ issues: issue2.issues }, [...
|
|
6549
|
+
processError({ issues: issue2.issues }, [...path28, ...issue2.path]);
|
|
6550
6550
|
} else if (issue2.code === "invalid_element") {
|
|
6551
|
-
processError({ issues: issue2.issues }, [...
|
|
6551
|
+
processError({ issues: issue2.issues }, [...path28, ...issue2.path]);
|
|
6552
6552
|
} else {
|
|
6553
|
-
const fullpath = [...
|
|
6553
|
+
const fullpath = [...path28, ...issue2.path];
|
|
6554
6554
|
if (fullpath.length === 0) {
|
|
6555
6555
|
fieldErrors._errors.push(mapper(issue2));
|
|
6556
6556
|
} else {
|
|
@@ -6577,17 +6577,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
6577
6577
|
}
|
|
6578
6578
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
6579
6579
|
const result = { errors: [] };
|
|
6580
|
-
const processError = (error52,
|
|
6580
|
+
const processError = (error52, path28 = []) => {
|
|
6581
6581
|
var _a3, _b;
|
|
6582
6582
|
for (const issue2 of error52.issues) {
|
|
6583
6583
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
6584
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
6584
|
+
issue2.errors.map((issues) => processError({ issues }, [...path28, ...issue2.path]));
|
|
6585
6585
|
} else if (issue2.code === "invalid_key") {
|
|
6586
|
-
processError({ issues: issue2.issues }, [...
|
|
6586
|
+
processError({ issues: issue2.issues }, [...path28, ...issue2.path]);
|
|
6587
6587
|
} else if (issue2.code === "invalid_element") {
|
|
6588
|
-
processError({ issues: issue2.issues }, [...
|
|
6588
|
+
processError({ issues: issue2.issues }, [...path28, ...issue2.path]);
|
|
6589
6589
|
} else {
|
|
6590
|
-
const fullpath = [...
|
|
6590
|
+
const fullpath = [...path28, ...issue2.path];
|
|
6591
6591
|
if (fullpath.length === 0) {
|
|
6592
6592
|
result.errors.push(mapper(issue2));
|
|
6593
6593
|
continue;
|
|
@@ -6619,8 +6619,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
6619
6619
|
}
|
|
6620
6620
|
function toDotPath(_path) {
|
|
6621
6621
|
const segs = [];
|
|
6622
|
-
const
|
|
6623
|
-
for (const seg of
|
|
6622
|
+
const path28 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
6623
|
+
for (const seg of path28) {
|
|
6624
6624
|
if (typeof seg === "number")
|
|
6625
6625
|
segs.push(`[${seg}]`);
|
|
6626
6626
|
else if (typeof seg === "symbol")
|
|
@@ -19312,13 +19312,13 @@ function resolveRef(ref, ctx) {
|
|
|
19312
19312
|
if (!ref.startsWith("#")) {
|
|
19313
19313
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
19314
19314
|
}
|
|
19315
|
-
const
|
|
19316
|
-
if (
|
|
19315
|
+
const path28 = ref.slice(1).split("/").filter(Boolean);
|
|
19316
|
+
if (path28.length === 0) {
|
|
19317
19317
|
return ctx.rootSchema;
|
|
19318
19318
|
}
|
|
19319
19319
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
19320
|
-
if (
|
|
19321
|
-
const key =
|
|
19320
|
+
if (path28[0] === defsKey) {
|
|
19321
|
+
const key = path28[1];
|
|
19322
19322
|
if (!key || !ctx.defs[key]) {
|
|
19323
19323
|
throw new Error(`Reference not found: ${ref}`);
|
|
19324
19324
|
}
|
|
@@ -19726,6 +19726,62 @@ function date4(params) {
|
|
|
19726
19726
|
// node_modules/zod/v4/classic/external.js
|
|
19727
19727
|
config(en_default());
|
|
19728
19728
|
|
|
19729
|
+
// packages/shared-contracts/dist/credential-imports.js
|
|
19730
|
+
var credentialSourceSchema = external_exports.object({
|
|
19731
|
+
id: external_exports.string().min(1).max(256),
|
|
19732
|
+
harnessId: external_exports.string().min(1),
|
|
19733
|
+
label: external_exports.string().min(1).max(512),
|
|
19734
|
+
provider: external_exports.enum(["openai-codex", "xai"])
|
|
19735
|
+
}).strict();
|
|
19736
|
+
var credentialImportNameSchema = external_exports.string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
19737
|
+
var credentialImportRecordSchema = external_exports.object({
|
|
19738
|
+
name: credentialImportNameSchema,
|
|
19739
|
+
source: credentialSourceSchema,
|
|
19740
|
+
importedAt: external_exports.string()
|
|
19741
|
+
}).strict();
|
|
19742
|
+
var credentialImportsRequestSchema = external_exports.discriminatedUnion("action", [
|
|
19743
|
+
external_exports.object({ action: external_exports.literal("list") }).strict(),
|
|
19744
|
+
external_exports.object({
|
|
19745
|
+
action: external_exports.literal("import"),
|
|
19746
|
+
sourceId: external_exports.string().min(1).max(256),
|
|
19747
|
+
name: credentialImportNameSchema,
|
|
19748
|
+
confirmed: external_exports.literal(true)
|
|
19749
|
+
}).strict(),
|
|
19750
|
+
external_exports.object({
|
|
19751
|
+
action: external_exports.literal("reimport"),
|
|
19752
|
+
sourceId: external_exports.string().min(1).max(256),
|
|
19753
|
+
name: credentialImportNameSchema,
|
|
19754
|
+
confirmed: external_exports.literal(true)
|
|
19755
|
+
}).strict(),
|
|
19756
|
+
external_exports.object({
|
|
19757
|
+
action: external_exports.literal("remove"),
|
|
19758
|
+
name: credentialImportNameSchema,
|
|
19759
|
+
confirmed: external_exports.literal(true)
|
|
19760
|
+
}).strict()
|
|
19761
|
+
]);
|
|
19762
|
+
var credentialOtherLoginSchema = external_exports.object({
|
|
19763
|
+
provider: external_exports.string().min(1).max(128),
|
|
19764
|
+
type: external_exports.enum(["oauth", "api_key", "unknown"]),
|
|
19765
|
+
/** Best-effort account label (e.g. the email in a Codex token), derived locally when present. */
|
|
19766
|
+
label: external_exports.string().min(1).max(512).optional(),
|
|
19767
|
+
/** Recognized credential vendor, derived from the OAuth token issuer. Absent when unknown. */
|
|
19768
|
+
vendor: external_exports.enum(["openai-codex", "xai"]).optional()
|
|
19769
|
+
}).strict();
|
|
19770
|
+
var credentialImportsResultSchema = external_exports.object({
|
|
19771
|
+
sources: external_exports.array(credentialSourceSchema),
|
|
19772
|
+
targets: external_exports.array(external_exports.object({
|
|
19773
|
+
harnessId: external_exports.string(),
|
|
19774
|
+
providers: external_exports.array(external_exports.enum(["openai-codex", "xai"])),
|
|
19775
|
+
imports: external_exports.array(credentialImportRecordSchema),
|
|
19776
|
+
others: external_exports.array(credentialOtherLoginSchema).default([])
|
|
19777
|
+
}).strict())
|
|
19778
|
+
}).strict();
|
|
19779
|
+
var credentialImportsParamsSchema = external_exports.object({
|
|
19780
|
+
targetHarnessId: external_exports.string().min(1).max(128).optional(),
|
|
19781
|
+
request: credentialImportsRequestSchema
|
|
19782
|
+
}).strict();
|
|
19783
|
+
var CREDENTIAL_IMPORTS_METHOD = "codexhost/harness/credential-imports";
|
|
19784
|
+
|
|
19729
19785
|
// packages/shared-contracts/dist/version.js
|
|
19730
19786
|
var WORKSPACE_CONTRACT_VERSION = 1;
|
|
19731
19787
|
|
|
@@ -20282,6 +20338,8 @@ var pluginPresentationShape = {
|
|
|
20282
20338
|
id: harnessPluginIdSchema,
|
|
20283
20339
|
name: external_exports.string().trim().min(1).max(128),
|
|
20284
20340
|
version: external_exports.string().min(1).max(128),
|
|
20341
|
+
/** The factory accepts a persisted local entrypoint through its construction context. */
|
|
20342
|
+
launchCommand: external_exports.literal(true).optional(),
|
|
20285
20343
|
links: external_exports.object({
|
|
20286
20344
|
documentation: documentationUrlSchema.optional(),
|
|
20287
20345
|
installation: documentationUrlSchema.optional()
|
|
@@ -20343,6 +20401,21 @@ function decodeHarnessPluginRoute(value2) {
|
|
|
20343
20401
|
}
|
|
20344
20402
|
}
|
|
20345
20403
|
|
|
20404
|
+
// packages/shared-contracts/dist/harness-launch-settings.js
|
|
20405
|
+
var HARNESS_LAUNCH_SETTINGS_GET_METHOD = "codexhost/harness/launch-settings/get";
|
|
20406
|
+
var HARNESS_LAUNCH_SETTINGS_SET_METHOD = "codexhost/harness/launch-settings/set";
|
|
20407
|
+
var harnessLaunchPathSchema = external_exports.string().trim().min(1).max(4096).refine((value2) => !/[\u0000\r\n]/u.test(value2), "Invalid entrypoint path");
|
|
20408
|
+
var harnessLaunchSettingsGetSchema = external_exports.object({
|
|
20409
|
+
harnessId: harnessPluginIdSchema
|
|
20410
|
+
}).strict();
|
|
20411
|
+
var harnessLaunchSettingsSetSchema = harnessLaunchSettingsGetSchema.extend({
|
|
20412
|
+
path: harnessLaunchPathSchema.nullable()
|
|
20413
|
+
});
|
|
20414
|
+
var harnessLaunchSettingsSchema = external_exports.object({
|
|
20415
|
+
path: harnessLaunchPathSchema.nullable(),
|
|
20416
|
+
restartRequired: external_exports.boolean()
|
|
20417
|
+
}).strict();
|
|
20418
|
+
|
|
20346
20419
|
// packages/shared-contracts/dist/codex-accounts.js
|
|
20347
20420
|
var accountIdSchema = external_exports.string().min(1).max(256).regex(/^[A-Za-z0-9._~-]+$/u);
|
|
20348
20421
|
var nonBlankTextSchema3 = external_exports.string().trim().min(1);
|
|
@@ -20637,6 +20710,97 @@ var updateStatusResultSchema = external_exports.strictObject({
|
|
|
20637
20710
|
// packages/shared-contracts/dist/index.js
|
|
20638
20711
|
var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
|
|
20639
20712
|
|
|
20713
|
+
// packages/host-runtime/src/account/codex-credential-export.ts
|
|
20714
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
20715
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
20716
|
+
import os from "node:os";
|
|
20717
|
+
import path5 from "node:path";
|
|
20718
|
+
async function readCodexCredential(environment) {
|
|
20719
|
+
try {
|
|
20720
|
+
const home = environment.CODEX_HOME ?? path5.join(environment.HOME ?? os.homedir(), ".codex");
|
|
20721
|
+
const auth = JSON.parse(await readFile4(path5.join(home, "auth.json"), "utf8"));
|
|
20722
|
+
if (auth.OPENAI_API_KEY || auth.auth_mode && auth.auth_mode !== "chatgpt") return [];
|
|
20723
|
+
const t = auth.tokens;
|
|
20724
|
+
if (!t || ![t.access_token, t.refresh_token, t.account_id].every(
|
|
20725
|
+
(v) => typeof v === "string" && v.length
|
|
20726
|
+
))
|
|
20727
|
+
return [];
|
|
20728
|
+
const claims = JSON.parse(Buffer.from(t.access_token.split(".")[1], "base64url").toString());
|
|
20729
|
+
if (claims.client_id !== "app_EMoamEEZ73f0CkXaXp7hrann" || !Number.isFinite(claims.exp * 1e3))
|
|
20730
|
+
return [];
|
|
20731
|
+
const account = claims["https://api.openai.com/auth"]?.chatgpt_account_id;
|
|
20732
|
+
if (account !== t.account_id) return [];
|
|
20733
|
+
let email3;
|
|
20734
|
+
try {
|
|
20735
|
+
email3 = JSON.parse(Buffer.from(t.id_token.split(".")[1], "base64url").toString()).email;
|
|
20736
|
+
} catch {
|
|
20737
|
+
}
|
|
20738
|
+
const identity = `${t.account_id}:${claims.sub ?? ""}`;
|
|
20739
|
+
return [
|
|
20740
|
+
{
|
|
20741
|
+
source: {
|
|
20742
|
+
id: `codex:${createHash2("sha256").update(identity).digest("hex")}`,
|
|
20743
|
+
harnessId: "codex",
|
|
20744
|
+
provider: "openai-codex",
|
|
20745
|
+
label: typeof email3 === "string" && email3 ? email3 : "Codex"
|
|
20746
|
+
},
|
|
20747
|
+
oauth: {
|
|
20748
|
+
access: t.access_token,
|
|
20749
|
+
refresh: t.refresh_token,
|
|
20750
|
+
expires: claims.exp * 1e3,
|
|
20751
|
+
accountId: t.account_id
|
|
20752
|
+
}
|
|
20753
|
+
}
|
|
20754
|
+
];
|
|
20755
|
+
} catch {
|
|
20756
|
+
return [];
|
|
20757
|
+
}
|
|
20758
|
+
}
|
|
20759
|
+
|
|
20760
|
+
// packages/host-runtime/src/credential-imports.ts
|
|
20761
|
+
async function handleCredentialImports(params, adapters, environment) {
|
|
20762
|
+
const input = credentialImportsParamsSchema.parse(params);
|
|
20763
|
+
const installed = [...adapters];
|
|
20764
|
+
const sources = await readCodexCredential(environment);
|
|
20765
|
+
for (const adapter of installed) {
|
|
20766
|
+
if (adapter.credentialExport) sources.push(...await adapter.credentialExport.read());
|
|
20767
|
+
}
|
|
20768
|
+
const request = input.request;
|
|
20769
|
+
if (request.action !== "list") {
|
|
20770
|
+
const target = installed.find((a) => a.harnessId === input.targetHarnessId)?.credentialImports;
|
|
20771
|
+
if (!target) throw new Error("Target Harness does not support credential imports");
|
|
20772
|
+
if (request.action === "remove") await target.remove(request.name);
|
|
20773
|
+
else {
|
|
20774
|
+
const source = sources.find((s) => s.source.id === request.sourceId);
|
|
20775
|
+
if (!source || !target.providers.includes(source.source.provider))
|
|
20776
|
+
throw new Error("Source login changed or is unavailable; refresh and confirm again");
|
|
20777
|
+
if (request.action === "reimport") await target.reimport(request.name, source);
|
|
20778
|
+
else await target.add(request.name, source);
|
|
20779
|
+
}
|
|
20780
|
+
}
|
|
20781
|
+
const targets = [];
|
|
20782
|
+
for (const adapter of installed) {
|
|
20783
|
+
if (!adapter.credentialImports) continue;
|
|
20784
|
+
try {
|
|
20785
|
+
targets.push({
|
|
20786
|
+
harnessId: adapter.harnessId,
|
|
20787
|
+
providers: [...adapter.credentialImports.providers],
|
|
20788
|
+
imports: await adapter.credentialImports.list(),
|
|
20789
|
+
others: await listOthers(adapter)
|
|
20790
|
+
});
|
|
20791
|
+
} catch {
|
|
20792
|
+
}
|
|
20793
|
+
}
|
|
20794
|
+
return credentialImportsResultSchema.parse({ sources: sources.map((s) => s.source), targets });
|
|
20795
|
+
}
|
|
20796
|
+
async function listOthers(adapter) {
|
|
20797
|
+
try {
|
|
20798
|
+
return await adapter.credentialImports?.listOthers?.() ?? [];
|
|
20799
|
+
} catch {
|
|
20800
|
+
return [];
|
|
20801
|
+
}
|
|
20802
|
+
}
|
|
20803
|
+
|
|
20640
20804
|
// packages/harness-adapter/dist/output-channel.js
|
|
20641
20805
|
var HarnessOutputChannel = class {
|
|
20642
20806
|
outputs;
|
|
@@ -20792,8 +20956,8 @@ var packageMetadata = {
|
|
|
20792
20956
|
import { execFileSync } from "node:child_process";
|
|
20793
20957
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
20794
20958
|
import { constants } from "node:fs";
|
|
20795
|
-
import { copyFile as copyFile2, mkdir as mkdir3, open as open3, readFile as
|
|
20796
|
-
import
|
|
20959
|
+
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";
|
|
20960
|
+
import path6 from "node:path";
|
|
20797
20961
|
|
|
20798
20962
|
// packages/mapping-store/dist/records.js
|
|
20799
20963
|
var nonBlankTextSchema6 = external_exports.string().refine((value2) => value2.trim().length > 0, {
|
|
@@ -21056,12 +21220,12 @@ var MappingStore = class {
|
|
|
21056
21220
|
#initialized = false;
|
|
21057
21221
|
#lockHandle = null;
|
|
21058
21222
|
constructor(options2) {
|
|
21059
|
-
this.#directory =
|
|
21060
|
-
this.#threadsDirectory =
|
|
21061
|
-
this.#delegationsDirectory =
|
|
21062
|
-
this.#backupsDirectory =
|
|
21063
|
-
this.#quarantineDirectory =
|
|
21064
|
-
this.#lockPath =
|
|
21223
|
+
this.#directory = path6.resolve(options2.directory);
|
|
21224
|
+
this.#threadsDirectory = path6.join(this.#directory, "threads");
|
|
21225
|
+
this.#delegationsDirectory = path6.join(this.#directory, "delegations");
|
|
21226
|
+
this.#backupsDirectory = path6.join(this.#directory, "backups");
|
|
21227
|
+
this.#quarantineDirectory = path6.join(this.#directory, "quarantine");
|
|
21228
|
+
this.#lockPath = path6.join(this.#directory, "store.lock");
|
|
21065
21229
|
this.#instanceId = options2.instanceId ?? randomUUID2();
|
|
21066
21230
|
this.#now = options2.now ?? (() => /* @__PURE__ */ new Date());
|
|
21067
21231
|
this.#beforeReplace = options2.beforeReplace;
|
|
@@ -21080,8 +21244,8 @@ var MappingStore = class {
|
|
|
21080
21244
|
await this.#cleanupResidue();
|
|
21081
21245
|
const names = (await readdir2(this.#threadsDirectory)).filter((name) => name.endsWith(".json"));
|
|
21082
21246
|
for (const name of names) {
|
|
21083
|
-
const primary =
|
|
21084
|
-
const backup =
|
|
21247
|
+
const primary = path6.join(this.#threadsDirectory, name);
|
|
21248
|
+
const backup = path6.join(this.#backupsDirectory, name);
|
|
21085
21249
|
let record3 = null;
|
|
21086
21250
|
try {
|
|
21087
21251
|
record3 = await this.#readRecord(primary, name);
|
|
@@ -21090,7 +21254,7 @@ var MappingStore = class {
|
|
|
21090
21254
|
record3 = await this.#readRecord(backup, name);
|
|
21091
21255
|
await this.#replaceFile(primary, record3, false);
|
|
21092
21256
|
} catch (backupError) {
|
|
21093
|
-
const quarantine =
|
|
21257
|
+
const quarantine = path6.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid`);
|
|
21094
21258
|
await rename2(primary, quarantine).catch(() => void 0);
|
|
21095
21259
|
void primaryError;
|
|
21096
21260
|
void backupError;
|
|
@@ -21106,14 +21270,14 @@ var MappingStore = class {
|
|
|
21106
21270
|
}
|
|
21107
21271
|
const delegationNames = (await readdir2(this.#delegationsDirectory)).filter((name) => name.endsWith(".json"));
|
|
21108
21272
|
for (const name of delegationNames) {
|
|
21109
|
-
const file2 =
|
|
21273
|
+
const file2 = path6.join(this.#delegationsDirectory, name);
|
|
21110
21274
|
try {
|
|
21111
|
-
const parsed = storedDelegationRecordV1Schema.parse(JSON.parse(await
|
|
21275
|
+
const parsed = storedDelegationRecordV1Schema.parse(JSON.parse(await readFile5(file2, "utf8")));
|
|
21112
21276
|
if (`${parsed.delegationId}.json` !== name)
|
|
21113
21277
|
throw new Error("filename mismatch");
|
|
21114
21278
|
this.#delegations.set(parsed.delegationId, parsed);
|
|
21115
21279
|
} catch {
|
|
21116
|
-
const quarantine =
|
|
21280
|
+
const quarantine = path6.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid-delegation`);
|
|
21117
21281
|
await rename2(file2, quarantine).catch(() => void 0);
|
|
21118
21282
|
}
|
|
21119
21283
|
}
|
|
@@ -21407,7 +21571,7 @@ var MappingStore = class {
|
|
|
21407
21571
|
if (handle)
|
|
21408
21572
|
await handle.close().catch(() => void 0);
|
|
21409
21573
|
try {
|
|
21410
|
-
const current = JSON.parse(await
|
|
21574
|
+
const current = JSON.parse(await readFile5(this.#lockPath, "utf8"));
|
|
21411
21575
|
if (current.instanceId === this.#instanceId)
|
|
21412
21576
|
await rm3(this.#lockPath, { force: true });
|
|
21413
21577
|
} catch {
|
|
@@ -21523,7 +21687,7 @@ var MappingStore = class {
|
|
|
21523
21687
|
}
|
|
21524
21688
|
}
|
|
21525
21689
|
async #readRecord(file2, expectedName) {
|
|
21526
|
-
const parsed = storedThreadRecordV1Schema.safeParse(JSON.parse(await
|
|
21690
|
+
const parsed = storedThreadRecordV1Schema.safeParse(JSON.parse(await readFile5(file2, "utf8")));
|
|
21527
21691
|
if (!parsed.success) {
|
|
21528
21692
|
throw new MappingStoreError("INVALID_RECORD", "Mapping Store record is invalid", {
|
|
21529
21693
|
cause: parsed.error
|
|
@@ -21541,10 +21705,10 @@ var MappingStore = class {
|
|
|
21541
21705
|
readdir2(this.#directory)
|
|
21542
21706
|
]);
|
|
21543
21707
|
await Promise.all([
|
|
21544
|
-
...threadNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(
|
|
21545
|
-
...delegationNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(
|
|
21708
|
+
...threadNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(path6.join(this.#threadsDirectory, name), { force: true })),
|
|
21709
|
+
...delegationNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(path6.join(this.#delegationsDirectory, name), { force: true })),
|
|
21546
21710
|
// Renamed aside by #acquireLock; nothing reads them back, and they accumulate one per run.
|
|
21547
|
-
...rootNames.filter((name) => name.startsWith(`${
|
|
21711
|
+
...rootNames.filter((name) => name.startsWith(`${path6.basename(this.#lockPath)}.stale-`)).map((name) => rm3(path6.join(this.#directory, name), { force: true }))
|
|
21548
21712
|
]);
|
|
21549
21713
|
}
|
|
21550
21714
|
async #acquireLock() {
|
|
@@ -21571,7 +21735,7 @@ var MappingStore = class {
|
|
|
21571
21735
|
}
|
|
21572
21736
|
let existing = {};
|
|
21573
21737
|
try {
|
|
21574
|
-
existing = JSON.parse(await
|
|
21738
|
+
existing = JSON.parse(await readFile5(this.#lockPath, "utf8"));
|
|
21575
21739
|
} catch {
|
|
21576
21740
|
}
|
|
21577
21741
|
if (typeof existing.pid === "number" && lockOwnerIsLive(existing)) {
|
|
@@ -21645,13 +21809,13 @@ var MappingStore = class {
|
|
|
21645
21809
|
await next;
|
|
21646
21810
|
}
|
|
21647
21811
|
#recordPath(hostThreadId) {
|
|
21648
|
-
return
|
|
21812
|
+
return path6.join(this.#threadsDirectory, `${hostThreadId}.json`);
|
|
21649
21813
|
}
|
|
21650
21814
|
#delegationPath(delegationId) {
|
|
21651
|
-
return
|
|
21815
|
+
return path6.join(this.#delegationsDirectory, `${delegationId}.json`);
|
|
21652
21816
|
}
|
|
21653
21817
|
#backupPath(hostThreadId) {
|
|
21654
|
-
return
|
|
21818
|
+
return path6.join(this.#backupsDirectory, `${hostThreadId}.json`);
|
|
21655
21819
|
}
|
|
21656
21820
|
#requireInitialized() {
|
|
21657
21821
|
if (!this.#initialized) {
|
|
@@ -22348,16 +22512,16 @@ var Diff = class {
|
|
|
22348
22512
|
}
|
|
22349
22513
|
}
|
|
22350
22514
|
}
|
|
22351
|
-
addToPath(
|
|
22352
|
-
const last =
|
|
22515
|
+
addToPath(path28, added, removed, oldPosInc, options2) {
|
|
22516
|
+
const last = path28.lastComponent;
|
|
22353
22517
|
if (last && !options2.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
22354
22518
|
return {
|
|
22355
|
-
oldPos:
|
|
22519
|
+
oldPos: path28.oldPos + oldPosInc,
|
|
22356
22520
|
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
22357
22521
|
};
|
|
22358
22522
|
} else {
|
|
22359
22523
|
return {
|
|
22360
|
-
oldPos:
|
|
22524
|
+
oldPos: path28.oldPos + oldPosInc,
|
|
22361
22525
|
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
22362
22526
|
};
|
|
22363
22527
|
}
|
|
@@ -22786,10 +22950,10 @@ function splitLines(text2) {
|
|
|
22786
22950
|
}
|
|
22787
22951
|
|
|
22788
22952
|
// packages/protocol-core/dist/file-change-summary.js
|
|
22789
|
-
import
|
|
22953
|
+
import path7 from "node:path";
|
|
22790
22954
|
function filePathKey(file2, cwd) {
|
|
22791
22955
|
const windows = /^[a-z]:[/\\]/i.test(cwd) || /^[a-z]:[/\\]/i.test(file2);
|
|
22792
|
-
const paths = windows ?
|
|
22956
|
+
const paths = windows ? path7.win32 : path7.posix;
|
|
22793
22957
|
const resolved = paths.resolve(cwd, file2).replaceAll("\\", "/");
|
|
22794
22958
|
return windows ? resolved.toLowerCase() : resolved;
|
|
22795
22959
|
}
|
|
@@ -23059,8 +23223,8 @@ function projectFileChangeKind(kind) {
|
|
|
23059
23223
|
return { type: kind };
|
|
23060
23224
|
}
|
|
23061
23225
|
function projectFileChanges(changes) {
|
|
23062
|
-
return changes.map(({ path:
|
|
23063
|
-
path:
|
|
23226
|
+
return changes.map(({ path: path28, kind, unifiedDiff }) => ({
|
|
23227
|
+
path: path28,
|
|
23064
23228
|
kind: projectFileChangeKind(kind),
|
|
23065
23229
|
diff: unifiedDiff
|
|
23066
23230
|
}));
|
|
@@ -24007,13 +24171,13 @@ function decodeThreadForkRequest(request) {
|
|
|
24007
24171
|
if (runtimeWorkspaceRoots !== void 0 && runtimeWorkspaceRoots !== null && (!Array.isArray(runtimeWorkspaceRoots) || runtimeWorkspaceRoots.some((root) => typeof root !== "string" || root.length === 0))) {
|
|
24008
24172
|
throw new Error("thread/fork params.runtimeWorkspaceRoots must be text paths or null");
|
|
24009
24173
|
}
|
|
24010
|
-
const
|
|
24174
|
+
const path28 = optionalText(params, "path", { allowEmpty: true });
|
|
24011
24175
|
const ephemeral = optionalBoolean(params, "ephemeral");
|
|
24012
24176
|
return {
|
|
24013
24177
|
threadId: threadId2,
|
|
24014
24178
|
...lastTurnText ? { lastTurnId: hostTurnIdSchema.parse(lastTurnText) } : {},
|
|
24015
24179
|
...beforeTurnText ? { beforeTurnId: hostTurnIdSchema.parse(beforeTurnText) } : {},
|
|
24016
|
-
...
|
|
24180
|
+
...path28 ? { path: path28 } : {},
|
|
24017
24181
|
...optionalField(params, "model"),
|
|
24018
24182
|
...optionalField(params, "modelProvider"),
|
|
24019
24183
|
...optionalField(params, "cwd"),
|
|
@@ -24106,7 +24270,7 @@ function threadForkResult(thread, input) {
|
|
|
24106
24270
|
}
|
|
24107
24271
|
|
|
24108
24272
|
// packages/protocol-core/dist/thread-management.js
|
|
24109
|
-
import { createHash as
|
|
24273
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
24110
24274
|
var HOST_CURSOR_PREFIX = "codexhost:thread-list:v1:";
|
|
24111
24275
|
var MAX_CURSOR_LENGTH = 65536;
|
|
24112
24276
|
var DEFAULT_PAGE_SIZE = 25;
|
|
@@ -24197,13 +24361,13 @@ function decodeSortDirection(value2) {
|
|
|
24197
24361
|
function decodeSortKey(value2) {
|
|
24198
24362
|
if (value2 === void 0 || value2 === null)
|
|
24199
24363
|
return "created_at";
|
|
24200
|
-
if (value2 !== "created_at" && value2 !== "updated_at" && value2 !== "recency_at") {
|
|
24364
|
+
if (value2 !== "created_at" && value2 !== "updated_at" && value2 !== "recency_at" && value2 !== "section_position") {
|
|
24201
24365
|
throw new Error("thread/list params.sortKey is unsupported");
|
|
24202
24366
|
}
|
|
24203
24367
|
return value2;
|
|
24204
24368
|
}
|
|
24205
24369
|
function queryFingerprint(value2) {
|
|
24206
|
-
return
|
|
24370
|
+
return createHash3("sha256").update(JSON.stringify(value2)).digest("hex");
|
|
24207
24371
|
}
|
|
24208
24372
|
function cursorPayload(value2) {
|
|
24209
24373
|
return {
|
|
@@ -24301,7 +24465,10 @@ function decodeThreadListRequest(request) {
|
|
|
24301
24465
|
const cursorText = nullableText(params.cursor, "thread/list params.cursor");
|
|
24302
24466
|
const hasUnknownFields = Object.keys(params).some((name) => !THREAD_LIST_FIELDS.has(name));
|
|
24303
24467
|
const isHostCursor = cursorText?.startsWith(HOST_CURSOR_PREFIX) === true;
|
|
24304
|
-
|
|
24468
|
+
if (sortKey === "section_position" && isHostCursor) {
|
|
24469
|
+
throw new Error("thread/list Host cursor cannot be used with section_position sorting");
|
|
24470
|
+
}
|
|
24471
|
+
const supportsExternal = sortKey !== "section_position" && !hasUnknownFields && (cursorText === null || isHostCursor);
|
|
24305
24472
|
const cursor = supportsExternal && cursorText ? decodeHostThreadListCursor(cursorText, {
|
|
24306
24473
|
queryFingerprint: fingerprint,
|
|
24307
24474
|
sortDirection: sortDirection2
|
|
@@ -24880,22 +25047,38 @@ async function* readLfFrames(stream, options2 = {}) {
|
|
|
24880
25047
|
const maximum = options2.maxFrameBytes ?? Infinity;
|
|
24881
25048
|
if (maximum !== Infinity && (!Number.isSafeInteger(maximum) || maximum < 1))
|
|
24882
25049
|
throw new Error("Invalid protocol frame limit");
|
|
24883
|
-
let
|
|
25050
|
+
let pendingChunks = [];
|
|
25051
|
+
let pendingLength = 0;
|
|
24884
25052
|
for await (const chunk of stream) {
|
|
24885
25053
|
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
24886
|
-
|
|
24887
|
-
let newlineIndex =
|
|
25054
|
+
let frameStart = 0;
|
|
25055
|
+
let newlineIndex = bytes.indexOf(10);
|
|
24888
25056
|
while (newlineIndex >= 0) {
|
|
24889
|
-
|
|
25057
|
+
const tail = bytes.subarray(frameStart, newlineIndex);
|
|
25058
|
+
const frameLength = pendingLength + tail.length;
|
|
25059
|
+
if (frameLength > maximum)
|
|
25060
|
+
throw new Error("Protocol frame exceeds its limit");
|
|
25061
|
+
if (pendingLength === 0) {
|
|
25062
|
+
yield tail;
|
|
25063
|
+
} else {
|
|
25064
|
+
pendingChunks.push(tail);
|
|
25065
|
+
pendingLength = frameLength;
|
|
25066
|
+
yield Buffer.concat(pendingChunks, pendingLength);
|
|
25067
|
+
pendingChunks = [];
|
|
25068
|
+
pendingLength = 0;
|
|
25069
|
+
}
|
|
25070
|
+
frameStart = newlineIndex + 1;
|
|
25071
|
+
newlineIndex = bytes.indexOf(10, frameStart);
|
|
25072
|
+
}
|
|
25073
|
+
if (frameStart < bytes.length) {
|
|
25074
|
+
const remainder = bytes.subarray(frameStart);
|
|
25075
|
+
pendingChunks.push(remainder);
|
|
25076
|
+
pendingLength += remainder.length;
|
|
25077
|
+
if (pendingLength > maximum)
|
|
24890
25078
|
throw new Error("Protocol frame exceeds its limit");
|
|
24891
|
-
yield pending.subarray(0, newlineIndex);
|
|
24892
|
-
pending = pending.subarray(newlineIndex + 1);
|
|
24893
|
-
newlineIndex = pending.indexOf(10);
|
|
24894
25079
|
}
|
|
24895
|
-
if (pending.length > maximum)
|
|
24896
|
-
throw new Error("Protocol frame exceeds its limit");
|
|
24897
25080
|
}
|
|
24898
|
-
if (
|
|
25081
|
+
if (pendingLength !== 0) {
|
|
24899
25082
|
throw new Error("Protocol stream ended with an unterminated JSONL frame");
|
|
24900
25083
|
}
|
|
24901
25084
|
}
|
|
@@ -25170,22 +25353,22 @@ var HarnessAccountInspectionCache = class {
|
|
|
25170
25353
|
};
|
|
25171
25354
|
|
|
25172
25355
|
// packages/host-runtime/src/app-server-host.ts
|
|
25173
|
-
import { createHash as
|
|
25174
|
-
import
|
|
25175
|
-
import
|
|
25356
|
+
import { createHash as createHash7, randomUUID as randomUUID9 } from "node:crypto";
|
|
25357
|
+
import os4 from "node:os";
|
|
25358
|
+
import path14 from "node:path";
|
|
25176
25359
|
|
|
25177
25360
|
// packages/host-runtime/src/external-thread-fork.ts
|
|
25178
25361
|
import nodePath from "node:path";
|
|
25179
25362
|
|
|
25180
25363
|
// packages/host-runtime/src/external-thread-repository.ts
|
|
25181
25364
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
25182
|
-
import
|
|
25183
|
-
import
|
|
25365
|
+
import os2 from "node:os";
|
|
25366
|
+
import path8 from "node:path";
|
|
25184
25367
|
|
|
25185
25368
|
// packages/host-runtime/src/external-subagent-threads.ts
|
|
25186
|
-
import { createHash as
|
|
25369
|
+
import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
|
|
25187
25370
|
function childCreateRequest(parent, nativeRef, id2) {
|
|
25188
|
-
const key =
|
|
25371
|
+
const key = createHash4("sha256").update(JSON.stringify([parent.hostThreadId, parent.harnessId, nativeRef.nativeSessionId, id2])).digest("hex");
|
|
25189
25372
|
return `subagent:${key}`;
|
|
25190
25373
|
}
|
|
25191
25374
|
function subagentMaterializer(store, parent, previousParent) {
|
|
@@ -25320,8 +25503,8 @@ function sameMapping(left, right) {
|
|
|
25320
25503
|
}
|
|
25321
25504
|
function defaultMappingStoreDirectory(environment) {
|
|
25322
25505
|
const dataDirectory = environment.CODEXHOST_DATA_DIR;
|
|
25323
|
-
return
|
|
25324
|
-
dataDirectory ?
|
|
25506
|
+
return path8.join(
|
|
25507
|
+
dataDirectory ? path8.resolve(dataDirectory) : path8.join(os2.homedir(), ".codexhost"),
|
|
25325
25508
|
"mapping-store"
|
|
25326
25509
|
);
|
|
25327
25510
|
}
|
|
@@ -27395,11 +27578,11 @@ var ExternalTurnSteering = class {
|
|
|
27395
27578
|
};
|
|
27396
27579
|
|
|
27397
27580
|
// packages/host-runtime/src/harness-delegation-coordinator.ts
|
|
27398
|
-
import { createHash as
|
|
27399
|
-
import
|
|
27581
|
+
import { createHash as createHash6, randomUUID as randomUUID5 } from "node:crypto";
|
|
27582
|
+
import path9 from "node:path";
|
|
27400
27583
|
|
|
27401
27584
|
// packages/host-runtime/src/delegation-snapshot.ts
|
|
27402
|
-
import { createHash as
|
|
27585
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
27403
27586
|
var CURSOR_PREFIX = "codexhost:thread-messages:v1:";
|
|
27404
27587
|
var DEFAULT_MESSAGE_LIMIT = 25;
|
|
27405
27588
|
var MAX_MESSAGE_LIMIT = 100;
|
|
@@ -27453,7 +27636,7 @@ function allVisibleMessages(turns) {
|
|
|
27453
27636
|
return messages;
|
|
27454
27637
|
}
|
|
27455
27638
|
function cursorFingerprint(threadId2) {
|
|
27456
|
-
return
|
|
27639
|
+
return createHash5("sha256").update(threadId2).digest("hex");
|
|
27457
27640
|
}
|
|
27458
27641
|
function encodeCursor(threadId2, offset) {
|
|
27459
27642
|
const payload = JSON.stringify({ version: 1, fingerprint: cursorFingerprint(threadId2), offset });
|
|
@@ -27564,10 +27747,10 @@ function terminal(status) {
|
|
|
27564
27747
|
return status === "completed" || status === "failed" || status === "interrupted";
|
|
27565
27748
|
}
|
|
27566
27749
|
function taskDigest(input) {
|
|
27567
|
-
return
|
|
27750
|
+
return createHash6("sha256").update(
|
|
27568
27751
|
JSON.stringify({
|
|
27569
27752
|
task: input.task,
|
|
27570
|
-
cwd:
|
|
27753
|
+
cwd: path9.resolve(input.cwd),
|
|
27571
27754
|
modelId: input.model?.id ?? null,
|
|
27572
27755
|
thinkingOptionId: input.thinkingOptionId ?? null
|
|
27573
27756
|
})
|
|
@@ -27638,7 +27821,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
27638
27821
|
return {
|
|
27639
27822
|
harnessId: input.harnessId,
|
|
27640
27823
|
inspection: await adapter.inspect({
|
|
27641
|
-
...input.cwd ? { cwd:
|
|
27824
|
+
...input.cwd ? { cwd: path9.resolve(input.cwd) } : {},
|
|
27642
27825
|
...input.refresh !== void 0 ? { refresh: input.refresh } : {}
|
|
27643
27826
|
})
|
|
27644
27827
|
};
|
|
@@ -27652,7 +27835,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
27652
27835
|
const result = await this.#startOfficial({ ...input, parentThreadId, cwd: selectedCwd });
|
|
27653
27836
|
return { ...result, parentThreadId, cwd: result.cwd ?? selectedCwd };
|
|
27654
27837
|
}
|
|
27655
|
-
const startInput = { ...input, parentThreadId, cwd:
|
|
27838
|
+
const startInput = { ...input, parentThreadId, cwd: path9.resolve(selectedCwd) };
|
|
27656
27839
|
if (!this.#adapters.has(input.harnessId)) {
|
|
27657
27840
|
throw new DelegationControlError(
|
|
27658
27841
|
"HARNESS_NOT_FOUND",
|
|
@@ -28081,7 +28264,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
28081
28264
|
|
|
28082
28265
|
// packages/host-runtime/src/harness-plugin-loader.ts
|
|
28083
28266
|
import { readdir as readdir3, realpath as realpath2 } from "node:fs/promises";
|
|
28084
|
-
import
|
|
28267
|
+
import path11 from "node:path";
|
|
28085
28268
|
import { pathToFileURL } from "node:url";
|
|
28086
28269
|
|
|
28087
28270
|
// packages/host-runtime/src/harness-plugin-registry.ts
|
|
@@ -28119,16 +28302,16 @@ var HarnessPluginRegistry = class {
|
|
|
28119
28302
|
|
|
28120
28303
|
// packages/host-runtime/src/plugin-files.ts
|
|
28121
28304
|
import { open as open4, realpath, stat as stat2 } from "node:fs/promises";
|
|
28122
|
-
import
|
|
28305
|
+
import path10 from "node:path";
|
|
28123
28306
|
function inside(root, candidate) {
|
|
28124
|
-
const relative =
|
|
28125
|
-
return relative !== "" && !
|
|
28307
|
+
const relative = path10.relative(root, candidate);
|
|
28308
|
+
return relative !== "" && !path10.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path10.sep}`);
|
|
28126
28309
|
}
|
|
28127
28310
|
async function pluginResourcePath(root, relative) {
|
|
28128
|
-
if (
|
|
28311
|
+
if (path10.isAbsolute(relative) || !inside(root, path10.resolve(root, relative))) {
|
|
28129
28312
|
throw new Error("Plugin resource escapes its root");
|
|
28130
28313
|
}
|
|
28131
|
-
const resolved = await realpath(
|
|
28314
|
+
const resolved = await realpath(path10.resolve(root, relative));
|
|
28132
28315
|
if (!inside(root, resolved) || !(await stat2(resolved)).isFile()) {
|
|
28133
28316
|
throw new Error("Plugin resource must be a regular file inside its root");
|
|
28134
28317
|
}
|
|
@@ -28290,7 +28473,7 @@ async function loadHarnessPlugins(options2) {
|
|
|
28290
28473
|
const enabledIds = /* @__PURE__ */ new Set();
|
|
28291
28474
|
const roots = /* @__PURE__ */ new Set();
|
|
28292
28475
|
for (const configuredRoot of options2.roots) {
|
|
28293
|
-
if (!
|
|
28476
|
+
if (!path11.isAbsolute(configuredRoot)) {
|
|
28294
28477
|
diagnose({ code: "invalidRoot" });
|
|
28295
28478
|
continue;
|
|
28296
28479
|
}
|
|
@@ -28320,7 +28503,7 @@ async function loadHarnessPlugins(options2) {
|
|
|
28320
28503
|
for (const directory of directories) {
|
|
28321
28504
|
try {
|
|
28322
28505
|
const file2 = await pluginResourcePath(root, `${directory.name}/manifest.json`);
|
|
28323
|
-
const pluginRoot = await realpath2(
|
|
28506
|
+
const pluginRoot = await realpath2(path11.join(root, directory.name));
|
|
28324
28507
|
await pluginResourcePath(pluginRoot, "manifest.json");
|
|
28325
28508
|
const manifest = harnessPluginManifestSchema.parse(
|
|
28326
28509
|
JSON.parse(
|
|
@@ -28372,6 +28555,7 @@ async function loadHarnessPlugins(options2) {
|
|
|
28372
28555
|
id: manifest.id,
|
|
28373
28556
|
name: manifest.name,
|
|
28374
28557
|
version: manifest.version,
|
|
28558
|
+
...manifest.launchCommand && !options2.context.managedRemoteHost ? { launchCommand: true } : {},
|
|
28375
28559
|
...manifest.links ? { links: manifest.links } : {}
|
|
28376
28560
|
});
|
|
28377
28561
|
let adapter;
|
|
@@ -28382,9 +28566,10 @@ async function loadHarnessPlugins(options2) {
|
|
|
28382
28566
|
} else {
|
|
28383
28567
|
try {
|
|
28384
28568
|
if (manifest.icon) descriptor.icon = await readPluginIcon(candidate.root, manifest.icon);
|
|
28569
|
+
const launchCommand = descriptor.launchCommand ? await options2.launchCommandForPlugin?.(manifest.id) : void 0;
|
|
28385
28570
|
adapter = await loadAdapter(
|
|
28386
28571
|
candidate,
|
|
28387
|
-
options2.context,
|
|
28572
|
+
{ ...options2.context, ...launchCommand ? { launchCommand } : {} },
|
|
28388
28573
|
timeoutMs,
|
|
28389
28574
|
diagnose,
|
|
28390
28575
|
options2.warmup !== false,
|
|
@@ -28412,6 +28597,76 @@ async function loadHarnessPlugins(options2) {
|
|
|
28412
28597
|
return registry2;
|
|
28413
28598
|
}
|
|
28414
28599
|
|
|
28600
|
+
// packages/host-runtime/src/harness-launch-settings.ts
|
|
28601
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
28602
|
+
import { mkdir as mkdir4, readFile as readFile6, rename as rename3, rm as rm4, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
|
|
28603
|
+
import os3 from "node:os";
|
|
28604
|
+
import path12 from "node:path";
|
|
28605
|
+
var HarnessLaunchSettingsStore = class {
|
|
28606
|
+
#directory;
|
|
28607
|
+
#initial = /* @__PURE__ */ new Map();
|
|
28608
|
+
constructor(environment) {
|
|
28609
|
+
this.#directory = path12.join(
|
|
28610
|
+
environment.CODEXHOST_DATA_DIR ? path12.resolve(environment.CODEXHOST_DATA_DIR) : path12.join(os3.homedir(), ".codexhost"),
|
|
28611
|
+
"harness-launch-settings"
|
|
28612
|
+
);
|
|
28613
|
+
}
|
|
28614
|
+
#file(id2) {
|
|
28615
|
+
return path12.join(this.#directory, `${harnessPluginIdSchema.parse(id2)}.json`);
|
|
28616
|
+
}
|
|
28617
|
+
async #read(id2) {
|
|
28618
|
+
try {
|
|
28619
|
+
const value2 = harnessLaunchPathSchema.parse(
|
|
28620
|
+
JSON.parse(await readFile6(this.#file(id2), "utf8"))
|
|
28621
|
+
);
|
|
28622
|
+
if (!path12.isAbsolute(value2)) throw new Error("Expected an absolute entrypoint path");
|
|
28623
|
+
return value2;
|
|
28624
|
+
} catch (error51) {
|
|
28625
|
+
if (error51 && typeof error51 === "object" && "code" in error51 && error51.code === "ENOENT")
|
|
28626
|
+
return null;
|
|
28627
|
+
throw new Error("Could not read Harness launch settings");
|
|
28628
|
+
}
|
|
28629
|
+
}
|
|
28630
|
+
/** Capture the value used to construct this Host's Adapter; changes require a restart. */
|
|
28631
|
+
async initialCommand(id2) {
|
|
28632
|
+
let initial = this.#initial.get(id2);
|
|
28633
|
+
if (!initial) {
|
|
28634
|
+
initial = this.#read(id2);
|
|
28635
|
+
this.#initial.set(id2, initial);
|
|
28636
|
+
}
|
|
28637
|
+
return await initial ?? void 0;
|
|
28638
|
+
}
|
|
28639
|
+
async get(id2) {
|
|
28640
|
+
const initial = await this.initialCommand(id2) ?? null;
|
|
28641
|
+
const value2 = await this.#read(id2);
|
|
28642
|
+
return { path: value2, restartRequired: value2 !== initial };
|
|
28643
|
+
}
|
|
28644
|
+
async set(id2, value2) {
|
|
28645
|
+
const initial = await this.initialCommand(id2) ?? null;
|
|
28646
|
+
const file2 = this.#file(id2);
|
|
28647
|
+
if (value2 === null) {
|
|
28648
|
+
await rm4(file2, { force: true });
|
|
28649
|
+
} else {
|
|
28650
|
+
value2 = harnessLaunchPathSchema.parse(value2);
|
|
28651
|
+
if (!path12.isAbsolute(value2))
|
|
28652
|
+
throw new Error("Use an absolute entrypoint path without arguments");
|
|
28653
|
+
const metadata = await stat3(value2).catch(() => void 0);
|
|
28654
|
+
if (!metadata?.isDirectory() && !metadata?.isFile())
|
|
28655
|
+
throw new Error("The installation path must be an existing directory on this Host");
|
|
28656
|
+
await mkdir4(this.#directory, { recursive: true, mode: 448 });
|
|
28657
|
+
const temporary = `${file2}.${randomUUID6()}.tmp`;
|
|
28658
|
+
try {
|
|
28659
|
+
await writeFile3(temporary, `${JSON.stringify(value2)}
|
|
28660
|
+
`, { mode: 384, flag: "wx" });
|
|
28661
|
+
await rename3(temporary, file2);
|
|
28662
|
+
} finally {
|
|
28663
|
+
await rm4(temporary, { force: true });
|
|
28664
|
+
}
|
|
28665
|
+
}
|
|
28666
|
+
return { path: value2, restartRequired: value2 !== initial };
|
|
28667
|
+
}
|
|
28668
|
+
};
|
|
28669
|
+
|
|
28415
28670
|
// packages/host-runtime/src/official-codex-model-ref.ts
|
|
28416
28671
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
28417
28672
|
var OFFICIAL_CODEX_MODEL_REF_PREFIX = "codex-model-v1.";
|
|
@@ -28602,8 +28857,8 @@ var SingleNativeCodexAccount = class {
|
|
|
28602
28857
|
};
|
|
28603
28858
|
|
|
28604
28859
|
// packages/host-runtime/src/account/codex-home-auth.ts
|
|
28605
|
-
import { readFile as
|
|
28606
|
-
import
|
|
28860
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
28861
|
+
import path13 from "node:path";
|
|
28607
28862
|
var CODEX_API_AUTH_IDENTITY_FALLBACK = "BANK OF TOKEN";
|
|
28608
28863
|
function tomlUnquote(value2) {
|
|
28609
28864
|
const trimmed = value2.trim();
|
|
@@ -28724,7 +28979,7 @@ function inspectCodexAuthDocuments(input) {
|
|
|
28724
28979
|
}
|
|
28725
28980
|
async function readOptionalUtf8(file2) {
|
|
28726
28981
|
try {
|
|
28727
|
-
return await
|
|
28982
|
+
return await readFile7(file2, "utf8");
|
|
28728
28983
|
} catch (error51) {
|
|
28729
28984
|
if (error51.code === "ENOENT") return void 0;
|
|
28730
28985
|
throw error51;
|
|
@@ -28749,10 +29004,10 @@ function inspectCodexApiUsageSource(input) {
|
|
|
28749
29004
|
return { baseUrl, apiKey };
|
|
28750
29005
|
}
|
|
28751
29006
|
async function inspectCodexHomeAuth(codexHome) {
|
|
28752
|
-
const root =
|
|
29007
|
+
const root = path13.resolve(codexHome);
|
|
28753
29008
|
const [configToml, authJson] = await Promise.all([
|
|
28754
|
-
readOptionalUtf8(
|
|
28755
|
-
readOptionalUtf8(
|
|
29009
|
+
readOptionalUtf8(path13.join(root, "config.toml")),
|
|
29010
|
+
readOptionalUtf8(path13.join(root, "auth.json"))
|
|
28756
29011
|
]);
|
|
28757
29012
|
return inspectCodexAuthDocuments({
|
|
28758
29013
|
...configToml ? { configToml } : {},
|
|
@@ -28760,10 +29015,10 @@ async function inspectCodexHomeAuth(codexHome) {
|
|
|
28760
29015
|
});
|
|
28761
29016
|
}
|
|
28762
29017
|
async function inspectCodexHomeApiUsageSource(codexHome, env = process.env) {
|
|
28763
|
-
const root =
|
|
29018
|
+
const root = path13.resolve(codexHome);
|
|
28764
29019
|
const [configToml, authJson] = await Promise.all([
|
|
28765
|
-
readOptionalUtf8(
|
|
28766
|
-
readOptionalUtf8(
|
|
29020
|
+
readOptionalUtf8(path13.join(root, "config.toml")),
|
|
29021
|
+
readOptionalUtf8(path13.join(root, "auth.json"))
|
|
28767
29022
|
]);
|
|
28768
29023
|
return inspectCodexApiUsageSource({
|
|
28769
29024
|
...configToml ? { configToml } : {},
|
|
@@ -28879,10 +29134,10 @@ function projectCodexAccountAuth(snapshot, homeAuth) {
|
|
|
28879
29134
|
}
|
|
28880
29135
|
|
|
28881
29136
|
// packages/host-runtime/src/codex-runtime/official-runtime-owner.ts
|
|
28882
|
-
import { randomUUID as
|
|
29137
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
28883
29138
|
|
|
28884
29139
|
// packages/host-runtime/src/official-request-broker.ts
|
|
28885
|
-
import { randomUUID as
|
|
29140
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
28886
29141
|
var INTERNAL_REQUEST_PREFIX = "codexhost:official:";
|
|
28887
29142
|
var MAX_RETIRED_IDS = 1024;
|
|
28888
29143
|
function isRecord11(value2) {
|
|
@@ -28898,7 +29153,7 @@ var OfficialRequestBroker = class {
|
|
|
28898
29153
|
constructor(input) {
|
|
28899
29154
|
this.#send = input.send;
|
|
28900
29155
|
this.#timeoutMs = input.timeoutMs ?? 3e4;
|
|
28901
|
-
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${
|
|
29156
|
+
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID7()}`);
|
|
28902
29157
|
}
|
|
28903
29158
|
get pendingCount() {
|
|
28904
29159
|
return this.#pending.size;
|
|
@@ -29252,7 +29507,7 @@ var OfficialRuntimeOwner = class {
|
|
|
29252
29507
|
}
|
|
29253
29508
|
#attach(role, output, onBackendStopped) {
|
|
29254
29509
|
const client = {
|
|
29255
|
-
id:
|
|
29510
|
+
id: randomUUID8(),
|
|
29256
29511
|
role,
|
|
29257
29512
|
output,
|
|
29258
29513
|
...onBackendStopped ? { onBackendStopped } : {},
|
|
@@ -29410,7 +29665,7 @@ var OfficialRuntimeOwner = class {
|
|
|
29410
29665
|
if (!object4(value2)) return client.output(event);
|
|
29411
29666
|
if (typeof value2.id === "string" || typeof value2.id === "number") {
|
|
29412
29667
|
if (typeof value2.method === "string") {
|
|
29413
|
-
const id2 = `codexhost:server:${client.id}:${event.generation}:${
|
|
29668
|
+
const id2 = `codexhost:server:${client.id}:${event.generation}:${randomUUID8()}`;
|
|
29414
29669
|
client.serverRequests.set(id2, value2.id);
|
|
29415
29670
|
const projected = { ...value2, id: id2 };
|
|
29416
29671
|
return client.output({
|
|
@@ -29805,25 +30060,25 @@ function resolveExternalSessionTreeIds(records) {
|
|
|
29805
30060
|
const resolve = (start) => {
|
|
29806
30061
|
const cached2 = resolved.get(start.hostThreadId);
|
|
29807
30062
|
if (cached2) return cached2;
|
|
29808
|
-
const
|
|
30063
|
+
const path28 = [];
|
|
29809
30064
|
const visited = /* @__PURE__ */ new Set();
|
|
29810
30065
|
let current = start;
|
|
29811
30066
|
while (true) {
|
|
29812
30067
|
const known = resolved.get(current.hostThreadId);
|
|
29813
30068
|
if (known) {
|
|
29814
|
-
for (const record3 of
|
|
30069
|
+
for (const record3 of path28) resolved.set(record3.hostThreadId, known);
|
|
29815
30070
|
return known;
|
|
29816
30071
|
}
|
|
29817
30072
|
if (visited.has(current.hostThreadId)) {
|
|
29818
30073
|
throw new Error("External Thread Fork tree contains a cycle");
|
|
29819
30074
|
}
|
|
29820
30075
|
visited.add(current.hostThreadId);
|
|
29821
|
-
|
|
30076
|
+
path28.push(current);
|
|
29822
30077
|
const sourceId = current.subagent?.parentHostThreadId ?? current.forkSource?.hostThreadId;
|
|
29823
30078
|
const source = sourceId ? byId.get(sourceId) : void 0;
|
|
29824
30079
|
if (!source) {
|
|
29825
30080
|
const root = current.hostThreadId;
|
|
29826
|
-
for (const record3 of
|
|
30081
|
+
for (const record3 of path28) resolved.set(record3.hostThreadId, root);
|
|
29827
30082
|
return root;
|
|
29828
30083
|
}
|
|
29829
30084
|
current = source;
|
|
@@ -29833,7 +30088,9 @@ function resolveExternalSessionTreeIds(records) {
|
|
|
29833
30088
|
return resolved;
|
|
29834
30089
|
}
|
|
29835
30090
|
function listExternalThreadMetadata(input) {
|
|
29836
|
-
if (!input.query.supportsExternal
|
|
30091
|
+
if (!input.query.supportsExternal || input.query.sortKey === "section_position") {
|
|
30092
|
+
return { data: [], hasMore: false };
|
|
30093
|
+
}
|
|
29837
30094
|
const sessionIds = resolveExternalSessionTreeIds(input.records);
|
|
29838
30095
|
const byId = new Map(input.records.map((record3) => [record3.hostThreadId, record3]));
|
|
29839
30096
|
const entries = input.records.filter((record3) => includesExternalRecord(record3, input.query, byId)).map((record3) => {
|
|
@@ -29910,7 +30167,10 @@ function cursorValue(input) {
|
|
|
29910
30167
|
}
|
|
29911
30168
|
async function aggregateThreadList(input) {
|
|
29912
30169
|
const { query } = input;
|
|
29913
|
-
if (!query.supportsExternal
|
|
30170
|
+
if (!query.supportsExternal || query.sortKey === "section_position") {
|
|
30171
|
+
throw new Error("External aggregation is not supported for query");
|
|
30172
|
+
}
|
|
30173
|
+
const externalSortKey = query.sortKey;
|
|
29914
30174
|
const start = query.cursor ?? {
|
|
29915
30175
|
queryFingerprint: query.queryFingerprint,
|
|
29916
30176
|
sortDirection: query.sortDirection,
|
|
@@ -29960,7 +30220,7 @@ async function aggregateThreadList(input) {
|
|
|
29960
30220
|
firstOfficialBackwardsCursor = page.backwardsCursor;
|
|
29961
30221
|
}
|
|
29962
30222
|
officialBatch = page;
|
|
29963
|
-
officialEntries = page.data.map((thread) => officialThreadListEntry(thread,
|
|
30223
|
+
officialEntries = page.data.map((thread) => officialThreadListEntry(thread, externalSortKey));
|
|
29964
30224
|
officialIndex = 0;
|
|
29965
30225
|
if (officialEntries.length === 0) {
|
|
29966
30226
|
if (page.nextCursor === null || page.nextCursor === officialCursor) {
|
|
@@ -30237,6 +30497,7 @@ var AppServerHost = class {
|
|
|
30237
30497
|
#nativeAccountObserver;
|
|
30238
30498
|
#externalAdapters;
|
|
30239
30499
|
#pluginDescriptors = [];
|
|
30500
|
+
#launchSettings;
|
|
30240
30501
|
#accountInspections = new HarnessAccountInspectionCache();
|
|
30241
30502
|
#externalRuntime;
|
|
30242
30503
|
#externalSteering = new ExternalTurnSteering();
|
|
@@ -30278,7 +30539,10 @@ var AppServerHost = class {
|
|
|
30278
30539
|
};
|
|
30279
30540
|
this.#writer = new OrderedWriter(this.#options.desktopOutput);
|
|
30280
30541
|
const environment = this.#options.environment ?? process.env;
|
|
30281
|
-
|
|
30542
|
+
this.#launchSettings = new HarnessLaunchSettingsStore(
|
|
30543
|
+
this.#options.pluginContext?.environment ?? environment
|
|
30544
|
+
);
|
|
30545
|
+
const permanentHome = path14.resolve(environment.CODEX_HOME ?? path14.join(os4.homedir(), ".codex"));
|
|
30282
30546
|
this.#ownsOfficialRuntimeScope = options2.officialRuntimeScope === void 0;
|
|
30283
30547
|
this.#officialRuntimeScope = options2.officialRuntimeScope ?? new OfficialRuntimeScope({
|
|
30284
30548
|
diagnosticOutput: this.#options.diagnosticOutput,
|
|
@@ -30291,7 +30555,8 @@ var AppServerHost = class {
|
|
|
30291
30555
|
...officialEnvironment(environment),
|
|
30292
30556
|
CODEX_HOME: permanentHome
|
|
30293
30557
|
},
|
|
30294
|
-
...this.#options.spawnOfficial ? { spawnOfficial: this.#options.spawnOfficial } : {}
|
|
30558
|
+
...this.#options.spawnOfficial ? { spawnOfficial: this.#options.spawnOfficial } : {},
|
|
30559
|
+
...this.#options.officialCloseTimeoutMs === void 0 ? {} : { closeTimeoutMs: this.#options.officialCloseTimeoutMs }
|
|
30295
30560
|
})
|
|
30296
30561
|
)
|
|
30297
30562
|
});
|
|
@@ -30431,6 +30696,7 @@ var AppServerHost = class {
|
|
|
30431
30696
|
if (!this.#options.pluginRoots || this.#pluginLoadAbort.signal.aborted) return;
|
|
30432
30697
|
const plugins = await loadHarnessPlugins({
|
|
30433
30698
|
roots: this.#options.pluginRoots,
|
|
30699
|
+
launchCommandForPlugin: (id2) => this.#launchSettings.initialCommand(id2),
|
|
30434
30700
|
context: this.#options.pluginContext ?? {
|
|
30435
30701
|
environment: this.#options.environment ?? process.env,
|
|
30436
30702
|
platform: process.platform,
|
|
@@ -30632,6 +30898,32 @@ var AppServerHost = class {
|
|
|
30632
30898
|
this.#dispatchDesktopRequest(() => this.#handleCodexAccountRequest(request));
|
|
30633
30899
|
return;
|
|
30634
30900
|
}
|
|
30901
|
+
if (request.method === CREDENTIAL_IMPORTS_METHOD) {
|
|
30902
|
+
this.#dispatchDesktopRequest(async () => {
|
|
30903
|
+
if (!credentialImportsParamsSchema.safeParse(request.params).success) {
|
|
30904
|
+
await this.#writer.json(rpcError(request, -32602, "Invalid credential import request"));
|
|
30905
|
+
return;
|
|
30906
|
+
}
|
|
30907
|
+
await this.#waitForPlugins();
|
|
30908
|
+
try {
|
|
30909
|
+
const result = await handleCredentialImports(
|
|
30910
|
+
request.params,
|
|
30911
|
+
this.#externalAdapters.values(),
|
|
30912
|
+
this.#options.environment ?? process.env
|
|
30913
|
+
);
|
|
30914
|
+
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
30915
|
+
} catch {
|
|
30916
|
+
await this.#writer.json(
|
|
30917
|
+
rpcError(
|
|
30918
|
+
request,
|
|
30919
|
+
-32077,
|
|
30920
|
+
"Credential operation failed. Check the source login, choose an unused Provider name, and verify Pi configuration access."
|
|
30921
|
+
)
|
|
30922
|
+
);
|
|
30923
|
+
}
|
|
30924
|
+
});
|
|
30925
|
+
return;
|
|
30926
|
+
}
|
|
30635
30927
|
if (request.method === "codexhost/harness/accounts/sources") {
|
|
30636
30928
|
this.#dispatchDesktopRequest(async () => {
|
|
30637
30929
|
if (!harnessAccountSourceListParamsSchema.safeParse(request.params).success) {
|
|
@@ -30703,6 +30995,41 @@ var AppServerHost = class {
|
|
|
30703
30995
|
this.#dispatchDesktopRequest(() => this.#openHarnessWebUi(request));
|
|
30704
30996
|
return;
|
|
30705
30997
|
}
|
|
30998
|
+
if (request.method === HARNESS_LAUNCH_SETTINGS_GET_METHOD || request.method === HARNESS_LAUNCH_SETTINGS_SET_METHOD) {
|
|
30999
|
+
this.#dispatchDesktopRequest(async () => {
|
|
31000
|
+
const schema = request.method === HARNESS_LAUNCH_SETTINGS_SET_METHOD ? harnessLaunchSettingsSetSchema : harnessLaunchSettingsGetSchema;
|
|
31001
|
+
const params = schema.safeParse(request.params);
|
|
31002
|
+
if (!params.success) {
|
|
31003
|
+
await this.#writer.json(rpcError(request, -32602, "Invalid Harness launch settings"));
|
|
31004
|
+
return;
|
|
31005
|
+
}
|
|
31006
|
+
await this.#waitForPlugins();
|
|
31007
|
+
if (!this.#pluginDescriptors.some(
|
|
31008
|
+
(plugin) => plugin.id === params.data.harnessId && plugin.launchCommand
|
|
31009
|
+
)) {
|
|
31010
|
+
await this.#writer.json(
|
|
31011
|
+
rpcError(request, -32602, "Harness launch settings are unavailable")
|
|
31012
|
+
);
|
|
31013
|
+
return;
|
|
31014
|
+
}
|
|
31015
|
+
try {
|
|
31016
|
+
const result = request.method === HARNESS_LAUNCH_SETTINGS_SET_METHOD ? await this.#launchSettings.set(
|
|
31017
|
+
params.data.harnessId,
|
|
31018
|
+
harnessLaunchSettingsSetSchema.parse(request.params).path
|
|
31019
|
+
) : await this.#launchSettings.get(params.data.harnessId);
|
|
31020
|
+
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
31021
|
+
} catch {
|
|
31022
|
+
await this.#writer.json(
|
|
31023
|
+
rpcError(
|
|
31024
|
+
request,
|
|
31025
|
+
-32602,
|
|
31026
|
+
"Could not read or save launch settings. Use an existing absolute installation directory on this Host, without arguments, and check configuration permissions."
|
|
31027
|
+
)
|
|
31028
|
+
);
|
|
31029
|
+
}
|
|
31030
|
+
});
|
|
31031
|
+
return;
|
|
31032
|
+
}
|
|
30706
31033
|
if (request.method === "codexhost/harness/plugins/list") {
|
|
30707
31034
|
this.#dispatchDesktopRequest(async () => {
|
|
30708
31035
|
if (!harnessPluginListParamsSchema.safeParse(request.params).success) {
|
|
@@ -31326,7 +31653,7 @@ var AppServerHost = class {
|
|
|
31326
31653
|
throw new DelegationControlError("INVALID_ARGUMENT", "Official Model Ref is invalid");
|
|
31327
31654
|
}
|
|
31328
31655
|
const nativeModelId = requestedModel ? decodeOfficialCodexModelRef(requestedModel) : void 0;
|
|
31329
|
-
const digest2 =
|
|
31656
|
+
const digest2 = createHash7("sha256").update(
|
|
31330
31657
|
JSON.stringify({
|
|
31331
31658
|
task: input.task,
|
|
31332
31659
|
cwd: input.cwd,
|
|
@@ -31427,7 +31754,7 @@ var AppServerHost = class {
|
|
|
31427
31754
|
throw error51;
|
|
31428
31755
|
}
|
|
31429
31756
|
this.#activeOfficialTurns.set(threadId2, turnId);
|
|
31430
|
-
const delegationId = hostThreadIdSchema.parse(
|
|
31757
|
+
const delegationId = hostThreadIdSchema.parse(randomUUID9());
|
|
31431
31758
|
try {
|
|
31432
31759
|
const source = await this.#repository.find(input.parentThreadId);
|
|
31433
31760
|
const pendingTerminal = this.#pendingOfficialTerminalStatuses.get(threadId2);
|
|
@@ -31591,7 +31918,7 @@ var AppServerHost = class {
|
|
|
31591
31918
|
async #listDelegationThreads(input) {
|
|
31592
31919
|
const [sortKey, sortDirection2] = input.sort.split("-");
|
|
31593
31920
|
const request = {
|
|
31594
|
-
id: `codexhost:delegation-list:${
|
|
31921
|
+
id: `codexhost:delegation-list:${randomUUID9()}`,
|
|
31595
31922
|
method: "thread/list",
|
|
31596
31923
|
params: {
|
|
31597
31924
|
cwd: input.cwd ? [input.cwd] : null,
|
|
@@ -32075,7 +32402,7 @@ var AppServerHost = class {
|
|
|
32075
32402
|
);
|
|
32076
32403
|
return;
|
|
32077
32404
|
}
|
|
32078
|
-
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(
|
|
32405
|
+
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID9());
|
|
32079
32406
|
const projection = {
|
|
32080
32407
|
projector: new CodexTurnProjector({
|
|
32081
32408
|
threadId: thread.id,
|
|
@@ -32942,7 +33269,7 @@ var AppServerHost = class {
|
|
|
32942
33269
|
if (thread.running || thread.activeTurnId || this.#pendingExternalCommandRequests.has(thread.id)) {
|
|
32943
33270
|
throw new ExternalSteerError(-32072, "External Thread already has an active Turn");
|
|
32944
33271
|
}
|
|
32945
|
-
const turnId = hostTurnIdSchema.parse(
|
|
33272
|
+
const turnId = hostTurnIdSchema.parse(randomUUID9());
|
|
32946
33273
|
const startedAtMs = Date.now();
|
|
32947
33274
|
const projection = {
|
|
32948
33275
|
projector: new CodexTurnProjector({
|
|
@@ -33570,7 +33897,7 @@ var AppServerHost = class {
|
|
|
33570
33897
|
try {
|
|
33571
33898
|
result = projection.projector.projectQuestion(
|
|
33572
33899
|
interaction,
|
|
33573
|
-
hostItemIdSchema.parse(
|
|
33900
|
+
hostItemIdSchema.parse(randomUUID9())
|
|
33574
33901
|
);
|
|
33575
33902
|
} catch (error51) {
|
|
33576
33903
|
this.#diagnose(error51);
|
|
@@ -33736,19 +34063,19 @@ var AppServerHost = class {
|
|
|
33736
34063
|
};
|
|
33737
34064
|
|
|
33738
34065
|
// packages/host-runtime/src/native-account-host.ts
|
|
33739
|
-
import { mkdir as
|
|
34066
|
+
import { mkdir as mkdir7, realpath as realpath3 } from "node:fs/promises";
|
|
33740
34067
|
import { homedir } from "node:os";
|
|
33741
|
-
import
|
|
34068
|
+
import path18 from "node:path";
|
|
33742
34069
|
|
|
33743
34070
|
// packages/host-runtime/src/codex-runtime/owned-official-backends.ts
|
|
33744
|
-
import { createHash as
|
|
34071
|
+
import { createHash as createHash8, randomBytes } from "node:crypto";
|
|
33745
34072
|
import { Writable as Writable2 } from "node:stream";
|
|
33746
34073
|
|
|
33747
34074
|
// packages/host-runtime/src/remote-app-server.ts
|
|
33748
34075
|
import { createServer } from "node:http";
|
|
33749
34076
|
import net from "node:net";
|
|
33750
|
-
import { chmod as chmod3, lstat as lstat6, mkdir as
|
|
33751
|
-
import
|
|
34077
|
+
import { chmod as chmod3, lstat as lstat6, mkdir as mkdir6, rm as rm6 } from "node:fs/promises";
|
|
34078
|
+
import path16 from "node:path";
|
|
33752
34079
|
import { PassThrough } from "node:stream";
|
|
33753
34080
|
|
|
33754
34081
|
// node_modules/ws/wrapper.mjs
|
|
@@ -33763,10 +34090,10 @@ var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
|
33763
34090
|
var wrapper_default = import_websocket.default;
|
|
33764
34091
|
|
|
33765
34092
|
// packages/host-runtime/src/remote-socket-lock.ts
|
|
33766
|
-
import { randomUUID as
|
|
33767
|
-
import { chmod as chmod2, lstat as lstat5, mkdir as
|
|
34093
|
+
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
34094
|
+
import { chmod as chmod2, lstat as lstat5, mkdir as mkdir5, open as open5, readFile as readFile8, readdir as readdir4, rename as rename4, rm as rm5 } from "node:fs/promises";
|
|
33768
34095
|
import { uptime } from "node:os";
|
|
33769
|
-
import
|
|
34096
|
+
import path15 from "node:path";
|
|
33770
34097
|
import { setTimeout as delay4 } from "node:timers/promises";
|
|
33771
34098
|
var LOCK_RETRY_COUNT = 200;
|
|
33772
34099
|
var LOCK_RETRY_DELAY_MS = 25;
|
|
@@ -33829,7 +34156,7 @@ async function readLockEntrySnapshot(filePath) {
|
|
|
33829
34156
|
throw error51;
|
|
33830
34157
|
});
|
|
33831
34158
|
if (metadata === null || !metadata.isFile()) return null;
|
|
33832
|
-
const source = await
|
|
34159
|
+
const source = await readFile8(filePath, "utf8").catch((error51) => {
|
|
33833
34160
|
if (error51.code === "ENOENT") return null;
|
|
33834
34161
|
throw error51;
|
|
33835
34162
|
});
|
|
@@ -33840,7 +34167,7 @@ async function readLockEntrySnapshot(filePath) {
|
|
|
33840
34167
|
source,
|
|
33841
34168
|
identity: { dev: metadata.dev, ino: metadata.ino },
|
|
33842
34169
|
mtimeMs: metadata.mtimeMs,
|
|
33843
|
-
record: record3 &&
|
|
34170
|
+
record: record3 && path15.basename(filePath) === lockEntryName(record3.ownerToken) ? record3 : null
|
|
33844
34171
|
};
|
|
33845
34172
|
}
|
|
33846
34173
|
function lockEntryIsAbandoned(snapshot) {
|
|
@@ -33852,7 +34179,7 @@ async function removeAbandonedLockEntry(snapshot) {
|
|
|
33852
34179
|
if (current === null || current.source !== snapshot.source || !sameUnixFileIdentity(current.identity, snapshot.identity) || !lockEntryIsAbandoned(current)) {
|
|
33853
34180
|
return false;
|
|
33854
34181
|
}
|
|
33855
|
-
await
|
|
34182
|
+
await rm5(snapshot.filePath, { force: true });
|
|
33856
34183
|
return true;
|
|
33857
34184
|
}
|
|
33858
34185
|
async function readLockEntryCatalog(lockDirectory) {
|
|
@@ -33861,7 +34188,7 @@ async function readLockEntryCatalog(lockDirectory) {
|
|
|
33861
34188
|
let unsettled = false;
|
|
33862
34189
|
for (const name of names) {
|
|
33863
34190
|
if (!name.startsWith(LOCK_ENTRY_PREFIX) || !name.endsWith(LOCK_ENTRY_SUFFIX)) continue;
|
|
33864
|
-
const snapshot = await readLockEntrySnapshot(
|
|
34191
|
+
const snapshot = await readLockEntrySnapshot(path15.join(lockDirectory, name));
|
|
33865
34192
|
if (snapshot === null) continue;
|
|
33866
34193
|
if (lockEntryIsAbandoned(snapshot)) {
|
|
33867
34194
|
if (!await removeAbandonedLockEntry(snapshot)) unsettled = true;
|
|
@@ -33876,7 +34203,7 @@ async function readLockEntryCatalog(lockDirectory) {
|
|
|
33876
34203
|
return { entries, unsettled };
|
|
33877
34204
|
}
|
|
33878
34205
|
async function preparePrivateLockDirectory(lockDirectory) {
|
|
33879
|
-
await
|
|
34206
|
+
await mkdir5(lockDirectory, { mode: 448 }).catch((error51) => {
|
|
33880
34207
|
if (error51.code !== "EEXIST") throw error51;
|
|
33881
34208
|
});
|
|
33882
34209
|
const metadata = await lstat5(lockDirectory);
|
|
@@ -33889,7 +34216,7 @@ async function preparePrivateLockDirectory(lockDirectory) {
|
|
|
33889
34216
|
await chmod2(lockDirectory, 448);
|
|
33890
34217
|
}
|
|
33891
34218
|
async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
|
|
33892
|
-
const temporary =
|
|
34219
|
+
const temporary = path15.join(lockDirectory, `.tmp-${record3.ownerToken}-${randomUUID10()}`);
|
|
33893
34220
|
const handle = await open5(temporary, "wx", 384);
|
|
33894
34221
|
try {
|
|
33895
34222
|
await handle.writeFile(`${JSON.stringify(record3)}
|
|
@@ -33899,15 +34226,15 @@ async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
|
|
|
33899
34226
|
await handle.close();
|
|
33900
34227
|
}
|
|
33901
34228
|
try {
|
|
33902
|
-
await
|
|
34229
|
+
await rename4(temporary, entryPath);
|
|
33903
34230
|
} finally {
|
|
33904
|
-
await
|
|
34231
|
+
await rm5(temporary, { force: true });
|
|
33905
34232
|
}
|
|
33906
34233
|
}
|
|
33907
34234
|
async function removeOwnedLockEntry(entryPath, ownerToken) {
|
|
33908
34235
|
const snapshot = await readLockEntrySnapshot(entryPath);
|
|
33909
34236
|
if (snapshot?.record?.ownerToken !== ownerToken) return;
|
|
33910
|
-
await
|
|
34237
|
+
await rm5(entryPath, { force: true });
|
|
33911
34238
|
}
|
|
33912
34239
|
async function legacyLockState(legacyPath) {
|
|
33913
34240
|
const metadata = await lstat5(legacyPath).catch((error51) => {
|
|
@@ -33916,7 +34243,7 @@ async function legacyLockState(legacyPath) {
|
|
|
33916
34243
|
});
|
|
33917
34244
|
if (metadata === null) return "absent";
|
|
33918
34245
|
if (!metadata.isFile()) return "blocking";
|
|
33919
|
-
const source = await
|
|
34246
|
+
const source = await readFile8(legacyPath, "utf8").catch((error51) => {
|
|
33920
34247
|
if (error51.code === "ENOENT") return null;
|
|
33921
34248
|
throw error51;
|
|
33922
34249
|
});
|
|
@@ -33953,7 +34280,7 @@ async function releaseLegacyCompatibilityGuard(legacyPath, guard) {
|
|
|
33953
34280
|
throw error51;
|
|
33954
34281
|
});
|
|
33955
34282
|
if (metadata?.isFile() && sameUnixFileIdentity({ dev: metadata.dev, ino: metadata.ino }, guard.identity)) {
|
|
33956
|
-
await
|
|
34283
|
+
await rm5(legacyPath, { force: true });
|
|
33957
34284
|
}
|
|
33958
34285
|
}
|
|
33959
34286
|
}
|
|
@@ -33964,8 +34291,8 @@ async function withRemoteAppServerSocketInitializationLock(socketPath, action) {
|
|
|
33964
34291
|
const legacyPath = `${socketPath}.initializing`;
|
|
33965
34292
|
const lockDirectory = `${socketPath}.initializers`;
|
|
33966
34293
|
await preparePrivateLockDirectory(lockDirectory);
|
|
33967
|
-
const ownerToken =
|
|
33968
|
-
const entryPath =
|
|
34294
|
+
const ownerToken = randomUUID10();
|
|
34295
|
+
const entryPath = path15.join(lockDirectory, lockEntryName(ownerToken));
|
|
33969
34296
|
const baseRecord = {
|
|
33970
34297
|
version: 2,
|
|
33971
34298
|
ownerToken,
|
|
@@ -34139,14 +34466,14 @@ function remoteAppServerSocketPath(environment, listenUrl = "unix://") {
|
|
|
34139
34466
|
throw new Error("Remote app-server listener must use a Unix URL");
|
|
34140
34467
|
}
|
|
34141
34468
|
const explicit = listenUrl.slice("unix://".length);
|
|
34142
|
-
if (explicit.length > 0) return
|
|
34143
|
-
const codexHome = environment.CODEX_HOME ?? (environment.HOME ?
|
|
34469
|
+
if (explicit.length > 0) return path16.posix.resolve(decodeURIComponent(explicit));
|
|
34470
|
+
const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path16.posix.join(environment.HOME, ".codex") : void 0);
|
|
34144
34471
|
if (!codexHome)
|
|
34145
34472
|
throw new Error("CODEX_HOME or HOME is required for the remote app-server socket");
|
|
34146
|
-
return
|
|
34473
|
+
return path16.posix.join(codexHome, "app-server-control", "app-server-control.sock");
|
|
34147
34474
|
}
|
|
34148
34475
|
function officialListenerArgumentsForRemoteListener(arguments_2, socketPath) {
|
|
34149
|
-
if (!
|
|
34476
|
+
if (!path16.posix.isAbsolute(socketPath)) {
|
|
34150
34477
|
throw new Error("Shared official app-server socket path must be absolute");
|
|
34151
34478
|
}
|
|
34152
34479
|
if (remoteUnixListenerUrl(arguments_2) === null) {
|
|
@@ -34254,10 +34581,10 @@ async function removeStaleSocket(socketPath) {
|
|
|
34254
34581
|
});
|
|
34255
34582
|
});
|
|
34256
34583
|
if (active) throw new Error(`Remote app-server socket is already in use at ${socketPath}`);
|
|
34257
|
-
await
|
|
34584
|
+
await rm6(socketPath, { force: true });
|
|
34258
34585
|
}
|
|
34259
34586
|
async function prepareRemoteAppServerSocketDirectory(socketPath) {
|
|
34260
|
-
const socketDirectory =
|
|
34587
|
+
const socketDirectory = path16.dirname(socketPath);
|
|
34261
34588
|
const existing = await lstat6(socketDirectory).catch((error51) => {
|
|
34262
34589
|
if (error51.code === "ENOENT") return null;
|
|
34263
34590
|
throw error51;
|
|
@@ -34271,7 +34598,7 @@ async function prepareRemoteAppServerSocketDirectory(socketPath) {
|
|
|
34271
34598
|
);
|
|
34272
34599
|
}
|
|
34273
34600
|
}
|
|
34274
|
-
await
|
|
34601
|
+
await mkdir6(socketDirectory, { recursive: true, mode: 448 });
|
|
34275
34602
|
await chmod3(socketDirectory, 448);
|
|
34276
34603
|
}
|
|
34277
34604
|
function sendOutputFrames(socket, output) {
|
|
@@ -34444,7 +34771,7 @@ function createRemoteAppServerWebSocketListener(input) {
|
|
|
34444
34771
|
if (ownedSocketIdentity) {
|
|
34445
34772
|
const current = await unixSocketIdentity(input.socketPath);
|
|
34446
34773
|
if (current && sameUnixFileIdentity2(current, ownedSocketIdentity)) {
|
|
34447
|
-
await
|
|
34774
|
+
await rm6(input.socketPath, { force: true });
|
|
34448
34775
|
}
|
|
34449
34776
|
ownedSocketIdentity = null;
|
|
34450
34777
|
}
|
|
@@ -34462,20 +34789,20 @@ function createRemoteAppServerWebSocketListener(input) {
|
|
|
34462
34789
|
|
|
34463
34790
|
// packages/host-runtime/src/remote-official-app-server.ts
|
|
34464
34791
|
import { spawn as spawn3 } from "node:child_process";
|
|
34465
|
-
import { randomUUID as
|
|
34466
|
-
import { lstat as lstat7, rm as
|
|
34467
|
-
import
|
|
34792
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
34793
|
+
import { lstat as lstat7, rm as rm7 } from "node:fs/promises";
|
|
34794
|
+
import path17 from "node:path";
|
|
34468
34795
|
var DEFAULT_CLOSE_TIMEOUT_MS = 2e3;
|
|
34469
34796
|
var DEFAULT_LISTEN_TIMEOUT_MS = 1e4;
|
|
34470
|
-
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token =
|
|
34471
|
-
if (!
|
|
34797
|
+
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID11()) {
|
|
34798
|
+
if (!path17.posix.isAbsolute(desktopControlSocketPath)) {
|
|
34472
34799
|
throw new Error("Desktop control socket path must be absolute");
|
|
34473
34800
|
}
|
|
34474
34801
|
if (!/^[A-Za-z0-9-]+$/u.test(token) || !/[A-Za-z0-9]/u.test(token)) {
|
|
34475
34802
|
throw new Error("Shared official app-server socket token is invalid");
|
|
34476
34803
|
}
|
|
34477
34804
|
const compactToken = token.replaceAll("-", "").slice(0, 15);
|
|
34478
|
-
return
|
|
34805
|
+
return path17.posix.join(path17.posix.dirname(desktopControlSocketPath), `.c-${compactToken}.sock`);
|
|
34479
34806
|
}
|
|
34480
34807
|
function errorMessage4(error51) {
|
|
34481
34808
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
@@ -34547,7 +34874,7 @@ function createRemoteOfficialAppServerListener(input) {
|
|
|
34547
34874
|
if (ownedSocketIdentity === null) return;
|
|
34548
34875
|
const current = await socketIdentity(input.socketPath).catch(() => null);
|
|
34549
34876
|
if (current && sameUnixFileIdentity3(current, ownedSocketIdentity)) {
|
|
34550
|
-
await
|
|
34877
|
+
await rm7(input.socketPath, { force: true });
|
|
34551
34878
|
}
|
|
34552
34879
|
ownedSocketIdentity = null;
|
|
34553
34880
|
};
|
|
@@ -34751,7 +35078,10 @@ async function createRemoteOfficialAppServerConnection(endpoint, options2 = {})
|
|
|
34751
35078
|
let pending = Buffer.alloc(0);
|
|
34752
35079
|
let outputPaused = false;
|
|
34753
35080
|
const webSocketOptions = {
|
|
34754
|
-
|
|
35081
|
+
// This private native listener can return large history pages, including
|
|
35082
|
+
// images. Match stdio instead of retiring the connection at an arbitrary
|
|
35083
|
+
// response size; ws uses zero for an unlimited payload.
|
|
35084
|
+
maxPayload: 0,
|
|
34755
35085
|
// The native Codex daemon client uses tokio-tungstenite without offering
|
|
34756
35086
|
// permessage-deflate. Keep the same handshake for every private listener.
|
|
34757
35087
|
perMessageDeflate: false,
|
|
@@ -34905,7 +35235,7 @@ function createOwnedLoopbackBackend(input) {
|
|
|
34905
35235
|
"--ws-auth",
|
|
34906
35236
|
"capability-token",
|
|
34907
35237
|
"--ws-token-sha256",
|
|
34908
|
-
|
|
35238
|
+
createHash8("sha256").update(capabilityToken).digest("hex")
|
|
34909
35239
|
],
|
|
34910
35240
|
// Managed stderr may carry credential-bearing errors. Never forward raw bytes.
|
|
34911
35241
|
diagnosticOutput: new Writable2({
|
|
@@ -34958,21 +35288,21 @@ function createOwnedUnixBackend(input) {
|
|
|
34958
35288
|
|
|
34959
35289
|
// packages/host-runtime/src/native-account-host.ts
|
|
34960
35290
|
async function canonicalCodexHome(home) {
|
|
34961
|
-
const absolute =
|
|
35291
|
+
const absolute = path18.resolve(home);
|
|
34962
35292
|
try {
|
|
34963
35293
|
return await realpath3(absolute);
|
|
34964
35294
|
} catch (error51) {
|
|
34965
35295
|
if (!(error51 instanceof Error && "code" in error51 && error51.code === "ENOENT")) throw error51;
|
|
34966
|
-
const parent =
|
|
35296
|
+
const parent = path18.dirname(absolute);
|
|
34967
35297
|
if (parent === absolute) throw error51;
|
|
34968
|
-
return
|
|
35298
|
+
return path18.join(await canonicalCodexHome(parent), path18.basename(absolute));
|
|
34969
35299
|
}
|
|
34970
35300
|
}
|
|
34971
35301
|
async function prepareLocalCodex(input) {
|
|
34972
35302
|
const home = await canonicalCodexHome(
|
|
34973
|
-
input.environment.CODEX_HOME ??
|
|
35303
|
+
input.environment.CODEX_HOME ?? path18.join(homedir(), ".codex")
|
|
34974
35304
|
);
|
|
34975
|
-
await
|
|
35305
|
+
await mkdir7(home, { recursive: true });
|
|
34976
35306
|
const scope = new OfficialRuntimeScope({
|
|
34977
35307
|
permanentHome: home,
|
|
34978
35308
|
diagnosticOutput: input.diagnosticOutput,
|
|
@@ -35136,18 +35466,18 @@ var DelegationControlRegistry = class {
|
|
|
35136
35466
|
};
|
|
35137
35467
|
|
|
35138
35468
|
// packages/host-runtime/src/installed-harness-plugins.ts
|
|
35139
|
-
import
|
|
35140
|
-
import
|
|
35469
|
+
import os5 from "node:os";
|
|
35470
|
+
import path20 from "node:path";
|
|
35141
35471
|
import { fileURLToPath } from "node:url";
|
|
35142
35472
|
|
|
35143
35473
|
// packages/host-runtime/src/launcher-url-opener.ts
|
|
35144
35474
|
import { spawn as spawn4 } from "node:child_process";
|
|
35145
|
-
import
|
|
35475
|
+
import path19 from "node:path";
|
|
35146
35476
|
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "[::1]"]);
|
|
35147
35477
|
var OPEN_TIMEOUT_MS = 1e4;
|
|
35148
35478
|
function createLauncherUrlOpener(environment, spawnLauncher = (command, arguments_2, options2) => spawn4(command, arguments_2, options2)) {
|
|
35149
35479
|
const launcher = environment.CODEXHOST_LAUNCHER_EXECUTABLE;
|
|
35150
|
-
if (!launcher || !
|
|
35480
|
+
if (!launcher || !path19.isAbsolute(launcher)) return void 0;
|
|
35151
35481
|
const launcherEnvironment = Object.fromEntries(
|
|
35152
35482
|
Object.entries(environment).filter(([name]) => {
|
|
35153
35483
|
const normalized = name.toUpperCase();
|
|
@@ -35205,9 +35535,9 @@ function installedHarnessPluginOptions(environment, managedRemoteHost = false, h
|
|
|
35205
35535
|
const opener = managedRemoteHost ? void 0 : createLauncherUrlOpener(environment);
|
|
35206
35536
|
return {
|
|
35207
35537
|
pluginRoots: [
|
|
35208
|
-
|
|
35209
|
-
environment[HARNESS_PLUGIN_DIRECTORY_ENV] ??
|
|
35210
|
-
environment.CODEXHOST_DATA_DIR ?
|
|
35538
|
+
path20.join(path20.dirname(fileURLToPath(hostRuntimeUrl)), "plugins"),
|
|
35539
|
+
environment[HARNESS_PLUGIN_DIRECTORY_ENV] ?? path20.join(
|
|
35540
|
+
environment.CODEXHOST_DATA_DIR ? path20.resolve(environment.CODEXHOST_DATA_DIR) : path20.join(os5.homedir(), ".codexhost"),
|
|
35211
35541
|
"plugins"
|
|
35212
35542
|
)
|
|
35213
35543
|
],
|
|
@@ -35332,12 +35662,12 @@ async function startDelegationControlServer(input) {
|
|
|
35332
35662
|
}
|
|
35333
35663
|
|
|
35334
35664
|
// packages/host-runtime/src/delegation-skill.ts
|
|
35335
|
-
import { createHash as
|
|
35336
|
-
import { mkdir as
|
|
35337
|
-
import
|
|
35338
|
-
import
|
|
35665
|
+
import { createHash as createHash9, randomUUID as randomUUID12 } from "node:crypto";
|
|
35666
|
+
import { mkdir as mkdir8, open as open6, readFile as readFile9, rename as rename5, rm as rm8, stat as stat4 } from "node:fs/promises";
|
|
35667
|
+
import os6 from "node:os";
|
|
35668
|
+
import path21 from "node:path";
|
|
35339
35669
|
var SKILL_VERSION = 7;
|
|
35340
|
-
var SKILL_RELATIVE_PATH =
|
|
35670
|
+
var SKILL_RELATIVE_PATH = path21.join("skills", "codexhost-delegation", "SKILL.md");
|
|
35341
35671
|
var PREVIOUS_MANAGED_DIGESTS = [
|
|
35342
35672
|
"9d2f491850fb0b4084a31ba9b5e4a550b5e833747af322090d8ed0ff80b88c30",
|
|
35343
35673
|
"2bb0aebb9b06febbc6c0c0bcdb0b32506c7cdbf8dc3b734cc6b2a86621270e4e",
|
|
@@ -35393,9 +35723,9 @@ user’s request and the task:
|
|
|
35393
35723
|
Report the result returned by read or a completed wait, together with the target
|
|
35394
35724
|
agent, status, and a labeled task link. Keep internal tracking IDs in tool calls.
|
|
35395
35725
|
`;
|
|
35396
|
-
var CURRENT_DIGEST =
|
|
35726
|
+
var CURRENT_DIGEST = createHash9("sha256").update(CODEXHOST_DELEGATION_SKILL).digest("hex");
|
|
35397
35727
|
function digest(value2) {
|
|
35398
|
-
return
|
|
35728
|
+
return createHash9("sha256").update(value2).digest("hex");
|
|
35399
35729
|
}
|
|
35400
35730
|
function managedVersion(value2) {
|
|
35401
35731
|
const match = /^version:\s*(\d+)\s*$/mu.exec(value2);
|
|
@@ -35403,15 +35733,15 @@ function managedVersion(value2) {
|
|
|
35403
35733
|
}
|
|
35404
35734
|
async function readOptional(filePath) {
|
|
35405
35735
|
try {
|
|
35406
|
-
return await
|
|
35736
|
+
return await readFile9(filePath, "utf8");
|
|
35407
35737
|
} catch (error51) {
|
|
35408
35738
|
if (error51.code === "ENOENT") return null;
|
|
35409
35739
|
throw error51;
|
|
35410
35740
|
}
|
|
35411
35741
|
}
|
|
35412
35742
|
async function atomicWrite(filePath, content) {
|
|
35413
|
-
await
|
|
35414
|
-
const temporaryPath =
|
|
35743
|
+
await mkdir8(path21.dirname(filePath), { recursive: true, mode: 448 });
|
|
35744
|
+
const temporaryPath = path21.join(path21.dirname(filePath), `.SKILL.md.${randomUUID12()}.tmp`);
|
|
35415
35745
|
const handle = await open6(temporaryPath, "wx", 384);
|
|
35416
35746
|
try {
|
|
35417
35747
|
await handle.writeFile(content, "utf8");
|
|
@@ -35420,16 +35750,16 @@ async function atomicWrite(filePath, content) {
|
|
|
35420
35750
|
await handle.close();
|
|
35421
35751
|
}
|
|
35422
35752
|
try {
|
|
35423
|
-
await
|
|
35753
|
+
await rename5(temporaryPath, filePath);
|
|
35424
35754
|
} finally {
|
|
35425
|
-
await
|
|
35755
|
+
await rm8(temporaryPath, { force: true });
|
|
35426
35756
|
}
|
|
35427
35757
|
}
|
|
35428
35758
|
async function installDelegationSkills(input = {}) {
|
|
35429
|
-
const home = input.homeDirectory ??
|
|
35759
|
+
const home = input.homeDirectory ?? os6.homedir();
|
|
35430
35760
|
const destinations = [
|
|
35431
|
-
|
|
35432
|
-
|
|
35761
|
+
path21.join(home, ".agents", SKILL_RELATIVE_PATH),
|
|
35762
|
+
path21.join(home, ".claude", SKILL_RELATIVE_PATH)
|
|
35433
35763
|
];
|
|
35434
35764
|
const knownDigests = /* @__PURE__ */ new Set([
|
|
35435
35765
|
CURRENT_DIGEST,
|
|
@@ -35474,8 +35804,8 @@ async function installDelegationSkills(input = {}) {
|
|
|
35474
35804
|
}
|
|
35475
35805
|
for (const result of results) {
|
|
35476
35806
|
if (result.status === "conflict") continue;
|
|
35477
|
-
const source = await
|
|
35478
|
-
const metadata = await
|
|
35807
|
+
const source = await readFile9(result.path, "utf8");
|
|
35808
|
+
const metadata = await stat4(result.path);
|
|
35479
35809
|
if (!metadata.isFile() || source !== CODEXHOST_DELEGATION_SKILL) {
|
|
35480
35810
|
throw new Error(`Delegation Skill verification failed: ${result.path}`);
|
|
35481
35811
|
}
|
|
@@ -35485,7 +35815,7 @@ async function installDelegationSkills(input = {}) {
|
|
|
35485
35815
|
throw new Error("Delegation Skill copies are inconsistent");
|
|
35486
35816
|
}
|
|
35487
35817
|
if (results.every((result) => result.status !== "conflict")) {
|
|
35488
|
-
const copies = await Promise.all(results.map((result) =>
|
|
35818
|
+
const copies = await Promise.all(results.map((result) => readFile9(result.path, "utf8")));
|
|
35489
35819
|
if (copies.some((copy) => copy !== copies[0])) {
|
|
35490
35820
|
throw new Error("Delegation Skill copies are inconsistent");
|
|
35491
35821
|
}
|
|
@@ -35494,9 +35824,9 @@ async function installDelegationSkills(input = {}) {
|
|
|
35494
35824
|
}
|
|
35495
35825
|
|
|
35496
35826
|
// packages/host-runtime/src/remote-control-app-server.ts
|
|
35497
|
-
import { randomUUID as
|
|
35498
|
-
import { mkdir as
|
|
35499
|
-
import
|
|
35827
|
+
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
35828
|
+
import { mkdir as mkdir9, open as open7, rename as rename6, rm as rm9 } from "node:fs/promises";
|
|
35829
|
+
import path22 from "node:path";
|
|
35500
35830
|
var REMOTE_CONTROL_BRIDGE_PIPE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_PIPE";
|
|
35501
35831
|
var REMOTE_CONTROL_BRIDGE_NODE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_NODE_PATH";
|
|
35502
35832
|
var REMOTE_CONTROL_BRIDGE_RUNTIME_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_RUNTIME_PATH";
|
|
@@ -35507,30 +35837,30 @@ var BRIDGE_READY_METHOD = "codexhost/remote-control-bridge/ready";
|
|
|
35507
35837
|
function absoluteEnvironmentPath2(environment, name, fallback, platform = process.platform) {
|
|
35508
35838
|
const value2 = environment[name] ?? fallback;
|
|
35509
35839
|
if (!value2) return null;
|
|
35510
|
-
if (
|
|
35511
|
-
return platform === "win32" &&
|
|
35840
|
+
if (path22.isAbsolute(value2)) return path22.normalize(value2);
|
|
35841
|
+
return platform === "win32" && path22.win32.isAbsolute(value2) ? path22.win32.normalize(value2) : null;
|
|
35512
35842
|
}
|
|
35513
35843
|
function nodeCompatibleWindowsPath(value2) {
|
|
35514
35844
|
if (value2.startsWith("\\\\?\\UNC\\")) return `\\\\${value2.slice(8)}`;
|
|
35515
35845
|
if (value2.startsWith("\\\\?\\")) return value2.slice(4);
|
|
35516
35846
|
return value2;
|
|
35517
35847
|
}
|
|
35518
|
-
function remoteControlBridgePipePath(processId = process.pid, instanceId =
|
|
35848
|
+
function remoteControlBridgePipePath(processId = process.pid, instanceId = randomUUID13()) {
|
|
35519
35849
|
const safeInstance = instanceId.replaceAll(/[^a-zA-Z0-9-]/gu, "");
|
|
35520
35850
|
if (!safeInstance) throw new Error("Remote Control bridge instance ID is invalid");
|
|
35521
35851
|
return `\\\\.\\pipe\\codexhost-remote-control-${processId}-${safeInstance}`;
|
|
35522
35852
|
}
|
|
35523
35853
|
function remoteControlBridgeDescriptorPath(environment) {
|
|
35524
35854
|
const root = environment.LOCALAPPDATA;
|
|
35525
|
-
if (!root || !
|
|
35526
|
-
return
|
|
35855
|
+
if (!root || !path22.isAbsolute(root)) return null;
|
|
35856
|
+
return path22.join(path22.normalize(root), "codexhost", REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE);
|
|
35527
35857
|
}
|
|
35528
35858
|
async function publishRemoteControlAppServerDescriptor(plan) {
|
|
35529
|
-
const directory =
|
|
35530
|
-
await
|
|
35531
|
-
const temporaryPath =
|
|
35859
|
+
const directory = path22.dirname(plan.descriptorPath);
|
|
35860
|
+
await mkdir9(directory, { recursive: true, mode: 448 });
|
|
35861
|
+
const temporaryPath = path22.join(
|
|
35532
35862
|
directory,
|
|
35533
|
-
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${
|
|
35863
|
+
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID13()}.tmp`
|
|
35534
35864
|
);
|
|
35535
35865
|
const handle = await open7(temporaryPath, "wx", 384);
|
|
35536
35866
|
try {
|
|
@@ -35541,9 +35871,9 @@ async function publishRemoteControlAppServerDescriptor(plan) {
|
|
|
35541
35871
|
await handle.close();
|
|
35542
35872
|
}
|
|
35543
35873
|
try {
|
|
35544
|
-
await
|
|
35874
|
+
await rename6(temporaryPath, plan.descriptorPath);
|
|
35545
35875
|
} finally {
|
|
35546
|
-
await
|
|
35876
|
+
await rm9(temporaryPath, { force: true });
|
|
35547
35877
|
}
|
|
35548
35878
|
}
|
|
35549
35879
|
function createRemoteControlAppServerPlan(input) {
|
|
@@ -35829,9 +36159,9 @@ function hasLauncherManagedUpdateRuntime(environment, hostRuntimePath) {
|
|
|
35829
36159
|
if (!environment[UPDATE_RUNTIME_ENV.launcherPid]) return false;
|
|
35830
36160
|
const npmPackageRoot = environment[UPDATE_RUNTIME_ENV.npmPackageRoot];
|
|
35831
36161
|
if (!npmPackageRoot || !hostRuntimePath) return true;
|
|
35832
|
-
if (!
|
|
35833
|
-
const runtimePackageRoot =
|
|
35834
|
-
return
|
|
36162
|
+
if (!path23.isAbsolute(npmPackageRoot) || !path23.isAbsolute(hostRuntimePath)) return false;
|
|
36163
|
+
const runtimePackageRoot = path23.dirname(path23.dirname(path23.normalize(hostRuntimePath)));
|
|
36164
|
+
return path23.relative(path23.normalize(npmPackageRoot), runtimePackageRoot) === "";
|
|
35835
36165
|
}
|
|
35836
36166
|
function requiredRuntimeConfiguration(environment) {
|
|
35837
36167
|
const stockCodexPath = environment[STOCK_CODEX_PATH_ENV];
|
|
@@ -35977,8 +36307,8 @@ async function runHostRuntime(input) {
|
|
|
35977
36307
|
const socketPath = remoteAppServerSocketPath(delegationEnvironment, listenUrl);
|
|
35978
36308
|
const officialPlan = createRemoteOfficialAppServerPlan(input.arguments, socketPath);
|
|
35979
36309
|
const officialRuntimeScope = new OfficialRuntimeScope({
|
|
35980
|
-
permanentHome:
|
|
35981
|
-
delegationEnvironment.CODEX_HOME ??
|
|
36310
|
+
permanentHome: path23.resolve(
|
|
36311
|
+
delegationEnvironment.CODEX_HOME ?? path23.join(homedir2(), ".codex")
|
|
35982
36312
|
),
|
|
35983
36313
|
diagnosticOutput: process.stderr,
|
|
35984
36314
|
createBackend: () => createOwnedUnixBackend({
|
|
@@ -36059,22 +36389,22 @@ async function runHostRuntime(input) {
|
|
|
36059
36389
|
}
|
|
36060
36390
|
|
|
36061
36391
|
// packages/host-runtime/src/remote-host-install.ts
|
|
36062
|
-
import { createHash as
|
|
36392
|
+
import { createHash as createHash10, randomUUID as randomUUID14 } from "node:crypto";
|
|
36063
36393
|
import { constants as fsConstants } from "node:fs";
|
|
36064
36394
|
import {
|
|
36065
36395
|
access,
|
|
36066
36396
|
chmod as chmod4,
|
|
36067
36397
|
copyFile as copyFile3,
|
|
36068
36398
|
lstat as lstat8,
|
|
36069
|
-
mkdir as
|
|
36070
|
-
readFile as
|
|
36071
|
-
rename as
|
|
36072
|
-
rm as
|
|
36399
|
+
mkdir as mkdir10,
|
|
36400
|
+
readFile as readFile10,
|
|
36401
|
+
rename as rename7,
|
|
36402
|
+
rm as rm10,
|
|
36073
36403
|
rmdir,
|
|
36074
|
-
stat as
|
|
36075
|
-
writeFile as
|
|
36404
|
+
stat as stat5,
|
|
36405
|
+
writeFile as writeFile4
|
|
36076
36406
|
} from "node:fs/promises";
|
|
36077
|
-
import
|
|
36407
|
+
import path24 from "node:path";
|
|
36078
36408
|
var MANIFEST_FORMAT = 1;
|
|
36079
36409
|
var WRAPPER_MARKER = "# codexhost remote SSH wrapper v1";
|
|
36080
36410
|
var PROFILE_START = "# >>> codexhost remote SSH >>>";
|
|
@@ -36085,25 +36415,25 @@ function resolvePaths(options2) {
|
|
|
36085
36415
|
if (!configuredHome) {
|
|
36086
36416
|
throw new Error("A non-root HOME is required for remote Host installation");
|
|
36087
36417
|
}
|
|
36088
|
-
const home =
|
|
36089
|
-
if (!home || home ===
|
|
36418
|
+
const home = path24.resolve(configuredHome);
|
|
36419
|
+
if (!home || home === path24.parse(home).root) {
|
|
36090
36420
|
throw new Error("A non-root HOME is required for remote Host installation");
|
|
36091
36421
|
}
|
|
36092
|
-
const installRoot =
|
|
36093
|
-
const profilePath =
|
|
36094
|
-
options2.profilePath ??
|
|
36422
|
+
const installRoot = path24.resolve(options2.installRoot ?? path24.join(home, ".codexhost", "remote"));
|
|
36423
|
+
const profilePath = path24.resolve(
|
|
36424
|
+
options2.profilePath ?? path24.join(
|
|
36095
36425
|
home,
|
|
36096
|
-
|
|
36426
|
+
path24.basename(environment.SHELL ?? "") === "zsh" ? ".zshenv" : path24.basename(environment.SHELL ?? "") === "bash" ? ".bashrc" : ".profile"
|
|
36097
36427
|
)
|
|
36098
36428
|
);
|
|
36099
|
-
const binDirectory =
|
|
36429
|
+
const binDirectory = path24.join(installRoot, "bin");
|
|
36100
36430
|
return {
|
|
36101
36431
|
home,
|
|
36102
36432
|
installRoot,
|
|
36103
36433
|
binDirectory,
|
|
36104
|
-
wrapperPath:
|
|
36105
|
-
manifestPath:
|
|
36106
|
-
dataDirectory:
|
|
36434
|
+
wrapperPath: path24.join(binDirectory, "codex"),
|
|
36435
|
+
manifestPath: path24.join(installRoot, "manifest.json"),
|
|
36436
|
+
dataDirectory: path24.join(installRoot, "data"),
|
|
36107
36437
|
profilePath
|
|
36108
36438
|
};
|
|
36109
36439
|
}
|
|
@@ -36112,19 +36442,19 @@ function shellQuote(value2) {
|
|
|
36112
36442
|
}
|
|
36113
36443
|
async function existingText(filePath) {
|
|
36114
36444
|
try {
|
|
36115
|
-
return await
|
|
36445
|
+
return await readFile10(filePath, "utf8");
|
|
36116
36446
|
} catch (error51) {
|
|
36117
36447
|
if (error51.code === "ENOENT") return null;
|
|
36118
36448
|
throw error51;
|
|
36119
36449
|
}
|
|
36120
36450
|
}
|
|
36121
36451
|
async function fileSha256(filePath) {
|
|
36122
|
-
return
|
|
36452
|
+
return createHash10("sha256").update(await readFile10(filePath)).digest("hex");
|
|
36123
36453
|
}
|
|
36124
36454
|
async function executable(filePath, label) {
|
|
36125
|
-
const absolute =
|
|
36455
|
+
const absolute = path24.resolve(filePath);
|
|
36126
36456
|
try {
|
|
36127
|
-
if (!(await
|
|
36457
|
+
if (!(await stat5(absolute)).isFile()) throw new Error("not a regular file");
|
|
36128
36458
|
await access(absolute, fsConstants.X_OK);
|
|
36129
36459
|
} catch {
|
|
36130
36460
|
throw new Error(`${label} is not an executable file: ${absolute}`);
|
|
@@ -36132,9 +36462,9 @@ async function executable(filePath, label) {
|
|
|
36132
36462
|
return absolute;
|
|
36133
36463
|
}
|
|
36134
36464
|
async function existingFile(filePath, label) {
|
|
36135
|
-
const absolute =
|
|
36465
|
+
const absolute = path24.resolve(filePath);
|
|
36136
36466
|
try {
|
|
36137
|
-
const metadata = await
|
|
36467
|
+
const metadata = await stat5(absolute);
|
|
36138
36468
|
if (!metadata.isFile()) throw new Error("not a regular file");
|
|
36139
36469
|
} catch {
|
|
36140
36470
|
throw new Error(`${label} is not a regular file: ${absolute}`);
|
|
@@ -36142,9 +36472,9 @@ async function existingFile(filePath, label) {
|
|
|
36142
36472
|
return absolute;
|
|
36143
36473
|
}
|
|
36144
36474
|
async function discoverExecutable(name, environment) {
|
|
36145
|
-
for (const directory of (environment.PATH ?? "").split(
|
|
36475
|
+
for (const directory of (environment.PATH ?? "").split(path24.delimiter)) {
|
|
36146
36476
|
if (!directory) continue;
|
|
36147
|
-
const candidate =
|
|
36477
|
+
const candidate = path24.resolve(directory, name);
|
|
36148
36478
|
try {
|
|
36149
36479
|
await access(candidate, fsConstants.X_OK);
|
|
36150
36480
|
return candidate;
|
|
@@ -36155,47 +36485,47 @@ async function discoverExecutable(name, environment) {
|
|
|
36155
36485
|
return null;
|
|
36156
36486
|
}
|
|
36157
36487
|
async function writeAtomic(filePath, contents, mode) {
|
|
36158
|
-
await
|
|
36159
|
-
const temporary =
|
|
36160
|
-
|
|
36161
|
-
`.${
|
|
36488
|
+
await mkdir10(path24.dirname(filePath), { recursive: true, mode: 448 });
|
|
36489
|
+
const temporary = path24.join(
|
|
36490
|
+
path24.dirname(filePath),
|
|
36491
|
+
`.${path24.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
|
|
36162
36492
|
);
|
|
36163
36493
|
try {
|
|
36164
36494
|
if (typeof contents === "string") {
|
|
36165
|
-
await
|
|
36495
|
+
await writeFile4(temporary, contents, { encoding: "utf8", flag: "wx", mode });
|
|
36166
36496
|
} else {
|
|
36167
|
-
await
|
|
36497
|
+
await writeFile4(temporary, contents, { flag: "wx", mode });
|
|
36168
36498
|
}
|
|
36169
36499
|
await chmod4(temporary, mode);
|
|
36170
36500
|
try {
|
|
36171
|
-
await
|
|
36501
|
+
await rename7(temporary, filePath);
|
|
36172
36502
|
} catch (error51) {
|
|
36173
36503
|
if (process.platform !== "win32") throw error51;
|
|
36174
|
-
await
|
|
36175
|
-
await
|
|
36504
|
+
await rm10(filePath, { force: true });
|
|
36505
|
+
await rename7(temporary, filePath);
|
|
36176
36506
|
}
|
|
36177
36507
|
} finally {
|
|
36178
|
-
await
|
|
36508
|
+
await rm10(temporary, { force: true });
|
|
36179
36509
|
}
|
|
36180
36510
|
}
|
|
36181
36511
|
async function writeAtomicExecutable(filePath, sourcePath) {
|
|
36182
|
-
await
|
|
36183
|
-
const temporary =
|
|
36184
|
-
|
|
36185
|
-
`.${
|
|
36512
|
+
await mkdir10(path24.dirname(filePath), { recursive: true, mode: 448 });
|
|
36513
|
+
const temporary = path24.join(
|
|
36514
|
+
path24.dirname(filePath),
|
|
36515
|
+
`.${path24.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
|
|
36186
36516
|
);
|
|
36187
36517
|
try {
|
|
36188
36518
|
await copyFile3(sourcePath, temporary);
|
|
36189
36519
|
await chmod4(temporary, 448);
|
|
36190
36520
|
try {
|
|
36191
|
-
await
|
|
36521
|
+
await rename7(temporary, filePath);
|
|
36192
36522
|
} catch (error51) {
|
|
36193
36523
|
if (process.platform !== "win32") throw error51;
|
|
36194
|
-
await
|
|
36195
|
-
await
|
|
36524
|
+
await rm10(filePath, { force: true });
|
|
36525
|
+
await rename7(temporary, filePath);
|
|
36196
36526
|
}
|
|
36197
36527
|
} finally {
|
|
36198
|
-
await
|
|
36528
|
+
await rm10(temporary, { force: true });
|
|
36199
36529
|
}
|
|
36200
36530
|
}
|
|
36201
36531
|
function managedBlockRange(contents) {
|
|
@@ -36223,15 +36553,14 @@ function removeManagedProfileBlock(contents) {
|
|
|
36223
36553
|
function installManagedProfileBlock(contents, manifest) {
|
|
36224
36554
|
const base = removeManagedProfileBlock(contents);
|
|
36225
36555
|
const environment = [
|
|
36226
|
-
`export CODEX_INSTALL_DIR=${shellQuote(
|
|
36227
|
-
`export PATH=${shellQuote(
|
|
36556
|
+
`export CODEX_INSTALL_DIR=${shellQuote(path24.dirname(manifest.wrapperPath))}`,
|
|
36557
|
+
`export PATH=${shellQuote(path24.dirname(manifest.wrapperPath))}:${shellQuote(path24.dirname(manifest.nodePath))}:${shellQuote(path24.dirname(manifest.stockCodexPath))}:"\${PATH:-/usr/local/bin:/usr/bin:/bin}"`,
|
|
36228
36558
|
`export CODEXHOST_STOCK_CODEX_PATH=${shellQuote(manifest.stockCodexPath)}`,
|
|
36229
36559
|
`export CODEXHOST_HOST_NODE_PATH=${shellQuote(manifest.nodePath)}`,
|
|
36230
36560
|
`export CODEXHOST_HOST_RUNTIME_PATH=${shellQuote(manifest.hostRuntimePath)}`,
|
|
36231
36561
|
`export CODEXHOST_DATA_DIR=${shellQuote(manifest.dataDirectory)}`,
|
|
36232
36562
|
"export CODEXHOST_DEFAULT_AGENT='codex'",
|
|
36233
|
-
"export CODEXHOST_REMOTE_SSH_MANAGED='1'"
|
|
36234
|
-
...manifest.claudeCommand ? [`export CODEXHOST_CLAUDE_COMMAND=${shellQuote(manifest.claudeCommand)}`] : []
|
|
36563
|
+
"export CODEXHOST_REMOTE_SSH_MANAGED='1'"
|
|
36235
36564
|
];
|
|
36236
36565
|
const block = [
|
|
36237
36566
|
PROFILE_START,
|
|
@@ -36241,7 +36570,7 @@ function installManagedProfileBlock(contents, manifest) {
|
|
|
36241
36570
|
PROFILE_END,
|
|
36242
36571
|
""
|
|
36243
36572
|
].join("\n");
|
|
36244
|
-
if (
|
|
36573
|
+
if (path24.basename(manifest.profilePath) === ".bashrc") return `${block}${base}`;
|
|
36245
36574
|
const separator = base.length > 0 && !base.endsWith("\n") ? "\n" : "";
|
|
36246
36575
|
return `${base}${separator}${block}`;
|
|
36247
36576
|
}
|
|
@@ -36253,16 +36582,16 @@ async function managedEntrypointState(manifest) {
|
|
|
36253
36582
|
if (metadata === null) return "missing";
|
|
36254
36583
|
if (!metadata.isFile()) return "modified";
|
|
36255
36584
|
if (process.platform !== "win32" && (metadata.mode & 73) === 0) return "modified";
|
|
36256
|
-
const entrypoint = await
|
|
36585
|
+
const entrypoint = await readFile10(manifest.wrapperPath);
|
|
36257
36586
|
if (entrypoint.subarray(0, 256).toString("utf8").startsWith(`#!/usr/bin/env sh
|
|
36258
36587
|
${WRAPPER_MARKER}
|
|
36259
36588
|
`)) {
|
|
36260
36589
|
return "legacy-wrapper";
|
|
36261
36590
|
}
|
|
36262
36591
|
if (manifest.entrypointSha256 !== void 0) {
|
|
36263
|
-
return
|
|
36592
|
+
return createHash10("sha256").update(entrypoint).digest("hex") === manifest.entrypointSha256 ? "native" : "modified";
|
|
36264
36593
|
}
|
|
36265
|
-
const shim = await
|
|
36594
|
+
const shim = await readFile10(manifest.shimPath).catch((error51) => {
|
|
36266
36595
|
if (error51.code === "ENOENT") return null;
|
|
36267
36596
|
throw error51;
|
|
36268
36597
|
});
|
|
@@ -36293,6 +36622,7 @@ async function readManifest(filePath) {
|
|
|
36293
36622
|
"dataDirectory",
|
|
36294
36623
|
"entrypointSha256",
|
|
36295
36624
|
"claudeCommand",
|
|
36625
|
+
// Inert metadata accepted from older format-1 manifests.
|
|
36296
36626
|
"profileBackupPath"
|
|
36297
36627
|
]);
|
|
36298
36628
|
const requiredPaths = [
|
|
@@ -36306,9 +36636,9 @@ async function readManifest(filePath) {
|
|
|
36306
36636
|
];
|
|
36307
36637
|
const optionalPaths = ["claudeCommand", "profileBackupPath"];
|
|
36308
36638
|
if (manifest.format !== MANIFEST_FORMAT || Object.keys(manifest).some((key) => !allowed.has(key)) || requiredPaths.some(
|
|
36309
|
-
(key) => typeof manifest[key] !== "string" || !
|
|
36639
|
+
(key) => typeof manifest[key] !== "string" || !path24.isAbsolute(manifest[key])
|
|
36310
36640
|
) || optionalPaths.some(
|
|
36311
|
-
(key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !
|
|
36641
|
+
(key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !path24.isAbsolute(manifest[key]))
|
|
36312
36642
|
) || manifest.entrypointSha256 !== void 0 && (typeof manifest.entrypointSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(manifest.entrypointSha256))) {
|
|
36313
36643
|
throw new Error("Remote Host manifest has an unsupported format");
|
|
36314
36644
|
}
|
|
@@ -36317,7 +36647,7 @@ async function readManifest(filePath) {
|
|
|
36317
36647
|
async function backupProfile(profilePath, contents, action) {
|
|
36318
36648
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(/[-:.TZ]/gu, "");
|
|
36319
36649
|
const backupPath = `${profilePath}.codexhost-${action}-${timestamp}.bak`;
|
|
36320
|
-
const metadata = await
|
|
36650
|
+
const metadata = await stat5(profilePath).catch(() => null);
|
|
36321
36651
|
await writeAtomic(backupPath, contents, metadata?.mode ?? 384);
|
|
36322
36652
|
return backupPath;
|
|
36323
36653
|
}
|
|
@@ -36330,8 +36660,8 @@ async function installRemoteHost(options2) {
|
|
|
36330
36660
|
const paths = resolvePaths(options2);
|
|
36331
36661
|
const previousManifest = await readManifest(paths.manifestPath);
|
|
36332
36662
|
const previousManifestFile = previousManifest ? {
|
|
36333
|
-
contents: await
|
|
36334
|
-
mode: (await
|
|
36663
|
+
contents: await readFile10(paths.manifestPath),
|
|
36664
|
+
mode: (await stat5(paths.manifestPath)).mode & 511
|
|
36335
36665
|
} : null;
|
|
36336
36666
|
const existingEntrypoint = await lstat8(paths.wrapperPath).catch(
|
|
36337
36667
|
(error51) => {
|
|
@@ -36355,7 +36685,7 @@ async function installRemoteHost(options2) {
|
|
|
36355
36685
|
}
|
|
36356
36686
|
const profilePath = previousManifest?.profilePath ?? paths.profilePath;
|
|
36357
36687
|
const previousEntrypoint = existingEntrypoint?.isFile() ? {
|
|
36358
|
-
contents: await
|
|
36688
|
+
contents: await readFile10(paths.wrapperPath),
|
|
36359
36689
|
mode: existingEntrypoint.mode & 511
|
|
36360
36690
|
} : null;
|
|
36361
36691
|
const discoveredStock = options2.stockCodexPath ?? previousManifest?.stockCodexPath ?? await discoverExecutable("codex", environment);
|
|
@@ -36372,8 +36702,6 @@ async function installRemoteHost(options2) {
|
|
|
36372
36702
|
const nodePath2 = await executable(options2.nodePath, "Node runtime");
|
|
36373
36703
|
const shimPath = await executable(options2.shimPath, "codexhost Shim");
|
|
36374
36704
|
const hostRuntimePath = await existingFile(options2.hostRuntimePath, "codexhost Host Runtime");
|
|
36375
|
-
const discoveredClaude = options2.claudeCommand ?? previousManifest?.claudeCommand ?? await discoverExecutable("claude", environment);
|
|
36376
|
-
const claudeCommand = discoveredClaude ? await executable(discoveredClaude, "Claude Code command") : void 0;
|
|
36377
36705
|
let manifest = {
|
|
36378
36706
|
format: MANIFEST_FORMAT,
|
|
36379
36707
|
wrapperPath: paths.wrapperPath,
|
|
@@ -36383,21 +36711,20 @@ async function installRemoteHost(options2) {
|
|
|
36383
36711
|
shimPath,
|
|
36384
36712
|
hostRuntimePath,
|
|
36385
36713
|
dataDirectory: paths.dataDirectory,
|
|
36386
|
-
...claudeCommand ? { claudeCommand } : {},
|
|
36387
36714
|
...previousManifest?.profileBackupPath ? { profileBackupPath: previousManifest.profileBackupPath } : {}
|
|
36388
36715
|
};
|
|
36389
36716
|
const existingProfileSource = await existingText(profilePath);
|
|
36390
36717
|
const existingProfile = existingProfileSource ?? "";
|
|
36391
36718
|
const nextProfile = installManagedProfileBlock(existingProfile, manifest);
|
|
36392
36719
|
const profileChanged = nextProfile !== existingProfile;
|
|
36393
|
-
const profileMetadata = await
|
|
36720
|
+
const profileMetadata = await stat5(profilePath).catch(() => null);
|
|
36394
36721
|
try {
|
|
36395
36722
|
if (profileChanged) {
|
|
36396
36723
|
const profileBackupPath = await backupProfile(profilePath, existingProfile, "install");
|
|
36397
36724
|
manifest = { ...manifest, profileBackupPath };
|
|
36398
36725
|
await writeAtomic(profilePath, nextProfile, profileMetadata?.mode ?? 384);
|
|
36399
36726
|
}
|
|
36400
|
-
await
|
|
36727
|
+
await mkdir10(paths.dataDirectory, { recursive: true, mode: 448 });
|
|
36401
36728
|
await chmod4(paths.dataDirectory, 448);
|
|
36402
36729
|
await writeAtomicExecutable(paths.wrapperPath, manifest.shimPath);
|
|
36403
36730
|
manifest = { ...manifest, entrypointSha256: await fileSha256(paths.wrapperPath) };
|
|
@@ -36410,7 +36737,7 @@ async function installRemoteHost(options2) {
|
|
|
36410
36737
|
if (previousEntrypoint) {
|
|
36411
36738
|
await writeAtomic(paths.wrapperPath, previousEntrypoint.contents, previousEntrypoint.mode);
|
|
36412
36739
|
} else {
|
|
36413
|
-
await
|
|
36740
|
+
await rm10(paths.wrapperPath, { force: true });
|
|
36414
36741
|
}
|
|
36415
36742
|
} catch (rollbackError) {
|
|
36416
36743
|
rollbackErrors.push(rollbackError);
|
|
@@ -36418,7 +36745,7 @@ async function installRemoteHost(options2) {
|
|
|
36418
36745
|
if (profileChanged) {
|
|
36419
36746
|
try {
|
|
36420
36747
|
if (existingProfileSource === null) {
|
|
36421
|
-
await
|
|
36748
|
+
await rm10(profilePath, { force: true });
|
|
36422
36749
|
} else {
|
|
36423
36750
|
await writeAtomic(profilePath, existingProfile, profileMetadata?.mode ?? 384);
|
|
36424
36751
|
}
|
|
@@ -36434,7 +36761,7 @@ async function installRemoteHost(options2) {
|
|
|
36434
36761
|
previousManifestFile.mode
|
|
36435
36762
|
);
|
|
36436
36763
|
} else {
|
|
36437
|
-
await
|
|
36764
|
+
await rm10(paths.manifestPath, { force: true });
|
|
36438
36765
|
}
|
|
36439
36766
|
} catch (rollbackError) {
|
|
36440
36767
|
rollbackErrors.push(rollbackError);
|
|
@@ -36481,7 +36808,7 @@ async function inspectRemoteHostInstallation(options2) {
|
|
|
36481
36808
|
if (!profileMatches && profileIssue === null)
|
|
36482
36809
|
profileIssue = "shell profile does not configure the managed native entrypoint";
|
|
36483
36810
|
if (profileIssue !== null) issues.push(profileIssue);
|
|
36484
|
-
const dataDirectory = await
|
|
36811
|
+
const dataDirectory = await stat5(manifest.dataDirectory).catch(() => null);
|
|
36485
36812
|
if (!dataDirectory?.isDirectory()) issues.push("remote Host data directory is unavailable");
|
|
36486
36813
|
for (const [label, filePath, requiresExecutable] of [
|
|
36487
36814
|
["stock Codex", manifest.stockCodexPath, true],
|
|
@@ -36491,7 +36818,7 @@ async function inspectRemoteHostInstallation(options2) {
|
|
|
36491
36818
|
]) {
|
|
36492
36819
|
try {
|
|
36493
36820
|
if (requiresExecutable) await executable(filePath, label);
|
|
36494
|
-
else if (!(await
|
|
36821
|
+
else if (!(await stat5(filePath)).isFile()) throw new Error("not a regular file");
|
|
36495
36822
|
} catch {
|
|
36496
36823
|
issues.push(`${label} is unavailable`);
|
|
36497
36824
|
}
|
|
@@ -36520,11 +36847,11 @@ async function uninstallRemoteHost(options2) {
|
|
|
36520
36847
|
const nextProfile = removeManagedProfileBlock(profile);
|
|
36521
36848
|
if (nextProfile !== profile) {
|
|
36522
36849
|
await backupProfile(manifest.profilePath, profile, "uninstall");
|
|
36523
|
-
const metadata = await
|
|
36850
|
+
const metadata = await stat5(manifest.profilePath).catch(() => null);
|
|
36524
36851
|
await writeAtomic(manifest.profilePath, nextProfile, metadata?.mode ?? 384);
|
|
36525
36852
|
}
|
|
36526
|
-
await
|
|
36527
|
-
await
|
|
36853
|
+
await rm10(manifest.wrapperPath, { force: true });
|
|
36854
|
+
await rm10(paths.manifestPath, { force: true });
|
|
36528
36855
|
await rmdir(paths.binDirectory).catch((error51) => {
|
|
36529
36856
|
if (error51.code !== "ENOENT" && error51.code !== "ENOTEMPTY") throw error51;
|
|
36530
36857
|
});
|
|
@@ -36535,9 +36862,9 @@ async function uninstallRemoteHost(options2) {
|
|
|
36535
36862
|
|
|
36536
36863
|
// packages/host-runtime/src/remote-host-lifecycle.ts
|
|
36537
36864
|
import { spawn as spawn5 } from "node:child_process";
|
|
36538
|
-
import { stat as
|
|
36865
|
+
import { stat as stat6 } from "node:fs/promises";
|
|
36539
36866
|
import net3 from "node:net";
|
|
36540
|
-
import
|
|
36867
|
+
import path25 from "node:path";
|
|
36541
36868
|
import { Duplex } from "node:stream";
|
|
36542
36869
|
|
|
36543
36870
|
// packages/host-runtime/src/app-server-websocket-options.ts
|
|
@@ -36564,12 +36891,12 @@ function classifyRemoteHostProbeResponse(response, socketPath) {
|
|
|
36564
36891
|
}
|
|
36565
36892
|
var lifecycleDependencyOverrides = {};
|
|
36566
36893
|
function socketPathFor(environment) {
|
|
36567
|
-
const codexHome = environment.CODEX_HOME ?? (environment.HOME ?
|
|
36894
|
+
const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path25.join(environment.HOME, ".codex") : void 0);
|
|
36568
36895
|
if (!codexHome) throw new Error("CODEX_HOME or HOME is required for remote Host lifecycle");
|
|
36569
|
-
return
|
|
36896
|
+
return path25.join(codexHome, "app-server-control", "app-server-control.sock");
|
|
36570
36897
|
}
|
|
36571
36898
|
async function defaultSocketExists(socketPath) {
|
|
36572
|
-
const metadata = await
|
|
36899
|
+
const metadata = await stat6(socketPath).catch((error51) => {
|
|
36573
36900
|
if (error51.code === "ENOENT") return null;
|
|
36574
36901
|
throw error51;
|
|
36575
36902
|
});
|
|
@@ -36696,15 +37023,14 @@ function installedManifest(status) {
|
|
|
36696
37023
|
function managedEnvironment(manifest, environment) {
|
|
36697
37024
|
return {
|
|
36698
37025
|
...environment,
|
|
36699
|
-
CODEX_INSTALL_DIR:
|
|
37026
|
+
CODEX_INSTALL_DIR: path25.dirname(manifest.wrapperPath),
|
|
36700
37027
|
CODEXHOST_STOCK_CODEX_PATH: manifest.stockCodexPath,
|
|
36701
37028
|
CODEXHOST_HOST_NODE_PATH: manifest.nodePath,
|
|
36702
37029
|
CODEXHOST_HOST_RUNTIME_PATH: manifest.hostRuntimePath,
|
|
36703
37030
|
CODEXHOST_DATA_DIR: manifest.dataDirectory,
|
|
36704
37031
|
CODEXHOST_DEFAULT_AGENT: "codex",
|
|
36705
37032
|
CODEXHOST_REMOTE_SSH_MANAGED: "1",
|
|
36706
|
-
|
|
36707
|
-
PATH: `${path23.dirname(manifest.wrapperPath)}${path23.delimiter}${path23.dirname(manifest.stockCodexPath)}${path23.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
|
|
37033
|
+
PATH: `${path25.dirname(manifest.wrapperPath)}${path25.delimiter}${path25.dirname(manifest.stockCodexPath)}${path25.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
|
|
36708
37034
|
};
|
|
36709
37035
|
}
|
|
36710
37036
|
async function defaultRunTerminator(manifest, socketPath, role, environment) {
|
|
@@ -36852,9 +37178,6 @@ function parseRemoteCliArguments(arguments_2) {
|
|
|
36852
37178
|
case "--stock-codex":
|
|
36853
37179
|
options2.stockCodexPath = value2;
|
|
36854
37180
|
break;
|
|
36855
|
-
case "--claude-command":
|
|
36856
|
-
options2.claudeCommand = value2;
|
|
36857
|
-
break;
|
|
36858
37181
|
case "--node":
|
|
36859
37182
|
resources.nodePath = value2;
|
|
36860
37183
|
break;
|
|
@@ -36881,7 +37204,7 @@ async function runRemoteHostCli(input) {
|
|
|
36881
37204
|
output.write(
|
|
36882
37205
|
[
|
|
36883
37206
|
"usage:",
|
|
36884
|
-
" boft remote install [--stock-codex PATH]
|
|
37207
|
+
" boft remote install [--stock-codex PATH]",
|
|
36885
37208
|
" boft remote start",
|
|
36886
37209
|
" boft remote stop",
|
|
36887
37210
|
" boft remote status",
|
|
@@ -37045,26 +37368,26 @@ function consumeBrokerFrames(socket, onFrame, onError) {
|
|
|
37045
37368
|
}
|
|
37046
37369
|
|
|
37047
37370
|
// packages/harness-broker/dist/paths.js
|
|
37048
|
-
import
|
|
37049
|
-
import
|
|
37371
|
+
import os7 from "node:os";
|
|
37372
|
+
import path26 from "node:path";
|
|
37050
37373
|
var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
|
|
37051
37374
|
var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
|
|
37052
37375
|
var HARNESS_BROKER_SOCKET_FILE = "claude-code-broker-v1.sock";
|
|
37053
37376
|
function defaultHarnessBrokerDirectory(environment = process.env) {
|
|
37054
|
-
const home = environment.HOME ||
|
|
37055
|
-
return
|
|
37377
|
+
const home = environment.HOME || os7.homedir();
|
|
37378
|
+
return path26.join(home, ".codexhost", "harness-broker");
|
|
37056
37379
|
}
|
|
37057
37380
|
function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
|
|
37058
37381
|
harnessPluginIdSchema.parse(harnessId);
|
|
37059
37382
|
if (harnessId !== "claude-code")
|
|
37060
|
-
return
|
|
37061
|
-
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ??
|
|
37383
|
+
return path26.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
|
|
37384
|
+
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path26.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
|
|
37062
37385
|
}
|
|
37063
37386
|
function defaultHarnessBrokerSocketPath(environment = process.env, harnessId = "claude-code") {
|
|
37064
37387
|
harnessPluginIdSchema.parse(harnessId);
|
|
37065
37388
|
if (harnessId !== "claude-code")
|
|
37066
|
-
return
|
|
37067
|
-
return
|
|
37389
|
+
return path26.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
|
|
37390
|
+
return path26.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
|
|
37068
37391
|
}
|
|
37069
37392
|
|
|
37070
37393
|
// packages/harness-broker/dist/validation.js
|
|
@@ -37298,10 +37621,10 @@ var harnessOutputSchema = external_exports.custom((value2) => {
|
|
|
37298
37621
|
});
|
|
37299
37622
|
|
|
37300
37623
|
// packages/harness-broker/dist/server.js
|
|
37301
|
-
import { randomBytes as randomBytes3, randomUUID as
|
|
37302
|
-
import { chmod as chmod5, lstat as lstat9, mkdir as
|
|
37624
|
+
import { randomBytes as randomBytes3, randomUUID as randomUUID15 } from "node:crypto";
|
|
37625
|
+
import { chmod as chmod5, lstat as lstat9, mkdir as mkdir11, open as open8, readFile as readFile11, rename as rename8, rm as rm11 } from "node:fs/promises";
|
|
37303
37626
|
import net4, {} from "node:net";
|
|
37304
|
-
import
|
|
37627
|
+
import path27 from "node:path";
|
|
37305
37628
|
function harnessError(message, retryable = true) {
|
|
37306
37629
|
return { code: "unavailable", message, retryable, stage: "harnessBroker" };
|
|
37307
37630
|
}
|
|
@@ -37312,7 +37635,7 @@ function nativeWriterKey(nativeSessionId) {
|
|
|
37312
37635
|
return nativeSessionId;
|
|
37313
37636
|
}
|
|
37314
37637
|
async function privateDirectory(directory) {
|
|
37315
|
-
await
|
|
37638
|
+
await mkdir11(directory, { recursive: true, mode: 448 });
|
|
37316
37639
|
if (process.platform === "win32")
|
|
37317
37640
|
return;
|
|
37318
37641
|
const metadata = await lstat9(directory);
|
|
@@ -37347,7 +37670,7 @@ async function assertNoLiveDescriptor(descriptorPath) {
|
|
|
37347
37670
|
throw new Error("Harness broker descriptor is not owner-only");
|
|
37348
37671
|
}
|
|
37349
37672
|
}
|
|
37350
|
-
const descriptor = harnessBrokerDescriptorSchema.parse(JSON.parse(await
|
|
37673
|
+
const descriptor = harnessBrokerDescriptorSchema.parse(JSON.parse(await readFile11(descriptorPath, "utf8")));
|
|
37351
37674
|
if (processIsAlive2(descriptor.ownerPid)) {
|
|
37352
37675
|
throw new Error("Harness broker descriptor already has a live owner");
|
|
37353
37676
|
}
|
|
@@ -37357,7 +37680,7 @@ async function assertNoLiveDescriptor(descriptorPath) {
|
|
|
37357
37680
|
}
|
|
37358
37681
|
}
|
|
37359
37682
|
async function publishDescriptor(descriptorPath, descriptor) {
|
|
37360
|
-
const temporary = `${descriptorPath}.${process.pid}.${
|
|
37683
|
+
const temporary = `${descriptorPath}.${process.pid}.${randomUUID15()}.tmp`;
|
|
37361
37684
|
const handle = await open8(temporary, "wx", 384);
|
|
37362
37685
|
try {
|
|
37363
37686
|
await handle.writeFile(`${JSON.stringify(descriptor)}
|
|
@@ -37366,7 +37689,7 @@ async function publishDescriptor(descriptorPath, descriptor) {
|
|
|
37366
37689
|
} finally {
|
|
37367
37690
|
await handle.close();
|
|
37368
37691
|
}
|
|
37369
|
-
await
|
|
37692
|
+
await rename8(temporary, descriptorPath);
|
|
37370
37693
|
if (process.platform !== "win32")
|
|
37371
37694
|
await chmod5(descriptorPath, 384);
|
|
37372
37695
|
}
|
|
@@ -37416,7 +37739,7 @@ async function prepareUnixSocketPath(socketPath) {
|
|
|
37416
37739
|
if (await socketAcceptsConnections(socketPath)) {
|
|
37417
37740
|
throw new Error("Harness broker socket is already active");
|
|
37418
37741
|
}
|
|
37419
|
-
await
|
|
37742
|
+
await rm11(socketPath);
|
|
37420
37743
|
} catch (error51) {
|
|
37421
37744
|
if (error51.code !== "ENOENT")
|
|
37422
37745
|
throw error51;
|
|
@@ -37424,17 +37747,17 @@ async function prepareUnixSocketPath(socketPath) {
|
|
|
37424
37747
|
}
|
|
37425
37748
|
async function startHarnessBrokerServer(input) {
|
|
37426
37749
|
harnessPluginIdSchema.parse(input.adapter.harnessId);
|
|
37427
|
-
if (process.platform !== "win32" &&
|
|
37750
|
+
if (process.platform !== "win32" && path27.dirname(input.descriptorPath) !== path27.dirname(input.socketPath)) {
|
|
37428
37751
|
throw new Error("Harness broker descriptor and socket must share one private directory");
|
|
37429
37752
|
}
|
|
37430
37753
|
if (process.platform === "darwin" && Buffer.byteLength(input.socketPath) > 103) {
|
|
37431
37754
|
throw new Error("Harness broker Unix socket path is too long for macOS");
|
|
37432
37755
|
}
|
|
37433
|
-
await privateDirectory(
|
|
37756
|
+
await privateDirectory(path27.dirname(input.descriptorPath));
|
|
37434
37757
|
await assertNoLiveDescriptor(input.descriptorPath);
|
|
37435
37758
|
if (process.platform !== "win32")
|
|
37436
37759
|
await prepareUnixSocketPath(input.socketPath);
|
|
37437
|
-
const generation = input.generation ??
|
|
37760
|
+
const generation = input.generation ?? randomUUID15();
|
|
37438
37761
|
const token = input.token ?? randomBytes3(32).toString("hex");
|
|
37439
37762
|
const descriptor = {
|
|
37440
37763
|
schemaVersion: 1,
|
|
@@ -37452,7 +37775,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
37452
37775
|
let closed = false;
|
|
37453
37776
|
const server = net4.createServer((socket) => {
|
|
37454
37777
|
const state = {
|
|
37455
|
-
id:
|
|
37778
|
+
id: randomUUID15(),
|
|
37456
37779
|
socket,
|
|
37457
37780
|
authenticated: false,
|
|
37458
37781
|
inputSequence: 0,
|
|
@@ -37711,7 +38034,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
37711
38034
|
}
|
|
37712
38035
|
};
|
|
37713
38036
|
}
|
|
37714
|
-
const openReservation =
|
|
38037
|
+
const openReservation = randomUUID15();
|
|
37715
38038
|
if (sourceKey)
|
|
37716
38039
|
nativeWriters.set(sourceKey, openReservation);
|
|
37717
38040
|
const provisionalReservation = openInput.kind === "create" ? openReservation : void 0;
|
|
@@ -37991,7 +38314,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
37991
38314
|
}
|
|
37992
38315
|
state.authenticated = true;
|
|
37993
38316
|
state.inputSequence = 1;
|
|
37994
|
-
await send({ kind: "response", id:
|
|
38317
|
+
await send({ kind: "response", id: randomUUID15(), ok: true, value: { ready: true } });
|
|
37995
38318
|
return;
|
|
37996
38319
|
}
|
|
37997
38320
|
const parsed = harnessBrokerRequestSchema.safeParse(raw);
|
|
@@ -38039,7 +38362,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
38039
38362
|
} catch (error51) {
|
|
38040
38363
|
await new Promise((resolve) => server.close(() => resolve()));
|
|
38041
38364
|
if (process.platform !== "win32")
|
|
38042
|
-
await
|
|
38365
|
+
await rm11(input.socketPath, { force: true });
|
|
38043
38366
|
throw error51;
|
|
38044
38367
|
}
|
|
38045
38368
|
return {
|
|
@@ -38057,8 +38380,8 @@ async function startHarnessBrokerServer(input) {
|
|
|
38057
38380
|
await input.adapter.close().catch(() => void 0);
|
|
38058
38381
|
await new Promise((resolve) => server.close(() => resolve()));
|
|
38059
38382
|
if (process.platform !== "win32")
|
|
38060
|
-
await
|
|
38061
|
-
await
|
|
38383
|
+
await rm11(input.socketPath, { force: true });
|
|
38384
|
+
await rm11(input.descriptorPath, { force: true });
|
|
38062
38385
|
}
|
|
38063
38386
|
};
|
|
38064
38387
|
}
|