@codexhost/cli-darwin-x64 0.9.1-test.2 → 0.9.2
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/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +256 -179
- package/app/host-runtime.mjs +594 -298
- package/app/plugins/antigravity/plugin.mjs +123 -1
- package/app/plugins/claude-code/plugin.mjs +248 -42
- package/app/plugins/codebuddy/plugin.mjs +2166 -758
- package/app/plugins/cursor-cli/plugin.mjs +35942 -10942
- 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/omp/plugin.mjs +106 -8
- package/app/plugins/opencode/plugin.mjs +70 -0
- package/app/plugins/pi/plugin.mjs +1933 -767
- 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 +24873 -0
- package/app/renderer-extension.js +5290 -3642
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- package/package.json +1 -1
package/app/host-runtime.mjs
CHANGED
|
@@ -2278,7 +2278,7 @@ var require_websocket = __commonJS({
|
|
|
2278
2278
|
var http = __require("http");
|
|
2279
2279
|
var net5 = __require("net");
|
|
2280
2280
|
var tls = __require("tls");
|
|
2281
|
-
var { randomBytes: 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 path22 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, path27) {
|
|
5982
|
+
if (!path27)
|
|
5983
5983
|
return obj;
|
|
5984
|
-
return
|
|
5984
|
+
return path27.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(path27, 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(path27);
|
|
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, path27 = []) => {
|
|
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 }, [...path27, ...issue2.path]));
|
|
6548
6548
|
} else if (issue2.code === "invalid_key") {
|
|
6549
|
-
processError({ issues: issue2.issues }, [...
|
|
6549
|
+
processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
|
|
6550
6550
|
} else if (issue2.code === "invalid_element") {
|
|
6551
|
-
processError({ issues: issue2.issues }, [...
|
|
6551
|
+
processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
|
|
6552
6552
|
} else {
|
|
6553
|
-
const fullpath = [...
|
|
6553
|
+
const fullpath = [...path27, ...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, path27 = []) => {
|
|
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 }, [...path27, ...issue2.path]));
|
|
6585
6585
|
} else if (issue2.code === "invalid_key") {
|
|
6586
|
-
processError({ issues: issue2.issues }, [...
|
|
6586
|
+
processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
|
|
6587
6587
|
} else if (issue2.code === "invalid_element") {
|
|
6588
|
-
processError({ issues: issue2.issues }, [...
|
|
6588
|
+
processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
|
|
6589
6589
|
} else {
|
|
6590
|
-
const fullpath = [...
|
|
6590
|
+
const fullpath = [...path27, ...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 path27 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
6623
|
+
for (const seg of path27) {
|
|
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 path27 = ref.slice(1).split("/").filter(Boolean);
|
|
19316
|
+
if (path27.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 (path27[0] === defsKey) {
|
|
19321
|
+
const key = path27[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
|
|
|
@@ -20261,6 +20317,8 @@ var pluginPresentationShape = {
|
|
|
20261
20317
|
id: harnessPluginIdSchema,
|
|
20262
20318
|
name: external_exports.string().trim().min(1).max(128),
|
|
20263
20319
|
version: external_exports.string().min(1).max(128),
|
|
20320
|
+
/** The factory accepts a persisted local entrypoint through its construction context. */
|
|
20321
|
+
launchCommand: external_exports.literal(true).optional(),
|
|
20264
20322
|
links: external_exports.object({
|
|
20265
20323
|
documentation: documentationUrlSchema.optional(),
|
|
20266
20324
|
installation: documentationUrlSchema.optional()
|
|
@@ -20322,6 +20380,21 @@ function decodeHarnessPluginRoute(value2) {
|
|
|
20322
20380
|
}
|
|
20323
20381
|
}
|
|
20324
20382
|
|
|
20383
|
+
// packages/shared-contracts/dist/harness-launch-settings.js
|
|
20384
|
+
var HARNESS_LAUNCH_SETTINGS_GET_METHOD = "codexhost/harness/launch-settings/get";
|
|
20385
|
+
var HARNESS_LAUNCH_SETTINGS_SET_METHOD = "codexhost/harness/launch-settings/set";
|
|
20386
|
+
var harnessLaunchPathSchema = external_exports.string().trim().min(1).max(4096).refine((value2) => !/[\u0000\r\n]/u.test(value2), "Invalid entrypoint path");
|
|
20387
|
+
var harnessLaunchSettingsGetSchema = external_exports.object({
|
|
20388
|
+
harnessId: harnessPluginIdSchema
|
|
20389
|
+
}).strict();
|
|
20390
|
+
var harnessLaunchSettingsSetSchema = harnessLaunchSettingsGetSchema.extend({
|
|
20391
|
+
path: harnessLaunchPathSchema.nullable()
|
|
20392
|
+
});
|
|
20393
|
+
var harnessLaunchSettingsSchema = external_exports.object({
|
|
20394
|
+
path: harnessLaunchPathSchema.nullable(),
|
|
20395
|
+
restartRequired: external_exports.boolean()
|
|
20396
|
+
}).strict();
|
|
20397
|
+
|
|
20325
20398
|
// packages/shared-contracts/dist/codex-accounts.js
|
|
20326
20399
|
var accountIdSchema = external_exports.string().min(1).max(256).regex(/^[A-Za-z0-9._~-]+$/u);
|
|
20327
20400
|
var nonBlankTextSchema3 = external_exports.string().trim().min(1);
|
|
@@ -20613,6 +20686,97 @@ var updateStatusResultSchema = external_exports.strictObject({
|
|
|
20613
20686
|
// packages/shared-contracts/dist/index.js
|
|
20614
20687
|
var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
|
|
20615
20688
|
|
|
20689
|
+
// packages/host-runtime/src/account/codex-credential-export.ts
|
|
20690
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
20691
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
20692
|
+
import os from "node:os";
|
|
20693
|
+
import path5 from "node:path";
|
|
20694
|
+
async function readCodexCredential(environment) {
|
|
20695
|
+
try {
|
|
20696
|
+
const home = environment.CODEX_HOME ?? path5.join(environment.HOME ?? os.homedir(), ".codex");
|
|
20697
|
+
const auth = JSON.parse(await readFile4(path5.join(home, "auth.json"), "utf8"));
|
|
20698
|
+
if (auth.OPENAI_API_KEY || auth.auth_mode && auth.auth_mode !== "chatgpt") return [];
|
|
20699
|
+
const t = auth.tokens;
|
|
20700
|
+
if (!t || ![t.access_token, t.refresh_token, t.account_id].every(
|
|
20701
|
+
(v) => typeof v === "string" && v.length
|
|
20702
|
+
))
|
|
20703
|
+
return [];
|
|
20704
|
+
const claims = JSON.parse(Buffer.from(t.access_token.split(".")[1], "base64url").toString());
|
|
20705
|
+
if (claims.client_id !== "app_EMoamEEZ73f0CkXaXp7hrann" || !Number.isFinite(claims.exp * 1e3))
|
|
20706
|
+
return [];
|
|
20707
|
+
const account = claims["https://api.openai.com/auth"]?.chatgpt_account_id;
|
|
20708
|
+
if (account !== t.account_id) return [];
|
|
20709
|
+
let email3;
|
|
20710
|
+
try {
|
|
20711
|
+
email3 = JSON.parse(Buffer.from(t.id_token.split(".")[1], "base64url").toString()).email;
|
|
20712
|
+
} catch {
|
|
20713
|
+
}
|
|
20714
|
+
const identity = `${t.account_id}:${claims.sub ?? ""}`;
|
|
20715
|
+
return [
|
|
20716
|
+
{
|
|
20717
|
+
source: {
|
|
20718
|
+
id: `codex:${createHash2("sha256").update(identity).digest("hex")}`,
|
|
20719
|
+
harnessId: "codex",
|
|
20720
|
+
provider: "openai-codex",
|
|
20721
|
+
label: typeof email3 === "string" && email3 ? email3 : "Codex"
|
|
20722
|
+
},
|
|
20723
|
+
oauth: {
|
|
20724
|
+
access: t.access_token,
|
|
20725
|
+
refresh: t.refresh_token,
|
|
20726
|
+
expires: claims.exp * 1e3,
|
|
20727
|
+
accountId: t.account_id
|
|
20728
|
+
}
|
|
20729
|
+
}
|
|
20730
|
+
];
|
|
20731
|
+
} catch {
|
|
20732
|
+
return [];
|
|
20733
|
+
}
|
|
20734
|
+
}
|
|
20735
|
+
|
|
20736
|
+
// packages/host-runtime/src/credential-imports.ts
|
|
20737
|
+
async function handleCredentialImports(params, adapters, environment) {
|
|
20738
|
+
const input = credentialImportsParamsSchema.parse(params);
|
|
20739
|
+
const installed = [...adapters];
|
|
20740
|
+
const sources = await readCodexCredential(environment);
|
|
20741
|
+
for (const adapter of installed) {
|
|
20742
|
+
if (adapter.credentialExport) sources.push(...await adapter.credentialExport.read());
|
|
20743
|
+
}
|
|
20744
|
+
const request = input.request;
|
|
20745
|
+
if (request.action !== "list") {
|
|
20746
|
+
const target = installed.find((a) => a.harnessId === input.targetHarnessId)?.credentialImports;
|
|
20747
|
+
if (!target) throw new Error("Target Harness does not support credential imports");
|
|
20748
|
+
if (request.action === "remove") await target.remove(request.name);
|
|
20749
|
+
else {
|
|
20750
|
+
const source = sources.find((s) => s.source.id === request.sourceId);
|
|
20751
|
+
if (!source || !target.providers.includes(source.source.provider))
|
|
20752
|
+
throw new Error("Source login changed or is unavailable; refresh and confirm again");
|
|
20753
|
+
if (request.action === "reimport") await target.reimport(request.name, source);
|
|
20754
|
+
else await target.add(request.name, source);
|
|
20755
|
+
}
|
|
20756
|
+
}
|
|
20757
|
+
const targets = [];
|
|
20758
|
+
for (const adapter of installed) {
|
|
20759
|
+
if (!adapter.credentialImports) continue;
|
|
20760
|
+
try {
|
|
20761
|
+
targets.push({
|
|
20762
|
+
harnessId: adapter.harnessId,
|
|
20763
|
+
providers: [...adapter.credentialImports.providers],
|
|
20764
|
+
imports: await adapter.credentialImports.list(),
|
|
20765
|
+
others: await listOthers(adapter)
|
|
20766
|
+
});
|
|
20767
|
+
} catch {
|
|
20768
|
+
}
|
|
20769
|
+
}
|
|
20770
|
+
return credentialImportsResultSchema.parse({ sources: sources.map((s) => s.source), targets });
|
|
20771
|
+
}
|
|
20772
|
+
async function listOthers(adapter) {
|
|
20773
|
+
try {
|
|
20774
|
+
return await adapter.credentialImports?.listOthers?.() ?? [];
|
|
20775
|
+
} catch {
|
|
20776
|
+
return [];
|
|
20777
|
+
}
|
|
20778
|
+
}
|
|
20779
|
+
|
|
20616
20780
|
// packages/harness-adapter/dist/output-channel.js
|
|
20617
20781
|
var HarnessOutputChannel = class {
|
|
20618
20782
|
outputs;
|
|
@@ -20762,8 +20926,8 @@ var packageMetadata = {
|
|
|
20762
20926
|
import { execFileSync } from "node:child_process";
|
|
20763
20927
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
20764
20928
|
import { constants } from "node:fs";
|
|
20765
|
-
import { copyFile as copyFile2, mkdir as mkdir3, open as open3, readFile as
|
|
20766
|
-
import
|
|
20929
|
+
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";
|
|
20930
|
+
import path6 from "node:path";
|
|
20767
20931
|
|
|
20768
20932
|
// packages/mapping-store/dist/records.js
|
|
20769
20933
|
var nonBlankTextSchema6 = external_exports.string().refine((value2) => value2.trim().length > 0, {
|
|
@@ -21024,12 +21188,12 @@ var MappingStore = class {
|
|
|
21024
21188
|
#initialized = false;
|
|
21025
21189
|
#lockHandle = null;
|
|
21026
21190
|
constructor(options2) {
|
|
21027
|
-
this.#directory =
|
|
21028
|
-
this.#threadsDirectory =
|
|
21029
|
-
this.#delegationsDirectory =
|
|
21030
|
-
this.#backupsDirectory =
|
|
21031
|
-
this.#quarantineDirectory =
|
|
21032
|
-
this.#lockPath =
|
|
21191
|
+
this.#directory = path6.resolve(options2.directory);
|
|
21192
|
+
this.#threadsDirectory = path6.join(this.#directory, "threads");
|
|
21193
|
+
this.#delegationsDirectory = path6.join(this.#directory, "delegations");
|
|
21194
|
+
this.#backupsDirectory = path6.join(this.#directory, "backups");
|
|
21195
|
+
this.#quarantineDirectory = path6.join(this.#directory, "quarantine");
|
|
21196
|
+
this.#lockPath = path6.join(this.#directory, "store.lock");
|
|
21033
21197
|
this.#instanceId = options2.instanceId ?? randomUUID2();
|
|
21034
21198
|
this.#now = options2.now ?? (() => /* @__PURE__ */ new Date());
|
|
21035
21199
|
this.#beforeReplace = options2.beforeReplace;
|
|
@@ -21048,8 +21212,8 @@ var MappingStore = class {
|
|
|
21048
21212
|
await this.#cleanupResidue();
|
|
21049
21213
|
const names = (await readdir2(this.#threadsDirectory)).filter((name) => name.endsWith(".json"));
|
|
21050
21214
|
for (const name of names) {
|
|
21051
|
-
const primary =
|
|
21052
|
-
const backup =
|
|
21215
|
+
const primary = path6.join(this.#threadsDirectory, name);
|
|
21216
|
+
const backup = path6.join(this.#backupsDirectory, name);
|
|
21053
21217
|
let record3 = null;
|
|
21054
21218
|
try {
|
|
21055
21219
|
record3 = await this.#readRecord(primary, name);
|
|
@@ -21058,7 +21222,7 @@ var MappingStore = class {
|
|
|
21058
21222
|
record3 = await this.#readRecord(backup, name);
|
|
21059
21223
|
await this.#replaceFile(primary, record3, false);
|
|
21060
21224
|
} catch (backupError) {
|
|
21061
|
-
const quarantine =
|
|
21225
|
+
const quarantine = path6.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid`);
|
|
21062
21226
|
await rename2(primary, quarantine).catch(() => void 0);
|
|
21063
21227
|
void primaryError;
|
|
21064
21228
|
void backupError;
|
|
@@ -21074,14 +21238,14 @@ var MappingStore = class {
|
|
|
21074
21238
|
}
|
|
21075
21239
|
const delegationNames = (await readdir2(this.#delegationsDirectory)).filter((name) => name.endsWith(".json"));
|
|
21076
21240
|
for (const name of delegationNames) {
|
|
21077
|
-
const file2 =
|
|
21241
|
+
const file2 = path6.join(this.#delegationsDirectory, name);
|
|
21078
21242
|
try {
|
|
21079
|
-
const parsed = storedDelegationRecordV1Schema.parse(JSON.parse(await
|
|
21243
|
+
const parsed = storedDelegationRecordV1Schema.parse(JSON.parse(await readFile5(file2, "utf8")));
|
|
21080
21244
|
if (`${parsed.delegationId}.json` !== name)
|
|
21081
21245
|
throw new Error("filename mismatch");
|
|
21082
21246
|
this.#delegations.set(parsed.delegationId, parsed);
|
|
21083
21247
|
} catch {
|
|
21084
|
-
const quarantine =
|
|
21248
|
+
const quarantine = path6.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid-delegation`);
|
|
21085
21249
|
await rename2(file2, quarantine).catch(() => void 0);
|
|
21086
21250
|
}
|
|
21087
21251
|
}
|
|
@@ -21367,7 +21531,7 @@ var MappingStore = class {
|
|
|
21367
21531
|
if (handle)
|
|
21368
21532
|
await handle.close().catch(() => void 0);
|
|
21369
21533
|
try {
|
|
21370
|
-
const current = JSON.parse(await
|
|
21534
|
+
const current = JSON.parse(await readFile5(this.#lockPath, "utf8"));
|
|
21371
21535
|
if (current.instanceId === this.#instanceId)
|
|
21372
21536
|
await rm3(this.#lockPath, { force: true });
|
|
21373
21537
|
} catch {
|
|
@@ -21483,7 +21647,7 @@ var MappingStore = class {
|
|
|
21483
21647
|
}
|
|
21484
21648
|
}
|
|
21485
21649
|
async #readRecord(file2, expectedName) {
|
|
21486
|
-
const parsed = storedThreadRecordV1Schema.safeParse(JSON.parse(await
|
|
21650
|
+
const parsed = storedThreadRecordV1Schema.safeParse(JSON.parse(await readFile5(file2, "utf8")));
|
|
21487
21651
|
if (!parsed.success) {
|
|
21488
21652
|
throw new MappingStoreError("INVALID_RECORD", "Mapping Store record is invalid", {
|
|
21489
21653
|
cause: parsed.error
|
|
@@ -21501,10 +21665,10 @@ var MappingStore = class {
|
|
|
21501
21665
|
readdir2(this.#directory)
|
|
21502
21666
|
]);
|
|
21503
21667
|
await Promise.all([
|
|
21504
|
-
...threadNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(
|
|
21505
|
-
...delegationNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(
|
|
21668
|
+
...threadNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(path6.join(this.#threadsDirectory, name), { force: true })),
|
|
21669
|
+
...delegationNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(path6.join(this.#delegationsDirectory, name), { force: true })),
|
|
21506
21670
|
// Renamed aside by #acquireLock; nothing reads them back, and they accumulate one per run.
|
|
21507
|
-
...rootNames.filter((name) => name.startsWith(`${
|
|
21671
|
+
...rootNames.filter((name) => name.startsWith(`${path6.basename(this.#lockPath)}.stale-`)).map((name) => rm3(path6.join(this.#directory, name), { force: true }))
|
|
21508
21672
|
]);
|
|
21509
21673
|
}
|
|
21510
21674
|
async #acquireLock() {
|
|
@@ -21531,7 +21695,7 @@ var MappingStore = class {
|
|
|
21531
21695
|
}
|
|
21532
21696
|
let existing = {};
|
|
21533
21697
|
try {
|
|
21534
|
-
existing = JSON.parse(await
|
|
21698
|
+
existing = JSON.parse(await readFile5(this.#lockPath, "utf8"));
|
|
21535
21699
|
} catch {
|
|
21536
21700
|
}
|
|
21537
21701
|
if (typeof existing.pid === "number" && lockOwnerIsLive(existing)) {
|
|
@@ -21605,13 +21769,13 @@ var MappingStore = class {
|
|
|
21605
21769
|
await next;
|
|
21606
21770
|
}
|
|
21607
21771
|
#recordPath(hostThreadId) {
|
|
21608
|
-
return
|
|
21772
|
+
return path6.join(this.#threadsDirectory, `${hostThreadId}.json`);
|
|
21609
21773
|
}
|
|
21610
21774
|
#delegationPath(delegationId) {
|
|
21611
|
-
return
|
|
21775
|
+
return path6.join(this.#delegationsDirectory, `${delegationId}.json`);
|
|
21612
21776
|
}
|
|
21613
21777
|
#backupPath(hostThreadId) {
|
|
21614
|
-
return
|
|
21778
|
+
return path6.join(this.#backupsDirectory, `${hostThreadId}.json`);
|
|
21615
21779
|
}
|
|
21616
21780
|
#requireInitialized() {
|
|
21617
21781
|
if (!this.#initialized) {
|
|
@@ -22299,16 +22463,16 @@ var Diff = class {
|
|
|
22299
22463
|
}
|
|
22300
22464
|
}
|
|
22301
22465
|
}
|
|
22302
|
-
addToPath(
|
|
22303
|
-
const last =
|
|
22466
|
+
addToPath(path27, added, removed, oldPosInc, options2) {
|
|
22467
|
+
const last = path27.lastComponent;
|
|
22304
22468
|
if (last && !options2.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
22305
22469
|
return {
|
|
22306
|
-
oldPos:
|
|
22470
|
+
oldPos: path27.oldPos + oldPosInc,
|
|
22307
22471
|
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
22308
22472
|
};
|
|
22309
22473
|
} else {
|
|
22310
22474
|
return {
|
|
22311
|
-
oldPos:
|
|
22475
|
+
oldPos: path27.oldPos + oldPosInc,
|
|
22312
22476
|
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
22313
22477
|
};
|
|
22314
22478
|
}
|
|
@@ -22737,10 +22901,10 @@ function splitLines(text) {
|
|
|
22737
22901
|
}
|
|
22738
22902
|
|
|
22739
22903
|
// packages/protocol-core/dist/file-change-summary.js
|
|
22740
|
-
import
|
|
22904
|
+
import path7 from "node:path";
|
|
22741
22905
|
function filePathKey(file2, cwd) {
|
|
22742
22906
|
const windows = /^[a-z]:[/\\]/i.test(cwd) || /^[a-z]:[/\\]/i.test(file2);
|
|
22743
|
-
const paths = windows ?
|
|
22907
|
+
const paths = windows ? path7.win32 : path7.posix;
|
|
22744
22908
|
const resolved = paths.resolve(cwd, file2).replaceAll("\\", "/");
|
|
22745
22909
|
return windows ? resolved.toLowerCase() : resolved;
|
|
22746
22910
|
}
|
|
@@ -23009,8 +23173,8 @@ function projectFileChangeKind(kind) {
|
|
|
23009
23173
|
return { type: kind };
|
|
23010
23174
|
}
|
|
23011
23175
|
function projectFileChanges(changes) {
|
|
23012
|
-
return changes.map(({ path:
|
|
23013
|
-
path:
|
|
23176
|
+
return changes.map(({ path: path27, kind, unifiedDiff }) => ({
|
|
23177
|
+
path: path27,
|
|
23014
23178
|
kind: projectFileChangeKind(kind),
|
|
23015
23179
|
diff: unifiedDiff
|
|
23016
23180
|
}));
|
|
@@ -23948,13 +24112,13 @@ function decodeThreadForkRequest(request) {
|
|
|
23948
24112
|
if (runtimeWorkspaceRoots !== void 0 && runtimeWorkspaceRoots !== null && (!Array.isArray(runtimeWorkspaceRoots) || runtimeWorkspaceRoots.some((root) => typeof root !== "string" || root.length === 0))) {
|
|
23949
24113
|
throw new Error("thread/fork params.runtimeWorkspaceRoots must be text paths or null");
|
|
23950
24114
|
}
|
|
23951
|
-
const
|
|
24115
|
+
const path27 = optionalText(params, "path", { allowEmpty: true });
|
|
23952
24116
|
const ephemeral = optionalBoolean(params, "ephemeral");
|
|
23953
24117
|
return {
|
|
23954
24118
|
threadId: threadId2,
|
|
23955
24119
|
...lastTurnText ? { lastTurnId: hostTurnIdSchema.parse(lastTurnText) } : {},
|
|
23956
24120
|
...beforeTurnText ? { beforeTurnId: hostTurnIdSchema.parse(beforeTurnText) } : {},
|
|
23957
|
-
...
|
|
24121
|
+
...path27 ? { path: path27 } : {},
|
|
23958
24122
|
...optionalField(params, "model"),
|
|
23959
24123
|
...optionalField(params, "modelProvider"),
|
|
23960
24124
|
...optionalField(params, "cwd"),
|
|
@@ -24047,7 +24211,7 @@ function threadForkResult(thread, input) {
|
|
|
24047
24211
|
}
|
|
24048
24212
|
|
|
24049
24213
|
// packages/protocol-core/dist/thread-management.js
|
|
24050
|
-
import { createHash as
|
|
24214
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
24051
24215
|
var HOST_CURSOR_PREFIX = "codexhost:thread-list:v1:";
|
|
24052
24216
|
var MAX_CURSOR_LENGTH = 65536;
|
|
24053
24217
|
var DEFAULT_PAGE_SIZE = 25;
|
|
@@ -24144,7 +24308,7 @@ function decodeSortKey(value2) {
|
|
|
24144
24308
|
return value2;
|
|
24145
24309
|
}
|
|
24146
24310
|
function queryFingerprint(value2) {
|
|
24147
|
-
return
|
|
24311
|
+
return createHash3("sha256").update(JSON.stringify(value2)).digest("hex");
|
|
24148
24312
|
}
|
|
24149
24313
|
function cursorPayload(value2) {
|
|
24150
24314
|
return {
|
|
@@ -25130,22 +25294,22 @@ var HarnessAccountInspectionCache = class {
|
|
|
25130
25294
|
};
|
|
25131
25295
|
|
|
25132
25296
|
// packages/host-runtime/src/app-server-host.ts
|
|
25133
|
-
import { createHash as
|
|
25134
|
-
import
|
|
25135
|
-
import
|
|
25297
|
+
import { createHash as createHash7, randomUUID as randomUUID9 } from "node:crypto";
|
|
25298
|
+
import os4 from "node:os";
|
|
25299
|
+
import path13 from "node:path";
|
|
25136
25300
|
|
|
25137
25301
|
// packages/host-runtime/src/external-thread-fork.ts
|
|
25138
25302
|
import nodePath from "node:path";
|
|
25139
25303
|
|
|
25140
25304
|
// packages/host-runtime/src/external-thread-repository.ts
|
|
25141
25305
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
25142
|
-
import
|
|
25143
|
-
import
|
|
25306
|
+
import os2 from "node:os";
|
|
25307
|
+
import path8 from "node:path";
|
|
25144
25308
|
|
|
25145
25309
|
// packages/host-runtime/src/external-subagent-threads.ts
|
|
25146
|
-
import { createHash as
|
|
25310
|
+
import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
|
|
25147
25311
|
function childCreateRequest(parent, nativeRef, id2) {
|
|
25148
|
-
const key =
|
|
25312
|
+
const key = createHash4("sha256").update(JSON.stringify([parent.hostThreadId, parent.harnessId, nativeRef.nativeSessionId, id2])).digest("hex");
|
|
25149
25313
|
return `subagent:${key}`;
|
|
25150
25314
|
}
|
|
25151
25315
|
function subagentMaterializer(store, parent, previousParent) {
|
|
@@ -25280,8 +25444,8 @@ function sameMapping(left, right) {
|
|
|
25280
25444
|
}
|
|
25281
25445
|
function defaultMappingStoreDirectory(environment) {
|
|
25282
25446
|
const dataDirectory = environment.CODEXHOST_DATA_DIR;
|
|
25283
|
-
return
|
|
25284
|
-
dataDirectory ?
|
|
25447
|
+
return path8.join(
|
|
25448
|
+
dataDirectory ? path8.resolve(dataDirectory) : path8.join(os2.homedir(), ".codexhost"),
|
|
25285
25449
|
"mapping-store"
|
|
25286
25450
|
);
|
|
25287
25451
|
}
|
|
@@ -27317,11 +27481,11 @@ var ExternalTurnSteering = class {
|
|
|
27317
27481
|
};
|
|
27318
27482
|
|
|
27319
27483
|
// packages/host-runtime/src/harness-delegation-coordinator.ts
|
|
27320
|
-
import { createHash as
|
|
27321
|
-
import
|
|
27484
|
+
import { createHash as createHash6, randomUUID as randomUUID5 } from "node:crypto";
|
|
27485
|
+
import path9 from "node:path";
|
|
27322
27486
|
|
|
27323
27487
|
// packages/host-runtime/src/delegation-snapshot.ts
|
|
27324
|
-
import { createHash as
|
|
27488
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
27325
27489
|
var CURSOR_PREFIX = "codexhost:thread-messages:v1:";
|
|
27326
27490
|
var DEFAULT_MESSAGE_LIMIT = 25;
|
|
27327
27491
|
var MAX_MESSAGE_LIMIT = 100;
|
|
@@ -27375,7 +27539,7 @@ function allVisibleMessages(turns) {
|
|
|
27375
27539
|
return messages;
|
|
27376
27540
|
}
|
|
27377
27541
|
function cursorFingerprint(threadId2) {
|
|
27378
|
-
return
|
|
27542
|
+
return createHash5("sha256").update(threadId2).digest("hex");
|
|
27379
27543
|
}
|
|
27380
27544
|
function encodeCursor(threadId2, offset) {
|
|
27381
27545
|
const payload = JSON.stringify({ version: 1, fingerprint: cursorFingerprint(threadId2), offset });
|
|
@@ -27470,10 +27634,10 @@ function terminal(status) {
|
|
|
27470
27634
|
return status === "completed" || status === "failed" || status === "interrupted";
|
|
27471
27635
|
}
|
|
27472
27636
|
function taskDigest(input) {
|
|
27473
|
-
return
|
|
27637
|
+
return createHash6("sha256").update(
|
|
27474
27638
|
JSON.stringify({
|
|
27475
27639
|
task: input.task,
|
|
27476
|
-
cwd:
|
|
27640
|
+
cwd: path9.resolve(input.cwd),
|
|
27477
27641
|
modelId: input.model?.id ?? null,
|
|
27478
27642
|
thinkingOptionId: input.thinkingOptionId ?? null
|
|
27479
27643
|
})
|
|
@@ -27544,7 +27708,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
27544
27708
|
return {
|
|
27545
27709
|
harnessId: input.harnessId,
|
|
27546
27710
|
inspection: await adapter.inspect({
|
|
27547
|
-
...input.cwd ? { cwd:
|
|
27711
|
+
...input.cwd ? { cwd: path9.resolve(input.cwd) } : {},
|
|
27548
27712
|
...input.refresh !== void 0 ? { refresh: input.refresh } : {}
|
|
27549
27713
|
})
|
|
27550
27714
|
};
|
|
@@ -27558,7 +27722,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
27558
27722
|
const result = await this.#startOfficial({ ...input, parentThreadId, cwd: selectedCwd });
|
|
27559
27723
|
return { ...result, parentThreadId, cwd: result.cwd ?? selectedCwd };
|
|
27560
27724
|
}
|
|
27561
|
-
const startInput = { ...input, parentThreadId, cwd:
|
|
27725
|
+
const startInput = { ...input, parentThreadId, cwd: path9.resolve(selectedCwd) };
|
|
27562
27726
|
if (!this.#adapters.has(input.harnessId)) {
|
|
27563
27727
|
throw new DelegationControlError(
|
|
27564
27728
|
"HARNESS_NOT_FOUND",
|
|
@@ -27987,7 +28151,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
27987
28151
|
|
|
27988
28152
|
// packages/host-runtime/src/harness-plugin-loader.ts
|
|
27989
28153
|
import { readdir as readdir3, realpath as realpath2 } from "node:fs/promises";
|
|
27990
|
-
import
|
|
28154
|
+
import path11 from "node:path";
|
|
27991
28155
|
import { pathToFileURL } from "node:url";
|
|
27992
28156
|
|
|
27993
28157
|
// packages/host-runtime/src/harness-plugin-registry.ts
|
|
@@ -28025,16 +28189,16 @@ var HarnessPluginRegistry = class {
|
|
|
28025
28189
|
|
|
28026
28190
|
// packages/host-runtime/src/plugin-files.ts
|
|
28027
28191
|
import { open as open4, realpath, stat as stat2 } from "node:fs/promises";
|
|
28028
|
-
import
|
|
28192
|
+
import path10 from "node:path";
|
|
28029
28193
|
function inside(root, candidate) {
|
|
28030
|
-
const relative =
|
|
28031
|
-
return relative !== "" && !
|
|
28194
|
+
const relative = path10.relative(root, candidate);
|
|
28195
|
+
return relative !== "" && !path10.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path10.sep}`);
|
|
28032
28196
|
}
|
|
28033
28197
|
async function pluginResourcePath(root, relative) {
|
|
28034
|
-
if (
|
|
28198
|
+
if (path10.isAbsolute(relative) || !inside(root, path10.resolve(root, relative))) {
|
|
28035
28199
|
throw new Error("Plugin resource escapes its root");
|
|
28036
28200
|
}
|
|
28037
|
-
const resolved = await realpath(
|
|
28201
|
+
const resolved = await realpath(path10.resolve(root, relative));
|
|
28038
28202
|
if (!inside(root, resolved) || !(await stat2(resolved)).isFile()) {
|
|
28039
28203
|
throw new Error("Plugin resource must be a regular file inside its root");
|
|
28040
28204
|
}
|
|
@@ -28196,7 +28360,7 @@ async function loadHarnessPlugins(options2) {
|
|
|
28196
28360
|
const enabledIds = /* @__PURE__ */ new Set();
|
|
28197
28361
|
const roots = /* @__PURE__ */ new Set();
|
|
28198
28362
|
for (const configuredRoot of options2.roots) {
|
|
28199
|
-
if (!
|
|
28363
|
+
if (!path11.isAbsolute(configuredRoot)) {
|
|
28200
28364
|
diagnose({ code: "invalidRoot" });
|
|
28201
28365
|
continue;
|
|
28202
28366
|
}
|
|
@@ -28226,7 +28390,7 @@ async function loadHarnessPlugins(options2) {
|
|
|
28226
28390
|
for (const directory of directories) {
|
|
28227
28391
|
try {
|
|
28228
28392
|
const file2 = await pluginResourcePath(root, `${directory.name}/manifest.json`);
|
|
28229
|
-
const pluginRoot = await realpath2(
|
|
28393
|
+
const pluginRoot = await realpath2(path11.join(root, directory.name));
|
|
28230
28394
|
await pluginResourcePath(pluginRoot, "manifest.json");
|
|
28231
28395
|
const manifest = harnessPluginManifestSchema.parse(
|
|
28232
28396
|
JSON.parse(
|
|
@@ -28278,6 +28442,7 @@ async function loadHarnessPlugins(options2) {
|
|
|
28278
28442
|
id: manifest.id,
|
|
28279
28443
|
name: manifest.name,
|
|
28280
28444
|
version: manifest.version,
|
|
28445
|
+
...manifest.launchCommand && !options2.context.managedRemoteHost ? { launchCommand: true } : {},
|
|
28281
28446
|
...manifest.links ? { links: manifest.links } : {}
|
|
28282
28447
|
});
|
|
28283
28448
|
let adapter;
|
|
@@ -28288,9 +28453,10 @@ async function loadHarnessPlugins(options2) {
|
|
|
28288
28453
|
} else {
|
|
28289
28454
|
try {
|
|
28290
28455
|
if (manifest.icon) descriptor.icon = await readPluginIcon(candidate.root, manifest.icon);
|
|
28456
|
+
const launchCommand = descriptor.launchCommand ? await options2.launchCommandForPlugin?.(manifest.id) : void 0;
|
|
28291
28457
|
adapter = await loadAdapter(
|
|
28292
28458
|
candidate,
|
|
28293
|
-
options2.context,
|
|
28459
|
+
{ ...options2.context, ...launchCommand ? { launchCommand } : {} },
|
|
28294
28460
|
timeoutMs,
|
|
28295
28461
|
diagnose,
|
|
28296
28462
|
options2.warmup !== false,
|
|
@@ -28318,6 +28484,76 @@ async function loadHarnessPlugins(options2) {
|
|
|
28318
28484
|
return registry2;
|
|
28319
28485
|
}
|
|
28320
28486
|
|
|
28487
|
+
// packages/host-runtime/src/harness-launch-settings.ts
|
|
28488
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
28489
|
+
import { mkdir as mkdir4, readFile as readFile6, rename as rename3, rm as rm4, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
|
|
28490
|
+
import os3 from "node:os";
|
|
28491
|
+
import path12 from "node:path";
|
|
28492
|
+
var HarnessLaunchSettingsStore = class {
|
|
28493
|
+
#directory;
|
|
28494
|
+
#initial = /* @__PURE__ */ new Map();
|
|
28495
|
+
constructor(environment) {
|
|
28496
|
+
this.#directory = path12.join(
|
|
28497
|
+
environment.CODEXHOST_DATA_DIR ? path12.resolve(environment.CODEXHOST_DATA_DIR) : path12.join(os3.homedir(), ".codexhost"),
|
|
28498
|
+
"harness-launch-settings"
|
|
28499
|
+
);
|
|
28500
|
+
}
|
|
28501
|
+
#file(id2) {
|
|
28502
|
+
return path12.join(this.#directory, `${harnessPluginIdSchema.parse(id2)}.json`);
|
|
28503
|
+
}
|
|
28504
|
+
async #read(id2) {
|
|
28505
|
+
try {
|
|
28506
|
+
const value2 = harnessLaunchPathSchema.parse(
|
|
28507
|
+
JSON.parse(await readFile6(this.#file(id2), "utf8"))
|
|
28508
|
+
);
|
|
28509
|
+
if (!path12.isAbsolute(value2)) throw new Error("Expected an absolute entrypoint path");
|
|
28510
|
+
return value2;
|
|
28511
|
+
} catch (error51) {
|
|
28512
|
+
if (error51 && typeof error51 === "object" && "code" in error51 && error51.code === "ENOENT")
|
|
28513
|
+
return null;
|
|
28514
|
+
throw new Error("Could not read Harness launch settings");
|
|
28515
|
+
}
|
|
28516
|
+
}
|
|
28517
|
+
/** Capture the value used to construct this Host's Adapter; changes require a restart. */
|
|
28518
|
+
async initialCommand(id2) {
|
|
28519
|
+
let initial = this.#initial.get(id2);
|
|
28520
|
+
if (!initial) {
|
|
28521
|
+
initial = this.#read(id2);
|
|
28522
|
+
this.#initial.set(id2, initial);
|
|
28523
|
+
}
|
|
28524
|
+
return await initial ?? void 0;
|
|
28525
|
+
}
|
|
28526
|
+
async get(id2) {
|
|
28527
|
+
const initial = await this.initialCommand(id2) ?? null;
|
|
28528
|
+
const value2 = await this.#read(id2);
|
|
28529
|
+
return { path: value2, restartRequired: value2 !== initial };
|
|
28530
|
+
}
|
|
28531
|
+
async set(id2, value2) {
|
|
28532
|
+
const initial = await this.initialCommand(id2) ?? null;
|
|
28533
|
+
const file2 = this.#file(id2);
|
|
28534
|
+
if (value2 === null) {
|
|
28535
|
+
await rm4(file2, { force: true });
|
|
28536
|
+
} else {
|
|
28537
|
+
value2 = harnessLaunchPathSchema.parse(value2);
|
|
28538
|
+
if (!path12.isAbsolute(value2))
|
|
28539
|
+
throw new Error("Use an absolute entrypoint path without arguments");
|
|
28540
|
+
const metadata = await stat3(value2).catch(() => void 0);
|
|
28541
|
+
if (!metadata?.isDirectory() && !metadata?.isFile())
|
|
28542
|
+
throw new Error("The installation path must be an existing directory on this Host");
|
|
28543
|
+
await mkdir4(this.#directory, { recursive: true, mode: 448 });
|
|
28544
|
+
const temporary = `${file2}.${randomUUID6()}.tmp`;
|
|
28545
|
+
try {
|
|
28546
|
+
await writeFile3(temporary, `${JSON.stringify(value2)}
|
|
28547
|
+
`, { mode: 384, flag: "wx" });
|
|
28548
|
+
await rename3(temporary, file2);
|
|
28549
|
+
} finally {
|
|
28550
|
+
await rm4(temporary, { force: true });
|
|
28551
|
+
}
|
|
28552
|
+
}
|
|
28553
|
+
return { path: value2, restartRequired: value2 !== initial };
|
|
28554
|
+
}
|
|
28555
|
+
};
|
|
28556
|
+
|
|
28321
28557
|
// packages/host-runtime/src/official-codex-model-ref.ts
|
|
28322
28558
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
28323
28559
|
var OFFICIAL_CODEX_MODEL_REF_PREFIX = "codex-model-v1.";
|
|
@@ -28508,10 +28744,10 @@ var SingleNativeCodexAccount = class {
|
|
|
28508
28744
|
};
|
|
28509
28745
|
|
|
28510
28746
|
// packages/host-runtime/src/codex-runtime/official-runtime-owner.ts
|
|
28511
|
-
import { randomUUID as
|
|
28747
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
28512
28748
|
|
|
28513
28749
|
// packages/host-runtime/src/official-request-broker.ts
|
|
28514
|
-
import { randomUUID as
|
|
28750
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
28515
28751
|
var INTERNAL_REQUEST_PREFIX = "codexhost:official:";
|
|
28516
28752
|
var MAX_RETIRED_IDS = 1024;
|
|
28517
28753
|
function isRecord10(value2) {
|
|
@@ -28527,7 +28763,7 @@ var OfficialRequestBroker = class {
|
|
|
28527
28763
|
constructor(input) {
|
|
28528
28764
|
this.#send = input.send;
|
|
28529
28765
|
this.#timeoutMs = input.timeoutMs ?? 3e4;
|
|
28530
|
-
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${
|
|
28766
|
+
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID7()}`);
|
|
28531
28767
|
}
|
|
28532
28768
|
get pendingCount() {
|
|
28533
28769
|
return this.#pending.size;
|
|
@@ -28881,7 +29117,7 @@ var OfficialRuntimeOwner = class {
|
|
|
28881
29117
|
}
|
|
28882
29118
|
#attach(role, output, onBackendStopped) {
|
|
28883
29119
|
const client = {
|
|
28884
|
-
id:
|
|
29120
|
+
id: randomUUID8(),
|
|
28885
29121
|
role,
|
|
28886
29122
|
output,
|
|
28887
29123
|
...onBackendStopped ? { onBackendStopped } : {},
|
|
@@ -29039,7 +29275,7 @@ var OfficialRuntimeOwner = class {
|
|
|
29039
29275
|
if (!object4(value2)) return client.output(event);
|
|
29040
29276
|
if (typeof value2.id === "string" || typeof value2.id === "number") {
|
|
29041
29277
|
if (typeof value2.method === "string") {
|
|
29042
|
-
const id2 = `codexhost:server:${client.id}:${event.generation}:${
|
|
29278
|
+
const id2 = `codexhost:server:${client.id}:${event.generation}:${randomUUID8()}`;
|
|
29043
29279
|
client.serverRequests.set(id2, value2.id);
|
|
29044
29280
|
const projected = { ...value2, id: id2 };
|
|
29045
29281
|
return client.output({
|
|
@@ -29434,25 +29670,25 @@ function resolveExternalSessionTreeIds(records) {
|
|
|
29434
29670
|
const resolve = (start) => {
|
|
29435
29671
|
const cached2 = resolved.get(start.hostThreadId);
|
|
29436
29672
|
if (cached2) return cached2;
|
|
29437
|
-
const
|
|
29673
|
+
const path27 = [];
|
|
29438
29674
|
const visited = /* @__PURE__ */ new Set();
|
|
29439
29675
|
let current = start;
|
|
29440
29676
|
while (true) {
|
|
29441
29677
|
const known = resolved.get(current.hostThreadId);
|
|
29442
29678
|
if (known) {
|
|
29443
|
-
for (const record3 of
|
|
29679
|
+
for (const record3 of path27) resolved.set(record3.hostThreadId, known);
|
|
29444
29680
|
return known;
|
|
29445
29681
|
}
|
|
29446
29682
|
if (visited.has(current.hostThreadId)) {
|
|
29447
29683
|
throw new Error("External Thread Fork tree contains a cycle");
|
|
29448
29684
|
}
|
|
29449
29685
|
visited.add(current.hostThreadId);
|
|
29450
|
-
|
|
29686
|
+
path27.push(current);
|
|
29451
29687
|
const sourceId = current.subagent?.parentHostThreadId ?? current.forkSource?.hostThreadId;
|
|
29452
29688
|
const source = sourceId ? byId.get(sourceId) : void 0;
|
|
29453
29689
|
if (!source) {
|
|
29454
29690
|
const root = current.hostThreadId;
|
|
29455
|
-
for (const record3 of
|
|
29691
|
+
for (const record3 of path27) resolved.set(record3.hostThreadId, root);
|
|
29456
29692
|
return root;
|
|
29457
29693
|
}
|
|
29458
29694
|
current = source;
|
|
@@ -29863,6 +30099,7 @@ var AppServerHost = class {
|
|
|
29863
30099
|
#nativeAccountObserver;
|
|
29864
30100
|
#externalAdapters;
|
|
29865
30101
|
#pluginDescriptors = [];
|
|
30102
|
+
#launchSettings;
|
|
29866
30103
|
#accountInspections = new HarnessAccountInspectionCache();
|
|
29867
30104
|
#externalRuntime;
|
|
29868
30105
|
#externalSteering = new ExternalTurnSteering();
|
|
@@ -29904,7 +30141,10 @@ var AppServerHost = class {
|
|
|
29904
30141
|
};
|
|
29905
30142
|
this.#writer = new OrderedWriter(this.#options.desktopOutput);
|
|
29906
30143
|
const environment = this.#options.environment ?? process.env;
|
|
29907
|
-
|
|
30144
|
+
this.#launchSettings = new HarnessLaunchSettingsStore(
|
|
30145
|
+
this.#options.pluginContext?.environment ?? environment
|
|
30146
|
+
);
|
|
30147
|
+
const permanentHome = path13.resolve(environment.CODEX_HOME ?? path13.join(os4.homedir(), ".codex"));
|
|
29908
30148
|
this.#ownsOfficialRuntimeScope = options2.officialRuntimeScope === void 0;
|
|
29909
30149
|
this.#officialRuntimeScope = options2.officialRuntimeScope ?? new OfficialRuntimeScope({
|
|
29910
30150
|
diagnosticOutput: this.#options.diagnosticOutput,
|
|
@@ -29917,7 +30157,8 @@ var AppServerHost = class {
|
|
|
29917
30157
|
...officialEnvironment(environment),
|
|
29918
30158
|
CODEX_HOME: permanentHome
|
|
29919
30159
|
},
|
|
29920
|
-
...this.#options.spawnOfficial ? { spawnOfficial: this.#options.spawnOfficial } : {}
|
|
30160
|
+
...this.#options.spawnOfficial ? { spawnOfficial: this.#options.spawnOfficial } : {},
|
|
30161
|
+
...this.#options.officialCloseTimeoutMs === void 0 ? {} : { closeTimeoutMs: this.#options.officialCloseTimeoutMs }
|
|
29921
30162
|
})
|
|
29922
30163
|
)
|
|
29923
30164
|
});
|
|
@@ -30051,6 +30292,7 @@ var AppServerHost = class {
|
|
|
30051
30292
|
if (!this.#options.pluginRoots || this.#pluginLoadAbort.signal.aborted) return;
|
|
30052
30293
|
const plugins = await loadHarnessPlugins({
|
|
30053
30294
|
roots: this.#options.pluginRoots,
|
|
30295
|
+
launchCommandForPlugin: (id2) => this.#launchSettings.initialCommand(id2),
|
|
30054
30296
|
context: this.#options.pluginContext ?? {
|
|
30055
30297
|
environment: this.#options.environment ?? process.env,
|
|
30056
30298
|
platform: process.platform,
|
|
@@ -30252,6 +30494,32 @@ var AppServerHost = class {
|
|
|
30252
30494
|
this.#dispatchDesktopRequest(() => this.#handleCodexAccountRequest(request));
|
|
30253
30495
|
return;
|
|
30254
30496
|
}
|
|
30497
|
+
if (request.method === CREDENTIAL_IMPORTS_METHOD) {
|
|
30498
|
+
this.#dispatchDesktopRequest(async () => {
|
|
30499
|
+
if (!credentialImportsParamsSchema.safeParse(request.params).success) {
|
|
30500
|
+
await this.#writer.json(rpcError(request, -32602, "Invalid credential import request"));
|
|
30501
|
+
return;
|
|
30502
|
+
}
|
|
30503
|
+
await this.#waitForPlugins();
|
|
30504
|
+
try {
|
|
30505
|
+
const result = await handleCredentialImports(
|
|
30506
|
+
request.params,
|
|
30507
|
+
this.#externalAdapters.values(),
|
|
30508
|
+
this.#options.environment ?? process.env
|
|
30509
|
+
);
|
|
30510
|
+
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
30511
|
+
} catch {
|
|
30512
|
+
await this.#writer.json(
|
|
30513
|
+
rpcError(
|
|
30514
|
+
request,
|
|
30515
|
+
-32077,
|
|
30516
|
+
"Credential operation failed. Check the source login, choose an unused Provider name, and verify Pi configuration access."
|
|
30517
|
+
)
|
|
30518
|
+
);
|
|
30519
|
+
}
|
|
30520
|
+
});
|
|
30521
|
+
return;
|
|
30522
|
+
}
|
|
30255
30523
|
if (request.method === "codexhost/harness/accounts/sources") {
|
|
30256
30524
|
this.#dispatchDesktopRequest(async () => {
|
|
30257
30525
|
if (!harnessAccountSourceListParamsSchema.safeParse(request.params).success) {
|
|
@@ -30323,6 +30591,41 @@ var AppServerHost = class {
|
|
|
30323
30591
|
this.#dispatchDesktopRequest(() => this.#openHarnessWebUi(request));
|
|
30324
30592
|
return;
|
|
30325
30593
|
}
|
|
30594
|
+
if (request.method === HARNESS_LAUNCH_SETTINGS_GET_METHOD || request.method === HARNESS_LAUNCH_SETTINGS_SET_METHOD) {
|
|
30595
|
+
this.#dispatchDesktopRequest(async () => {
|
|
30596
|
+
const schema = request.method === HARNESS_LAUNCH_SETTINGS_SET_METHOD ? harnessLaunchSettingsSetSchema : harnessLaunchSettingsGetSchema;
|
|
30597
|
+
const params = schema.safeParse(request.params);
|
|
30598
|
+
if (!params.success) {
|
|
30599
|
+
await this.#writer.json(rpcError(request, -32602, "Invalid Harness launch settings"));
|
|
30600
|
+
return;
|
|
30601
|
+
}
|
|
30602
|
+
await this.#waitForPlugins();
|
|
30603
|
+
if (!this.#pluginDescriptors.some(
|
|
30604
|
+
(plugin) => plugin.id === params.data.harnessId && plugin.launchCommand
|
|
30605
|
+
)) {
|
|
30606
|
+
await this.#writer.json(
|
|
30607
|
+
rpcError(request, -32602, "Harness launch settings are unavailable")
|
|
30608
|
+
);
|
|
30609
|
+
return;
|
|
30610
|
+
}
|
|
30611
|
+
try {
|
|
30612
|
+
const result = request.method === HARNESS_LAUNCH_SETTINGS_SET_METHOD ? await this.#launchSettings.set(
|
|
30613
|
+
params.data.harnessId,
|
|
30614
|
+
harnessLaunchSettingsSetSchema.parse(request.params).path
|
|
30615
|
+
) : await this.#launchSettings.get(params.data.harnessId);
|
|
30616
|
+
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
30617
|
+
} catch {
|
|
30618
|
+
await this.#writer.json(
|
|
30619
|
+
rpcError(
|
|
30620
|
+
request,
|
|
30621
|
+
-32602,
|
|
30622
|
+
"Could not read or save launch settings. Use an existing absolute installation directory on this Host, without arguments, and check configuration permissions."
|
|
30623
|
+
)
|
|
30624
|
+
);
|
|
30625
|
+
}
|
|
30626
|
+
});
|
|
30627
|
+
return;
|
|
30628
|
+
}
|
|
30326
30629
|
if (request.method === "codexhost/harness/plugins/list") {
|
|
30327
30630
|
this.#dispatchDesktopRequest(async () => {
|
|
30328
30631
|
if (!harnessPluginListParamsSchema.safeParse(request.params).success) {
|
|
@@ -30907,7 +31210,7 @@ var AppServerHost = class {
|
|
|
30907
31210
|
throw new DelegationControlError("INVALID_ARGUMENT", "Official Model Ref is invalid");
|
|
30908
31211
|
}
|
|
30909
31212
|
const nativeModelId = requestedModel ? decodeOfficialCodexModelRef(requestedModel) : void 0;
|
|
30910
|
-
const digest2 =
|
|
31213
|
+
const digest2 = createHash7("sha256").update(
|
|
30911
31214
|
JSON.stringify({
|
|
30912
31215
|
task: input.task,
|
|
30913
31216
|
cwd: input.cwd,
|
|
@@ -31008,7 +31311,7 @@ var AppServerHost = class {
|
|
|
31008
31311
|
throw error51;
|
|
31009
31312
|
}
|
|
31010
31313
|
this.#activeOfficialTurns.set(threadId2, turnId);
|
|
31011
|
-
const delegationId = hostThreadIdSchema.parse(
|
|
31314
|
+
const delegationId = hostThreadIdSchema.parse(randomUUID9());
|
|
31012
31315
|
try {
|
|
31013
31316
|
const source = await this.#repository.find(input.parentThreadId);
|
|
31014
31317
|
const pendingTerminal = this.#pendingOfficialTerminalStatuses.get(threadId2);
|
|
@@ -31172,7 +31475,7 @@ var AppServerHost = class {
|
|
|
31172
31475
|
async #listDelegationThreads(input) {
|
|
31173
31476
|
const [sortKey, sortDirection2] = input.sort.split("-");
|
|
31174
31477
|
const request = {
|
|
31175
|
-
id: `codexhost:delegation-list:${
|
|
31478
|
+
id: `codexhost:delegation-list:${randomUUID9()}`,
|
|
31176
31479
|
method: "thread/list",
|
|
31177
31480
|
params: {
|
|
31178
31481
|
cwd: input.cwd ? [input.cwd] : null,
|
|
@@ -31618,7 +31921,7 @@ var AppServerHost = class {
|
|
|
31618
31921
|
);
|
|
31619
31922
|
return;
|
|
31620
31923
|
}
|
|
31621
|
-
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(
|
|
31924
|
+
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID9());
|
|
31622
31925
|
const projection = {
|
|
31623
31926
|
projector: new CodexTurnProjector({
|
|
31624
31927
|
threadId: thread.id,
|
|
@@ -32485,7 +32788,7 @@ var AppServerHost = class {
|
|
|
32485
32788
|
if (thread.running || thread.activeTurnId || this.#pendingExternalCommandRequests.has(thread.id)) {
|
|
32486
32789
|
throw new ExternalSteerError(-32072, "External Thread already has an active Turn");
|
|
32487
32790
|
}
|
|
32488
|
-
const turnId = hostTurnIdSchema.parse(
|
|
32791
|
+
const turnId = hostTurnIdSchema.parse(randomUUID9());
|
|
32489
32792
|
const startedAtMs = Date.now();
|
|
32490
32793
|
const projection = {
|
|
32491
32794
|
projector: new CodexTurnProjector({
|
|
@@ -33033,7 +33336,7 @@ var AppServerHost = class {
|
|
|
33033
33336
|
try {
|
|
33034
33337
|
result = projection.projector.projectQuestion(
|
|
33035
33338
|
interaction,
|
|
33036
|
-
hostItemIdSchema.parse(
|
|
33339
|
+
hostItemIdSchema.parse(randomUUID9())
|
|
33037
33340
|
);
|
|
33038
33341
|
} catch (error51) {
|
|
33039
33342
|
this.#diagnose(error51);
|
|
@@ -33199,19 +33502,19 @@ var AppServerHost = class {
|
|
|
33199
33502
|
};
|
|
33200
33503
|
|
|
33201
33504
|
// packages/host-runtime/src/native-account-host.ts
|
|
33202
|
-
import { mkdir as
|
|
33505
|
+
import { mkdir as mkdir7, realpath as realpath3 } from "node:fs/promises";
|
|
33203
33506
|
import { homedir } from "node:os";
|
|
33204
|
-
import
|
|
33507
|
+
import path17 from "node:path";
|
|
33205
33508
|
|
|
33206
33509
|
// packages/host-runtime/src/codex-runtime/owned-official-backends.ts
|
|
33207
|
-
import { createHash as
|
|
33510
|
+
import { createHash as createHash8, randomBytes } from "node:crypto";
|
|
33208
33511
|
import { Writable as Writable2 } from "node:stream";
|
|
33209
33512
|
|
|
33210
33513
|
// packages/host-runtime/src/remote-app-server.ts
|
|
33211
33514
|
import { createServer } from "node:http";
|
|
33212
33515
|
import net from "node:net";
|
|
33213
|
-
import { chmod as chmod3, lstat as lstat6, mkdir as
|
|
33214
|
-
import
|
|
33516
|
+
import { chmod as chmod3, lstat as lstat6, mkdir as mkdir6, rm as rm6 } from "node:fs/promises";
|
|
33517
|
+
import path15 from "node:path";
|
|
33215
33518
|
import { PassThrough } from "node:stream";
|
|
33216
33519
|
|
|
33217
33520
|
// node_modules/ws/wrapper.mjs
|
|
@@ -33226,10 +33529,10 @@ var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
|
33226
33529
|
var wrapper_default = import_websocket.default;
|
|
33227
33530
|
|
|
33228
33531
|
// packages/host-runtime/src/remote-socket-lock.ts
|
|
33229
|
-
import { randomUUID as
|
|
33230
|
-
import { chmod as chmod2, lstat as lstat5, mkdir as
|
|
33532
|
+
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
33533
|
+
import { chmod as chmod2, lstat as lstat5, mkdir as mkdir5, open as open5, readFile as readFile7, readdir as readdir4, rename as rename4, rm as rm5 } from "node:fs/promises";
|
|
33231
33534
|
import { uptime } from "node:os";
|
|
33232
|
-
import
|
|
33535
|
+
import path14 from "node:path";
|
|
33233
33536
|
import { setTimeout as delay4 } from "node:timers/promises";
|
|
33234
33537
|
var LOCK_RETRY_COUNT = 200;
|
|
33235
33538
|
var LOCK_RETRY_DELAY_MS = 25;
|
|
@@ -33292,7 +33595,7 @@ async function readLockEntrySnapshot(filePath) {
|
|
|
33292
33595
|
throw error51;
|
|
33293
33596
|
});
|
|
33294
33597
|
if (metadata === null || !metadata.isFile()) return null;
|
|
33295
|
-
const source = await
|
|
33598
|
+
const source = await readFile7(filePath, "utf8").catch((error51) => {
|
|
33296
33599
|
if (error51.code === "ENOENT") return null;
|
|
33297
33600
|
throw error51;
|
|
33298
33601
|
});
|
|
@@ -33303,7 +33606,7 @@ async function readLockEntrySnapshot(filePath) {
|
|
|
33303
33606
|
source,
|
|
33304
33607
|
identity: { dev: metadata.dev, ino: metadata.ino },
|
|
33305
33608
|
mtimeMs: metadata.mtimeMs,
|
|
33306
|
-
record: record3 &&
|
|
33609
|
+
record: record3 && path14.basename(filePath) === lockEntryName(record3.ownerToken) ? record3 : null
|
|
33307
33610
|
};
|
|
33308
33611
|
}
|
|
33309
33612
|
function lockEntryIsAbandoned(snapshot) {
|
|
@@ -33315,7 +33618,7 @@ async function removeAbandonedLockEntry(snapshot) {
|
|
|
33315
33618
|
if (current === null || current.source !== snapshot.source || !sameUnixFileIdentity(current.identity, snapshot.identity) || !lockEntryIsAbandoned(current)) {
|
|
33316
33619
|
return false;
|
|
33317
33620
|
}
|
|
33318
|
-
await
|
|
33621
|
+
await rm5(snapshot.filePath, { force: true });
|
|
33319
33622
|
return true;
|
|
33320
33623
|
}
|
|
33321
33624
|
async function readLockEntryCatalog(lockDirectory) {
|
|
@@ -33324,7 +33627,7 @@ async function readLockEntryCatalog(lockDirectory) {
|
|
|
33324
33627
|
let unsettled = false;
|
|
33325
33628
|
for (const name of names) {
|
|
33326
33629
|
if (!name.startsWith(LOCK_ENTRY_PREFIX) || !name.endsWith(LOCK_ENTRY_SUFFIX)) continue;
|
|
33327
|
-
const snapshot = await readLockEntrySnapshot(
|
|
33630
|
+
const snapshot = await readLockEntrySnapshot(path14.join(lockDirectory, name));
|
|
33328
33631
|
if (snapshot === null) continue;
|
|
33329
33632
|
if (lockEntryIsAbandoned(snapshot)) {
|
|
33330
33633
|
if (!await removeAbandonedLockEntry(snapshot)) unsettled = true;
|
|
@@ -33339,7 +33642,7 @@ async function readLockEntryCatalog(lockDirectory) {
|
|
|
33339
33642
|
return { entries, unsettled };
|
|
33340
33643
|
}
|
|
33341
33644
|
async function preparePrivateLockDirectory(lockDirectory) {
|
|
33342
|
-
await
|
|
33645
|
+
await mkdir5(lockDirectory, { mode: 448 }).catch((error51) => {
|
|
33343
33646
|
if (error51.code !== "EEXIST") throw error51;
|
|
33344
33647
|
});
|
|
33345
33648
|
const metadata = await lstat5(lockDirectory);
|
|
@@ -33352,7 +33655,7 @@ async function preparePrivateLockDirectory(lockDirectory) {
|
|
|
33352
33655
|
await chmod2(lockDirectory, 448);
|
|
33353
33656
|
}
|
|
33354
33657
|
async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
|
|
33355
|
-
const temporary =
|
|
33658
|
+
const temporary = path14.join(lockDirectory, `.tmp-${record3.ownerToken}-${randomUUID10()}`);
|
|
33356
33659
|
const handle = await open5(temporary, "wx", 384);
|
|
33357
33660
|
try {
|
|
33358
33661
|
await handle.writeFile(`${JSON.stringify(record3)}
|
|
@@ -33362,15 +33665,15 @@ async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
|
|
|
33362
33665
|
await handle.close();
|
|
33363
33666
|
}
|
|
33364
33667
|
try {
|
|
33365
|
-
await
|
|
33668
|
+
await rename4(temporary, entryPath);
|
|
33366
33669
|
} finally {
|
|
33367
|
-
await
|
|
33670
|
+
await rm5(temporary, { force: true });
|
|
33368
33671
|
}
|
|
33369
33672
|
}
|
|
33370
33673
|
async function removeOwnedLockEntry(entryPath, ownerToken) {
|
|
33371
33674
|
const snapshot = await readLockEntrySnapshot(entryPath);
|
|
33372
33675
|
if (snapshot?.record?.ownerToken !== ownerToken) return;
|
|
33373
|
-
await
|
|
33676
|
+
await rm5(entryPath, { force: true });
|
|
33374
33677
|
}
|
|
33375
33678
|
async function legacyLockState(legacyPath) {
|
|
33376
33679
|
const metadata = await lstat5(legacyPath).catch((error51) => {
|
|
@@ -33379,7 +33682,7 @@ async function legacyLockState(legacyPath) {
|
|
|
33379
33682
|
});
|
|
33380
33683
|
if (metadata === null) return "absent";
|
|
33381
33684
|
if (!metadata.isFile()) return "blocking";
|
|
33382
|
-
const source = await
|
|
33685
|
+
const source = await readFile7(legacyPath, "utf8").catch((error51) => {
|
|
33383
33686
|
if (error51.code === "ENOENT") return null;
|
|
33384
33687
|
throw error51;
|
|
33385
33688
|
});
|
|
@@ -33416,7 +33719,7 @@ async function releaseLegacyCompatibilityGuard(legacyPath, guard) {
|
|
|
33416
33719
|
throw error51;
|
|
33417
33720
|
});
|
|
33418
33721
|
if (metadata?.isFile() && sameUnixFileIdentity({ dev: metadata.dev, ino: metadata.ino }, guard.identity)) {
|
|
33419
|
-
await
|
|
33722
|
+
await rm5(legacyPath, { force: true });
|
|
33420
33723
|
}
|
|
33421
33724
|
}
|
|
33422
33725
|
}
|
|
@@ -33427,8 +33730,8 @@ async function withRemoteAppServerSocketInitializationLock(socketPath, action) {
|
|
|
33427
33730
|
const legacyPath = `${socketPath}.initializing`;
|
|
33428
33731
|
const lockDirectory = `${socketPath}.initializers`;
|
|
33429
33732
|
await preparePrivateLockDirectory(lockDirectory);
|
|
33430
|
-
const ownerToken =
|
|
33431
|
-
const entryPath =
|
|
33733
|
+
const ownerToken = randomUUID10();
|
|
33734
|
+
const entryPath = path14.join(lockDirectory, lockEntryName(ownerToken));
|
|
33432
33735
|
const baseRecord = {
|
|
33433
33736
|
version: 2,
|
|
33434
33737
|
ownerToken,
|
|
@@ -33602,14 +33905,14 @@ function remoteAppServerSocketPath(environment, listenUrl = "unix://") {
|
|
|
33602
33905
|
throw new Error("Remote app-server listener must use a Unix URL");
|
|
33603
33906
|
}
|
|
33604
33907
|
const explicit = listenUrl.slice("unix://".length);
|
|
33605
|
-
if (explicit.length > 0) return
|
|
33606
|
-
const codexHome = environment.CODEX_HOME ?? (environment.HOME ?
|
|
33908
|
+
if (explicit.length > 0) return path15.posix.resolve(decodeURIComponent(explicit));
|
|
33909
|
+
const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path15.posix.join(environment.HOME, ".codex") : void 0);
|
|
33607
33910
|
if (!codexHome)
|
|
33608
33911
|
throw new Error("CODEX_HOME or HOME is required for the remote app-server socket");
|
|
33609
|
-
return
|
|
33912
|
+
return path15.posix.join(codexHome, "app-server-control", "app-server-control.sock");
|
|
33610
33913
|
}
|
|
33611
33914
|
function officialListenerArgumentsForRemoteListener(arguments_2, socketPath) {
|
|
33612
|
-
if (!
|
|
33915
|
+
if (!path15.posix.isAbsolute(socketPath)) {
|
|
33613
33916
|
throw new Error("Shared official app-server socket path must be absolute");
|
|
33614
33917
|
}
|
|
33615
33918
|
if (remoteUnixListenerUrl(arguments_2) === null) {
|
|
@@ -33717,10 +34020,10 @@ async function removeStaleSocket(socketPath) {
|
|
|
33717
34020
|
});
|
|
33718
34021
|
});
|
|
33719
34022
|
if (active) throw new Error(`Remote app-server socket is already in use at ${socketPath}`);
|
|
33720
|
-
await
|
|
34023
|
+
await rm6(socketPath, { force: true });
|
|
33721
34024
|
}
|
|
33722
34025
|
async function prepareRemoteAppServerSocketDirectory(socketPath) {
|
|
33723
|
-
const socketDirectory =
|
|
34026
|
+
const socketDirectory = path15.dirname(socketPath);
|
|
33724
34027
|
const existing = await lstat6(socketDirectory).catch((error51) => {
|
|
33725
34028
|
if (error51.code === "ENOENT") return null;
|
|
33726
34029
|
throw error51;
|
|
@@ -33734,7 +34037,7 @@ async function prepareRemoteAppServerSocketDirectory(socketPath) {
|
|
|
33734
34037
|
);
|
|
33735
34038
|
}
|
|
33736
34039
|
}
|
|
33737
|
-
await
|
|
34040
|
+
await mkdir6(socketDirectory, { recursive: true, mode: 448 });
|
|
33738
34041
|
await chmod3(socketDirectory, 448);
|
|
33739
34042
|
}
|
|
33740
34043
|
function sendOutputFrames(socket, output) {
|
|
@@ -33907,7 +34210,7 @@ function createRemoteAppServerWebSocketListener(input) {
|
|
|
33907
34210
|
if (ownedSocketIdentity) {
|
|
33908
34211
|
const current = await unixSocketIdentity(input.socketPath);
|
|
33909
34212
|
if (current && sameUnixFileIdentity2(current, ownedSocketIdentity)) {
|
|
33910
|
-
await
|
|
34213
|
+
await rm6(input.socketPath, { force: true });
|
|
33911
34214
|
}
|
|
33912
34215
|
ownedSocketIdentity = null;
|
|
33913
34216
|
}
|
|
@@ -33925,20 +34228,20 @@ function createRemoteAppServerWebSocketListener(input) {
|
|
|
33925
34228
|
|
|
33926
34229
|
// packages/host-runtime/src/remote-official-app-server.ts
|
|
33927
34230
|
import { spawn as spawn3 } from "node:child_process";
|
|
33928
|
-
import { randomUUID as
|
|
33929
|
-
import { lstat as lstat7, rm as
|
|
33930
|
-
import
|
|
34231
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
34232
|
+
import { lstat as lstat7, rm as rm7 } from "node:fs/promises";
|
|
34233
|
+
import path16 from "node:path";
|
|
33931
34234
|
var DEFAULT_CLOSE_TIMEOUT_MS = 2e3;
|
|
33932
34235
|
var DEFAULT_LISTEN_TIMEOUT_MS = 1e4;
|
|
33933
|
-
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token =
|
|
33934
|
-
if (!
|
|
34236
|
+
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID11()) {
|
|
34237
|
+
if (!path16.posix.isAbsolute(desktopControlSocketPath)) {
|
|
33935
34238
|
throw new Error("Desktop control socket path must be absolute");
|
|
33936
34239
|
}
|
|
33937
34240
|
if (!/^[A-Za-z0-9-]+$/u.test(token) || !/[A-Za-z0-9]/u.test(token)) {
|
|
33938
34241
|
throw new Error("Shared official app-server socket token is invalid");
|
|
33939
34242
|
}
|
|
33940
34243
|
const compactToken = token.replaceAll("-", "").slice(0, 15);
|
|
33941
|
-
return
|
|
34244
|
+
return path16.posix.join(path16.posix.dirname(desktopControlSocketPath), `.c-${compactToken}.sock`);
|
|
33942
34245
|
}
|
|
33943
34246
|
function errorMessage4(error51) {
|
|
33944
34247
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
@@ -34010,7 +34313,7 @@ function createRemoteOfficialAppServerListener(input) {
|
|
|
34010
34313
|
if (ownedSocketIdentity === null) return;
|
|
34011
34314
|
const current = await socketIdentity(input.socketPath).catch(() => null);
|
|
34012
34315
|
if (current && sameUnixFileIdentity3(current, ownedSocketIdentity)) {
|
|
34013
|
-
await
|
|
34316
|
+
await rm7(input.socketPath, { force: true });
|
|
34014
34317
|
}
|
|
34015
34318
|
ownedSocketIdentity = null;
|
|
34016
34319
|
};
|
|
@@ -34371,7 +34674,7 @@ function createOwnedLoopbackBackend(input) {
|
|
|
34371
34674
|
"--ws-auth",
|
|
34372
34675
|
"capability-token",
|
|
34373
34676
|
"--ws-token-sha256",
|
|
34374
|
-
|
|
34677
|
+
createHash8("sha256").update(capabilityToken).digest("hex")
|
|
34375
34678
|
],
|
|
34376
34679
|
// Managed stderr may carry credential-bearing errors. Never forward raw bytes.
|
|
34377
34680
|
diagnosticOutput: new Writable2({
|
|
@@ -34424,21 +34727,21 @@ function createOwnedUnixBackend(input) {
|
|
|
34424
34727
|
|
|
34425
34728
|
// packages/host-runtime/src/native-account-host.ts
|
|
34426
34729
|
async function canonicalCodexHome(home) {
|
|
34427
|
-
const absolute =
|
|
34730
|
+
const absolute = path17.resolve(home);
|
|
34428
34731
|
try {
|
|
34429
34732
|
return await realpath3(absolute);
|
|
34430
34733
|
} catch (error51) {
|
|
34431
34734
|
if (!(error51 instanceof Error && "code" in error51 && error51.code === "ENOENT")) throw error51;
|
|
34432
|
-
const parent =
|
|
34735
|
+
const parent = path17.dirname(absolute);
|
|
34433
34736
|
if (parent === absolute) throw error51;
|
|
34434
|
-
return
|
|
34737
|
+
return path17.join(await canonicalCodexHome(parent), path17.basename(absolute));
|
|
34435
34738
|
}
|
|
34436
34739
|
}
|
|
34437
34740
|
async function prepareLocalCodex(input) {
|
|
34438
34741
|
const home = await canonicalCodexHome(
|
|
34439
|
-
input.environment.CODEX_HOME ??
|
|
34742
|
+
input.environment.CODEX_HOME ?? path17.join(homedir(), ".codex")
|
|
34440
34743
|
);
|
|
34441
|
-
await
|
|
34744
|
+
await mkdir7(home, { recursive: true });
|
|
34442
34745
|
const scope = new OfficialRuntimeScope({
|
|
34443
34746
|
permanentHome: home,
|
|
34444
34747
|
diagnosticOutput: input.diagnosticOutput,
|
|
@@ -34602,18 +34905,18 @@ var DelegationControlRegistry = class {
|
|
|
34602
34905
|
};
|
|
34603
34906
|
|
|
34604
34907
|
// packages/host-runtime/src/installed-harness-plugins.ts
|
|
34605
|
-
import
|
|
34606
|
-
import
|
|
34908
|
+
import os5 from "node:os";
|
|
34909
|
+
import path19 from "node:path";
|
|
34607
34910
|
import { fileURLToPath } from "node:url";
|
|
34608
34911
|
|
|
34609
34912
|
// packages/host-runtime/src/launcher-url-opener.ts
|
|
34610
34913
|
import { spawn as spawn4 } from "node:child_process";
|
|
34611
|
-
import
|
|
34914
|
+
import path18 from "node:path";
|
|
34612
34915
|
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "[::1]"]);
|
|
34613
34916
|
var OPEN_TIMEOUT_MS = 1e4;
|
|
34614
34917
|
function createLauncherUrlOpener(environment, spawnLauncher = (command, arguments_2, options2) => spawn4(command, arguments_2, options2)) {
|
|
34615
34918
|
const launcher = environment.CODEXHOST_LAUNCHER_EXECUTABLE;
|
|
34616
|
-
if (!launcher || !
|
|
34919
|
+
if (!launcher || !path18.isAbsolute(launcher)) return void 0;
|
|
34617
34920
|
const launcherEnvironment = Object.fromEntries(
|
|
34618
34921
|
Object.entries(environment).filter(([name]) => {
|
|
34619
34922
|
const normalized = name.toUpperCase();
|
|
@@ -34671,9 +34974,9 @@ function installedHarnessPluginOptions(environment, managedRemoteHost = false, h
|
|
|
34671
34974
|
const opener = managedRemoteHost ? void 0 : createLauncherUrlOpener(environment);
|
|
34672
34975
|
return {
|
|
34673
34976
|
pluginRoots: [
|
|
34674
|
-
|
|
34675
|
-
environment[HARNESS_PLUGIN_DIRECTORY_ENV] ??
|
|
34676
|
-
environment.CODEXHOST_DATA_DIR ?
|
|
34977
|
+
path19.join(path19.dirname(fileURLToPath(hostRuntimeUrl)), "plugins"),
|
|
34978
|
+
environment[HARNESS_PLUGIN_DIRECTORY_ENV] ?? path19.join(
|
|
34979
|
+
environment.CODEXHOST_DATA_DIR ? path19.resolve(environment.CODEXHOST_DATA_DIR) : path19.join(os5.homedir(), ".codexhost"),
|
|
34677
34980
|
"plugins"
|
|
34678
34981
|
)
|
|
34679
34982
|
],
|
|
@@ -34798,12 +35101,12 @@ async function startDelegationControlServer(input) {
|
|
|
34798
35101
|
}
|
|
34799
35102
|
|
|
34800
35103
|
// packages/host-runtime/src/delegation-skill.ts
|
|
34801
|
-
import { createHash as
|
|
34802
|
-
import { mkdir as
|
|
34803
|
-
import
|
|
34804
|
-
import
|
|
35104
|
+
import { createHash as createHash9, randomUUID as randomUUID12 } from "node:crypto";
|
|
35105
|
+
import { mkdir as mkdir8, open as open6, readFile as readFile8, rename as rename5, rm as rm8, stat as stat4 } from "node:fs/promises";
|
|
35106
|
+
import os6 from "node:os";
|
|
35107
|
+
import path20 from "node:path";
|
|
34805
35108
|
var SKILL_VERSION = 7;
|
|
34806
|
-
var SKILL_RELATIVE_PATH =
|
|
35109
|
+
var SKILL_RELATIVE_PATH = path20.join("skills", "codexhost-delegation", "SKILL.md");
|
|
34807
35110
|
var PREVIOUS_MANAGED_DIGESTS = [
|
|
34808
35111
|
"9d2f491850fb0b4084a31ba9b5e4a550b5e833747af322090d8ed0ff80b88c30",
|
|
34809
35112
|
"2bb0aebb9b06febbc6c0c0bcdb0b32506c7cdbf8dc3b734cc6b2a86621270e4e",
|
|
@@ -34858,9 +35161,9 @@ user’s request and the task:
|
|
|
34858
35161
|
Report the result returned by read or a completed wait, together with the target
|
|
34859
35162
|
agent, status, and a labeled task link. Keep internal tracking IDs in tool calls.
|
|
34860
35163
|
`;
|
|
34861
|
-
var CURRENT_DIGEST =
|
|
35164
|
+
var CURRENT_DIGEST = createHash9("sha256").update(CODEXHOST_DELEGATION_SKILL).digest("hex");
|
|
34862
35165
|
function digest(value2) {
|
|
34863
|
-
return
|
|
35166
|
+
return createHash9("sha256").update(value2).digest("hex");
|
|
34864
35167
|
}
|
|
34865
35168
|
function managedVersion(value2) {
|
|
34866
35169
|
const match = /^version:\s*(\d+)\s*$/mu.exec(value2);
|
|
@@ -34868,15 +35171,15 @@ function managedVersion(value2) {
|
|
|
34868
35171
|
}
|
|
34869
35172
|
async function readOptional(filePath) {
|
|
34870
35173
|
try {
|
|
34871
|
-
return await
|
|
35174
|
+
return await readFile8(filePath, "utf8");
|
|
34872
35175
|
} catch (error51) {
|
|
34873
35176
|
if (error51.code === "ENOENT") return null;
|
|
34874
35177
|
throw error51;
|
|
34875
35178
|
}
|
|
34876
35179
|
}
|
|
34877
35180
|
async function atomicWrite(filePath, content) {
|
|
34878
|
-
await
|
|
34879
|
-
const temporaryPath =
|
|
35181
|
+
await mkdir8(path20.dirname(filePath), { recursive: true, mode: 448 });
|
|
35182
|
+
const temporaryPath = path20.join(path20.dirname(filePath), `.SKILL.md.${randomUUID12()}.tmp`);
|
|
34880
35183
|
const handle = await open6(temporaryPath, "wx", 384);
|
|
34881
35184
|
try {
|
|
34882
35185
|
await handle.writeFile(content, "utf8");
|
|
@@ -34885,16 +35188,16 @@ async function atomicWrite(filePath, content) {
|
|
|
34885
35188
|
await handle.close();
|
|
34886
35189
|
}
|
|
34887
35190
|
try {
|
|
34888
|
-
await
|
|
35191
|
+
await rename5(temporaryPath, filePath);
|
|
34889
35192
|
} finally {
|
|
34890
|
-
await
|
|
35193
|
+
await rm8(temporaryPath, { force: true });
|
|
34891
35194
|
}
|
|
34892
35195
|
}
|
|
34893
35196
|
async function installDelegationSkills(input = {}) {
|
|
34894
|
-
const home = input.homeDirectory ??
|
|
35197
|
+
const home = input.homeDirectory ?? os6.homedir();
|
|
34895
35198
|
const destinations = [
|
|
34896
|
-
|
|
34897
|
-
|
|
35199
|
+
path20.join(home, ".agents", SKILL_RELATIVE_PATH),
|
|
35200
|
+
path20.join(home, ".claude", SKILL_RELATIVE_PATH)
|
|
34898
35201
|
];
|
|
34899
35202
|
const knownDigests = /* @__PURE__ */ new Set([
|
|
34900
35203
|
CURRENT_DIGEST,
|
|
@@ -34939,8 +35242,8 @@ async function installDelegationSkills(input = {}) {
|
|
|
34939
35242
|
}
|
|
34940
35243
|
for (const result of results) {
|
|
34941
35244
|
if (result.status === "conflict") continue;
|
|
34942
|
-
const source = await
|
|
34943
|
-
const metadata = await
|
|
35245
|
+
const source = await readFile8(result.path, "utf8");
|
|
35246
|
+
const metadata = await stat4(result.path);
|
|
34944
35247
|
if (!metadata.isFile() || source !== CODEXHOST_DELEGATION_SKILL) {
|
|
34945
35248
|
throw new Error(`Delegation Skill verification failed: ${result.path}`);
|
|
34946
35249
|
}
|
|
@@ -34950,7 +35253,7 @@ async function installDelegationSkills(input = {}) {
|
|
|
34950
35253
|
throw new Error("Delegation Skill copies are inconsistent");
|
|
34951
35254
|
}
|
|
34952
35255
|
if (results.every((result) => result.status !== "conflict")) {
|
|
34953
|
-
const copies = await Promise.all(results.map((result) =>
|
|
35256
|
+
const copies = await Promise.all(results.map((result) => readFile8(result.path, "utf8")));
|
|
34954
35257
|
if (copies.some((copy) => copy !== copies[0])) {
|
|
34955
35258
|
throw new Error("Delegation Skill copies are inconsistent");
|
|
34956
35259
|
}
|
|
@@ -34959,9 +35262,9 @@ async function installDelegationSkills(input = {}) {
|
|
|
34959
35262
|
}
|
|
34960
35263
|
|
|
34961
35264
|
// packages/host-runtime/src/remote-control-app-server.ts
|
|
34962
|
-
import { randomUUID as
|
|
34963
|
-
import { mkdir as
|
|
34964
|
-
import
|
|
35265
|
+
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
35266
|
+
import { mkdir as mkdir9, open as open7, rename as rename6, rm as rm9 } from "node:fs/promises";
|
|
35267
|
+
import path21 from "node:path";
|
|
34965
35268
|
var REMOTE_CONTROL_BRIDGE_PIPE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_PIPE";
|
|
34966
35269
|
var REMOTE_CONTROL_BRIDGE_NODE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_NODE_PATH";
|
|
34967
35270
|
var REMOTE_CONTROL_BRIDGE_RUNTIME_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_RUNTIME_PATH";
|
|
@@ -34972,30 +35275,30 @@ var BRIDGE_READY_METHOD = "codexhost/remote-control-bridge/ready";
|
|
|
34972
35275
|
function absoluteEnvironmentPath2(environment, name, fallback, platform = process.platform) {
|
|
34973
35276
|
const value2 = environment[name] ?? fallback;
|
|
34974
35277
|
if (!value2) return null;
|
|
34975
|
-
if (
|
|
34976
|
-
return platform === "win32" &&
|
|
35278
|
+
if (path21.isAbsolute(value2)) return path21.normalize(value2);
|
|
35279
|
+
return platform === "win32" && path21.win32.isAbsolute(value2) ? path21.win32.normalize(value2) : null;
|
|
34977
35280
|
}
|
|
34978
35281
|
function nodeCompatibleWindowsPath(value2) {
|
|
34979
35282
|
if (value2.startsWith("\\\\?\\UNC\\")) return `\\\\${value2.slice(8)}`;
|
|
34980
35283
|
if (value2.startsWith("\\\\?\\")) return value2.slice(4);
|
|
34981
35284
|
return value2;
|
|
34982
35285
|
}
|
|
34983
|
-
function remoteControlBridgePipePath(processId = process.pid, instanceId =
|
|
35286
|
+
function remoteControlBridgePipePath(processId = process.pid, instanceId = randomUUID13()) {
|
|
34984
35287
|
const safeInstance = instanceId.replaceAll(/[^a-zA-Z0-9-]/gu, "");
|
|
34985
35288
|
if (!safeInstance) throw new Error("Remote Control bridge instance ID is invalid");
|
|
34986
35289
|
return `\\\\.\\pipe\\codexhost-remote-control-${processId}-${safeInstance}`;
|
|
34987
35290
|
}
|
|
34988
35291
|
function remoteControlBridgeDescriptorPath(environment) {
|
|
34989
35292
|
const root = environment.LOCALAPPDATA;
|
|
34990
|
-
if (!root || !
|
|
34991
|
-
return
|
|
35293
|
+
if (!root || !path21.isAbsolute(root)) return null;
|
|
35294
|
+
return path21.join(path21.normalize(root), "codexhost", REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE);
|
|
34992
35295
|
}
|
|
34993
35296
|
async function publishRemoteControlAppServerDescriptor(plan) {
|
|
34994
|
-
const directory =
|
|
34995
|
-
await
|
|
34996
|
-
const temporaryPath =
|
|
35297
|
+
const directory = path21.dirname(plan.descriptorPath);
|
|
35298
|
+
await mkdir9(directory, { recursive: true, mode: 448 });
|
|
35299
|
+
const temporaryPath = path21.join(
|
|
34997
35300
|
directory,
|
|
34998
|
-
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${
|
|
35301
|
+
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID13()}.tmp`
|
|
34999
35302
|
);
|
|
35000
35303
|
const handle = await open7(temporaryPath, "wx", 384);
|
|
35001
35304
|
try {
|
|
@@ -35006,9 +35309,9 @@ async function publishRemoteControlAppServerDescriptor(plan) {
|
|
|
35006
35309
|
await handle.close();
|
|
35007
35310
|
}
|
|
35008
35311
|
try {
|
|
35009
|
-
await
|
|
35312
|
+
await rename6(temporaryPath, plan.descriptorPath);
|
|
35010
35313
|
} finally {
|
|
35011
|
-
await
|
|
35314
|
+
await rm9(temporaryPath, { force: true });
|
|
35012
35315
|
}
|
|
35013
35316
|
}
|
|
35014
35317
|
function createRemoteControlAppServerPlan(input) {
|
|
@@ -35294,9 +35597,9 @@ function hasLauncherManagedUpdateRuntime(environment, hostRuntimePath) {
|
|
|
35294
35597
|
if (!environment[UPDATE_RUNTIME_ENV.launcherPid]) return false;
|
|
35295
35598
|
const npmPackageRoot = environment[UPDATE_RUNTIME_ENV.npmPackageRoot];
|
|
35296
35599
|
if (!npmPackageRoot || !hostRuntimePath) return true;
|
|
35297
|
-
if (!
|
|
35298
|
-
const runtimePackageRoot =
|
|
35299
|
-
return
|
|
35600
|
+
if (!path22.isAbsolute(npmPackageRoot) || !path22.isAbsolute(hostRuntimePath)) return false;
|
|
35601
|
+
const runtimePackageRoot = path22.dirname(path22.dirname(path22.normalize(hostRuntimePath)));
|
|
35602
|
+
return path22.relative(path22.normalize(npmPackageRoot), runtimePackageRoot) === "";
|
|
35300
35603
|
}
|
|
35301
35604
|
function requiredRuntimeConfiguration(environment) {
|
|
35302
35605
|
const stockCodexPath = environment[STOCK_CODEX_PATH_ENV];
|
|
@@ -35442,8 +35745,8 @@ async function runHostRuntime(input) {
|
|
|
35442
35745
|
const socketPath = remoteAppServerSocketPath(delegationEnvironment, listenUrl);
|
|
35443
35746
|
const officialPlan = createRemoteOfficialAppServerPlan(input.arguments, socketPath);
|
|
35444
35747
|
const officialRuntimeScope = new OfficialRuntimeScope({
|
|
35445
|
-
permanentHome:
|
|
35446
|
-
delegationEnvironment.CODEX_HOME ??
|
|
35748
|
+
permanentHome: path22.resolve(
|
|
35749
|
+
delegationEnvironment.CODEX_HOME ?? path22.join(homedir2(), ".codex")
|
|
35447
35750
|
),
|
|
35448
35751
|
diagnosticOutput: process.stderr,
|
|
35449
35752
|
createBackend: () => createOwnedUnixBackend({
|
|
@@ -35524,22 +35827,22 @@ async function runHostRuntime(input) {
|
|
|
35524
35827
|
}
|
|
35525
35828
|
|
|
35526
35829
|
// packages/host-runtime/src/remote-host-install.ts
|
|
35527
|
-
import { createHash as
|
|
35830
|
+
import { createHash as createHash10, randomUUID as randomUUID14 } from "node:crypto";
|
|
35528
35831
|
import { constants as fsConstants } from "node:fs";
|
|
35529
35832
|
import {
|
|
35530
35833
|
access,
|
|
35531
35834
|
chmod as chmod4,
|
|
35532
35835
|
copyFile as copyFile3,
|
|
35533
35836
|
lstat as lstat8,
|
|
35534
|
-
mkdir as
|
|
35535
|
-
readFile as
|
|
35536
|
-
rename as
|
|
35537
|
-
rm as
|
|
35837
|
+
mkdir as mkdir10,
|
|
35838
|
+
readFile as readFile9,
|
|
35839
|
+
rename as rename7,
|
|
35840
|
+
rm as rm10,
|
|
35538
35841
|
rmdir,
|
|
35539
|
-
stat as
|
|
35540
|
-
writeFile as
|
|
35842
|
+
stat as stat5,
|
|
35843
|
+
writeFile as writeFile4
|
|
35541
35844
|
} from "node:fs/promises";
|
|
35542
|
-
import
|
|
35845
|
+
import path23 from "node:path";
|
|
35543
35846
|
var MANIFEST_FORMAT = 1;
|
|
35544
35847
|
var WRAPPER_MARKER = "# codexhost remote SSH wrapper v1";
|
|
35545
35848
|
var PROFILE_START = "# >>> codexhost remote SSH >>>";
|
|
@@ -35550,25 +35853,25 @@ function resolvePaths(options2) {
|
|
|
35550
35853
|
if (!configuredHome) {
|
|
35551
35854
|
throw new Error("A non-root HOME is required for remote Host installation");
|
|
35552
35855
|
}
|
|
35553
|
-
const home =
|
|
35554
|
-
if (!home || home ===
|
|
35856
|
+
const home = path23.resolve(configuredHome);
|
|
35857
|
+
if (!home || home === path23.parse(home).root) {
|
|
35555
35858
|
throw new Error("A non-root HOME is required for remote Host installation");
|
|
35556
35859
|
}
|
|
35557
|
-
const installRoot =
|
|
35558
|
-
const profilePath =
|
|
35559
|
-
options2.profilePath ??
|
|
35860
|
+
const installRoot = path23.resolve(options2.installRoot ?? path23.join(home, ".codexhost", "remote"));
|
|
35861
|
+
const profilePath = path23.resolve(
|
|
35862
|
+
options2.profilePath ?? path23.join(
|
|
35560
35863
|
home,
|
|
35561
|
-
|
|
35864
|
+
path23.basename(environment.SHELL ?? "") === "zsh" ? ".zshenv" : path23.basename(environment.SHELL ?? "") === "bash" ? ".bashrc" : ".profile"
|
|
35562
35865
|
)
|
|
35563
35866
|
);
|
|
35564
|
-
const binDirectory =
|
|
35867
|
+
const binDirectory = path23.join(installRoot, "bin");
|
|
35565
35868
|
return {
|
|
35566
35869
|
home,
|
|
35567
35870
|
installRoot,
|
|
35568
35871
|
binDirectory,
|
|
35569
|
-
wrapperPath:
|
|
35570
|
-
manifestPath:
|
|
35571
|
-
dataDirectory:
|
|
35872
|
+
wrapperPath: path23.join(binDirectory, "codex"),
|
|
35873
|
+
manifestPath: path23.join(installRoot, "manifest.json"),
|
|
35874
|
+
dataDirectory: path23.join(installRoot, "data"),
|
|
35572
35875
|
profilePath
|
|
35573
35876
|
};
|
|
35574
35877
|
}
|
|
@@ -35577,19 +35880,19 @@ function shellQuote(value2) {
|
|
|
35577
35880
|
}
|
|
35578
35881
|
async function existingText(filePath) {
|
|
35579
35882
|
try {
|
|
35580
|
-
return await
|
|
35883
|
+
return await readFile9(filePath, "utf8");
|
|
35581
35884
|
} catch (error51) {
|
|
35582
35885
|
if (error51.code === "ENOENT") return null;
|
|
35583
35886
|
throw error51;
|
|
35584
35887
|
}
|
|
35585
35888
|
}
|
|
35586
35889
|
async function fileSha256(filePath) {
|
|
35587
|
-
return
|
|
35890
|
+
return createHash10("sha256").update(await readFile9(filePath)).digest("hex");
|
|
35588
35891
|
}
|
|
35589
35892
|
async function executable(filePath, label) {
|
|
35590
|
-
const absolute =
|
|
35893
|
+
const absolute = path23.resolve(filePath);
|
|
35591
35894
|
try {
|
|
35592
|
-
if (!(await
|
|
35895
|
+
if (!(await stat5(absolute)).isFile()) throw new Error("not a regular file");
|
|
35593
35896
|
await access(absolute, fsConstants.X_OK);
|
|
35594
35897
|
} catch {
|
|
35595
35898
|
throw new Error(`${label} is not an executable file: ${absolute}`);
|
|
@@ -35597,9 +35900,9 @@ async function executable(filePath, label) {
|
|
|
35597
35900
|
return absolute;
|
|
35598
35901
|
}
|
|
35599
35902
|
async function existingFile(filePath, label) {
|
|
35600
|
-
const absolute =
|
|
35903
|
+
const absolute = path23.resolve(filePath);
|
|
35601
35904
|
try {
|
|
35602
|
-
const metadata = await
|
|
35905
|
+
const metadata = await stat5(absolute);
|
|
35603
35906
|
if (!metadata.isFile()) throw new Error("not a regular file");
|
|
35604
35907
|
} catch {
|
|
35605
35908
|
throw new Error(`${label} is not a regular file: ${absolute}`);
|
|
@@ -35607,9 +35910,9 @@ async function existingFile(filePath, label) {
|
|
|
35607
35910
|
return absolute;
|
|
35608
35911
|
}
|
|
35609
35912
|
async function discoverExecutable(name, environment) {
|
|
35610
|
-
for (const directory of (environment.PATH ?? "").split(
|
|
35913
|
+
for (const directory of (environment.PATH ?? "").split(path23.delimiter)) {
|
|
35611
35914
|
if (!directory) continue;
|
|
35612
|
-
const candidate =
|
|
35915
|
+
const candidate = path23.resolve(directory, name);
|
|
35613
35916
|
try {
|
|
35614
35917
|
await access(candidate, fsConstants.X_OK);
|
|
35615
35918
|
return candidate;
|
|
@@ -35620,47 +35923,47 @@ async function discoverExecutable(name, environment) {
|
|
|
35620
35923
|
return null;
|
|
35621
35924
|
}
|
|
35622
35925
|
async function writeAtomic(filePath, contents, mode) {
|
|
35623
|
-
await
|
|
35624
|
-
const temporary =
|
|
35625
|
-
|
|
35626
|
-
`.${
|
|
35926
|
+
await mkdir10(path23.dirname(filePath), { recursive: true, mode: 448 });
|
|
35927
|
+
const temporary = path23.join(
|
|
35928
|
+
path23.dirname(filePath),
|
|
35929
|
+
`.${path23.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
|
|
35627
35930
|
);
|
|
35628
35931
|
try {
|
|
35629
35932
|
if (typeof contents === "string") {
|
|
35630
|
-
await
|
|
35933
|
+
await writeFile4(temporary, contents, { encoding: "utf8", flag: "wx", mode });
|
|
35631
35934
|
} else {
|
|
35632
|
-
await
|
|
35935
|
+
await writeFile4(temporary, contents, { flag: "wx", mode });
|
|
35633
35936
|
}
|
|
35634
35937
|
await chmod4(temporary, mode);
|
|
35635
35938
|
try {
|
|
35636
|
-
await
|
|
35939
|
+
await rename7(temporary, filePath);
|
|
35637
35940
|
} catch (error51) {
|
|
35638
35941
|
if (process.platform !== "win32") throw error51;
|
|
35639
|
-
await
|
|
35640
|
-
await
|
|
35942
|
+
await rm10(filePath, { force: true });
|
|
35943
|
+
await rename7(temporary, filePath);
|
|
35641
35944
|
}
|
|
35642
35945
|
} finally {
|
|
35643
|
-
await
|
|
35946
|
+
await rm10(temporary, { force: true });
|
|
35644
35947
|
}
|
|
35645
35948
|
}
|
|
35646
35949
|
async function writeAtomicExecutable(filePath, sourcePath) {
|
|
35647
|
-
await
|
|
35648
|
-
const temporary =
|
|
35649
|
-
|
|
35650
|
-
`.${
|
|
35950
|
+
await mkdir10(path23.dirname(filePath), { recursive: true, mode: 448 });
|
|
35951
|
+
const temporary = path23.join(
|
|
35952
|
+
path23.dirname(filePath),
|
|
35953
|
+
`.${path23.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
|
|
35651
35954
|
);
|
|
35652
35955
|
try {
|
|
35653
35956
|
await copyFile3(sourcePath, temporary);
|
|
35654
35957
|
await chmod4(temporary, 448);
|
|
35655
35958
|
try {
|
|
35656
|
-
await
|
|
35959
|
+
await rename7(temporary, filePath);
|
|
35657
35960
|
} catch (error51) {
|
|
35658
35961
|
if (process.platform !== "win32") throw error51;
|
|
35659
|
-
await
|
|
35660
|
-
await
|
|
35962
|
+
await rm10(filePath, { force: true });
|
|
35963
|
+
await rename7(temporary, filePath);
|
|
35661
35964
|
}
|
|
35662
35965
|
} finally {
|
|
35663
|
-
await
|
|
35966
|
+
await rm10(temporary, { force: true });
|
|
35664
35967
|
}
|
|
35665
35968
|
}
|
|
35666
35969
|
function managedBlockRange(contents) {
|
|
@@ -35688,15 +35991,14 @@ function removeManagedProfileBlock(contents) {
|
|
|
35688
35991
|
function installManagedProfileBlock(contents, manifest) {
|
|
35689
35992
|
const base = removeManagedProfileBlock(contents);
|
|
35690
35993
|
const environment = [
|
|
35691
|
-
`export CODEX_INSTALL_DIR=${shellQuote(
|
|
35692
|
-
`export PATH=${shellQuote(
|
|
35994
|
+
`export CODEX_INSTALL_DIR=${shellQuote(path23.dirname(manifest.wrapperPath))}`,
|
|
35995
|
+
`export PATH=${shellQuote(path23.dirname(manifest.wrapperPath))}:${shellQuote(path23.dirname(manifest.nodePath))}:${shellQuote(path23.dirname(manifest.stockCodexPath))}:"\${PATH:-/usr/local/bin:/usr/bin:/bin}"`,
|
|
35693
35996
|
`export CODEXHOST_STOCK_CODEX_PATH=${shellQuote(manifest.stockCodexPath)}`,
|
|
35694
35997
|
`export CODEXHOST_HOST_NODE_PATH=${shellQuote(manifest.nodePath)}`,
|
|
35695
35998
|
`export CODEXHOST_HOST_RUNTIME_PATH=${shellQuote(manifest.hostRuntimePath)}`,
|
|
35696
35999
|
`export CODEXHOST_DATA_DIR=${shellQuote(manifest.dataDirectory)}`,
|
|
35697
36000
|
"export CODEXHOST_DEFAULT_AGENT='codex'",
|
|
35698
|
-
"export CODEXHOST_REMOTE_SSH_MANAGED='1'"
|
|
35699
|
-
...manifest.claudeCommand ? [`export CODEXHOST_CLAUDE_COMMAND=${shellQuote(manifest.claudeCommand)}`] : []
|
|
36001
|
+
"export CODEXHOST_REMOTE_SSH_MANAGED='1'"
|
|
35700
36002
|
];
|
|
35701
36003
|
const block = [
|
|
35702
36004
|
PROFILE_START,
|
|
@@ -35706,7 +36008,7 @@ function installManagedProfileBlock(contents, manifest) {
|
|
|
35706
36008
|
PROFILE_END,
|
|
35707
36009
|
""
|
|
35708
36010
|
].join("\n");
|
|
35709
|
-
if (
|
|
36011
|
+
if (path23.basename(manifest.profilePath) === ".bashrc") return `${block}${base}`;
|
|
35710
36012
|
const separator = base.length > 0 && !base.endsWith("\n") ? "\n" : "";
|
|
35711
36013
|
return `${base}${separator}${block}`;
|
|
35712
36014
|
}
|
|
@@ -35718,16 +36020,16 @@ async function managedEntrypointState(manifest) {
|
|
|
35718
36020
|
if (metadata === null) return "missing";
|
|
35719
36021
|
if (!metadata.isFile()) return "modified";
|
|
35720
36022
|
if (process.platform !== "win32" && (metadata.mode & 73) === 0) return "modified";
|
|
35721
|
-
const entrypoint = await
|
|
36023
|
+
const entrypoint = await readFile9(manifest.wrapperPath);
|
|
35722
36024
|
if (entrypoint.subarray(0, 256).toString("utf8").startsWith(`#!/usr/bin/env sh
|
|
35723
36025
|
${WRAPPER_MARKER}
|
|
35724
36026
|
`)) {
|
|
35725
36027
|
return "legacy-wrapper";
|
|
35726
36028
|
}
|
|
35727
36029
|
if (manifest.entrypointSha256 !== void 0) {
|
|
35728
|
-
return
|
|
36030
|
+
return createHash10("sha256").update(entrypoint).digest("hex") === manifest.entrypointSha256 ? "native" : "modified";
|
|
35729
36031
|
}
|
|
35730
|
-
const shim = await
|
|
36032
|
+
const shim = await readFile9(manifest.shimPath).catch((error51) => {
|
|
35731
36033
|
if (error51.code === "ENOENT") return null;
|
|
35732
36034
|
throw error51;
|
|
35733
36035
|
});
|
|
@@ -35758,6 +36060,7 @@ async function readManifest(filePath) {
|
|
|
35758
36060
|
"dataDirectory",
|
|
35759
36061
|
"entrypointSha256",
|
|
35760
36062
|
"claudeCommand",
|
|
36063
|
+
// Inert metadata accepted from older format-1 manifests.
|
|
35761
36064
|
"profileBackupPath"
|
|
35762
36065
|
]);
|
|
35763
36066
|
const requiredPaths = [
|
|
@@ -35771,9 +36074,9 @@ async function readManifest(filePath) {
|
|
|
35771
36074
|
];
|
|
35772
36075
|
const optionalPaths = ["claudeCommand", "profileBackupPath"];
|
|
35773
36076
|
if (manifest.format !== MANIFEST_FORMAT || Object.keys(manifest).some((key) => !allowed.has(key)) || requiredPaths.some(
|
|
35774
|
-
(key) => typeof manifest[key] !== "string" || !
|
|
36077
|
+
(key) => typeof manifest[key] !== "string" || !path23.isAbsolute(manifest[key])
|
|
35775
36078
|
) || optionalPaths.some(
|
|
35776
|
-
(key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !
|
|
36079
|
+
(key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !path23.isAbsolute(manifest[key]))
|
|
35777
36080
|
) || manifest.entrypointSha256 !== void 0 && (typeof manifest.entrypointSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(manifest.entrypointSha256))) {
|
|
35778
36081
|
throw new Error("Remote Host manifest has an unsupported format");
|
|
35779
36082
|
}
|
|
@@ -35782,7 +36085,7 @@ async function readManifest(filePath) {
|
|
|
35782
36085
|
async function backupProfile(profilePath, contents, action) {
|
|
35783
36086
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(/[-:.TZ]/gu, "");
|
|
35784
36087
|
const backupPath = `${profilePath}.codexhost-${action}-${timestamp}.bak`;
|
|
35785
|
-
const metadata = await
|
|
36088
|
+
const metadata = await stat5(profilePath).catch(() => null);
|
|
35786
36089
|
await writeAtomic(backupPath, contents, metadata?.mode ?? 384);
|
|
35787
36090
|
return backupPath;
|
|
35788
36091
|
}
|
|
@@ -35795,8 +36098,8 @@ async function installRemoteHost(options2) {
|
|
|
35795
36098
|
const paths = resolvePaths(options2);
|
|
35796
36099
|
const previousManifest = await readManifest(paths.manifestPath);
|
|
35797
36100
|
const previousManifestFile = previousManifest ? {
|
|
35798
|
-
contents: await
|
|
35799
|
-
mode: (await
|
|
36101
|
+
contents: await readFile9(paths.manifestPath),
|
|
36102
|
+
mode: (await stat5(paths.manifestPath)).mode & 511
|
|
35800
36103
|
} : null;
|
|
35801
36104
|
const existingEntrypoint = await lstat8(paths.wrapperPath).catch(
|
|
35802
36105
|
(error51) => {
|
|
@@ -35820,7 +36123,7 @@ async function installRemoteHost(options2) {
|
|
|
35820
36123
|
}
|
|
35821
36124
|
const profilePath = previousManifest?.profilePath ?? paths.profilePath;
|
|
35822
36125
|
const previousEntrypoint = existingEntrypoint?.isFile() ? {
|
|
35823
|
-
contents: await
|
|
36126
|
+
contents: await readFile9(paths.wrapperPath),
|
|
35824
36127
|
mode: existingEntrypoint.mode & 511
|
|
35825
36128
|
} : null;
|
|
35826
36129
|
const discoveredStock = options2.stockCodexPath ?? previousManifest?.stockCodexPath ?? await discoverExecutable("codex", environment);
|
|
@@ -35837,8 +36140,6 @@ async function installRemoteHost(options2) {
|
|
|
35837
36140
|
const nodePath2 = await executable(options2.nodePath, "Node runtime");
|
|
35838
36141
|
const shimPath = await executable(options2.shimPath, "codexhost Shim");
|
|
35839
36142
|
const hostRuntimePath = await existingFile(options2.hostRuntimePath, "codexhost Host Runtime");
|
|
35840
|
-
const discoveredClaude = options2.claudeCommand ?? previousManifest?.claudeCommand ?? await discoverExecutable("claude", environment);
|
|
35841
|
-
const claudeCommand = discoveredClaude ? await executable(discoveredClaude, "Claude Code command") : void 0;
|
|
35842
36143
|
let manifest = {
|
|
35843
36144
|
format: MANIFEST_FORMAT,
|
|
35844
36145
|
wrapperPath: paths.wrapperPath,
|
|
@@ -35848,21 +36149,20 @@ async function installRemoteHost(options2) {
|
|
|
35848
36149
|
shimPath,
|
|
35849
36150
|
hostRuntimePath,
|
|
35850
36151
|
dataDirectory: paths.dataDirectory,
|
|
35851
|
-
...claudeCommand ? { claudeCommand } : {},
|
|
35852
36152
|
...previousManifest?.profileBackupPath ? { profileBackupPath: previousManifest.profileBackupPath } : {}
|
|
35853
36153
|
};
|
|
35854
36154
|
const existingProfileSource = await existingText(profilePath);
|
|
35855
36155
|
const existingProfile = existingProfileSource ?? "";
|
|
35856
36156
|
const nextProfile = installManagedProfileBlock(existingProfile, manifest);
|
|
35857
36157
|
const profileChanged = nextProfile !== existingProfile;
|
|
35858
|
-
const profileMetadata = await
|
|
36158
|
+
const profileMetadata = await stat5(profilePath).catch(() => null);
|
|
35859
36159
|
try {
|
|
35860
36160
|
if (profileChanged) {
|
|
35861
36161
|
const profileBackupPath = await backupProfile(profilePath, existingProfile, "install");
|
|
35862
36162
|
manifest = { ...manifest, profileBackupPath };
|
|
35863
36163
|
await writeAtomic(profilePath, nextProfile, profileMetadata?.mode ?? 384);
|
|
35864
36164
|
}
|
|
35865
|
-
await
|
|
36165
|
+
await mkdir10(paths.dataDirectory, { recursive: true, mode: 448 });
|
|
35866
36166
|
await chmod4(paths.dataDirectory, 448);
|
|
35867
36167
|
await writeAtomicExecutable(paths.wrapperPath, manifest.shimPath);
|
|
35868
36168
|
manifest = { ...manifest, entrypointSha256: await fileSha256(paths.wrapperPath) };
|
|
@@ -35875,7 +36175,7 @@ async function installRemoteHost(options2) {
|
|
|
35875
36175
|
if (previousEntrypoint) {
|
|
35876
36176
|
await writeAtomic(paths.wrapperPath, previousEntrypoint.contents, previousEntrypoint.mode);
|
|
35877
36177
|
} else {
|
|
35878
|
-
await
|
|
36178
|
+
await rm10(paths.wrapperPath, { force: true });
|
|
35879
36179
|
}
|
|
35880
36180
|
} catch (rollbackError) {
|
|
35881
36181
|
rollbackErrors.push(rollbackError);
|
|
@@ -35883,7 +36183,7 @@ async function installRemoteHost(options2) {
|
|
|
35883
36183
|
if (profileChanged) {
|
|
35884
36184
|
try {
|
|
35885
36185
|
if (existingProfileSource === null) {
|
|
35886
|
-
await
|
|
36186
|
+
await rm10(profilePath, { force: true });
|
|
35887
36187
|
} else {
|
|
35888
36188
|
await writeAtomic(profilePath, existingProfile, profileMetadata?.mode ?? 384);
|
|
35889
36189
|
}
|
|
@@ -35899,7 +36199,7 @@ async function installRemoteHost(options2) {
|
|
|
35899
36199
|
previousManifestFile.mode
|
|
35900
36200
|
);
|
|
35901
36201
|
} else {
|
|
35902
|
-
await
|
|
36202
|
+
await rm10(paths.manifestPath, { force: true });
|
|
35903
36203
|
}
|
|
35904
36204
|
} catch (rollbackError) {
|
|
35905
36205
|
rollbackErrors.push(rollbackError);
|
|
@@ -35946,7 +36246,7 @@ async function inspectRemoteHostInstallation(options2) {
|
|
|
35946
36246
|
if (!profileMatches && profileIssue === null)
|
|
35947
36247
|
profileIssue = "shell profile does not configure the managed native entrypoint";
|
|
35948
36248
|
if (profileIssue !== null) issues.push(profileIssue);
|
|
35949
|
-
const dataDirectory = await
|
|
36249
|
+
const dataDirectory = await stat5(manifest.dataDirectory).catch(() => null);
|
|
35950
36250
|
if (!dataDirectory?.isDirectory()) issues.push("remote Host data directory is unavailable");
|
|
35951
36251
|
for (const [label, filePath, requiresExecutable] of [
|
|
35952
36252
|
["stock Codex", manifest.stockCodexPath, true],
|
|
@@ -35956,7 +36256,7 @@ async function inspectRemoteHostInstallation(options2) {
|
|
|
35956
36256
|
]) {
|
|
35957
36257
|
try {
|
|
35958
36258
|
if (requiresExecutable) await executable(filePath, label);
|
|
35959
|
-
else if (!(await
|
|
36259
|
+
else if (!(await stat5(filePath)).isFile()) throw new Error("not a regular file");
|
|
35960
36260
|
} catch {
|
|
35961
36261
|
issues.push(`${label} is unavailable`);
|
|
35962
36262
|
}
|
|
@@ -35985,11 +36285,11 @@ async function uninstallRemoteHost(options2) {
|
|
|
35985
36285
|
const nextProfile = removeManagedProfileBlock(profile);
|
|
35986
36286
|
if (nextProfile !== profile) {
|
|
35987
36287
|
await backupProfile(manifest.profilePath, profile, "uninstall");
|
|
35988
|
-
const metadata = await
|
|
36288
|
+
const metadata = await stat5(manifest.profilePath).catch(() => null);
|
|
35989
36289
|
await writeAtomic(manifest.profilePath, nextProfile, metadata?.mode ?? 384);
|
|
35990
36290
|
}
|
|
35991
|
-
await
|
|
35992
|
-
await
|
|
36291
|
+
await rm10(manifest.wrapperPath, { force: true });
|
|
36292
|
+
await rm10(paths.manifestPath, { force: true });
|
|
35993
36293
|
await rmdir(paths.binDirectory).catch((error51) => {
|
|
35994
36294
|
if (error51.code !== "ENOENT" && error51.code !== "ENOTEMPTY") throw error51;
|
|
35995
36295
|
});
|
|
@@ -36000,9 +36300,9 @@ async function uninstallRemoteHost(options2) {
|
|
|
36000
36300
|
|
|
36001
36301
|
// packages/host-runtime/src/remote-host-lifecycle.ts
|
|
36002
36302
|
import { spawn as spawn5 } from "node:child_process";
|
|
36003
|
-
import { stat as
|
|
36303
|
+
import { stat as stat6 } from "node:fs/promises";
|
|
36004
36304
|
import net3 from "node:net";
|
|
36005
|
-
import
|
|
36305
|
+
import path24 from "node:path";
|
|
36006
36306
|
import { Duplex } from "node:stream";
|
|
36007
36307
|
var CODEXHOST_STATUS_METHOD = "codexhost/update/status";
|
|
36008
36308
|
var DIRECT_PROBE_TIMEOUT_MS = 5e3;
|
|
@@ -36021,12 +36321,12 @@ function classifyRemoteHostProbeResponse(response, socketPath) {
|
|
|
36021
36321
|
}
|
|
36022
36322
|
var lifecycleDependencyOverrides = {};
|
|
36023
36323
|
function socketPathFor(environment) {
|
|
36024
|
-
const codexHome = environment.CODEX_HOME ?? (environment.HOME ?
|
|
36324
|
+
const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path24.join(environment.HOME, ".codex") : void 0);
|
|
36025
36325
|
if (!codexHome) throw new Error("CODEX_HOME or HOME is required for remote Host lifecycle");
|
|
36026
|
-
return
|
|
36326
|
+
return path24.join(codexHome, "app-server-control", "app-server-control.sock");
|
|
36027
36327
|
}
|
|
36028
36328
|
async function defaultSocketExists(socketPath) {
|
|
36029
|
-
const metadata = await
|
|
36329
|
+
const metadata = await stat6(socketPath).catch((error51) => {
|
|
36030
36330
|
if (error51.code === "ENOENT") return null;
|
|
36031
36331
|
throw error51;
|
|
36032
36332
|
});
|
|
@@ -36150,15 +36450,14 @@ function installedManifest(status) {
|
|
|
36150
36450
|
function managedEnvironment(manifest, environment) {
|
|
36151
36451
|
return {
|
|
36152
36452
|
...environment,
|
|
36153
|
-
CODEX_INSTALL_DIR:
|
|
36453
|
+
CODEX_INSTALL_DIR: path24.dirname(manifest.wrapperPath),
|
|
36154
36454
|
CODEXHOST_STOCK_CODEX_PATH: manifest.stockCodexPath,
|
|
36155
36455
|
CODEXHOST_HOST_NODE_PATH: manifest.nodePath,
|
|
36156
36456
|
CODEXHOST_HOST_RUNTIME_PATH: manifest.hostRuntimePath,
|
|
36157
36457
|
CODEXHOST_DATA_DIR: manifest.dataDirectory,
|
|
36158
36458
|
CODEXHOST_DEFAULT_AGENT: "codex",
|
|
36159
36459
|
CODEXHOST_REMOTE_SSH_MANAGED: "1",
|
|
36160
|
-
|
|
36161
|
-
PATH: `${path22.dirname(manifest.wrapperPath)}${path22.delimiter}${path22.dirname(manifest.stockCodexPath)}${path22.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
|
|
36460
|
+
PATH: `${path24.dirname(manifest.wrapperPath)}${path24.delimiter}${path24.dirname(manifest.stockCodexPath)}${path24.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
|
|
36162
36461
|
};
|
|
36163
36462
|
}
|
|
36164
36463
|
async function defaultRunTerminator(manifest, socketPath, role, environment) {
|
|
@@ -36306,9 +36605,6 @@ function parseRemoteCliArguments(arguments_2) {
|
|
|
36306
36605
|
case "--stock-codex":
|
|
36307
36606
|
options2.stockCodexPath = value2;
|
|
36308
36607
|
break;
|
|
36309
|
-
case "--claude-command":
|
|
36310
|
-
options2.claudeCommand = value2;
|
|
36311
|
-
break;
|
|
36312
36608
|
case "--node":
|
|
36313
36609
|
resources.nodePath = value2;
|
|
36314
36610
|
break;
|
|
@@ -36335,7 +36631,7 @@ async function runRemoteHostCli(input) {
|
|
|
36335
36631
|
output.write(
|
|
36336
36632
|
[
|
|
36337
36633
|
"usage:",
|
|
36338
|
-
" codexhost remote install [--stock-codex PATH]
|
|
36634
|
+
" codexhost remote install [--stock-codex PATH]",
|
|
36339
36635
|
" codexhost remote start",
|
|
36340
36636
|
" codexhost remote stop",
|
|
36341
36637
|
" codexhost remote status",
|
|
@@ -36496,26 +36792,26 @@ function consumeBrokerFrames(socket, onFrame, onError) {
|
|
|
36496
36792
|
}
|
|
36497
36793
|
|
|
36498
36794
|
// packages/harness-broker/dist/paths.js
|
|
36499
|
-
import
|
|
36500
|
-
import
|
|
36795
|
+
import os7 from "node:os";
|
|
36796
|
+
import path25 from "node:path";
|
|
36501
36797
|
var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
|
|
36502
36798
|
var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
|
|
36503
36799
|
var HARNESS_BROKER_SOCKET_FILE = "claude-code-broker-v1.sock";
|
|
36504
36800
|
function defaultHarnessBrokerDirectory(environment = process.env) {
|
|
36505
|
-
const home = environment.HOME ||
|
|
36506
|
-
return
|
|
36801
|
+
const home = environment.HOME || os7.homedir();
|
|
36802
|
+
return path25.join(home, ".codexhost", "harness-broker");
|
|
36507
36803
|
}
|
|
36508
36804
|
function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
|
|
36509
36805
|
harnessPluginIdSchema.parse(harnessId);
|
|
36510
36806
|
if (harnessId !== "claude-code")
|
|
36511
|
-
return
|
|
36512
|
-
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ??
|
|
36807
|
+
return path25.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
|
|
36808
|
+
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path25.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
|
|
36513
36809
|
}
|
|
36514
36810
|
function defaultHarnessBrokerSocketPath(environment = process.env, harnessId = "claude-code") {
|
|
36515
36811
|
harnessPluginIdSchema.parse(harnessId);
|
|
36516
36812
|
if (harnessId !== "claude-code")
|
|
36517
|
-
return
|
|
36518
|
-
return
|
|
36813
|
+
return path25.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
|
|
36814
|
+
return path25.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
|
|
36519
36815
|
}
|
|
36520
36816
|
|
|
36521
36817
|
// packages/harness-broker/dist/validation.js
|
|
@@ -36728,10 +37024,10 @@ var harnessOutputSchema = external_exports.custom((value2) => {
|
|
|
36728
37024
|
});
|
|
36729
37025
|
|
|
36730
37026
|
// packages/harness-broker/dist/server.js
|
|
36731
|
-
import { randomBytes as randomBytes3, randomUUID as
|
|
36732
|
-
import { chmod as chmod5, lstat as lstat9, mkdir as
|
|
37027
|
+
import { randomBytes as randomBytes3, randomUUID as randomUUID15 } from "node:crypto";
|
|
37028
|
+
import { chmod as chmod5, lstat as lstat9, mkdir as mkdir11, open as open8, readFile as readFile10, rename as rename8, rm as rm11 } from "node:fs/promises";
|
|
36733
37029
|
import net4, {} from "node:net";
|
|
36734
|
-
import
|
|
37030
|
+
import path26 from "node:path";
|
|
36735
37031
|
function harnessError(message, retryable = true) {
|
|
36736
37032
|
return { code: "unavailable", message, retryable, stage: "harnessBroker" };
|
|
36737
37033
|
}
|
|
@@ -36742,7 +37038,7 @@ function nativeWriterKey(nativeSessionId) {
|
|
|
36742
37038
|
return nativeSessionId;
|
|
36743
37039
|
}
|
|
36744
37040
|
async function privateDirectory(directory) {
|
|
36745
|
-
await
|
|
37041
|
+
await mkdir11(directory, { recursive: true, mode: 448 });
|
|
36746
37042
|
if (process.platform === "win32")
|
|
36747
37043
|
return;
|
|
36748
37044
|
const metadata = await lstat9(directory);
|
|
@@ -36777,7 +37073,7 @@ async function assertNoLiveDescriptor(descriptorPath) {
|
|
|
36777
37073
|
throw new Error("Harness broker descriptor is not owner-only");
|
|
36778
37074
|
}
|
|
36779
37075
|
}
|
|
36780
|
-
const descriptor = harnessBrokerDescriptorSchema.parse(JSON.parse(await
|
|
37076
|
+
const descriptor = harnessBrokerDescriptorSchema.parse(JSON.parse(await readFile10(descriptorPath, "utf8")));
|
|
36781
37077
|
if (processIsAlive2(descriptor.ownerPid)) {
|
|
36782
37078
|
throw new Error("Harness broker descriptor already has a live owner");
|
|
36783
37079
|
}
|
|
@@ -36787,7 +37083,7 @@ async function assertNoLiveDescriptor(descriptorPath) {
|
|
|
36787
37083
|
}
|
|
36788
37084
|
}
|
|
36789
37085
|
async function publishDescriptor(descriptorPath, descriptor) {
|
|
36790
|
-
const temporary = `${descriptorPath}.${process.pid}.${
|
|
37086
|
+
const temporary = `${descriptorPath}.${process.pid}.${randomUUID15()}.tmp`;
|
|
36791
37087
|
const handle = await open8(temporary, "wx", 384);
|
|
36792
37088
|
try {
|
|
36793
37089
|
await handle.writeFile(`${JSON.stringify(descriptor)}
|
|
@@ -36796,7 +37092,7 @@ async function publishDescriptor(descriptorPath, descriptor) {
|
|
|
36796
37092
|
} finally {
|
|
36797
37093
|
await handle.close();
|
|
36798
37094
|
}
|
|
36799
|
-
await
|
|
37095
|
+
await rename8(temporary, descriptorPath);
|
|
36800
37096
|
if (process.platform !== "win32")
|
|
36801
37097
|
await chmod5(descriptorPath, 384);
|
|
36802
37098
|
}
|
|
@@ -36846,7 +37142,7 @@ async function prepareUnixSocketPath(socketPath) {
|
|
|
36846
37142
|
if (await socketAcceptsConnections(socketPath)) {
|
|
36847
37143
|
throw new Error("Harness broker socket is already active");
|
|
36848
37144
|
}
|
|
36849
|
-
await
|
|
37145
|
+
await rm11(socketPath);
|
|
36850
37146
|
} catch (error51) {
|
|
36851
37147
|
if (error51.code !== "ENOENT")
|
|
36852
37148
|
throw error51;
|
|
@@ -36854,17 +37150,17 @@ async function prepareUnixSocketPath(socketPath) {
|
|
|
36854
37150
|
}
|
|
36855
37151
|
async function startHarnessBrokerServer(input) {
|
|
36856
37152
|
harnessPluginIdSchema.parse(input.adapter.harnessId);
|
|
36857
|
-
if (process.platform !== "win32" &&
|
|
37153
|
+
if (process.platform !== "win32" && path26.dirname(input.descriptorPath) !== path26.dirname(input.socketPath)) {
|
|
36858
37154
|
throw new Error("Harness broker descriptor and socket must share one private directory");
|
|
36859
37155
|
}
|
|
36860
37156
|
if (process.platform === "darwin" && Buffer.byteLength(input.socketPath) > 103) {
|
|
36861
37157
|
throw new Error("Harness broker Unix socket path is too long for macOS");
|
|
36862
37158
|
}
|
|
36863
|
-
await privateDirectory(
|
|
37159
|
+
await privateDirectory(path26.dirname(input.descriptorPath));
|
|
36864
37160
|
await assertNoLiveDescriptor(input.descriptorPath);
|
|
36865
37161
|
if (process.platform !== "win32")
|
|
36866
37162
|
await prepareUnixSocketPath(input.socketPath);
|
|
36867
|
-
const generation = input.generation ??
|
|
37163
|
+
const generation = input.generation ?? randomUUID15();
|
|
36868
37164
|
const token = input.token ?? randomBytes3(32).toString("hex");
|
|
36869
37165
|
const descriptor = {
|
|
36870
37166
|
schemaVersion: 1,
|
|
@@ -36882,7 +37178,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
36882
37178
|
let closed = false;
|
|
36883
37179
|
const server = net4.createServer((socket) => {
|
|
36884
37180
|
const state = {
|
|
36885
|
-
id:
|
|
37181
|
+
id: randomUUID15(),
|
|
36886
37182
|
socket,
|
|
36887
37183
|
authenticated: false,
|
|
36888
37184
|
inputSequence: 0,
|
|
@@ -37097,7 +37393,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
37097
37393
|
}
|
|
37098
37394
|
};
|
|
37099
37395
|
}
|
|
37100
|
-
const openReservation =
|
|
37396
|
+
const openReservation = randomUUID15();
|
|
37101
37397
|
if (sourceKey)
|
|
37102
37398
|
nativeWriters.set(sourceKey, openReservation);
|
|
37103
37399
|
const provisionalReservation = openInput.kind === "create" ? openReservation : void 0;
|
|
@@ -37377,7 +37673,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
37377
37673
|
}
|
|
37378
37674
|
state.authenticated = true;
|
|
37379
37675
|
state.inputSequence = 1;
|
|
37380
|
-
await send({ kind: "response", id:
|
|
37676
|
+
await send({ kind: "response", id: randomUUID15(), ok: true, value: { ready: true } });
|
|
37381
37677
|
return;
|
|
37382
37678
|
}
|
|
37383
37679
|
const parsed = harnessBrokerRequestSchema.safeParse(raw);
|
|
@@ -37425,7 +37721,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
37425
37721
|
} catch (error51) {
|
|
37426
37722
|
await new Promise((resolve) => server.close(() => resolve()));
|
|
37427
37723
|
if (process.platform !== "win32")
|
|
37428
|
-
await
|
|
37724
|
+
await rm11(input.socketPath, { force: true });
|
|
37429
37725
|
throw error51;
|
|
37430
37726
|
}
|
|
37431
37727
|
return {
|
|
@@ -37443,8 +37739,8 @@ async function startHarnessBrokerServer(input) {
|
|
|
37443
37739
|
await input.adapter.close().catch(() => void 0);
|
|
37444
37740
|
await new Promise((resolve) => server.close(() => resolve()));
|
|
37445
37741
|
if (process.platform !== "win32")
|
|
37446
|
-
await
|
|
37447
|
-
await
|
|
37742
|
+
await rm11(input.socketPath, { force: true });
|
|
37743
|
+
await rm11(input.descriptorPath, { force: true });
|
|
37448
37744
|
}
|
|
37449
37745
|
};
|
|
37450
37746
|
}
|