@zixt/host 0.0.49 → 0.0.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +586 -315
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,23 +15,23 @@ import { spawn as spawn4 } from "node:child_process";
|
|
|
15
15
|
import { fstatSync } from "node:fs";
|
|
16
16
|
import {
|
|
17
17
|
access as access2,
|
|
18
|
-
lstat as
|
|
18
|
+
lstat as lstat4,
|
|
19
19
|
mkdir as mkdir3,
|
|
20
20
|
open as open3,
|
|
21
|
-
readFile as
|
|
21
|
+
readFile as readFile5,
|
|
22
22
|
readlink,
|
|
23
23
|
readdir as readdir2,
|
|
24
24
|
rename as rename2,
|
|
25
25
|
rm as rm3,
|
|
26
26
|
symlink
|
|
27
27
|
} from "node:fs/promises";
|
|
28
|
-
import { basename as
|
|
28
|
+
import { basename as basename3, dirname as dirname3, isAbsolute as isAbsolute7, join as join6, relative as relative3, resolve as resolve4, sep as sep3 } from "node:path";
|
|
29
29
|
import { homedir } from "node:os";
|
|
30
30
|
|
|
31
31
|
// package.json
|
|
32
32
|
var package_default = {
|
|
33
33
|
name: "@zixt/host",
|
|
34
|
-
version: "0.0.
|
|
34
|
+
version: "0.0.51",
|
|
35
35
|
type: "module",
|
|
36
36
|
exports: {
|
|
37
37
|
".": "./src/client.ts",
|
|
@@ -14647,6 +14647,8 @@ var ID_PREFIXES = {
|
|
|
14647
14647
|
browserSession: "brs",
|
|
14648
14648
|
/** One file a person attached to a chat message ('att' is taken by attempt). */
|
|
14649
14649
|
attachment: "atc",
|
|
14650
|
+
/** Immutable file created by an AI teammate during a Task. */
|
|
14651
|
+
artifact: "art",
|
|
14650
14652
|
/** One curated memory entry an agent chose to keep ('mem' is taken by member). */
|
|
14651
14653
|
memory: "mry",
|
|
14652
14654
|
/** Org-singleton Manager configuration (PRD §8.13). */
|
|
@@ -14694,6 +14696,7 @@ var OrgSkillId = idSchema(ID_PREFIXES.orgSkill, "organization skill id");
|
|
|
14694
14696
|
var OrgRoutineId = idSchema(ID_PREFIXES.orgRoutine, "organization routine id");
|
|
14695
14697
|
var BrowserSessionId = idSchema(ID_PREFIXES.browserSession, "browser session id");
|
|
14696
14698
|
var AttachmentId = idSchema(ID_PREFIXES.attachment, "attachment id");
|
|
14699
|
+
var TaskArtifactId = idSchema(ID_PREFIXES.artifact, "task artifact id");
|
|
14697
14700
|
var MemoryId = idSchema(ID_PREFIXES.memory, "memory id");
|
|
14698
14701
|
var ManagerId = idSchema(ID_PREFIXES.manager, "manager id");
|
|
14699
14702
|
var ManagerMemoryId = idSchema(ID_PREFIXES.managerMemory, "manager memory id");
|
|
@@ -16019,6 +16022,28 @@ var UploadAttachmentRequest = external_exports.object({
|
|
|
16019
16022
|
data: external_exports.string().min(1).max(Math.ceil(TASK_ATTACHMENT_MAX_BYTES / 3 * 4) + 4)
|
|
16020
16023
|
});
|
|
16021
16024
|
var UploadAttachmentResponse = external_exports.object({ attachment: TaskAttachmentRef });
|
|
16025
|
+
var TASK_ARTIFACT_MAX_BYTES = 10 * 1024 * 1024;
|
|
16026
|
+
var TaskArtifact = external_exports.object({
|
|
16027
|
+
id: TaskArtifactId,
|
|
16028
|
+
taskId: TaskId,
|
|
16029
|
+
name: external_exports.string().min(1).max(200).regex(/^[^/\\]+$/, "artifact name must be a filename").refine(isSafeSingleLineDisplayText, "invalid artifact name"),
|
|
16030
|
+
mediaType: external_exports.string().max(200).regex(/^[\w.+-]+\/[\w.+-]+$/, "invalid media type"),
|
|
16031
|
+
size: external_exports.number().int().min(1).max(TASK_ARTIFACT_MAX_BYTES),
|
|
16032
|
+
sha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
|
|
16033
|
+
createdAt: IsoDate
|
|
16034
|
+
});
|
|
16035
|
+
var TaskFileCapability = external_exports.object({
|
|
16036
|
+
target: external_exports.enum(["zixt", "slack", "linear"]),
|
|
16037
|
+
operation: external_exports.enum(["download", "share", "issue_attachment"]),
|
|
16038
|
+
supported: external_exports.boolean(),
|
|
16039
|
+
available: external_exports.boolean(),
|
|
16040
|
+
maxBytes: external_exports.number().int().positive(),
|
|
16041
|
+
reason: external_exports.string().min(1).max(500).nullable(),
|
|
16042
|
+
remedy: external_exports.enum(["none", "connect", "reconnect", "grant_scope", "manual_link"])
|
|
16043
|
+
});
|
|
16044
|
+
var TaskFileCapabilities = external_exports.object({
|
|
16045
|
+
capabilities: external_exports.array(TaskFileCapability).length(3)
|
|
16046
|
+
});
|
|
16022
16047
|
var TaskDisposition = external_exports.object({
|
|
16023
16048
|
outcome: external_exports.enum(["done", "nothing_to_do", "escalated", "cancelled", "failed"]),
|
|
16024
16049
|
summary: external_exports.string().max(5e4)
|
|
@@ -16451,6 +16476,7 @@ var TaskWorkingContextObservation = TaskWorkingContextBase.omit({
|
|
|
16451
16476
|
var TaskDetailResponse = external_exports.object({
|
|
16452
16477
|
task: TaskProjection,
|
|
16453
16478
|
events: external_exports.array(TaskEventRecord),
|
|
16479
|
+
artifacts: external_exports.array(TaskArtifact),
|
|
16454
16480
|
/** Newest assignment epoch first. */
|
|
16455
16481
|
attempts: external_exports.array(TaskAttemptProjection),
|
|
16456
16482
|
/** Only unresolved asks for this task; decisions still use the typed approval endpoint. */
|
|
@@ -16982,6 +17008,39 @@ var AgentOp = external_exports.union([
|
|
|
16982
17008
|
}),
|
|
16983
17009
|
/** The channels a teammate can actually post to: the ones the bot is in. */
|
|
16984
17010
|
external_exports.object({ kind: external_exports.literal("comm.list_channels"), provider: external_exports.literal("slack") }),
|
|
17011
|
+
/** Snapshot a regular Task-workspace file into immutable tenant storage. */
|
|
17012
|
+
external_exports.object({
|
|
17013
|
+
kind: external_exports.literal("artifact.create"),
|
|
17014
|
+
name: TaskArtifact.shape.name,
|
|
17015
|
+
mediaType: external_exports.string().max(200).regex(/^[\w.+-]+\/[\w.+-]+$/),
|
|
17016
|
+
size: external_exports.number().int().min(1).max(TASK_ARTIFACT_MAX_BYTES),
|
|
17017
|
+
sha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
|
|
17018
|
+
data: external_exports.string().min(1).max(Math.ceil(TASK_ARTIFACT_MAX_BYTES / 3 * 4) + 4)
|
|
17019
|
+
}),
|
|
17020
|
+
/** Truthful per-provider file delivery inventory for the current Task. */
|
|
17021
|
+
external_exports.object({ kind: external_exports.literal("artifact.capabilities") }),
|
|
17022
|
+
/** Read-only, provider-verified labels for the exact approval card. */
|
|
17023
|
+
external_exports.object({
|
|
17024
|
+
kind: external_exports.literal("artifact.delivery.preview"),
|
|
17025
|
+
target: external_exports.enum(["slack", "linear"]),
|
|
17026
|
+
artifactId: TaskArtifactId,
|
|
17027
|
+
destinationId: external_exports.string().min(1).max(200)
|
|
17028
|
+
}),
|
|
17029
|
+
/** Cloud Comms Gateway delivery using the vault-held Slack bot token. */
|
|
17030
|
+
external_exports.object({
|
|
17031
|
+
kind: external_exports.literal("artifact.deliver.slack"),
|
|
17032
|
+
artifactId: TaskArtifactId,
|
|
17033
|
+
to: external_exports.string().min(1).max(200),
|
|
17034
|
+
comment: external_exports.string().max(3e3).optional(),
|
|
17035
|
+
threadTs: external_exports.string().max(64).optional()
|
|
17036
|
+
}),
|
|
17037
|
+
/** Upload to Linear private storage and attach the asset to one issue. */
|
|
17038
|
+
external_exports.object({
|
|
17039
|
+
kind: external_exports.literal("artifact.deliver.linear"),
|
|
17040
|
+
artifactId: TaskArtifactId,
|
|
17041
|
+
issueId: external_exports.string().min(1).max(200),
|
|
17042
|
+
title: external_exports.string().min(1).max(1e3).optional()
|
|
17043
|
+
}),
|
|
16985
17044
|
/** Claim a cloud-side intent before a direct host → Linear mutation. */
|
|
16986
17045
|
ProviderIntent,
|
|
16987
17046
|
/** Record provider-confirmed success after the direct mutation returns. */
|
|
@@ -19894,10 +19953,77 @@ async function discoverTools(params, fetchFn = fetch) {
|
|
|
19894
19953
|
})).filter((t) => t.name.length > 0);
|
|
19895
19954
|
}
|
|
19896
19955
|
|
|
19956
|
+
// src/runners/task-artifacts.ts
|
|
19957
|
+
import { createHash } from "node:crypto";
|
|
19958
|
+
import { lstat, readFile, realpath } from "node:fs/promises";
|
|
19959
|
+
import { basename, extname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
19960
|
+
var MEDIA_TYPES = {
|
|
19961
|
+
".csv": "text/csv",
|
|
19962
|
+
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
19963
|
+
".gif": "image/gif",
|
|
19964
|
+
".html": "text/html",
|
|
19965
|
+
".jpeg": "image/jpeg",
|
|
19966
|
+
".jpg": "image/jpeg",
|
|
19967
|
+
".json": "application/json",
|
|
19968
|
+
".md": "text/markdown",
|
|
19969
|
+
".pdf": "application/pdf",
|
|
19970
|
+
".png": "image/png",
|
|
19971
|
+
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
19972
|
+
".svg": "image/svg+xml",
|
|
19973
|
+
".txt": "text/plain",
|
|
19974
|
+
".webp": "image/webp",
|
|
19975
|
+
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
19976
|
+
".xml": "application/xml",
|
|
19977
|
+
".zip": "application/zip"
|
|
19978
|
+
};
|
|
19979
|
+
function artifactDataContainsSensitiveValue(data, sensitiveValues) {
|
|
19980
|
+
const decoded = Buffer.from(data, "base64").toString("utf8");
|
|
19981
|
+
return sensitiveValues.some((secret) => secret.length > 0 && decoded.includes(secret));
|
|
19982
|
+
}
|
|
19983
|
+
function isWithin(file2, root) {
|
|
19984
|
+
const child = relative(root, file2);
|
|
19985
|
+
return child === "" || !child.startsWith(`..${sep}`) && child !== ".." && !isAbsolute(child);
|
|
19986
|
+
}
|
|
19987
|
+
async function publishTaskFile(input) {
|
|
19988
|
+
const candidate = resolve(input.cwd, input.path);
|
|
19989
|
+
const [file2, roots] = await Promise.all([
|
|
19990
|
+
realpath(candidate),
|
|
19991
|
+
Promise.all(input.allowedRoots.map((root) => realpath(root)))
|
|
19992
|
+
]);
|
|
19993
|
+
if (!roots.some((root) => isWithin(file2, root))) {
|
|
19994
|
+
return { ok: false, error: "the file is outside this task workspace" };
|
|
19995
|
+
}
|
|
19996
|
+
const stat3 = await lstat(file2);
|
|
19997
|
+
if (!stat3.isFile()) return { ok: false, error: "only regular files can be published" };
|
|
19998
|
+
if (stat3.size < 1) return { ok: false, error: "empty files cannot be published" };
|
|
19999
|
+
if (stat3.size > TASK_ARTIFACT_MAX_BYTES) {
|
|
20000
|
+
return {
|
|
20001
|
+
ok: false,
|
|
20002
|
+
error: `the file is larger than Zixt's ${TASK_ARTIFACT_MAX_BYTES / 1024 / 1024} MB limit`
|
|
20003
|
+
};
|
|
20004
|
+
}
|
|
20005
|
+
const name = basename(file2);
|
|
20006
|
+
if (name.length > 200) return { ok: false, error: "the filename is too long" };
|
|
20007
|
+
const inferred = MEDIA_TYPES[extname(name).toLowerCase()] ?? "application/octet-stream";
|
|
20008
|
+
const mediaType = input.mediaType?.trim() || inferred;
|
|
20009
|
+
if (!/^[\w.+-]+\/[\w.+-]+$/.test(mediaType) || mediaType.length > 200) {
|
|
20010
|
+
return { ok: false, error: "media_type must be a valid content type" };
|
|
20011
|
+
}
|
|
20012
|
+
const bytes = await readFile(file2);
|
|
20013
|
+
return input.agentOp({
|
|
20014
|
+
kind: "artifact.create",
|
|
20015
|
+
name,
|
|
20016
|
+
mediaType,
|
|
20017
|
+
size: bytes.length,
|
|
20018
|
+
sha256: createHash("sha256").update(bytes).digest("hex"),
|
|
20019
|
+
data: bytes.toString("base64")
|
|
20020
|
+
});
|
|
20021
|
+
}
|
|
20022
|
+
|
|
19897
20023
|
// src/runners/exec.ts
|
|
19898
20024
|
import { spawn } from "node:child_process";
|
|
19899
|
-
import { realpath, stat } from "node:fs/promises";
|
|
19900
|
-
import { delimiter, extname, isAbsolute, join, resolve } from "node:path";
|
|
20025
|
+
import { realpath as realpath2, stat } from "node:fs/promises";
|
|
20026
|
+
import { delimiter, extname as extname2, isAbsolute as isAbsolute2, join, resolve as resolve2 } from "node:path";
|
|
19901
20027
|
function spawnCli(command, args, options = {}) {
|
|
19902
20028
|
if (process.platform === "win32") {
|
|
19903
20029
|
return spawn([quoteForCmd(command), ...args.map(quoteForCmd)].join(" "), {
|
|
@@ -19909,26 +20035,26 @@ function spawnCli(command, args, options = {}) {
|
|
|
19909
20035
|
}
|
|
19910
20036
|
async function resolveTrustedCliCommand(command, options = {}) {
|
|
19911
20037
|
const platform = options.platform ?? process.platform;
|
|
19912
|
-
const trustedCwd =
|
|
20038
|
+
const trustedCwd = resolve2(options.trustedCwd ?? process.cwd());
|
|
19913
20039
|
const hasSeparator = command.includes("/") || command.includes("\\");
|
|
19914
20040
|
const bases = [];
|
|
19915
|
-
if (
|
|
20041
|
+
if (isAbsolute2(command)) {
|
|
19916
20042
|
bases.push(command);
|
|
19917
20043
|
} else if (hasSeparator) {
|
|
19918
|
-
bases.push(
|
|
20044
|
+
bases.push(resolve2(trustedCwd, command));
|
|
19919
20045
|
} else {
|
|
19920
20046
|
for (const entry of (options.searchPath ?? process.env.PATH ?? "").split(delimiter)) {
|
|
19921
20047
|
if (!entry) continue;
|
|
19922
|
-
bases.push(join(
|
|
20048
|
+
bases.push(join(isAbsolute2(entry) ? entry : resolve2(trustedCwd, entry), command));
|
|
19923
20049
|
}
|
|
19924
20050
|
}
|
|
19925
|
-
const extensions = platform === "win32" &&
|
|
20051
|
+
const extensions = platform === "win32" && extname2(command) === "" ? (options.pathExt ?? process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
19926
20052
|
for (const base of bases) {
|
|
19927
20053
|
for (const extension of extensions) {
|
|
19928
20054
|
try {
|
|
19929
|
-
const candidate = await
|
|
20055
|
+
const candidate = await realpath2(`${base}${extension}`);
|
|
19930
20056
|
const entry = await stat(candidate);
|
|
19931
|
-
if (entry.isFile() &&
|
|
20057
|
+
if (entry.isFile() && isAbsolute2(candidate)) return candidate;
|
|
19932
20058
|
} catch {
|
|
19933
20059
|
}
|
|
19934
20060
|
}
|
|
@@ -19961,7 +20087,7 @@ async function generateTaskTitle(instructions, runner) {
|
|
|
19961
20087
|
instructions.slice(0, INSTRUCTIONS_BUDGET),
|
|
19962
20088
|
"</task_request>"
|
|
19963
20089
|
].join("\n");
|
|
19964
|
-
return new Promise((
|
|
20090
|
+
return new Promise((resolve16) => {
|
|
19965
20091
|
const child = spawnCli(
|
|
19966
20092
|
command,
|
|
19967
20093
|
[
|
|
@@ -19984,7 +20110,7 @@ async function generateTaskTitle(instructions, runner) {
|
|
|
19984
20110
|
if (settled) return;
|
|
19985
20111
|
settled = true;
|
|
19986
20112
|
clearTimeout(timer);
|
|
19987
|
-
|
|
20113
|
+
resolve16(value);
|
|
19988
20114
|
};
|
|
19989
20115
|
const timer = setTimeout(() => {
|
|
19990
20116
|
child.kill();
|
|
@@ -20022,7 +20148,7 @@ function isPlausibleTaskTitle(title) {
|
|
|
20022
20148
|
// src/worker-watchdog.ts
|
|
20023
20149
|
import { randomUUID } from "node:crypto";
|
|
20024
20150
|
import { writeFileSync as writeFileSync2 } from "node:fs";
|
|
20025
|
-
import { isAbsolute as
|
|
20151
|
+
import { isAbsolute as isAbsolute4 } from "node:path";
|
|
20026
20152
|
|
|
20027
20153
|
// src/worker-ownership.ts
|
|
20028
20154
|
import {
|
|
@@ -20035,8 +20161,8 @@ import {
|
|
|
20035
20161
|
rmSync,
|
|
20036
20162
|
writeFileSync
|
|
20037
20163
|
} from "node:fs";
|
|
20038
|
-
import { chmod, lstat, mkdir, open, readFile, readdir, rm, rmdir } from "node:fs/promises";
|
|
20039
|
-
import { basename, dirname, isAbsolute as
|
|
20164
|
+
import { chmod, lstat as lstat2, mkdir, open, readFile as readFile2, readdir, rm, rmdir } from "node:fs/promises";
|
|
20165
|
+
import { basename as basename2, dirname, isAbsolute as isAbsolute3, join as join2, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
|
|
20040
20166
|
var LAUNCHER_OWNERSHIP_DIR_ENV = "ZIXT_HOST_LAUNCHER_OWNERSHIP_DIR";
|
|
20041
20167
|
var WORKER_OWNERSHIP_FILE_ENV = "ZIXT_HOST_WORKER_OWNERSHIP_FILE";
|
|
20042
20168
|
var SUPERVISOR_OWNERSHIP_FILE_ENV = "ZIXT_HOST_SUPERVISOR_OWNERSHIP_FILE";
|
|
@@ -20046,7 +20172,7 @@ var MAX_OWNERSHIP_RECORD_BYTES = 4 * 1024;
|
|
|
20046
20172
|
var MAX_OWNERSHIP_RECORDS = 32;
|
|
20047
20173
|
var MAX_OWNERSHIP_GENERATIONS = 32;
|
|
20048
20174
|
function workerOwnershipFile(directory, nonce) {
|
|
20049
|
-
if (!
|
|
20175
|
+
if (!isAbsolute3(directory) || !SAFE_WORKER_OWNERSHIP_NONCE.test(nonce)) return null;
|
|
20050
20176
|
return join2(directory, `${nonce}.json`);
|
|
20051
20177
|
}
|
|
20052
20178
|
function workerOwnershipArguments(nonce) {
|
|
@@ -20056,7 +20182,7 @@ function consumeWorkerOwnershipArguments(argv, env) {
|
|
|
20056
20182
|
const file2 = env[WORKER_OWNERSHIP_FILE_ENV];
|
|
20057
20183
|
const nonce = env.ZIXT_HOST_WORKER_WATCHDOG_NONCE;
|
|
20058
20184
|
if (typeof file2 !== "string") return { argv: [...argv], requested: false, valid: true };
|
|
20059
|
-
if (typeof nonce !== "string" || !SAFE_WORKER_OWNERSHIP_NONCE.test(nonce) || !
|
|
20185
|
+
if (typeof nonce !== "string" || !SAFE_WORKER_OWNERSHIP_NONCE.test(nonce) || !isAbsolute3(file2) || basename2(file2) !== `${nonce}.json`) {
|
|
20060
20186
|
return { argv: [...argv], requested: true, valid: false };
|
|
20061
20187
|
}
|
|
20062
20188
|
const result = [];
|
|
@@ -20083,7 +20209,7 @@ function syncDirectorySync(path) {
|
|
|
20083
20209
|
}
|
|
20084
20210
|
}
|
|
20085
20211
|
function recordWorkerOwnership(path, nonce, pid = process.pid) {
|
|
20086
|
-
if (!
|
|
20212
|
+
if (!isAbsolute3(path) || !SAFE_WORKER_OWNERSHIP_NONCE.test(nonce) || basename2(path) !== `${nonce}.json` || !Number.isSafeInteger(pid) || pid <= 1) {
|
|
20087
20213
|
return false;
|
|
20088
20214
|
}
|
|
20089
20215
|
const directory = dirname(path);
|
|
@@ -20141,19 +20267,19 @@ async function syncDirectory(path) {
|
|
|
20141
20267
|
}
|
|
20142
20268
|
}
|
|
20143
20269
|
async function ensurePrivateOwnershipRoot(root) {
|
|
20144
|
-
if (!
|
|
20270
|
+
if (!isAbsolute3(root)) throw new Error("launcher ownership root is invalid");
|
|
20145
20271
|
const firstCreated = await mkdir(root, { recursive: true, mode: 448 });
|
|
20146
20272
|
if (firstCreated && process.platform !== "win32") {
|
|
20147
|
-
const first =
|
|
20148
|
-
const target =
|
|
20273
|
+
const first = resolve3(firstCreated);
|
|
20274
|
+
const target = resolve3(root);
|
|
20149
20275
|
await syncDirectory(dirname(first));
|
|
20150
20276
|
let current = first;
|
|
20151
|
-
for (const part of
|
|
20277
|
+
for (const part of relative2(first, target).split(sep2).filter(Boolean)) {
|
|
20152
20278
|
await syncDirectory(current);
|
|
20153
20279
|
current = join2(current, part);
|
|
20154
20280
|
}
|
|
20155
20281
|
}
|
|
20156
|
-
const metadata = await
|
|
20282
|
+
const metadata = await lstat2(root);
|
|
20157
20283
|
if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
|
|
20158
20284
|
throw new Error("launcher ownership root is not a trusted directory");
|
|
20159
20285
|
}
|
|
@@ -20190,7 +20316,7 @@ async function readLauncherOwnershipGenerations(root) {
|
|
|
20190
20316
|
throw new Error("launcher ownership root is malformed");
|
|
20191
20317
|
}
|
|
20192
20318
|
const directory = join2(root, entry.name);
|
|
20193
|
-
const metadata = await
|
|
20319
|
+
const metadata = await lstat2(directory);
|
|
20194
20320
|
if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
|
|
20195
20321
|
throw new Error("launcher ownership generation is not a trusted directory");
|
|
20196
20322
|
}
|
|
@@ -20212,7 +20338,7 @@ function parseRecord(value, path, expectedNonce) {
|
|
|
20212
20338
|
return { schema: 1, nonce: expectedNonce, pid: record2.pid, path };
|
|
20213
20339
|
}
|
|
20214
20340
|
async function readWorkerOwnershipRecords(directory) {
|
|
20215
|
-
if (!
|
|
20341
|
+
if (!isAbsolute3(directory)) throw new Error("worker ownership directory is invalid");
|
|
20216
20342
|
const entries = await readdir(directory, { withFileTypes: true }).catch(
|
|
20217
20343
|
(error52) => {
|
|
20218
20344
|
if (error52.code === "ENOENT") return [];
|
|
@@ -20231,13 +20357,13 @@ async function readWorkerOwnershipRecords(directory) {
|
|
|
20231
20357
|
}
|
|
20232
20358
|
const match = /^([A-Za-z0-9_-]{16,200})\.json$/.exec(entry.name);
|
|
20233
20359
|
if (!entry.isFile() || !match) throw new Error("worker ownership directory is malformed");
|
|
20234
|
-
const metadata = await
|
|
20360
|
+
const metadata = await lstat2(path);
|
|
20235
20361
|
if (!metadata.isFile() || metadata.size > MAX_OWNERSHIP_RECORD_BYTES) {
|
|
20236
20362
|
throw new Error("worker ownership record is invalid");
|
|
20237
20363
|
}
|
|
20238
20364
|
let value;
|
|
20239
20365
|
try {
|
|
20240
|
-
value = JSON.parse(await
|
|
20366
|
+
value = JSON.parse(await readFile2(path, "utf8"));
|
|
20241
20367
|
} catch {
|
|
20242
20368
|
throw new Error("worker ownership record is invalid");
|
|
20243
20369
|
}
|
|
@@ -20246,7 +20372,7 @@ async function readWorkerOwnershipRecords(directory) {
|
|
|
20246
20372
|
return records;
|
|
20247
20373
|
}
|
|
20248
20374
|
async function forgetWorkerOwnership(path) {
|
|
20249
|
-
if (!
|
|
20375
|
+
if (!isAbsolute3(path)) throw new Error("worker ownership path is invalid");
|
|
20250
20376
|
const directory = dirname(path);
|
|
20251
20377
|
await rm(path, { force: true });
|
|
20252
20378
|
await syncDirectory(directory);
|
|
@@ -20306,11 +20432,11 @@ function createWorkerWatchdogSendDrain() {
|
|
|
20306
20432
|
if (completed) return;
|
|
20307
20433
|
completed = true;
|
|
20308
20434
|
pending--;
|
|
20309
|
-
if (pending === 0) drained.splice(0).forEach((
|
|
20435
|
+
if (pending === 0) drained.splice(0).forEach((resolve16) => resolve16());
|
|
20310
20436
|
};
|
|
20311
20437
|
},
|
|
20312
20438
|
drain: async () => {
|
|
20313
|
-
if (pending > 0) await new Promise((
|
|
20439
|
+
if (pending > 0) await new Promise((resolve16) => drained.push(resolve16));
|
|
20314
20440
|
}
|
|
20315
20441
|
};
|
|
20316
20442
|
}
|
|
@@ -20336,7 +20462,7 @@ function startWorkerWatchdogHeartbeat(env = process.env, argv = process.argv.sli
|
|
|
20336
20462
|
}
|
|
20337
20463
|
const heartbeatFile = env[WORKER_WATCHDOG_FILE_ENV];
|
|
20338
20464
|
const ipc = typeof process.send === "function" && process.connected;
|
|
20339
|
-
const file2 = !ipc && typeof heartbeatFile === "string" &&
|
|
20465
|
+
const file2 = !ipc && typeof heartbeatFile === "string" && isAbsolute4(heartbeatFile) ? heartbeatFile : null;
|
|
20340
20466
|
if (!ipc && !file2) {
|
|
20341
20467
|
heartbeatActive = false;
|
|
20342
20468
|
heartbeatUsesIpc = false;
|
|
@@ -20555,7 +20681,7 @@ async function waitForOperationGrantRetry(retryAt, signal) {
|
|
|
20555
20681
|
const deadline = Date.parse(retryAt);
|
|
20556
20682
|
if (!Number.isFinite(deadline) || signal.aborted) return false;
|
|
20557
20683
|
if (deadline <= Date.now()) return true;
|
|
20558
|
-
return await new Promise((
|
|
20684
|
+
return await new Promise((resolve16) => {
|
|
20559
20685
|
let settled = false;
|
|
20560
20686
|
let timer;
|
|
20561
20687
|
const finish = (ready) => {
|
|
@@ -20563,7 +20689,7 @@ async function waitForOperationGrantRetry(retryAt, signal) {
|
|
|
20563
20689
|
settled = true;
|
|
20564
20690
|
if (timer) clearTimeout(timer);
|
|
20565
20691
|
signal.removeEventListener("abort", onAbort);
|
|
20566
|
-
|
|
20692
|
+
resolve16(ready);
|
|
20567
20693
|
};
|
|
20568
20694
|
const onAbort = () => finish(false);
|
|
20569
20695
|
const schedule = () => {
|
|
@@ -20831,22 +20957,22 @@ var HostClient = class _HostClient {
|
|
|
20831
20957
|
const unwindingAssignments = [...this.activeAssignments.values()];
|
|
20832
20958
|
for (const cancel of this.cancels.values()) cancel(stopReason);
|
|
20833
20959
|
for (const entry of this.secretGrants.values()) {
|
|
20834
|
-
for (const
|
|
20960
|
+
for (const resolve16 of entry.resolvers) resolve16({});
|
|
20835
20961
|
entry.resolvers = [];
|
|
20836
20962
|
delete entry.value;
|
|
20837
20963
|
}
|
|
20838
20964
|
for (const entry of this.connectionGrants.values()) {
|
|
20839
|
-
for (const
|
|
20965
|
+
for (const resolve16 of entry.resolvers) resolve16([]);
|
|
20840
20966
|
entry.resolvers = [];
|
|
20841
20967
|
delete entry.value;
|
|
20842
20968
|
}
|
|
20843
20969
|
for (const entry of this.providerGrants.values()) {
|
|
20844
|
-
for (const
|
|
20970
|
+
for (const resolve16 of entry.resolvers) resolve16([]);
|
|
20845
20971
|
entry.resolvers = [];
|
|
20846
20972
|
delete entry.value;
|
|
20847
20973
|
}
|
|
20848
20974
|
for (const waiters of this.approvalWaiters.values()) {
|
|
20849
|
-
for (const
|
|
20975
|
+
for (const resolve16 of waiters.values()) resolve16({ approved: false, guidance: reason });
|
|
20850
20976
|
}
|
|
20851
20977
|
for (const waiters of this.agentOpWaiters.values()) {
|
|
20852
20978
|
for (const waiter of waiters.values()) {
|
|
@@ -20872,9 +20998,9 @@ var HostClient = class _HostClient {
|
|
|
20872
20998
|
let drainTimer;
|
|
20873
20999
|
const drained = await Promise.race([
|
|
20874
21000
|
Promise.allSettled(runs).then(() => true),
|
|
20875
|
-
new Promise((
|
|
21001
|
+
new Promise((resolve16) => {
|
|
20876
21002
|
drainTimer = setTimeout(
|
|
20877
|
-
() =>
|
|
21003
|
+
() => resolve16(false),
|
|
20878
21004
|
this.opts.unwindTimeoutMs ?? _HostClient.DEFAULT_UNWIND_TIMEOUT_MS
|
|
20879
21005
|
);
|
|
20880
21006
|
drainTimer.unref?.();
|
|
@@ -21018,9 +21144,9 @@ var HostClient = class _HostClient {
|
|
|
21018
21144
|
let frameDrainTimer;
|
|
21019
21145
|
const framesDrained = await Promise.race([
|
|
21020
21146
|
frameTail.then(() => true),
|
|
21021
|
-
new Promise((
|
|
21147
|
+
new Promise((resolve16) => {
|
|
21022
21148
|
frameDrainTimer = setTimeout(
|
|
21023
|
-
() =>
|
|
21149
|
+
() => resolve16(false),
|
|
21024
21150
|
this.opts.unwindTimeoutMs ?? _HostClient.DEFAULT_UNWIND_TIMEOUT_MS
|
|
21025
21151
|
);
|
|
21026
21152
|
frameDrainTimer.unref?.();
|
|
@@ -21564,7 +21690,7 @@ var HostClient = class _HostClient {
|
|
|
21564
21690
|
const entry = this.secretGrants.get(key) ?? { resolvers: [] };
|
|
21565
21691
|
entry.value = message.secrets;
|
|
21566
21692
|
entry.expiresAt = expiresAt;
|
|
21567
|
-
for (const
|
|
21693
|
+
for (const resolve16 of entry.resolvers) resolve16(message.secrets);
|
|
21568
21694
|
entry.resolvers = [];
|
|
21569
21695
|
this.secretGrants.set(key, entry);
|
|
21570
21696
|
return;
|
|
@@ -21595,13 +21721,13 @@ var HostClient = class _HostClient {
|
|
|
21595
21721
|
const entry = this.connectionGrants.get(key) ?? { resolvers: [] };
|
|
21596
21722
|
entry.value = message.connections;
|
|
21597
21723
|
entry.expiresAt = expiresAt;
|
|
21598
|
-
for (const
|
|
21724
|
+
for (const resolve16 of entry.resolvers) resolve16(message.connections);
|
|
21599
21725
|
entry.resolvers = [];
|
|
21600
21726
|
this.connectionGrants.set(key, entry);
|
|
21601
21727
|
const providerEntry = this.providerGrants.get(key) ?? { resolvers: [] };
|
|
21602
21728
|
providerEntry.value = providers;
|
|
21603
21729
|
providerEntry.expiresAt = authorityExpiresAt;
|
|
21604
|
-
for (const
|
|
21730
|
+
for (const resolve16 of providerEntry.resolvers) resolve16(providers);
|
|
21605
21731
|
providerEntry.resolvers = [];
|
|
21606
21732
|
this.providerGrants.set(key, providerEntry);
|
|
21607
21733
|
return;
|
|
@@ -21735,8 +21861,8 @@ var HostClient = class _HostClient {
|
|
|
21735
21861
|
return redactCredentialText(text, sensitiveSnapshot()).slice(0, maxLength);
|
|
21736
21862
|
};
|
|
21737
21863
|
let resolveCancelled;
|
|
21738
|
-
const cancelledPromise = new Promise((
|
|
21739
|
-
resolveCancelled =
|
|
21864
|
+
const cancelledPromise = new Promise((resolve16) => {
|
|
21865
|
+
resolveCancelled = resolve16;
|
|
21740
21866
|
});
|
|
21741
21867
|
const endAuthority = (reason = "cloud_cancel") => {
|
|
21742
21868
|
if (stopReason) return;
|
|
@@ -21745,21 +21871,21 @@ var HostClient = class _HostClient {
|
|
|
21745
21871
|
authorityController.abort(reason);
|
|
21746
21872
|
const secretEntry = this.secretGrants.get(cancelKey);
|
|
21747
21873
|
if (secretEntry) {
|
|
21748
|
-
for (const
|
|
21874
|
+
for (const resolve16 of secretEntry.resolvers) resolve16({});
|
|
21749
21875
|
secretEntry.resolvers = [];
|
|
21750
21876
|
delete secretEntry.value;
|
|
21751
21877
|
}
|
|
21752
21878
|
this.secretGrants.delete(cancelKey);
|
|
21753
21879
|
const connectionEntry = this.connectionGrants.get(cancelKey);
|
|
21754
21880
|
if (connectionEntry) {
|
|
21755
|
-
for (const
|
|
21881
|
+
for (const resolve16 of connectionEntry.resolvers) resolve16([]);
|
|
21756
21882
|
connectionEntry.resolvers = [];
|
|
21757
21883
|
delete connectionEntry.value;
|
|
21758
21884
|
}
|
|
21759
21885
|
this.connectionGrants.delete(cancelKey);
|
|
21760
21886
|
const providerEntry = this.providerGrants.get(cancelKey);
|
|
21761
21887
|
if (providerEntry) {
|
|
21762
|
-
for (const
|
|
21888
|
+
for (const resolve16 of providerEntry.resolvers) resolve16([]);
|
|
21763
21889
|
providerEntry.resolvers = [];
|
|
21764
21890
|
delete providerEntry.value;
|
|
21765
21891
|
}
|
|
@@ -21767,8 +21893,8 @@ var HostClient = class _HostClient {
|
|
|
21767
21893
|
this.clearAuthorityExpiry(cancelKey);
|
|
21768
21894
|
const approvalWaiters = this.approvalWaiters.get(cancelKey);
|
|
21769
21895
|
if (approvalWaiters) {
|
|
21770
|
-
for (const
|
|
21771
|
-
|
|
21896
|
+
for (const resolve16 of approvalWaiters.values()) {
|
|
21897
|
+
resolve16({ approved: false, guidance: "task was cancelled" });
|
|
21772
21898
|
}
|
|
21773
21899
|
approvalWaiters.clear();
|
|
21774
21900
|
}
|
|
@@ -21894,9 +22020,9 @@ var HostClient = class _HostClient {
|
|
|
21894
22020
|
return value;
|
|
21895
22021
|
};
|
|
21896
22022
|
if (entry.value) return Promise.resolve(capture(entry.value));
|
|
21897
|
-
return new Promise((
|
|
21898
|
-
entry.resolvers.push((value) =>
|
|
21899
|
-
setTimeout(() =>
|
|
22023
|
+
return new Promise((resolve16) => {
|
|
22024
|
+
entry.resolvers.push((value) => resolve16(capture(value)));
|
|
22025
|
+
setTimeout(() => resolve16(capture(entry.value ?? {})), _HostClient.SECRETS_WAIT_MS);
|
|
21900
22026
|
});
|
|
21901
22027
|
};
|
|
21902
22028
|
const connections = () => {
|
|
@@ -21913,9 +22039,9 @@ var HostClient = class _HostClient {
|
|
|
21913
22039
|
return value;
|
|
21914
22040
|
};
|
|
21915
22041
|
if (entry.value) return Promise.resolve(capture(entry.value));
|
|
21916
|
-
return new Promise((
|
|
21917
|
-
entry.resolvers.push((value) =>
|
|
21918
|
-
setTimeout(() =>
|
|
22042
|
+
return new Promise((resolve16) => {
|
|
22043
|
+
entry.resolvers.push((value) => resolve16(capture(value)));
|
|
22044
|
+
setTimeout(() => resolve16(capture(entry.value ?? [])), _HostClient.SECRETS_WAIT_MS);
|
|
21919
22045
|
});
|
|
21920
22046
|
};
|
|
21921
22047
|
const providers = () => {
|
|
@@ -21932,9 +22058,9 @@ var HostClient = class _HostClient {
|
|
|
21932
22058
|
return value;
|
|
21933
22059
|
};
|
|
21934
22060
|
if (entry.value !== void 0) return Promise.resolve(capture(entry.value));
|
|
21935
|
-
return new Promise((
|
|
21936
|
-
entry.resolvers.push((value) =>
|
|
21937
|
-
setTimeout(() =>
|
|
22061
|
+
return new Promise((resolve16) => {
|
|
22062
|
+
entry.resolvers.push((value) => resolve16(capture(value)));
|
|
22063
|
+
setTimeout(() => resolve16(capture(entry.value ?? [])), _HostClient.SECRETS_WAIT_MS);
|
|
21938
22064
|
});
|
|
21939
22065
|
};
|
|
21940
22066
|
const linear = async () => {
|
|
@@ -21960,13 +22086,13 @@ var HostClient = class _HostClient {
|
|
|
21960
22086
|
payload: safe(payload, 5e4),
|
|
21961
22087
|
...questionChoices ? { questionChoices: [...questionChoices] } : {}
|
|
21962
22088
|
});
|
|
21963
|
-
return new Promise((
|
|
22089
|
+
return new Promise((resolve16) => {
|
|
21964
22090
|
const waiters = this.approvalWaiters.get(cancelKey) ?? /* @__PURE__ */ new Map();
|
|
21965
22091
|
this.approvalWaiters.set(cancelKey, waiters);
|
|
21966
|
-
waiters.set(requestId,
|
|
22092
|
+
waiters.set(requestId, resolve16);
|
|
21967
22093
|
void cancelledPromise.then(() => {
|
|
21968
22094
|
if (waiters.delete(requestId)) {
|
|
21969
|
-
|
|
22095
|
+
resolve16({ approved: false, guidance: "task was cancelled" });
|
|
21970
22096
|
}
|
|
21971
22097
|
});
|
|
21972
22098
|
});
|
|
@@ -21977,6 +22103,14 @@ var HostClient = class _HostClient {
|
|
|
21977
22103
|
const detail = parsed.error.issues.map((i) => `${i.path.join(".") || "op"}: ${i.message}`).join("; ");
|
|
21978
22104
|
return Promise.resolve({ ok: false, error: `invalid arguments: ${detail}` });
|
|
21979
22105
|
}
|
|
22106
|
+
if (parsed.data.kind === "artifact.create") {
|
|
22107
|
+
if (artifactDataContainsSensitiveValue(parsed.data.data, sensitiveSnapshot())) {
|
|
22108
|
+
return Promise.resolve({
|
|
22109
|
+
ok: false,
|
|
22110
|
+
error: "the file contains a task credential and cannot be published"
|
|
22111
|
+
});
|
|
22112
|
+
}
|
|
22113
|
+
}
|
|
21980
22114
|
if (requestId.length < 1 || requestId.length > 200) {
|
|
21981
22115
|
return Promise.resolve({ ok: false, error: "invalid provider settlement request id" });
|
|
21982
22116
|
}
|
|
@@ -22004,11 +22138,11 @@ var HostClient = class _HostClient {
|
|
|
22004
22138
|
if (existing) message = existing;
|
|
22005
22139
|
else terminalMessages.set(requestId, message);
|
|
22006
22140
|
}
|
|
22007
|
-
return new Promise((
|
|
22141
|
+
return new Promise((resolve16) => {
|
|
22008
22142
|
const waiters = this.agentOpWaiters.get(cancelKey) ?? /* @__PURE__ */ new Map();
|
|
22009
22143
|
this.agentOpWaiters.set(cancelKey, waiters);
|
|
22010
22144
|
if (waiters.has(requestId)) {
|
|
22011
|
-
|
|
22145
|
+
resolve16({ ok: false, error: "provider settlement request is already in flight" });
|
|
22012
22146
|
return;
|
|
22013
22147
|
}
|
|
22014
22148
|
const timer = setTimeout(() => {
|
|
@@ -22019,7 +22153,7 @@ var HostClient = class _HostClient {
|
|
|
22019
22153
|
(pending) => !(pending.type === "agent.op" && pending.requestId === requestId)
|
|
22020
22154
|
);
|
|
22021
22155
|
}
|
|
22022
|
-
|
|
22156
|
+
resolve16({
|
|
22023
22157
|
ok: false,
|
|
22024
22158
|
error: terminal ? "The provider call completed, but Zixt could not record its outcome. Do not retry; wait for reconciliation." : "the platform did not answer in time; verify with a list_* tool before retrying a mutating call"
|
|
22025
22159
|
});
|
|
@@ -22027,7 +22161,7 @@ var HostClient = class _HostClient {
|
|
|
22027
22161
|
}, _HostClient.AGENT_OP_TIMEOUT_MS);
|
|
22028
22162
|
timer.unref?.();
|
|
22029
22163
|
waiters.set(requestId, {
|
|
22030
|
-
resolve:
|
|
22164
|
+
resolve: resolve16,
|
|
22031
22165
|
timer,
|
|
22032
22166
|
...terminal ? { terminalMessage: message } : {}
|
|
22033
22167
|
});
|
|
@@ -22073,12 +22207,12 @@ var HostClient = class _HostClient {
|
|
|
22073
22207
|
"No GitHub change was attempted; the authority grant request was invalid."
|
|
22074
22208
|
);
|
|
22075
22209
|
}
|
|
22076
|
-
const outcome = await new Promise((
|
|
22210
|
+
const outcome = await new Promise((resolve16) => {
|
|
22077
22211
|
const timer = setTimeout(() => {
|
|
22078
22212
|
const waiter = this.operationGrantWaiters.get(requestId);
|
|
22079
22213
|
if (!waiter) return;
|
|
22080
22214
|
this.operationGrantWaiters.delete(requestId);
|
|
22081
|
-
|
|
22215
|
+
resolve16({ grant: null, retryable: true, reason: "no_reply_from_zixt" });
|
|
22082
22216
|
}, this.operationGrantTimeoutMs);
|
|
22083
22217
|
timer.unref?.();
|
|
22084
22218
|
this.operationGrantWaiters.set(requestId, {
|
|
@@ -22091,9 +22225,9 @@ var HostClient = class _HostClient {
|
|
|
22091
22225
|
timer,
|
|
22092
22226
|
accept: (grant) => {
|
|
22093
22227
|
addSensitiveValues(providerGrantSensitiveValues(grant));
|
|
22094
|
-
|
|
22228
|
+
resolve16({ grant });
|
|
22095
22229
|
},
|
|
22096
|
-
deny: (retryable, reason, detail, retryAt, retryCode) =>
|
|
22230
|
+
deny: (retryable, reason, detail, retryAt, retryCode) => resolve16({
|
|
22097
22231
|
grant: null,
|
|
22098
22232
|
retryable,
|
|
22099
22233
|
reason,
|
|
@@ -22107,7 +22241,7 @@ var HostClient = class _HostClient {
|
|
|
22107
22241
|
} catch {
|
|
22108
22242
|
clearTimeout(timer);
|
|
22109
22243
|
this.operationGrantWaiters.delete(requestId);
|
|
22110
|
-
|
|
22244
|
+
resolve16({ grant: null, retryable: false, reason: "connection_unavailable" });
|
|
22111
22245
|
}
|
|
22112
22246
|
});
|
|
22113
22247
|
if (outcome.grant) {
|
|
@@ -22163,7 +22297,7 @@ var HostClient = class _HostClient {
|
|
|
22163
22297
|
)
|
|
22164
22298
|
);
|
|
22165
22299
|
}
|
|
22166
|
-
return new Promise((
|
|
22300
|
+
return new Promise((resolve16, reject3) => {
|
|
22167
22301
|
const timer = setTimeout(() => {
|
|
22168
22302
|
if (this.browserCredentialWaiters.delete(requestId)) {
|
|
22169
22303
|
reject3(
|
|
@@ -22182,7 +22316,7 @@ var HostClient = class _HostClient {
|
|
|
22182
22316
|
timer,
|
|
22183
22317
|
accept: (credential) => {
|
|
22184
22318
|
addSensitiveValues(webLoginSensitiveValues(credential));
|
|
22185
|
-
|
|
22319
|
+
resolve16(credential);
|
|
22186
22320
|
},
|
|
22187
22321
|
deny: (reason) => reject3(new Error(reason))
|
|
22188
22322
|
});
|
|
@@ -22470,8 +22604,8 @@ function watchForUpdates(options) {
|
|
|
22470
22604
|
|
|
22471
22605
|
// src/runners/process-tree.ts
|
|
22472
22606
|
import { spawn as spawn2 } from "node:child_process";
|
|
22473
|
-
import { readFile as
|
|
22474
|
-
import { isAbsolute as
|
|
22607
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
22608
|
+
import { isAbsolute as isAbsolute5, join as join4 } from "node:path";
|
|
22475
22609
|
var windowsProcessTreeModule = process.platform === "win32" ? import("@vscode/windows-process-tree").catch(() => null) : null;
|
|
22476
22610
|
var PROCESS_TERM_GRACE_MS = 500;
|
|
22477
22611
|
var PROCESS_EXIT_POLL_MS = 20;
|
|
@@ -22503,14 +22637,14 @@ async function observeWindowsGuardianNonce(pid, nonce) {
|
|
|
22503
22637
|
"Windows runner identity could not be observed"
|
|
22504
22638
|
);
|
|
22505
22639
|
}
|
|
22506
|
-
return new Promise((
|
|
22640
|
+
return new Promise((resolve16, reject3) => {
|
|
22507
22641
|
let done = false;
|
|
22508
22642
|
const finish = (result) => {
|
|
22509
22643
|
if (done) return;
|
|
22510
22644
|
done = true;
|
|
22511
22645
|
clearTimeout(timeout);
|
|
22512
22646
|
if (result instanceof Error) reject3(result);
|
|
22513
|
-
else
|
|
22647
|
+
else resolve16(result);
|
|
22514
22648
|
};
|
|
22515
22649
|
const timeout = setTimeout(
|
|
22516
22650
|
() => finish(
|
|
@@ -22544,7 +22678,7 @@ async function observeWindowsGuardianNonce(pid, nonce) {
|
|
|
22544
22678
|
async function observePosixGuardianNonce(pid, nonce) {
|
|
22545
22679
|
if (process.platform === "linux") {
|
|
22546
22680
|
try {
|
|
22547
|
-
const command = await
|
|
22681
|
+
const command = await readFile3(`/proc/${pid}/cmdline`);
|
|
22548
22682
|
const args = command.toString("utf8").split("\0");
|
|
22549
22683
|
return args.includes(nonce) ? "match" : "mismatch";
|
|
22550
22684
|
} catch (error52) {
|
|
@@ -22555,7 +22689,7 @@ async function observePosixGuardianNonce(pid, nonce) {
|
|
|
22555
22689
|
);
|
|
22556
22690
|
}
|
|
22557
22691
|
}
|
|
22558
|
-
return new Promise((
|
|
22692
|
+
return new Promise((resolve16, reject3) => {
|
|
22559
22693
|
const observer = spawn2("/bin/ps", ["-ww", "-o", "command=", "-p", String(pid)], {
|
|
22560
22694
|
stdio: ["ignore", "pipe", "ignore"]
|
|
22561
22695
|
});
|
|
@@ -22566,7 +22700,7 @@ async function observePosixGuardianNonce(pid, nonce) {
|
|
|
22566
22700
|
done = true;
|
|
22567
22701
|
clearTimeout(timeout);
|
|
22568
22702
|
if (result instanceof Error) reject3(result);
|
|
22569
|
-
else
|
|
22703
|
+
else resolve16(result);
|
|
22570
22704
|
};
|
|
22571
22705
|
const timeout = setTimeout(() => {
|
|
22572
22706
|
observer.kill("SIGKILL");
|
|
@@ -22613,7 +22747,7 @@ async function observeGuardianIdentity(pid, identity) {
|
|
|
22613
22747
|
return process.platform === "win32" ? observeWindowsGuardianNonce(pid, identity.nonce) : observePosixGuardianNonce(pid, identity.nonce);
|
|
22614
22748
|
}
|
|
22615
22749
|
function delay(ms) {
|
|
22616
|
-
return new Promise((
|
|
22750
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
22617
22751
|
}
|
|
22618
22752
|
function posixProcessRecordsFromPs(output) {
|
|
22619
22753
|
const records = [];
|
|
@@ -22646,7 +22780,7 @@ function posixProcessRecordsFromPs(output) {
|
|
|
22646
22780
|
return records;
|
|
22647
22781
|
}
|
|
22648
22782
|
async function snapshotPosixProcesses() {
|
|
22649
|
-
return new Promise((
|
|
22783
|
+
return new Promise((resolve16, reject3) => {
|
|
22650
22784
|
const observer = spawn2("/bin/ps", ["-axo", "uid=,pid=,ppid=,pgid=,stat="], {
|
|
22651
22785
|
stdio: ["ignore", "pipe", "ignore"]
|
|
22652
22786
|
});
|
|
@@ -22659,7 +22793,7 @@ async function snapshotPosixProcesses() {
|
|
|
22659
22793
|
if (error52) reject3(error52);
|
|
22660
22794
|
else {
|
|
22661
22795
|
try {
|
|
22662
|
-
|
|
22796
|
+
resolve16(posixProcessRecordsFromPs(output));
|
|
22663
22797
|
} catch (caught) {
|
|
22664
22798
|
reject3(caught);
|
|
22665
22799
|
}
|
|
@@ -22927,7 +23061,7 @@ async function observePosixGroupIdentity(records, pgid, identity) {
|
|
|
22927
23061
|
}
|
|
22928
23062
|
function defaultTaskkillCommand() {
|
|
22929
23063
|
const windowsRoot = process.env.SystemRoot ?? process.env.WINDIR;
|
|
22930
|
-
if (!windowsRoot || !
|
|
23064
|
+
if (!windowsRoot || !isAbsolute5(windowsRoot)) {
|
|
22931
23065
|
throw new ProcessTreeTerminationError(
|
|
22932
23066
|
"termination_failed",
|
|
22933
23067
|
"Windows runner tree termination authority is unavailable"
|
|
@@ -22994,7 +23128,7 @@ async function snapshotWindowsDescendants(rootPid) {
|
|
|
22994
23128
|
"Windows process-tree observation could not start"
|
|
22995
23129
|
);
|
|
22996
23130
|
}
|
|
22997
|
-
return new Promise((
|
|
23131
|
+
return new Promise((resolve16, reject3) => {
|
|
22998
23132
|
let done = false;
|
|
22999
23133
|
const timeout = setTimeout(() => {
|
|
23000
23134
|
if (done) return;
|
|
@@ -23021,7 +23155,7 @@ async function snapshotWindowsDescendants(rootPid) {
|
|
|
23021
23155
|
return;
|
|
23022
23156
|
}
|
|
23023
23157
|
try {
|
|
23024
|
-
|
|
23158
|
+
resolve16(completeWindowsDescendantPids(rootPid, processes));
|
|
23025
23159
|
} catch (caught) {
|
|
23026
23160
|
reject3(caught);
|
|
23027
23161
|
}
|
|
@@ -23068,7 +23202,7 @@ async function waitForProcessesExit(pids, timeoutMs) {
|
|
|
23068
23202
|
}
|
|
23069
23203
|
async function runTaskkill(pid, command, timeoutMs = TASKKILL_TIMEOUT_MS, independentlyTrackedPids = []) {
|
|
23070
23204
|
const trustedCommand = command ?? defaultTaskkillCommand();
|
|
23071
|
-
const result = await new Promise((
|
|
23205
|
+
const result = await new Promise((resolve16, reject3) => {
|
|
23072
23206
|
const killer = spawn2(trustedCommand, ["/PID", String(pid), "/T", "/F"], {
|
|
23073
23207
|
stdio: ["ignore", "pipe", "pipe"],
|
|
23074
23208
|
windowsHide: true
|
|
@@ -23103,7 +23237,7 @@ async function runTaskkill(pid, command, timeoutMs = TASKKILL_TIMEOUT_MS, indepe
|
|
|
23103
23237
|
done = true;
|
|
23104
23238
|
clearTimeout(timeout);
|
|
23105
23239
|
if (error52) reject3(error52);
|
|
23106
|
-
else
|
|
23240
|
+
else resolve16({ code: killer.exitCode, output, outputTruncated });
|
|
23107
23241
|
};
|
|
23108
23242
|
killer.once(
|
|
23109
23243
|
"error",
|
|
@@ -23315,7 +23449,7 @@ async function terminateProcessTree(child, childExited, options = {}) {
|
|
|
23315
23449
|
}
|
|
23316
23450
|
|
|
23317
23451
|
// src/release-state.ts
|
|
23318
|
-
import { lstat as
|
|
23452
|
+
import { lstat as lstat3, mkdir as mkdir2, open as open2, readFile as readFile4, rename, rm as rm2 } from "node:fs/promises";
|
|
23319
23453
|
import { dirname as dirname2, join as join5 } from "node:path";
|
|
23320
23454
|
var STATE_FILE = "release-state.json";
|
|
23321
23455
|
var STATE_SCHEMA = 1;
|
|
@@ -23355,7 +23489,7 @@ function createReleaseStateStore(root) {
|
|
|
23355
23489
|
const path = releaseStatePath(root);
|
|
23356
23490
|
return {
|
|
23357
23491
|
async load() {
|
|
23358
|
-
const metadata = await
|
|
23492
|
+
const metadata = await lstat3(path).catch((error52) => {
|
|
23359
23493
|
if (error52.code === "ENOENT") return null;
|
|
23360
23494
|
throw error52;
|
|
23361
23495
|
});
|
|
@@ -23365,7 +23499,7 @@ function createReleaseStateStore(root) {
|
|
|
23365
23499
|
}
|
|
23366
23500
|
let value;
|
|
23367
23501
|
try {
|
|
23368
|
-
value = JSON.parse(await
|
|
23502
|
+
value = JSON.parse(await readFile4(path, "utf8"));
|
|
23369
23503
|
} catch {
|
|
23370
23504
|
throw new Error("Host release state cannot be read");
|
|
23371
23505
|
}
|
|
@@ -23390,7 +23524,7 @@ function createReleaseStateStore(root) {
|
|
|
23390
23524
|
}
|
|
23391
23525
|
},
|
|
23392
23526
|
async clear() {
|
|
23393
|
-
const present = await
|
|
23527
|
+
const present = await lstat3(path).then(
|
|
23394
23528
|
() => true,
|
|
23395
23529
|
(error52) => {
|
|
23396
23530
|
if (error52.code === "ENOENT") return false;
|
|
@@ -23407,7 +23541,7 @@ function createReleaseStateStore(root) {
|
|
|
23407
23541
|
// src/windows-job.ts
|
|
23408
23542
|
import { spawn as spawn3 } from "node:child_process";
|
|
23409
23543
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
23410
|
-
import { isAbsolute as
|
|
23544
|
+
import { isAbsolute as isAbsolute6, win32 } from "node:path";
|
|
23411
23545
|
var WINDOWS_CONTAINMENT_GATE_ENV = "ZIXT_WINDOWS_CONTAINMENT_GATE";
|
|
23412
23546
|
var WINDOWS_CONTAINMENT_GATE_PREFIX = "__ZIXT_WINDOWS_CONTAINMENT_READY__";
|
|
23413
23547
|
var WINDOWS_POST_CONTAINMENT_CWD_ENV = "ZIXT_WINDOWS_POST_CONTAINMENT_CWD";
|
|
@@ -23780,12 +23914,12 @@ async function createWindowsJobContainment(pid, options) {
|
|
|
23780
23914
|
stderr = `${stderr}${String(chunk)}`.slice(-HELPER_OUTPUT_LIMIT);
|
|
23781
23915
|
});
|
|
23782
23916
|
const helperEvents = helper;
|
|
23783
|
-
const exited = new Promise((
|
|
23917
|
+
const exited = new Promise((resolve16) => {
|
|
23784
23918
|
let completed = false;
|
|
23785
23919
|
const complete = (code, signal) => {
|
|
23786
23920
|
if (completed) return;
|
|
23787
23921
|
completed = true;
|
|
23788
|
-
|
|
23922
|
+
resolve16({ code, signal });
|
|
23789
23923
|
};
|
|
23790
23924
|
helperEvents.once("error", () => {
|
|
23791
23925
|
failProtocol(new Error("Windows Job Object helper could not start"));
|
|
@@ -23798,7 +23932,7 @@ async function createWindowsJobContainment(pid, options) {
|
|
|
23798
23932
|
});
|
|
23799
23933
|
const nextLine = async (expected) => {
|
|
23800
23934
|
if (protocolFailure) throw protocolFailure;
|
|
23801
|
-
const line = lines.shift() ?? await new Promise((
|
|
23935
|
+
const line = lines.shift() ?? await new Promise((resolve16, reject3) => {
|
|
23802
23936
|
const timer = setTimeout(
|
|
23803
23937
|
() => reject3(timeoutError("Windows Job Object helper did not answer in time")),
|
|
23804
23938
|
timeoutMs
|
|
@@ -23806,7 +23940,7 @@ async function createWindowsJobContainment(pid, options) {
|
|
|
23806
23940
|
timer.unref?.();
|
|
23807
23941
|
lineWaiters.push((value) => {
|
|
23808
23942
|
clearTimeout(timer);
|
|
23809
|
-
|
|
23943
|
+
resolve16(value);
|
|
23810
23944
|
});
|
|
23811
23945
|
});
|
|
23812
23946
|
if (protocolFailure) throw protocolFailure;
|
|
@@ -23819,8 +23953,8 @@ async function createWindowsJobContainment(pid, options) {
|
|
|
23819
23953
|
}
|
|
23820
23954
|
const stopped = await Promise.race([
|
|
23821
23955
|
exited.then(() => true),
|
|
23822
|
-
new Promise((
|
|
23823
|
-
const timer = setTimeout(() =>
|
|
23956
|
+
new Promise((resolve16) => {
|
|
23957
|
+
const timer = setTimeout(() => resolve16(false), timeoutMs);
|
|
23824
23958
|
timer.unref?.();
|
|
23825
23959
|
})
|
|
23826
23960
|
]);
|
|
@@ -23879,7 +24013,7 @@ async function awaitWindowsContainmentGate(env = process.env, input = process.st
|
|
|
23879
24013
|
if (nonce === void 0) return true;
|
|
23880
24014
|
if (!SAFE_NONCE2.test(nonce)) return false;
|
|
23881
24015
|
const expected = windowsContainmentGate(nonce).trimEnd();
|
|
23882
|
-
return new Promise((
|
|
24016
|
+
return new Promise((resolve16) => {
|
|
23883
24017
|
let pending = Buffer.alloc(0);
|
|
23884
24018
|
let settled = false;
|
|
23885
24019
|
const finish = (result) => {
|
|
@@ -23890,7 +24024,7 @@ async function awaitWindowsContainmentGate(env = process.env, input = process.st
|
|
|
23890
24024
|
input.off("end", onEnd);
|
|
23891
24025
|
input.off("error", onEnd);
|
|
23892
24026
|
if (result) input.pause();
|
|
23893
|
-
|
|
24027
|
+
resolve16(result);
|
|
23894
24028
|
};
|
|
23895
24029
|
const onData = (chunk) => {
|
|
23896
24030
|
pending = Buffer.concat([pending, chunk]);
|
|
@@ -23903,7 +24037,7 @@ async function awaitWindowsContainmentGate(env = process.env, input = process.st
|
|
|
23903
24037
|
const postContainmentCwd = env[WINDOWS_POST_CONTAINMENT_CWD_ENV];
|
|
23904
24038
|
delete env[WINDOWS_POST_CONTAINMENT_CWD_ENV];
|
|
23905
24039
|
if (postContainmentCwd !== void 0) {
|
|
23906
|
-
if (!
|
|
24040
|
+
if (!isAbsolute6(postContainmentCwd)) return finish(false);
|
|
23907
24041
|
try {
|
|
23908
24042
|
process.chdir(postContainmentCwd);
|
|
23909
24043
|
} catch {
|
|
@@ -23979,8 +24113,8 @@ function releaseManifestAtPrefix(prefix) {
|
|
|
23979
24113
|
async function validReleaseAtPrefix(prefix, version2) {
|
|
23980
24114
|
try {
|
|
23981
24115
|
const [entry, manifestText] = await Promise.all([
|
|
23982
|
-
|
|
23983
|
-
|
|
24116
|
+
lstat4(releaseEntryAtPrefix(prefix)),
|
|
24117
|
+
readFile5(releaseManifestAtPrefix(prefix), "utf8")
|
|
23984
24118
|
]);
|
|
23985
24119
|
if (!entry.isFile()) return false;
|
|
23986
24120
|
const manifest = JSON.parse(manifestText);
|
|
@@ -23999,14 +24133,14 @@ async function syncDirectory3(path) {
|
|
|
23999
24133
|
}
|
|
24000
24134
|
}
|
|
24001
24135
|
function installedReleaseVersion(entry, root = versionsRoot()) {
|
|
24002
|
-
if (!
|
|
24003
|
-
const relativeEntry =
|
|
24004
|
-
if (!relativeEntry || relativeEntry.startsWith(`..${
|
|
24136
|
+
if (!isAbsolute7(entry)) return null;
|
|
24137
|
+
const relativeEntry = relative3(resolve4(root), resolve4(entry));
|
|
24138
|
+
if (!relativeEntry || relativeEntry.startsWith(`..${sep3}`) || isAbsolute7(relativeEntry)) {
|
|
24005
24139
|
return null;
|
|
24006
24140
|
}
|
|
24007
|
-
const version2 = relativeEntry.split(
|
|
24141
|
+
const version2 = relativeEntry.split(sep3)[0];
|
|
24008
24142
|
if (!version2 || !VERSION_DIR.test(version2)) return null;
|
|
24009
|
-
return
|
|
24143
|
+
return resolve4(entry) === resolve4(installedReleaseEntry(version2, root)) ? version2 : null;
|
|
24010
24144
|
}
|
|
24011
24145
|
function currentReleaseEntry(root = versionsRoot(), platform = process.platform) {
|
|
24012
24146
|
return join6(root, platform === "win32" ? "current-launcher.cjs" : CURRENT_RELEASE_ENTRY);
|
|
@@ -24071,7 +24205,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
|
|
|
24071
24205
|
if (platform === "win32") {
|
|
24072
24206
|
await mkdir3(root, { recursive: true, mode: 448 });
|
|
24073
24207
|
const launcher = currentReleaseEntry(root, platform);
|
|
24074
|
-
const existingLauncher = await
|
|
24208
|
+
const existingLauncher = await lstat4(launcher).catch((error52) => {
|
|
24075
24209
|
if (error52.code === "ENOENT") return null;
|
|
24076
24210
|
throw error52;
|
|
24077
24211
|
});
|
|
@@ -24079,7 +24213,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
|
|
|
24079
24213
|
if (!existingLauncher.isFile()) {
|
|
24080
24214
|
throw new Error("the Zixt Host Windows launcher is not a regular file");
|
|
24081
24215
|
}
|
|
24082
|
-
const contents = await
|
|
24216
|
+
const contents = await readFile5(launcher, "utf8");
|
|
24083
24217
|
if (!contents.startsWith(WINDOWS_LAUNCHER_OWNED_MARKER)) {
|
|
24084
24218
|
throw new Error("the Zixt Host Windows launcher is not owned by Zixt");
|
|
24085
24219
|
}
|
|
@@ -24090,7 +24224,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
|
|
|
24090
24224
|
await replaceDurableFile(launcher, WINDOWS_STABLE_LAUNCHER, sync);
|
|
24091
24225
|
}
|
|
24092
24226
|
const pointerPath = windowsReleasePointer(root);
|
|
24093
|
-
const existingPointer = await
|
|
24227
|
+
const existingPointer = await lstat4(pointerPath).catch((error52) => {
|
|
24094
24228
|
if (error52.code === "ENOENT") return null;
|
|
24095
24229
|
throw error52;
|
|
24096
24230
|
});
|
|
@@ -24100,7 +24234,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
|
|
|
24100
24234
|
}
|
|
24101
24235
|
let prior;
|
|
24102
24236
|
try {
|
|
24103
|
-
prior = JSON.parse(await
|
|
24237
|
+
prior = JSON.parse(await readFile5(pointerPath, "utf8"));
|
|
24104
24238
|
} catch {
|
|
24105
24239
|
throw new Error("the Zixt Host Windows release pointer is invalid");
|
|
24106
24240
|
}
|
|
@@ -24111,7 +24245,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
|
|
|
24111
24245
|
}
|
|
24112
24246
|
await replaceDurableFile(
|
|
24113
24247
|
pointerPath,
|
|
24114
|
-
`${JSON.stringify({ schema: 1, entry:
|
|
24248
|
+
`${JSON.stringify({ schema: 1, entry: resolve4(entry) })}
|
|
24115
24249
|
`,
|
|
24116
24250
|
sync
|
|
24117
24251
|
);
|
|
@@ -24120,7 +24254,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
|
|
|
24120
24254
|
if (platform !== "linux" && platform !== "darwin") return entry;
|
|
24121
24255
|
await mkdir3(root, { recursive: true, mode: 448 });
|
|
24122
24256
|
const current = currentReleaseEntry(root, platform);
|
|
24123
|
-
const existing = await
|
|
24257
|
+
const existing = await lstat4(current).catch((error52) => {
|
|
24124
24258
|
if (error52.code === "ENOENT") return null;
|
|
24125
24259
|
throw error52;
|
|
24126
24260
|
});
|
|
@@ -24142,9 +24276,9 @@ async function activatedReleaseVersion(root = versionsRoot(), platform = process
|
|
|
24142
24276
|
if (platform === "win32") {
|
|
24143
24277
|
try {
|
|
24144
24278
|
const pointerPath = windowsReleasePointer(root);
|
|
24145
|
-
const metadata = await
|
|
24279
|
+
const metadata = await lstat4(pointerPath);
|
|
24146
24280
|
if (!metadata.isFile() || metadata.size > 4 * 1024) return null;
|
|
24147
|
-
const value = JSON.parse(await
|
|
24281
|
+
const value = JSON.parse(await readFile5(pointerPath, "utf8"));
|
|
24148
24282
|
return value.schema === 1 && typeof value.entry === "string" ? installedReleaseVersion(value.entry, root) : null;
|
|
24149
24283
|
} catch {
|
|
24150
24284
|
return null;
|
|
@@ -24154,7 +24288,7 @@ async function activatedReleaseVersion(root = versionsRoot(), platform = process
|
|
|
24154
24288
|
try {
|
|
24155
24289
|
const current = currentReleaseEntry(root, platform);
|
|
24156
24290
|
const target = await readlink(current);
|
|
24157
|
-
return installedReleaseVersion(
|
|
24291
|
+
return installedReleaseVersion(resolve4(dirname3(current), target), root);
|
|
24158
24292
|
} catch {
|
|
24159
24293
|
return null;
|
|
24160
24294
|
}
|
|
@@ -24315,7 +24449,7 @@ async function installRelease(version2, options = {}) {
|
|
|
24315
24449
|
installerContainmentSetupError = error52;
|
|
24316
24450
|
return null;
|
|
24317
24451
|
}) : Promise.resolve(null);
|
|
24318
|
-
const installed = await new Promise((
|
|
24452
|
+
const installed = await new Promise((resolve16, reject3) => {
|
|
24319
24453
|
let finished = false;
|
|
24320
24454
|
let cleanupStarted = false;
|
|
24321
24455
|
let exitObserved = false;
|
|
@@ -24331,7 +24465,7 @@ async function installRelease(version2, options = {}) {
|
|
|
24331
24465
|
finished = true;
|
|
24332
24466
|
clearTimeout(timer);
|
|
24333
24467
|
options.signal?.removeEventListener("abort", requestCleanup);
|
|
24334
|
-
|
|
24468
|
+
resolve16(result);
|
|
24335
24469
|
};
|
|
24336
24470
|
const requestCleanup = () => {
|
|
24337
24471
|
if (cleanupStarted || finished) return;
|
|
@@ -24428,7 +24562,7 @@ async function installRelease(version2, options = {}) {
|
|
|
24428
24562
|
return null;
|
|
24429
24563
|
}
|
|
24430
24564
|
if (await validReleaseAtPrefix(prefix, version2)) return entry;
|
|
24431
|
-
const existing = await
|
|
24565
|
+
const existing = await lstat4(prefix).catch((error52) => {
|
|
24432
24566
|
if (error52.code === "ENOENT") return null;
|
|
24433
24567
|
throw error52;
|
|
24434
24568
|
});
|
|
@@ -24447,7 +24581,7 @@ async function installRelease(version2, options = {}) {
|
|
|
24447
24581
|
}
|
|
24448
24582
|
async function pruneInstalledVersions(keep, root = versionsRoot()) {
|
|
24449
24583
|
const protectedDirs = new Set(keep);
|
|
24450
|
-
const running = process.argv[1] ?
|
|
24584
|
+
const running = process.argv[1] ? resolve4(process.argv[1]) : null;
|
|
24451
24585
|
let entries;
|
|
24452
24586
|
try {
|
|
24453
24587
|
entries = await readdir2(root);
|
|
@@ -24458,7 +24592,7 @@ async function pruneInstalledVersions(keep, root = versionsRoot()) {
|
|
|
24458
24592
|
for (const name of entries) {
|
|
24459
24593
|
if (protectedDirs.has(name) || !VERSION_DIR.test(name)) continue;
|
|
24460
24594
|
const dir = join6(root, name);
|
|
24461
|
-
if (running && running.startsWith(`${dir}${
|
|
24595
|
+
if (running && running.startsWith(`${dir}${sep3}`)) continue;
|
|
24462
24596
|
try {
|
|
24463
24597
|
await rm3(dir, { recursive: true, force: true });
|
|
24464
24598
|
removed.push(name);
|
|
@@ -24619,7 +24753,7 @@ async function runWorkerCompatibilityProxy(env = process.env, argv = process.arg
|
|
|
24619
24753
|
const ownership = consumeWorkerOwnershipArguments(argv, env);
|
|
24620
24754
|
const nonce = env[WORKER_WATCHDOG_NONCE_ENV];
|
|
24621
24755
|
const ownershipFile = env[WORKER_OWNERSHIP_FILE_ENV];
|
|
24622
|
-
if (typeof target !== "string" || !
|
|
24756
|
+
if (typeof target !== "string" || !isAbsolute7(target) || typeof nonce !== "string" || typeof ownershipFile !== "string" || !ownership.requested || !ownership.valid) {
|
|
24623
24757
|
return 1;
|
|
24624
24758
|
}
|
|
24625
24759
|
if (!recordWorkerOwnership(ownershipFile, nonce)) return 1;
|
|
@@ -24644,11 +24778,11 @@ async function runWorkerCompatibilityProxy(env = process.env, argv = process.arg
|
|
|
24644
24778
|
child.stdin?.on("error", () => {
|
|
24645
24779
|
});
|
|
24646
24780
|
process.stdin.pipe(child.stdin);
|
|
24647
|
-
return new Promise((
|
|
24648
|
-
child.once("error", () =>
|
|
24781
|
+
return new Promise((resolve16) => {
|
|
24782
|
+
child.once("error", () => resolve16(1));
|
|
24649
24783
|
child.once("exit", (code) => {
|
|
24650
24784
|
process.stdin.unpipe(child.stdin);
|
|
24651
|
-
|
|
24785
|
+
resolve16(code ?? 1);
|
|
24652
24786
|
});
|
|
24653
24787
|
});
|
|
24654
24788
|
}
|
|
@@ -24686,7 +24820,7 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24686
24820
|
delete env[WORKER_WATCHDOG_FILE_ENV];
|
|
24687
24821
|
delete env[WORKER_OWNERSHIP_FILE_ENV];
|
|
24688
24822
|
delete env[SUPERVISOR_OWNERSHIP_FILE_ENV];
|
|
24689
|
-
const generationNonce = ownershipDirectory ?
|
|
24823
|
+
const generationNonce = ownershipDirectory ? basename3(ownershipDirectory) : null;
|
|
24690
24824
|
if (ownershipDirectory && generationNonce) {
|
|
24691
24825
|
env[LAUNCHER_OWNERSHIP_DIR_ENV] = ownershipDirectory;
|
|
24692
24826
|
env[SUPERVISOR_OWNERSHIP_FILE_ENV] = join6(ownershipDirectory, `${generationNonce}.json`);
|
|
@@ -24726,11 +24860,11 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24726
24860
|
const waitOrStop = async (ms) => {
|
|
24727
24861
|
if (stopping) return false;
|
|
24728
24862
|
if (!customDelay) {
|
|
24729
|
-
await new Promise((
|
|
24863
|
+
await new Promise((resolve16) => {
|
|
24730
24864
|
const finish = () => {
|
|
24731
24865
|
clearTimeout(timer);
|
|
24732
24866
|
stopController.signal.removeEventListener("abort", finish);
|
|
24733
|
-
|
|
24867
|
+
resolve16();
|
|
24734
24868
|
};
|
|
24735
24869
|
const timer = setTimeout(finish, ms);
|
|
24736
24870
|
stopController.signal.addEventListener("abort", finish, { once: true });
|
|
@@ -24738,8 +24872,8 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24738
24872
|
return !stopping;
|
|
24739
24873
|
}
|
|
24740
24874
|
let finishStop;
|
|
24741
|
-
const stopped = new Promise((
|
|
24742
|
-
finishStop = () =>
|
|
24875
|
+
const stopped = new Promise((resolve16) => {
|
|
24876
|
+
finishStop = () => resolve16();
|
|
24743
24877
|
stopController.signal.addEventListener("abort", finishStop, { once: true });
|
|
24744
24878
|
});
|
|
24745
24879
|
await Promise.race([customDelay(ms), stopped]);
|
|
@@ -24764,7 +24898,7 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24764
24898
|
return false;
|
|
24765
24899
|
};
|
|
24766
24900
|
const cleanupOwnershipGeneration = async (directory) => {
|
|
24767
|
-
const generationNonce =
|
|
24901
|
+
const generationNonce = basename3(directory);
|
|
24768
24902
|
const firstRecords = await readWorkerOwnershipRecords(directory);
|
|
24769
24903
|
const supervisorRecord = firstRecords.find((record2) => record2.nonce === generationNonce);
|
|
24770
24904
|
if (firstRecords.length > 0 && !supervisorRecord) {
|
|
@@ -24862,19 +24996,19 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24862
24996
|
child = spawnSupervisor(entry, version2, ownershipDirectory, containmentGateNonce);
|
|
24863
24997
|
const launchedSupervisor = child;
|
|
24864
24998
|
let resolveChildExited;
|
|
24865
|
-
const childExited = new Promise((
|
|
24866
|
-
resolveChildExited =
|
|
24999
|
+
const childExited = new Promise((resolve16) => {
|
|
25000
|
+
resolveChildExited = resolve16;
|
|
24867
25001
|
});
|
|
24868
25002
|
const supervisorContainmentAbort = new AbortController();
|
|
24869
25003
|
void childExited.then(() => supervisorContainmentAbort.abort());
|
|
24870
25004
|
const outcomePromise = new Promise(
|
|
24871
|
-
(
|
|
25005
|
+
(resolve16) => {
|
|
24872
25006
|
let observed = false;
|
|
24873
25007
|
const finish = (code, signal) => {
|
|
24874
25008
|
if (observed) return;
|
|
24875
25009
|
observed = true;
|
|
24876
25010
|
resolveChildExited();
|
|
24877
|
-
|
|
25011
|
+
resolve16({ code, signal });
|
|
24878
25012
|
};
|
|
24879
25013
|
child.once("error", () => finish(1, null));
|
|
24880
25014
|
child.once("exit", finish);
|
|
@@ -24883,7 +25017,7 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24883
25017
|
let supervisorContainment = null;
|
|
24884
25018
|
try {
|
|
24885
25019
|
if (containmentGateNonce) {
|
|
24886
|
-
const supervisorIdentity = ownershipDirectory ?
|
|
25020
|
+
const supervisorIdentity = ownershipDirectory ? basename3(ownershipDirectory) : null;
|
|
24887
25021
|
if (!supervisorIdentity) {
|
|
24888
25022
|
throw new Error("supervisor containment identity is unavailable");
|
|
24889
25023
|
}
|
|
@@ -24895,12 +25029,12 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24895
25029
|
if (!supervisorContainment || !launchedSupervisor.stdin) {
|
|
24896
25030
|
throw new Error("supervisor Job Object gate is unavailable");
|
|
24897
25031
|
}
|
|
24898
|
-
await new Promise((
|
|
25032
|
+
await new Promise((resolve16, reject3) => {
|
|
24899
25033
|
launchedSupervisor.stdin.write(
|
|
24900
25034
|
windowsContainmentGate(containmentGateNonce),
|
|
24901
25035
|
(error52) => {
|
|
24902
25036
|
if (error52) reject3(error52);
|
|
24903
|
-
else
|
|
25037
|
+
else resolve16();
|
|
24904
25038
|
}
|
|
24905
25039
|
);
|
|
24906
25040
|
});
|
|
@@ -24972,9 +25106,9 @@ async function superviseHost(options = {}) {
|
|
|
24972
25106
|
const log2 = options.log ?? ((message) => console.error(message));
|
|
24973
25107
|
const signalWorker = options.signalWorker ?? signalWorkerGroup;
|
|
24974
25108
|
const inheritedOwnershipDirectory = process.env[LAUNCHER_OWNERSHIP_DIR_ENV];
|
|
24975
|
-
const launcherOwnershipDirectory = productionLifecycle && typeof inheritedOwnershipDirectory === "string" &&
|
|
25109
|
+
const launcherOwnershipDirectory = productionLifecycle && typeof inheritedOwnershipDirectory === "string" && isAbsolute7(inheritedOwnershipDirectory) ? inheritedOwnershipDirectory : null;
|
|
24976
25110
|
if (productionLifecycle && isSupervisorRole() && launcherOwnershipDirectory) {
|
|
24977
|
-
const generationNonce =
|
|
25111
|
+
const generationNonce = basename3(launcherOwnershipDirectory);
|
|
24978
25112
|
const expectedOwnershipFile = join6(launcherOwnershipDirectory, `${generationNonce}.json`);
|
|
24979
25113
|
const configuredOwnershipFile = process.env[SUPERVISOR_OWNERSHIP_FILE_ENV];
|
|
24980
25114
|
if (process.argv0 !== generationNonce || configuredOwnershipFile !== expectedOwnershipFile || !recordWorkerOwnership(expectedOwnershipFile, generationNonce)) {
|
|
@@ -25042,18 +25176,18 @@ async function superviseHost(options = {}) {
|
|
|
25042
25176
|
}
|
|
25043
25177
|
}
|
|
25044
25178
|
let announceShutdown;
|
|
25045
|
-
const shutdownAnnounced = new Promise((
|
|
25046
|
-
announceShutdown =
|
|
25179
|
+
const shutdownAnnounced = new Promise((resolve16) => {
|
|
25180
|
+
announceShutdown = resolve16;
|
|
25047
25181
|
});
|
|
25048
25182
|
const attempted = /* @__PURE__ */ new Set();
|
|
25049
25183
|
const waitOrShutdown = async (ms) => {
|
|
25050
25184
|
if (shuttingDown2) return false;
|
|
25051
25185
|
if (!customDelay) {
|
|
25052
|
-
await new Promise((
|
|
25186
|
+
await new Promise((resolve16) => {
|
|
25053
25187
|
const finish = () => {
|
|
25054
25188
|
clearTimeout(timer);
|
|
25055
25189
|
shutdownController.signal.removeEventListener("abort", finish);
|
|
25056
|
-
|
|
25190
|
+
resolve16();
|
|
25057
25191
|
};
|
|
25058
25192
|
const timer = setTimeout(finish, ms);
|
|
25059
25193
|
shutdownController.signal.addEventListener("abort", finish, { once: true });
|
|
@@ -25196,19 +25330,19 @@ async function superviseHost(options = {}) {
|
|
|
25196
25330
|
child = spawnWorker(command, watchdogLaunch, compatibilityOwnership, containmentGateNonce);
|
|
25197
25331
|
const watchedChild = child;
|
|
25198
25332
|
let resolveChildExited;
|
|
25199
|
-
const childExited = new Promise((
|
|
25200
|
-
resolveChildExited =
|
|
25333
|
+
const childExited = new Promise((resolve16) => {
|
|
25334
|
+
resolveChildExited = resolve16;
|
|
25201
25335
|
});
|
|
25202
25336
|
const workerContainmentAbort = new AbortController();
|
|
25203
25337
|
void childExited.then(() => workerContainmentAbort.abort());
|
|
25204
25338
|
const outcomePromise = new Promise(
|
|
25205
|
-
(
|
|
25339
|
+
(resolve16) => {
|
|
25206
25340
|
let observed = false;
|
|
25207
25341
|
const finish = (result) => {
|
|
25208
25342
|
if (observed) return;
|
|
25209
25343
|
observed = true;
|
|
25210
25344
|
resolveChildExited();
|
|
25211
|
-
|
|
25345
|
+
resolve16(result);
|
|
25212
25346
|
};
|
|
25213
25347
|
watchedChild.once("error", () => finish({ code: 1, signal: null }));
|
|
25214
25348
|
watchedChild.once(
|
|
@@ -25230,10 +25364,10 @@ async function superviseHost(options = {}) {
|
|
|
25230
25364
|
if (!workerContainment || !watchedChild.stdin) {
|
|
25231
25365
|
throw new Error("worker Job Object gate is unavailable");
|
|
25232
25366
|
}
|
|
25233
|
-
await new Promise((
|
|
25367
|
+
await new Promise((resolve16, reject3) => {
|
|
25234
25368
|
watchedChild.stdin.write(windowsContainmentGate(containmentGateNonce), (error52) => {
|
|
25235
25369
|
if (error52) reject3(error52);
|
|
25236
|
-
else
|
|
25370
|
+
else resolve16();
|
|
25237
25371
|
});
|
|
25238
25372
|
});
|
|
25239
25373
|
}
|
|
@@ -25686,9 +25820,9 @@ function createDemoBrowserAdapterFactory() {
|
|
|
25686
25820
|
}
|
|
25687
25821
|
|
|
25688
25822
|
// src/browser/manager.ts
|
|
25689
|
-
import { lstat as
|
|
25823
|
+
import { lstat as lstat5, mkdir as mkdir4, open as open4, opendir, readFile as readFile6, rename as rename3, rm as rm4 } from "node:fs/promises";
|
|
25690
25824
|
import { homedir as homedir2 } from "node:os";
|
|
25691
|
-
import { dirname as dirname4, join as join7, resolve as
|
|
25825
|
+
import { dirname as dirname4, join as join7, resolve as resolve5 } from "node:path";
|
|
25692
25826
|
var SAFE_SEGMENT = /^[A-Za-z0-9_-]{1,200}$/;
|
|
25693
25827
|
var FRAME_MIN_INTERVAL_MS = 100;
|
|
25694
25828
|
var IDLE_TIMEOUT_MS = 15 * 6e4;
|
|
@@ -25786,8 +25920,8 @@ var BrowserManager = class {
|
|
|
25786
25920
|
}
|
|
25787
25921
|
}
|
|
25788
25922
|
exactChild(root, child) {
|
|
25789
|
-
const canonicalRoot =
|
|
25790
|
-
const target =
|
|
25923
|
+
const canonicalRoot = resolve5(root);
|
|
25924
|
+
const target = resolve5(canonicalRoot, child);
|
|
25791
25925
|
if (dirname4(target) !== canonicalRoot) {
|
|
25792
25926
|
throw new Error("browser profile path escaped its owned root");
|
|
25793
25927
|
}
|
|
@@ -25795,7 +25929,7 @@ var BrowserManager = class {
|
|
|
25795
25929
|
}
|
|
25796
25930
|
async ensureOwnedDirectory(path) {
|
|
25797
25931
|
await mkdir4(path, { recursive: true, mode: 448 });
|
|
25798
|
-
const stat3 = await
|
|
25932
|
+
const stat3 = await lstat5(path);
|
|
25799
25933
|
if (!stat3.isDirectory() || stat3.isSymbolicLink()) {
|
|
25800
25934
|
throw new Error("browser profile root must be an owned directory, not a symbolic link");
|
|
25801
25935
|
}
|
|
@@ -25830,7 +25964,7 @@ var BrowserManager = class {
|
|
|
25830
25964
|
}
|
|
25831
25965
|
async readProfileState(agentId) {
|
|
25832
25966
|
try {
|
|
25833
|
-
const raw = JSON.parse(await
|
|
25967
|
+
const raw = JSON.parse(await readFile6(this.statePath(agentId), "utf8"));
|
|
25834
25968
|
if (typeof raw !== "object" || raw === null || !Number.isInteger(raw.revision) || Number(raw.revision) < 0 || !["allowed", "purged"].includes(String(raw.state))) {
|
|
25835
25969
|
throw new Error("browser profile lifecycle marker is invalid");
|
|
25836
25970
|
}
|
|
@@ -25929,7 +26063,7 @@ var BrowserManager = class {
|
|
|
25929
26063
|
await this.ensureOwnedDirectory(this.profileRoot);
|
|
25930
26064
|
const profileDir = this.profilePath(agentId);
|
|
25931
26065
|
try {
|
|
25932
|
-
const existingProfile = await
|
|
26066
|
+
const existingProfile = await lstat5(profileDir);
|
|
25933
26067
|
if (existingProfile.isSymbolicLink() || !existingProfile.isDirectory()) {
|
|
25934
26068
|
throw new Error("browser profile path is not an owned directory");
|
|
25935
26069
|
}
|
|
@@ -26696,9 +26830,9 @@ function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
|
|
|
26696
26830
|
// src/runners/cli-runner.ts
|
|
26697
26831
|
import { spawn as spawn8 } from "node:child_process";
|
|
26698
26832
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
26699
|
-
import { lstat as
|
|
26833
|
+
import { lstat as lstat11, mkdir as mkdir10, realpath as realpath8 } from "node:fs/promises";
|
|
26700
26834
|
import { homedir as homedir4 } from "node:os";
|
|
26701
|
-
import { dirname as dirname7, isAbsolute as
|
|
26835
|
+
import { dirname as dirname7, isAbsolute as isAbsolute14, join as join14, resolve as resolve9 } from "node:path";
|
|
26702
26836
|
|
|
26703
26837
|
// src/tool-packs/browser/tool-definitions.ts
|
|
26704
26838
|
function definition(name, description, properties, required2 = []) {
|
|
@@ -26953,7 +27087,7 @@ function createBrowserToolPack(deps) {
|
|
|
26953
27087
|
}
|
|
26954
27088
|
|
|
26955
27089
|
// src/tool-packs/provider-intents.ts
|
|
26956
|
-
import { createHash, randomUUID as randomUUID3 } from "node:crypto";
|
|
27090
|
+
import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
|
|
26957
27091
|
|
|
26958
27092
|
// src/tool-packs/github/rest-transport.ts
|
|
26959
27093
|
var MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
@@ -27199,7 +27333,7 @@ function canonicalJson(value) {
|
|
|
27199
27333
|
return `{${Object.entries(value).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([key, child]) => `${JSON.stringify(key)}:${canonicalJson(child)}`).join(",")}}`;
|
|
27200
27334
|
}
|
|
27201
27335
|
function payloadFingerprint(value) {
|
|
27202
|
-
return
|
|
27336
|
+
return createHash2("sha256").update(canonicalJson(value)).digest("hex");
|
|
27203
27337
|
}
|
|
27204
27338
|
function claimResult(result) {
|
|
27205
27339
|
if (!result.ok || !result.result || typeof result.result !== "object") return null;
|
|
@@ -29391,14 +29525,14 @@ function createGithubPushOrchestrator(input) {
|
|
|
29391
29525
|
// src/tool-packs/github/git-bridge.ts
|
|
29392
29526
|
import { spawn as spawn5 } from "node:child_process";
|
|
29393
29527
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
29394
|
-
import { chmod as chmod3, lstat as
|
|
29395
|
-
import { dirname as dirname5, isAbsolute as
|
|
29528
|
+
import { chmod as chmod3, lstat as lstat7, mkdir as mkdir5, realpath as realpath4, rm as rm5 } from "node:fs/promises";
|
|
29529
|
+
import { dirname as dirname5, isAbsolute as isAbsolute9, join as join9, relative as relative5 } from "node:path";
|
|
29396
29530
|
|
|
29397
29531
|
// src/tool-packs/github/git-credential-broker.ts
|
|
29398
29532
|
import { createServer } from "node:http";
|
|
29399
29533
|
import { randomBytes, randomUUID as randomUUID6, timingSafeEqual } from "node:crypto";
|
|
29400
|
-
import { chmod as chmod2, lstat as
|
|
29401
|
-
import { isAbsolute as
|
|
29534
|
+
import { chmod as chmod2, lstat as lstat6, realpath as realpath3, writeFile } from "node:fs/promises";
|
|
29535
|
+
import { isAbsolute as isAbsolute8, join as join8, relative as relative4 } from "node:path";
|
|
29402
29536
|
var MAX_REQUEST_BYTES = 16 * 1024;
|
|
29403
29537
|
var FILE_MODE = 384;
|
|
29404
29538
|
var HELPER_SOURCE = String.raw`'use strict';
|
|
@@ -29511,8 +29645,8 @@ async function readBoundedBody2(request) {
|
|
|
29511
29645
|
return Buffer.concat(chunks, size);
|
|
29512
29646
|
}
|
|
29513
29647
|
function assertChildPath(parent, child) {
|
|
29514
|
-
const path =
|
|
29515
|
-
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") ||
|
|
29648
|
+
const path = relative4(parent, child);
|
|
29649
|
+
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute8(path)) {
|
|
29516
29650
|
throw new Error("Git credential helper path escaped its private run directory");
|
|
29517
29651
|
}
|
|
29518
29652
|
}
|
|
@@ -29522,11 +29656,11 @@ async function createGithubGitCredentialBroker(input) {
|
|
|
29522
29656
|
throw new Error("GitHub credential authority has expired");
|
|
29523
29657
|
}
|
|
29524
29658
|
assertRepositoryFullName(input.repositoryFullName);
|
|
29525
|
-
const rootEntry = await
|
|
29659
|
+
const rootEntry = await lstat6(input.runArtifactsRoot);
|
|
29526
29660
|
if (!rootEntry.isDirectory() || rootEntry.isSymbolicLink()) {
|
|
29527
29661
|
throw new Error("Git credential broker requires a private real run directory");
|
|
29528
29662
|
}
|
|
29529
|
-
const runRoot = await
|
|
29663
|
+
const runRoot = await realpath3(input.runArtifactsRoot);
|
|
29530
29664
|
const helperPath = join8(runRoot, `git-credential-${randomUUID6()}.cjs`);
|
|
29531
29665
|
assertChildPath(runRoot, helperPath);
|
|
29532
29666
|
await writeFile(helperPath, HELPER_SOURCE, { flag: "wx", mode: FILE_MODE });
|
|
@@ -29626,26 +29760,26 @@ ${stderr}`;
|
|
|
29626
29760
|
return explicitGithubRefusal ? "provider_rejected" : "command_failed";
|
|
29627
29761
|
}
|
|
29628
29762
|
function assertBelow(parent, child, label) {
|
|
29629
|
-
const path =
|
|
29630
|
-
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") ||
|
|
29763
|
+
const path = relative5(parent, child);
|
|
29764
|
+
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute9(path)) {
|
|
29631
29765
|
throw new GithubGitProcessError("invalid_input");
|
|
29632
29766
|
}
|
|
29633
29767
|
void label;
|
|
29634
29768
|
}
|
|
29635
29769
|
async function requireRealDirectory(path, label) {
|
|
29636
|
-
const entry = await
|
|
29770
|
+
const entry = await lstat7(path).catch(() => null);
|
|
29637
29771
|
if (!entry || !entry.isDirectory() || entry.isSymbolicLink()) {
|
|
29638
29772
|
void label;
|
|
29639
29773
|
throw new GithubGitProcessError("invalid_input");
|
|
29640
29774
|
}
|
|
29641
|
-
return
|
|
29775
|
+
return realpath4(path);
|
|
29642
29776
|
}
|
|
29643
29777
|
async function validateTokenlessPaths(command) {
|
|
29644
29778
|
if (command.kind === "clone-from-bridge") {
|
|
29645
|
-
if (!
|
|
29779
|
+
if (!isAbsolute9(command.destination)) throw new GithubGitProcessError("invalid_input");
|
|
29646
29780
|
const parent = await requireRealDirectory(dirname5(command.destination), "clone parent");
|
|
29647
29781
|
assertBelow(parent, command.destination, "clone destination");
|
|
29648
|
-
const destination = await
|
|
29782
|
+
const destination = await lstat7(command.destination).catch((error52) => {
|
|
29649
29783
|
if (error52.code === "ENOENT") return null;
|
|
29650
29784
|
throw error52;
|
|
29651
29785
|
});
|
|
@@ -29653,7 +29787,7 @@ async function validateTokenlessPaths(command) {
|
|
|
29653
29787
|
return;
|
|
29654
29788
|
}
|
|
29655
29789
|
if ("repositoryPath" in command) {
|
|
29656
|
-
if (!
|
|
29790
|
+
if (!isAbsolute9(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
|
|
29657
29791
|
const repositoryPath5 = await requireRealDirectory(command.repositoryPath, "repository path");
|
|
29658
29792
|
if (repositoryPath5 !== command.repositoryPath) throw new GithubGitProcessError("invalid_input");
|
|
29659
29793
|
}
|
|
@@ -29733,7 +29867,7 @@ async function runGit(input, args, env) {
|
|
|
29733
29867
|
if (input.authoritySignal.aborted || input.cancelledNow()) {
|
|
29734
29868
|
throw new GithubGitProcessError("cancelled");
|
|
29735
29869
|
}
|
|
29736
|
-
if (!
|
|
29870
|
+
if (!isAbsolute9(input.executablePath)) throw new GithubGitProcessError("invalid_input");
|
|
29737
29871
|
const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
29738
29872
|
if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > DEFAULT_TIMEOUT_MS2) {
|
|
29739
29873
|
throw new GithubGitProcessError("invalid_input");
|
|
@@ -29753,8 +29887,8 @@ async function runGit(input, args, env) {
|
|
|
29753
29887
|
let settled = false;
|
|
29754
29888
|
let stopping = false;
|
|
29755
29889
|
let resolveExited;
|
|
29756
|
-
const exited = new Promise((
|
|
29757
|
-
resolveExited =
|
|
29890
|
+
const exited = new Promise((resolve16) => {
|
|
29891
|
+
resolveExited = resolve16;
|
|
29758
29892
|
});
|
|
29759
29893
|
child.once("exit", resolveExited);
|
|
29760
29894
|
const cleanup = () => {
|
|
@@ -29839,7 +29973,7 @@ function tokenlessArgs(command) {
|
|
|
29839
29973
|
switch (command.kind) {
|
|
29840
29974
|
case "clone-from-bridge":
|
|
29841
29975
|
assertRef(command.branch);
|
|
29842
|
-
if (!
|
|
29976
|
+
if (!isAbsolute9(command.destination)) throw new GithubGitProcessError("invalid_input");
|
|
29843
29977
|
return [
|
|
29844
29978
|
"clone",
|
|
29845
29979
|
"--no-recurse-submodules",
|
|
@@ -29851,7 +29985,7 @@ function tokenlessArgs(command) {
|
|
|
29851
29985
|
];
|
|
29852
29986
|
case "fetch-from-bridge":
|
|
29853
29987
|
assertFetchRefspecs(command.refspecs);
|
|
29854
|
-
if (!
|
|
29988
|
+
if (!isAbsolute9(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
|
|
29855
29989
|
return [
|
|
29856
29990
|
"-C",
|
|
29857
29991
|
command.repositoryPath,
|
|
@@ -29863,7 +29997,7 @@ function tokenlessArgs(command) {
|
|
|
29863
29997
|
...command.refspecs
|
|
29864
29998
|
];
|
|
29865
29999
|
case "copy-commit-to-bridge":
|
|
29866
|
-
if (!
|
|
30000
|
+
if (!isAbsolute9(command.repositoryPath) || !SHA.test(command.sha)) {
|
|
29867
30001
|
throw new GithubGitProcessError("invalid_input");
|
|
29868
30002
|
}
|
|
29869
30003
|
return [
|
|
@@ -29875,11 +30009,11 @@ function tokenlessArgs(command) {
|
|
|
29875
30009
|
`${command.sha}:refs/zixt/push-source`
|
|
29876
30010
|
];
|
|
29877
30011
|
case "rev-parse":
|
|
29878
|
-
if (!
|
|
30012
|
+
if (!isAbsolute9(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
|
|
29879
30013
|
assertRef(command.ref);
|
|
29880
30014
|
return ["-C", command.repositoryPath, "rev-parse", "--verify", `${command.ref}^{commit}`];
|
|
29881
30015
|
case "remote-configure":
|
|
29882
|
-
if (!
|
|
30016
|
+
if (!isAbsolute9(command.repositoryPath) || !REPOSITORY.test(command.repositoryFullName)) {
|
|
29883
30017
|
throw new GithubGitProcessError("invalid_input");
|
|
29884
30018
|
}
|
|
29885
30019
|
return [
|
|
@@ -29891,7 +30025,7 @@ function tokenlessArgs(command) {
|
|
|
29891
30025
|
`https://github.com/${command.repositoryFullName}.git`
|
|
29892
30026
|
];
|
|
29893
30027
|
case "status":
|
|
29894
|
-
if (!
|
|
30028
|
+
if (!isAbsolute9(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
|
|
29895
30029
|
return [
|
|
29896
30030
|
"-C",
|
|
29897
30031
|
command.repositoryPath,
|
|
@@ -29921,7 +30055,7 @@ function createGithubGitBridge(input) {
|
|
|
29921
30055
|
})();
|
|
29922
30056
|
const requireBridge = async (value) => {
|
|
29923
30057
|
const current = await roots();
|
|
29924
|
-
if (!
|
|
30058
|
+
if (!isAbsolute9(value) || !active.has(value)) throw new GithubGitProcessError("invalid_input");
|
|
29925
30059
|
const real = await requireRealDirectory(value, "git bridge");
|
|
29926
30060
|
assertBelow(current.bridges, real, "git bridge");
|
|
29927
30061
|
if (real !== value) throw new GithubGitProcessError("invalid_input");
|
|
@@ -30401,8 +30535,8 @@ function createRepositoryTools(runtime) {
|
|
|
30401
30535
|
|
|
30402
30536
|
// src/tool-packs/github/workspace.ts
|
|
30403
30537
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
30404
|
-
import { chmod as chmod4, lstat as
|
|
30405
|
-
import { isAbsolute as
|
|
30538
|
+
import { chmod as chmod4, lstat as lstat8, mkdir as mkdir6, readFile as readFile7, realpath as realpath5, rename as rename4, rm as rm6, writeFile as writeFile2 } from "node:fs/promises";
|
|
30539
|
+
import { isAbsolute as isAbsolute10, join as join10, relative as relative6, resolve as resolve6 } from "node:path";
|
|
30406
30540
|
var SAFE_LOCAL_ID = /^[A-Za-z0-9_-]{1,200}$/;
|
|
30407
30541
|
var FULL_NAME2 = /^[A-Za-z0-9_.-]{1,100}\/[A-Za-z0-9_.-]{1,100}$/;
|
|
30408
30542
|
var DIRECTORY_MODE2 = 448;
|
|
@@ -30419,20 +30553,20 @@ function hasControlCharacter2(value) {
|
|
|
30419
30553
|
});
|
|
30420
30554
|
}
|
|
30421
30555
|
function assertBelow2(parent, child, label) {
|
|
30422
|
-
const path =
|
|
30423
|
-
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") ||
|
|
30556
|
+
const path = relative6(parent, child);
|
|
30557
|
+
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute10(path)) {
|
|
30424
30558
|
throw new Error(`${label} escaped the task workspace`);
|
|
30425
30559
|
}
|
|
30426
30560
|
}
|
|
30427
30561
|
function samePath(left, right) {
|
|
30428
|
-
return process.platform === "win32" ?
|
|
30562
|
+
return process.platform === "win32" ? resolve6(left).toLowerCase() === resolve6(right).toLowerCase() : resolve6(left) === resolve6(right);
|
|
30429
30563
|
}
|
|
30430
30564
|
async function requireRealDirectory2(path, label) {
|
|
30431
|
-
const entry = await
|
|
30565
|
+
const entry = await lstat8(path).catch(() => null);
|
|
30432
30566
|
if (!entry || !entry.isDirectory() || entry.isSymbolicLink()) {
|
|
30433
30567
|
throw new Error(`${label} must be a real directory, not a symbolic link or junction`);
|
|
30434
30568
|
}
|
|
30435
|
-
const real = await
|
|
30569
|
+
const real = await realpath5(path);
|
|
30436
30570
|
if (!samePath(real, path)) {
|
|
30437
30571
|
throw new Error(`${label} must not traverse a symbolic link or junction`);
|
|
30438
30572
|
}
|
|
@@ -30465,7 +30599,7 @@ function parseMetadata(text) {
|
|
|
30465
30599
|
}
|
|
30466
30600
|
async function pathExists(path) {
|
|
30467
30601
|
try {
|
|
30468
|
-
await
|
|
30602
|
+
await lstat8(path);
|
|
30469
30603
|
return true;
|
|
30470
30604
|
} catch (error52) {
|
|
30471
30605
|
if (error52.code === "ENOENT") return false;
|
|
@@ -30527,11 +30661,11 @@ async function createGithubWorkspaceService(input) {
|
|
|
30527
30661
|
if (!await pathExists(destination) || !await pathExists(metadataPath)) {
|
|
30528
30662
|
throw new Error("GitHub repository workspace has not been prepared");
|
|
30529
30663
|
}
|
|
30530
|
-
const metadataEntry = await
|
|
30664
|
+
const metadataEntry = await lstat8(metadataPath);
|
|
30531
30665
|
if (!metadataEntry.isFile() || metadataEntry.isSymbolicLink()) {
|
|
30532
30666
|
throw new Error("GitHub workspace metadata is invalid");
|
|
30533
30667
|
}
|
|
30534
|
-
const metadata = parseMetadata(await
|
|
30668
|
+
const metadata = parseMetadata(await readFile7(metadataPath, "utf8"));
|
|
30535
30669
|
if (metadata.repositoryId !== parsed.data || metadata.fullName !== repository.fullName || !samePath(metadata.path, destination)) {
|
|
30536
30670
|
throw new Error("GitHub workspace metadata does not match this repository");
|
|
30537
30671
|
}
|
|
@@ -30629,11 +30763,11 @@ async function createGithubWorkspaceService(input) {
|
|
|
30629
30763
|
expiresAt: authority.expiresAt
|
|
30630
30764
|
});
|
|
30631
30765
|
}
|
|
30632
|
-
const metadataEntry = await
|
|
30766
|
+
const metadataEntry = await lstat8(metadataPath);
|
|
30633
30767
|
if (!metadataEntry.isFile() || metadataEntry.isSymbolicLink()) {
|
|
30634
30768
|
throw new Error("GitHub workspace metadata is invalid");
|
|
30635
30769
|
}
|
|
30636
|
-
const metadata = parseMetadata(await
|
|
30770
|
+
const metadata = parseMetadata(await readFile7(metadataPath, "utf8"));
|
|
30637
30771
|
if (metadata.repositoryId !== repository.repositoryId || metadata.fullName !== repository.fullName || !samePath(metadata.path, destination)) {
|
|
30638
30772
|
throw new Error("GitHub workspace metadata does not match this repository");
|
|
30639
30773
|
}
|
|
@@ -31180,7 +31314,7 @@ function createGithubToolPackFactory(options = {}) {
|
|
|
31180
31314
|
var githubToolPackFactory = createGithubToolPackFactory();
|
|
31181
31315
|
|
|
31182
31316
|
// src/runners/linear-api.ts
|
|
31183
|
-
import { createHash as
|
|
31317
|
+
import { createHash as createHash3, randomUUID as randomUUID9 } from "node:crypto";
|
|
31184
31318
|
var MAX_RESPONSE_BYTES2 = 2 * 1024 * 1024;
|
|
31185
31319
|
var MAX_RESULT_STRING = 1e5;
|
|
31186
31320
|
var MAX_RESULT_ARRAY = 100;
|
|
@@ -31751,7 +31885,7 @@ function operationFor(name, args, appUserId, heldBy) {
|
|
|
31751
31885
|
}
|
|
31752
31886
|
}
|
|
31753
31887
|
function fingerprint(value) {
|
|
31754
|
-
return
|
|
31888
|
+
return createHash3("sha256").update(canonicalLinearMutationPayload(value)).digest("hex");
|
|
31755
31889
|
}
|
|
31756
31890
|
function providerIntentFor(mutation, payloadFingerprint2) {
|
|
31757
31891
|
const common = {
|
|
@@ -32242,8 +32376,8 @@ var linearToolPackFactory = {
|
|
|
32242
32376
|
async create(grant, context) {
|
|
32243
32377
|
let resolveCancelled;
|
|
32244
32378
|
let closed = false;
|
|
32245
|
-
const cancelled = new Promise((
|
|
32246
|
-
resolveCancelled =
|
|
32379
|
+
const cancelled = new Promise((resolve16) => {
|
|
32380
|
+
resolveCancelled = resolve16;
|
|
32247
32381
|
});
|
|
32248
32382
|
const cancel = () => {
|
|
32249
32383
|
if (closed) return;
|
|
@@ -32433,6 +32567,56 @@ var TOOLS = [
|
|
|
32433
32567
|
additionalProperties: false
|
|
32434
32568
|
}
|
|
32435
32569
|
},
|
|
32570
|
+
{
|
|
32571
|
+
name: "publish_file",
|
|
32572
|
+
description: "Snapshot a file you created in this Task workspace into Zixt so the user can download it. This only creates the Zixt file; it does not send it anywhere externally. The result returns an artifact_id.",
|
|
32573
|
+
inputSchema: {
|
|
32574
|
+
type: "object",
|
|
32575
|
+
properties: {
|
|
32576
|
+
path: { type: "string", description: "Workspace-relative or absolute path to the file." },
|
|
32577
|
+
media_type: {
|
|
32578
|
+
type: "string",
|
|
32579
|
+
description: "Optional MIME content type; inferred from the filename when omitted."
|
|
32580
|
+
}
|
|
32581
|
+
},
|
|
32582
|
+
required: ["path"],
|
|
32583
|
+
additionalProperties: false
|
|
32584
|
+
}
|
|
32585
|
+
},
|
|
32586
|
+
{
|
|
32587
|
+
name: "list_file_capabilities",
|
|
32588
|
+
description: "List the file actions currently available for this Task in Zixt, Slack, and Linear, including any missing connection or OAuth scope.",
|
|
32589
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
32590
|
+
},
|
|
32591
|
+
{
|
|
32592
|
+
name: "send_file_to_slack",
|
|
32593
|
+
description: "After publish_file, ask the user for approval and upload that immutable Zixt file to one Slack member or channel. Use ids returned by find_person or list_channels.",
|
|
32594
|
+
inputSchema: {
|
|
32595
|
+
type: "object",
|
|
32596
|
+
properties: {
|
|
32597
|
+
artifact_id: { type: "string" },
|
|
32598
|
+
to: { type: "string", description: "Slack U\u2026, C\u2026, or G\u2026 id." },
|
|
32599
|
+
comment: { type: "string", description: "Optional message accompanying the file." },
|
|
32600
|
+
thread_ts: { type: "string", description: "Optional existing Slack thread timestamp." }
|
|
32601
|
+
},
|
|
32602
|
+
required: ["artifact_id", "to"],
|
|
32603
|
+
additionalProperties: false
|
|
32604
|
+
}
|
|
32605
|
+
},
|
|
32606
|
+
{
|
|
32607
|
+
name: "attach_file_to_linear",
|
|
32608
|
+
description: "After publish_file, ask the user for approval, upload that immutable Zixt file to Linear private storage, and attach its private asset URL to one issue.",
|
|
32609
|
+
inputSchema: {
|
|
32610
|
+
type: "object",
|
|
32611
|
+
properties: {
|
|
32612
|
+
artifact_id: { type: "string" },
|
|
32613
|
+
issue_id: { type: "string", description: "Stable Linear issue id." },
|
|
32614
|
+
title: { type: "string", description: "Optional attachment title." }
|
|
32615
|
+
},
|
|
32616
|
+
required: ["artifact_id", "issue_id"],
|
|
32617
|
+
additionalProperties: false
|
|
32618
|
+
}
|
|
32619
|
+
},
|
|
32436
32620
|
{
|
|
32437
32621
|
name: "schedule_task",
|
|
32438
32622
|
description: 'Create a durable Zixt Automation for YOURSELF: every tick runs the given instructions as a new task. The Automation survives runner sessions and Machine restarts and has no end unless you explicitly provide ends_at because the user requested a limit. Use this tool for every request to schedule recurring Zixt work. If a tick finds nothing to do, end that run with "nothing to do"; never invent work.',
|
|
@@ -32911,6 +33095,23 @@ function opFor(name, args) {
|
|
|
32911
33095
|
};
|
|
32912
33096
|
case "list_channels":
|
|
32913
33097
|
return { kind: "comm.list_channels", provider: "slack" };
|
|
33098
|
+
case "list_file_capabilities":
|
|
33099
|
+
return { kind: "artifact.capabilities" };
|
|
33100
|
+
case "send_file_to_slack":
|
|
33101
|
+
return {
|
|
33102
|
+
kind: "artifact.deliver.slack",
|
|
33103
|
+
artifactId: str("artifact_id"),
|
|
33104
|
+
to: str("to"),
|
|
33105
|
+
...typeof args["comment"] === "string" && args["comment"] ? { comment: args["comment"] } : {},
|
|
33106
|
+
...typeof args["thread_ts"] === "string" && args["thread_ts"] ? { threadTs: args["thread_ts"] } : {}
|
|
33107
|
+
};
|
|
33108
|
+
case "attach_file_to_linear":
|
|
33109
|
+
return {
|
|
33110
|
+
kind: "artifact.deliver.linear",
|
|
33111
|
+
artifactId: str("artifact_id"),
|
|
33112
|
+
issueId: str("issue_id"),
|
|
33113
|
+
...typeof args["title"] === "string" && args["title"] ? { title: args["title"] } : {}
|
|
33114
|
+
};
|
|
32914
33115
|
case "send_message":
|
|
32915
33116
|
return {
|
|
32916
33117
|
kind: "comm.send",
|
|
@@ -32929,7 +33130,7 @@ function createAskUserServer() {
|
|
|
32929
33130
|
let server;
|
|
32930
33131
|
let listening;
|
|
32931
33132
|
function ensureListening() {
|
|
32932
|
-
listening ??= new Promise((
|
|
33133
|
+
listening ??= new Promise((resolve16, reject3) => {
|
|
32933
33134
|
server = createServer2((req, res) => {
|
|
32934
33135
|
res.on("error", () => {
|
|
32935
33136
|
});
|
|
@@ -32945,7 +33146,7 @@ function createAskUserServer() {
|
|
|
32945
33146
|
server.on("error", reject3);
|
|
32946
33147
|
server.listen(0, "127.0.0.1", () => {
|
|
32947
33148
|
const address = server.address();
|
|
32948
|
-
if (address && typeof address === "object")
|
|
33149
|
+
if (address && typeof address === "object") resolve16(address.port);
|
|
32949
33150
|
else reject3(new Error("ask_user server failed to bind"));
|
|
32950
33151
|
});
|
|
32951
33152
|
server.unref();
|
|
@@ -33046,6 +33247,26 @@ function createAskUserServer() {
|
|
|
33046
33247
|
}
|
|
33047
33248
|
return;
|
|
33048
33249
|
}
|
|
33250
|
+
if (name === "publish_file") {
|
|
33251
|
+
if (!handlers.publishFile) {
|
|
33252
|
+
toolText("file publishing is unavailable for this runner", true);
|
|
33253
|
+
return;
|
|
33254
|
+
}
|
|
33255
|
+
try {
|
|
33256
|
+
const path = typeof args["path"] === "string" ? args["path"] : "";
|
|
33257
|
+
if (!path) {
|
|
33258
|
+
toolText("missing required argument `path`", true);
|
|
33259
|
+
return;
|
|
33260
|
+
}
|
|
33261
|
+
const mediaType = typeof args["media_type"] === "string" && args["media_type"] ? args["media_type"] : void 0;
|
|
33262
|
+
const outcome = await handlers.publishFile(path, mediaType);
|
|
33263
|
+
if (outcome.ok) toolText(JSON.stringify(outcome.result ?? { ok: true }, null, 2));
|
|
33264
|
+
else toolText(outcome.error ?? "the file could not be published", true);
|
|
33265
|
+
} catch {
|
|
33266
|
+
toolText("the file could not be read safely", true);
|
|
33267
|
+
}
|
|
33268
|
+
return;
|
|
33269
|
+
}
|
|
33049
33270
|
const toolPack = run3.toolOwners.get(name);
|
|
33050
33271
|
if (toolPack) {
|
|
33051
33272
|
try {
|
|
@@ -33084,7 +33305,40 @@ function createAskUserServer() {
|
|
|
33084
33305
|
return;
|
|
33085
33306
|
}
|
|
33086
33307
|
try {
|
|
33087
|
-
const
|
|
33308
|
+
const op = opFor(name, args);
|
|
33309
|
+
if (op.kind === "artifact.deliver.slack" || op.kind === "artifact.deliver.linear") {
|
|
33310
|
+
if (!handlers.requestApproval) {
|
|
33311
|
+
toolText("file delivery requires user approval, but approval is unavailable", true);
|
|
33312
|
+
return;
|
|
33313
|
+
}
|
|
33314
|
+
const preview = await handlers.agentOp({
|
|
33315
|
+
kind: "artifact.delivery.preview",
|
|
33316
|
+
target: op.kind === "artifact.deliver.slack" ? "slack" : "linear",
|
|
33317
|
+
artifactId: op.artifactId,
|
|
33318
|
+
destinationId: op.kind === "artifact.deliver.slack" ? op.to : op.issueId
|
|
33319
|
+
});
|
|
33320
|
+
if (!preview.ok || !preview.result || typeof preview.result !== "object") {
|
|
33321
|
+
toolText(preview.error ?? "The file or destination is no longer available.", true);
|
|
33322
|
+
return;
|
|
33323
|
+
}
|
|
33324
|
+
const artifactName = preview.result["artifactName"];
|
|
33325
|
+
const destinationLabel = preview.result["destinationLabel"];
|
|
33326
|
+
if (typeof artifactName !== "string" || typeof destinationLabel !== "string") {
|
|
33327
|
+
toolText("Zixt could not verify the file and destination.", true);
|
|
33328
|
+
return;
|
|
33329
|
+
}
|
|
33330
|
+
const destination = op.kind === "artifact.deliver.slack" ? `Slack destination ${destinationLabel}` : `Linear issue ${destinationLabel}`;
|
|
33331
|
+
const decision = await handlers.requestApproval(
|
|
33332
|
+
"content.publish",
|
|
33333
|
+
`Send \u201C${artifactName}\u201D to ${destination}`,
|
|
33334
|
+
JSON.stringify({ file: artifactName, destination })
|
|
33335
|
+
);
|
|
33336
|
+
if (!decision.approved) {
|
|
33337
|
+
toolText(decision.guidance ?? "The user did not approve this file delivery.", true);
|
|
33338
|
+
return;
|
|
33339
|
+
}
|
|
33340
|
+
}
|
|
33341
|
+
const outcome = await handlers.agentOp(op);
|
|
33088
33342
|
if (outcome.ok) toolText(JSON.stringify(outcome.result ?? { ok: true }, null, 2));
|
|
33089
33343
|
else toolText(outcome.error ?? "the operation failed", true);
|
|
33090
33344
|
} catch (err) {
|
|
@@ -33106,6 +33360,8 @@ function createAskUserServer() {
|
|
|
33106
33360
|
const handlers = {
|
|
33107
33361
|
askUser: input.askUser,
|
|
33108
33362
|
agentOp: input.agentOp,
|
|
33363
|
+
..."requestApproval" in input && input.requestApproval ? { requestApproval: input.requestApproval } : {},
|
|
33364
|
+
..."publishFile" in input && input.publishFile ? { publishFile: input.publishFile } : {},
|
|
33109
33365
|
...toolPacks.length > 0 ? { toolPacks } : {}
|
|
33110
33366
|
};
|
|
33111
33367
|
const toolOwners = /* @__PURE__ */ new Map();
|
|
@@ -33137,7 +33393,7 @@ function createAskUserServer() {
|
|
|
33137
33393
|
}
|
|
33138
33394
|
|
|
33139
33395
|
// src/runners/runner-env.ts
|
|
33140
|
-
import { delimiter as delimiter2, isAbsolute as
|
|
33396
|
+
import { delimiter as delimiter2, isAbsolute as isAbsolute11 } from "node:path";
|
|
33141
33397
|
var PROVIDER_AUTHORITY_PREFIXES = ["GH_", "GITHUB_", "GIT_", "SSH_"];
|
|
33142
33398
|
var HOST_AUTHORITY_PREFIXES = [
|
|
33143
33399
|
"ZIXT_",
|
|
@@ -33196,7 +33452,7 @@ function inheritedValue(env, name) {
|
|
|
33196
33452
|
}
|
|
33197
33453
|
function sanitizeInheritedSearchPath(path) {
|
|
33198
33454
|
if (!path) return "";
|
|
33199
|
-
return path.split(delimiter2).filter((entry) => entry !== "" &&
|
|
33455
|
+
return path.split(delimiter2).filter((entry) => entry !== "" && isAbsolute11(entry)).join(delimiter2);
|
|
33200
33456
|
}
|
|
33201
33457
|
function buildRunnerEnv(input) {
|
|
33202
33458
|
const env = {};
|
|
@@ -33277,9 +33533,9 @@ function buildRunnerEnv(input) {
|
|
|
33277
33533
|
// src/runners/github-shell-auth.ts
|
|
33278
33534
|
import { execFile } from "node:child_process";
|
|
33279
33535
|
import { randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
33280
|
-
import { chmod as chmod5, lstat as
|
|
33536
|
+
import { chmod as chmod5, lstat as lstat9, mkdir as mkdir8, realpath as realpath6, writeFile as writeFile4 } from "node:fs/promises";
|
|
33281
33537
|
import { createServer as createServer3 } from "node:http";
|
|
33282
|
-
import { isAbsolute as
|
|
33538
|
+
import { isAbsolute as isAbsolute12, join as join12, relative as relative7 } from "node:path";
|
|
33283
33539
|
var MAX_REQUEST_BYTES2 = 16 * 1024;
|
|
33284
33540
|
var DIRECTORY_MODE3 = 448;
|
|
33285
33541
|
var PRIVATE_FILE_MODE = 384;
|
|
@@ -33485,7 +33741,7 @@ function parseGhInvocation(body) {
|
|
|
33485
33741
|
}
|
|
33486
33742
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
33487
33743
|
const { args, cwd } = value;
|
|
33488
|
-
if (!Array.isArray(args) || args.length > 256 || args.some((argument) => typeof argument !== "string" || argument.length > 4096) || typeof cwd !== "string" || cwd.length === 0 || cwd.length > 4096 || !
|
|
33744
|
+
if (!Array.isArray(args) || args.length > 256 || args.some((argument) => typeof argument !== "string" || argument.length > 4096) || typeof cwd !== "string" || cwd.length === 0 || cwd.length > 4096 || !isAbsolute12(cwd)) {
|
|
33489
33745
|
return null;
|
|
33490
33746
|
}
|
|
33491
33747
|
return { args, cwd };
|
|
@@ -33643,8 +33899,8 @@ function activationCredential(grant, now = Date.now()) {
|
|
|
33643
33899
|
return expiresAt.getTime() <= now ? null : { accessToken: grant.accessToken, expiresAt };
|
|
33644
33900
|
}
|
|
33645
33901
|
function assertChildPath2(parent, child) {
|
|
33646
|
-
const path =
|
|
33647
|
-
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") ||
|
|
33902
|
+
const path = relative7(parent, child);
|
|
33903
|
+
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute12(path)) {
|
|
33648
33904
|
throw new Error("GitHub shell helper path escaped its private run directory");
|
|
33649
33905
|
}
|
|
33650
33906
|
}
|
|
@@ -33662,11 +33918,11 @@ async function writePrivate(path, content, executable = false) {
|
|
|
33662
33918
|
await chmod5(path, executable ? EXECUTABLE_FILE_MODE : PRIVATE_FILE_MODE);
|
|
33663
33919
|
}
|
|
33664
33920
|
async function prepareHelpers(input) {
|
|
33665
|
-
const rootEntry = await
|
|
33921
|
+
const rootEntry = await lstat9(input.runRoot);
|
|
33666
33922
|
if (!rootEntry.isDirectory() || rootEntry.isSymbolicLink()) {
|
|
33667
33923
|
throw new Error("GitHub shell authentication requires a private real run directory");
|
|
33668
33924
|
}
|
|
33669
|
-
const runRoot = await
|
|
33925
|
+
const runRoot = await realpath6(input.runRoot);
|
|
33670
33926
|
const helperPath = join12(runRoot, "github-shell-git-credential.cjs");
|
|
33671
33927
|
assertChildPath2(runRoot, helperPath);
|
|
33672
33928
|
await writePrivate(helperPath, GIT_HELPER_SOURCE);
|
|
@@ -33909,7 +34165,7 @@ password=${credential.accessToken}
|
|
|
33909
34165
|
|
|
33910
34166
|
// src/runners/working-context.ts
|
|
33911
34167
|
import { spawn as spawn6 } from "node:child_process";
|
|
33912
|
-
import { resolve as
|
|
34168
|
+
import { resolve as resolve7 } from "node:path";
|
|
33913
34169
|
var COMMAND_TIMEOUT_MS = 5e3;
|
|
33914
34170
|
var OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
33915
34171
|
var COMMAND_STOP_TIMEOUT_MS = 2e4;
|
|
@@ -34267,8 +34523,8 @@ async function repositoryState(directory, git, env, signal) {
|
|
|
34267
34523
|
const pathLines = paths.trim().split(/\r?\n/);
|
|
34268
34524
|
if (pathLines.length < 3 || !pathLines[0] || !pathLines[1] || !pathLines[2]) return null;
|
|
34269
34525
|
const root = pathLines[0];
|
|
34270
|
-
const gitDirectory =
|
|
34271
|
-
const commonDirectory =
|
|
34526
|
+
const gitDirectory = resolve7(directory, pathLines[1]);
|
|
34527
|
+
const commonDirectory = resolve7(directory, pathLines[2]);
|
|
34272
34528
|
const records = status.split(/\0|\r?\n/).filter(Boolean);
|
|
34273
34529
|
const rawBranch = statusField(records, "branch.head");
|
|
34274
34530
|
if (!rawBranch || rawBranch.length > 512 || !isSafeSingleLineDisplayText(rawBranch)) return null;
|
|
@@ -34415,18 +34671,18 @@ var WorkingContextPullRequestCache = class {
|
|
|
34415
34671
|
import { spawn as spawn7 } from "node:child_process";
|
|
34416
34672
|
import {
|
|
34417
34673
|
chmod as chmod6,
|
|
34418
|
-
lstat as
|
|
34674
|
+
lstat as lstat10,
|
|
34419
34675
|
mkdir as mkdir9,
|
|
34420
34676
|
open as open5,
|
|
34421
34677
|
readdir as readdir3,
|
|
34422
|
-
readFile as
|
|
34423
|
-
realpath as
|
|
34678
|
+
readFile as readFile8,
|
|
34679
|
+
realpath as realpath7,
|
|
34424
34680
|
rename as rename5,
|
|
34425
34681
|
rm as rm7,
|
|
34426
34682
|
writeFile as writeFile5
|
|
34427
34683
|
} from "node:fs/promises";
|
|
34428
34684
|
import { homedir as homedir3 } from "node:os";
|
|
34429
|
-
import { dirname as dirname6, isAbsolute as
|
|
34685
|
+
import { dirname as dirname6, isAbsolute as isAbsolute13, join as join13, relative as relative8, resolve as resolve8, sep as sep4, win32 as win322 } from "node:path";
|
|
34430
34686
|
var SAFE_SEGMENT2 = /^[A-Za-z0-9_-]{1,200}$/;
|
|
34431
34687
|
var DIRECTORY_MODE4 = 448;
|
|
34432
34688
|
var FILE_MODE3 = 384;
|
|
@@ -34654,15 +34910,15 @@ function isMissing(error52) {
|
|
|
34654
34910
|
return error52.code === "ENOENT";
|
|
34655
34911
|
}
|
|
34656
34912
|
function assertBelow3(parent, child) {
|
|
34657
|
-
const path =
|
|
34658
|
-
const escapes = path === "" || path === ".." || path.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ||
|
|
34913
|
+
const path = relative8(parent, child);
|
|
34914
|
+
const escapes = path === "" || path === ".." || path.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute13(path);
|
|
34659
34915
|
if (escapes) throw new Error("run artifact path escapes its private root");
|
|
34660
34916
|
}
|
|
34661
34917
|
async function requireRealDirectory3(path, label) {
|
|
34662
|
-
const entry = await
|
|
34918
|
+
const entry = await lstat10(path);
|
|
34663
34919
|
if (entry.isSymbolicLink()) throw new Error(`${label} must not be a symbolic link`);
|
|
34664
34920
|
if (!entry.isDirectory()) throw new Error(`${label} must be a directory`);
|
|
34665
|
-
return
|
|
34921
|
+
return realpath7(path);
|
|
34666
34922
|
}
|
|
34667
34923
|
function assertWindowsProfileBoundary(profile, target) {
|
|
34668
34924
|
const path = win322.relative(win322.resolve(profile), win322.resolve(target));
|
|
@@ -34676,7 +34932,7 @@ async function rejectWindowsSymlinkAncestors(profile, target) {
|
|
|
34676
34932
|
for (const segment of path.split("\\").filter(Boolean)) {
|
|
34677
34933
|
current = win322.join(current, segment);
|
|
34678
34934
|
try {
|
|
34679
|
-
const entry = await
|
|
34935
|
+
const entry = await lstat10(current);
|
|
34680
34936
|
if (entry.isSymbolicLink()) {
|
|
34681
34937
|
throw new Error("run artifact path must not contain symbolic links or junctions");
|
|
34682
34938
|
}
|
|
@@ -34687,16 +34943,16 @@ async function rejectWindowsSymlinkAncestors(profile, target) {
|
|
|
34687
34943
|
}
|
|
34688
34944
|
}
|
|
34689
34945
|
async function prepareRoot(root) {
|
|
34690
|
-
const absolute =
|
|
34946
|
+
const absolute = resolve8(root);
|
|
34691
34947
|
let realProfile;
|
|
34692
34948
|
if (process.platform === "win32") {
|
|
34693
|
-
const profile =
|
|
34949
|
+
const profile = resolve8(homedir3());
|
|
34694
34950
|
assertWindowsProfileBoundary(profile, absolute);
|
|
34695
34951
|
await rejectWindowsSymlinkAncestors(profile, absolute);
|
|
34696
|
-
realProfile = await
|
|
34952
|
+
realProfile = await realpath7(profile);
|
|
34697
34953
|
}
|
|
34698
34954
|
try {
|
|
34699
|
-
await
|
|
34955
|
+
await lstat10(absolute);
|
|
34700
34956
|
} catch (error52) {
|
|
34701
34957
|
if (!isMissing(error52)) throw error52;
|
|
34702
34958
|
await mkdir9(absolute, { recursive: true, mode: DIRECTORY_MODE4 });
|
|
@@ -34710,7 +34966,7 @@ async function prepareAgentRoot(root, agentId) {
|
|
|
34710
34966
|
const path = join13(root, agentId);
|
|
34711
34967
|
assertBelow3(root, path);
|
|
34712
34968
|
try {
|
|
34713
|
-
await
|
|
34969
|
+
await lstat10(path);
|
|
34714
34970
|
} catch (error52) {
|
|
34715
34971
|
if (!isMissing(error52)) throw error52;
|
|
34716
34972
|
try {
|
|
@@ -34776,7 +35032,7 @@ async function createPrivateDirectory(parent, name) {
|
|
|
34776
35032
|
assertBelow3(parent, path);
|
|
34777
35033
|
await mkdir9(path, { mode: DIRECTORY_MODE4 });
|
|
34778
35034
|
await chmod6(path, DIRECTORY_MODE4);
|
|
34779
|
-
const real = await
|
|
35035
|
+
const real = await realpath7(path);
|
|
34780
35036
|
assertBelow3(parent, real);
|
|
34781
35037
|
return real;
|
|
34782
35038
|
}
|
|
@@ -34810,7 +35066,7 @@ async function createRunArtifacts(input) {
|
|
|
34810
35066
|
try {
|
|
34811
35067
|
await mkdir9(runRoot, { mode: DIRECTORY_MODE4 });
|
|
34812
35068
|
await chmod6(runRoot, DIRECTORY_MODE4);
|
|
34813
|
-
const realRunRoot = await
|
|
35069
|
+
const realRunRoot = await realpath7(runRoot);
|
|
34814
35070
|
assertBelow3(agentRoot, realRunRoot);
|
|
34815
35071
|
const emptyGithubConfigDirectory = await createPrivateDirectory(realRunRoot, "gh-config");
|
|
34816
35072
|
const emptyGitHooksDirectory = await createPrivateDirectory(realRunRoot, "git-hooks");
|
|
@@ -34860,13 +35116,13 @@ async function removePrivateTreeWithRetries(path, removeTree, retryDelayMs) {
|
|
|
34860
35116
|
}
|
|
34861
35117
|
}
|
|
34862
35118
|
async function sweepOrphanedRunArtifacts(root) {
|
|
34863
|
-
const absolute =
|
|
35119
|
+
const absolute = resolve8(root);
|
|
34864
35120
|
let realProfile;
|
|
34865
35121
|
if (process.platform === "win32") {
|
|
34866
|
-
const profile =
|
|
35122
|
+
const profile = resolve8(homedir3());
|
|
34867
35123
|
assertWindowsProfileBoundary(profile, absolute);
|
|
34868
35124
|
await rejectWindowsSymlinkAncestors(profile, absolute);
|
|
34869
|
-
realProfile = await
|
|
35125
|
+
realProfile = await realpath7(profile);
|
|
34870
35126
|
}
|
|
34871
35127
|
let realRoot;
|
|
34872
35128
|
try {
|
|
@@ -34908,11 +35164,11 @@ async function syncRunRegistryDirectory(path) {
|
|
|
34908
35164
|
async function ensureDurableRunRegistryRoot(registryRoot, syncDirectory7) {
|
|
34909
35165
|
const firstCreated = await mkdir9(registryRoot, { recursive: true, mode: DIRECTORY_MODE4 });
|
|
34910
35166
|
if (firstCreated && process.platform !== "win32") {
|
|
34911
|
-
const first =
|
|
34912
|
-
const target =
|
|
35167
|
+
const first = resolve8(firstCreated);
|
|
35168
|
+
const target = resolve8(registryRoot);
|
|
34913
35169
|
await syncDirectory7(dirname6(first));
|
|
34914
35170
|
let current = first;
|
|
34915
|
-
for (const part of
|
|
35171
|
+
for (const part of relative8(first, target).split(sep4).filter(Boolean)) {
|
|
34916
35172
|
await syncDirectory7(current);
|
|
34917
35173
|
current = join13(current, part);
|
|
34918
35174
|
}
|
|
@@ -34999,7 +35255,7 @@ async function readRecordedRunAssignmentEntries(registryRoot = defaultRunRegistr
|
|
|
34999
35255
|
if (!SAFE_SEGMENT2.test(runToken)) continue;
|
|
35000
35256
|
let text;
|
|
35001
35257
|
try {
|
|
35002
|
-
text = await
|
|
35258
|
+
text = await readFile8(join13(registryRoot, entry.name), "utf8");
|
|
35003
35259
|
} catch {
|
|
35004
35260
|
continue;
|
|
35005
35261
|
}
|
|
@@ -35011,7 +35267,7 @@ async function readRecordedRunAssignmentEntries(registryRoot = defaultRunRegistr
|
|
|
35011
35267
|
async function readRecordedRunAssignmentEntriesStrict(registryRoot = defaultRunRegistryRoot()) {
|
|
35012
35268
|
let rootStat;
|
|
35013
35269
|
try {
|
|
35014
|
-
rootStat = await
|
|
35270
|
+
rootStat = await lstat10(registryRoot);
|
|
35015
35271
|
} catch (error52) {
|
|
35016
35272
|
if (isMissing(error52)) return [];
|
|
35017
35273
|
throw new Error("run registry state could not be observed");
|
|
@@ -35035,7 +35291,7 @@ async function readRecordedRunAssignmentEntriesStrict(registryRoot = defaultRunR
|
|
|
35035
35291
|
}
|
|
35036
35292
|
let text;
|
|
35037
35293
|
try {
|
|
35038
|
-
text = await
|
|
35294
|
+
text = await readFile8(join13(registryRoot, entry.name), "utf8");
|
|
35039
35295
|
} catch {
|
|
35040
35296
|
throw new Error("committed run registry witness could not be read");
|
|
35041
35297
|
}
|
|
@@ -35129,11 +35385,11 @@ function truncateThought(text) {
|
|
|
35129
35385
|
}
|
|
35130
35386
|
var MAX_APPROVAL_PAYLOAD = 5e4;
|
|
35131
35387
|
async function requireRealDirectory4(path, label) {
|
|
35132
|
-
const entry = await
|
|
35388
|
+
const entry = await lstat11(path).catch(() => null);
|
|
35133
35389
|
if (!entry) throw new Error(`${label} does not exist`);
|
|
35134
35390
|
if (entry.isSymbolicLink()) throw new Error(`${label} must not be a symbolic link`);
|
|
35135
35391
|
if (!entry.isDirectory()) throw new Error(`${label} must be a directory`);
|
|
35136
|
-
return
|
|
35392
|
+
return realpath8(path);
|
|
35137
35393
|
}
|
|
35138
35394
|
function createCliRunner(adapter, opts = {}) {
|
|
35139
35395
|
const command = opts.command ?? adapter.defaultCommand;
|
|
@@ -35352,6 +35608,21 @@ function createCliRunner(adapter, opts = {}) {
|
|
|
35352
35608
|
pendingAsks--;
|
|
35353
35609
|
}
|
|
35354
35610
|
},
|
|
35611
|
+
requestApproval: async (category, summary, payload) => {
|
|
35612
|
+
pendingAsks++;
|
|
35613
|
+
try {
|
|
35614
|
+
return await task.requestApproval(category, summary, payload);
|
|
35615
|
+
} finally {
|
|
35616
|
+
pendingAsks--;
|
|
35617
|
+
}
|
|
35618
|
+
},
|
|
35619
|
+
publishFile: (path, mediaType) => publishTaskFile({
|
|
35620
|
+
path,
|
|
35621
|
+
...mediaType ? { mediaType } : {},
|
|
35622
|
+
cwd,
|
|
35623
|
+
allowedRoots: [taskRoot, cwd],
|
|
35624
|
+
agentOp: (op) => task.agentOp(op)
|
|
35625
|
+
}),
|
|
35355
35626
|
agentOp: (op) => task.agentOp(op),
|
|
35356
35627
|
// GitHub repository work belongs in the installed `git` and `gh`
|
|
35357
35628
|
// commands backed by GithubShellAuth. Do not advertise the bundled
|
|
@@ -35483,7 +35754,7 @@ ${attachmentSection}` : prompt;
|
|
|
35483
35754
|
let changed = false;
|
|
35484
35755
|
for (const path of paths) {
|
|
35485
35756
|
if (!path || path.length > 4096) continue;
|
|
35486
|
-
const absolutePath =
|
|
35757
|
+
const absolutePath = isAbsolute14(path) ? path : resolve9(cwd, path);
|
|
35487
35758
|
const directory = dirname7(absolutePath);
|
|
35488
35759
|
observedWorkingDirectories.delete(directory);
|
|
35489
35760
|
observedWorkingDirectories.add(directory);
|
|
@@ -35906,7 +36177,7 @@ function runCliProcess(options) {
|
|
|
35906
36177
|
usage: { inputTokens: 0, outputTokens: 0 }
|
|
35907
36178
|
});
|
|
35908
36179
|
}
|
|
35909
|
-
return new Promise((
|
|
36180
|
+
return new Promise((resolve16) => {
|
|
35910
36181
|
const platform = options.platform ?? process.platform;
|
|
35911
36182
|
const containmentGateNonce = options.guardian && platform === "win32" ? randomUUID10() : void 0;
|
|
35912
36183
|
const child = options.guardian ? spawn8(
|
|
@@ -35967,7 +36238,7 @@ function runCliProcess(options) {
|
|
|
35967
36238
|
clearInterval(timer);
|
|
35968
36239
|
unregisterFollowUps?.();
|
|
35969
36240
|
parser.stop?.();
|
|
35970
|
-
|
|
36241
|
+
resolve16(result);
|
|
35971
36242
|
};
|
|
35972
36243
|
const terminate = (result) => {
|
|
35973
36244
|
if (settled || forcedResult) return;
|
|
@@ -36198,7 +36469,7 @@ function runCliProcess(options) {
|
|
|
36198
36469
|
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
36199
36470
|
|
|
36200
36471
|
// src/runners/runtime-observation.ts
|
|
36201
|
-
import { open as open6, readdir as readdir4, realpath as
|
|
36472
|
+
import { open as open6, readdir as readdir4, realpath as realpath9 } from "node:fs/promises";
|
|
36202
36473
|
import { homedir as homedir5 } from "node:os";
|
|
36203
36474
|
import { join as join15 } from "node:path";
|
|
36204
36475
|
var READ_WINDOW_BYTES = 1024 * 1024;
|
|
@@ -36265,7 +36536,7 @@ function claudeTranscriptPath(input) {
|
|
|
36265
36536
|
return join15(configDir, "projects", slug, `${input.sessionId}.jsonl`);
|
|
36266
36537
|
}
|
|
36267
36538
|
async function readClaudeSessionEffort(input) {
|
|
36268
|
-
const resolvedCwd = await
|
|
36539
|
+
const resolvedCwd = await realpath9(input.cwd).catch(() => input.cwd);
|
|
36269
36540
|
const path = claudeTranscriptPath({ env: input.env, resolvedCwd, sessionId: input.sessionId });
|
|
36270
36541
|
const records = parseLines(await readTail(path));
|
|
36271
36542
|
for (let index = records.length - 1; index >= 0; index -= 1) {
|
|
@@ -36312,7 +36583,7 @@ async function readCodexSessionRuntime(input) {
|
|
|
36312
36583
|
}
|
|
36313
36584
|
var codexCatalogCache = /* @__PURE__ */ new Map();
|
|
36314
36585
|
async function loadCodexModelCatalog(command, prefixArgs, env) {
|
|
36315
|
-
const output = await new Promise((
|
|
36586
|
+
const output = await new Promise((resolve16) => {
|
|
36316
36587
|
const child = spawnCli(command, [...prefixArgs, "debug", "models"], {
|
|
36317
36588
|
stdio: ["ignore", "pipe", "ignore"],
|
|
36318
36589
|
windowsHide: true,
|
|
@@ -36327,7 +36598,7 @@ async function loadCodexModelCatalog(command, prefixArgs, env) {
|
|
|
36327
36598
|
if (settled) return;
|
|
36328
36599
|
settled = true;
|
|
36329
36600
|
clearTimeout(timer);
|
|
36330
|
-
|
|
36601
|
+
resolve16(value);
|
|
36331
36602
|
};
|
|
36332
36603
|
const timer = setTimeout(() => {
|
|
36333
36604
|
child.kill();
|
|
@@ -36432,8 +36703,8 @@ function createRuntimeReporter(input, sessionId) {
|
|
|
36432
36703
|
var EFFORT_READ_ATTEMPTS = 5;
|
|
36433
36704
|
var EFFORT_READ_INTERVAL_MS = 3e3;
|
|
36434
36705
|
function delay2(ms) {
|
|
36435
|
-
return new Promise((
|
|
36436
|
-
const timer = setTimeout(
|
|
36706
|
+
return new Promise((resolve16) => {
|
|
36707
|
+
const timer = setTimeout(resolve16, ms);
|
|
36437
36708
|
timer.unref?.();
|
|
36438
36709
|
});
|
|
36439
36710
|
}
|
|
@@ -36510,10 +36781,10 @@ function createClaudeLiveParser(onStream, onSessionModel) {
|
|
|
36510
36781
|
},
|
|
36511
36782
|
async steer(followUp) {
|
|
36512
36783
|
if (!write) return false;
|
|
36513
|
-
return await new Promise((
|
|
36514
|
-
acknowledgements.set(followUp.inputId,
|
|
36784
|
+
return await new Promise((resolve16) => {
|
|
36785
|
+
acknowledgements.set(followUp.inputId, resolve16);
|
|
36515
36786
|
void write(input(followUp.inputId, followUp.text)).catch(() => {
|
|
36516
|
-
if (acknowledgements.delete(followUp.inputId))
|
|
36787
|
+
if (acknowledgements.delete(followUp.inputId)) resolve16(false);
|
|
36517
36788
|
});
|
|
36518
36789
|
});
|
|
36519
36790
|
},
|
|
@@ -36673,7 +36944,7 @@ function improveErrorMessage(error52) {
|
|
|
36673
36944
|
}
|
|
36674
36945
|
|
|
36675
36946
|
// src/runners/codex.ts
|
|
36676
|
-
import { mkdir as mkdir11, readFile as
|
|
36947
|
+
import { mkdir as mkdir11, readFile as readFile9, writeFile as writeFile6 } from "node:fs/promises";
|
|
36677
36948
|
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
36678
36949
|
import { homedir as homedir6 } from "node:os";
|
|
36679
36950
|
import { join as join16 } from "node:path";
|
|
@@ -36688,7 +36959,7 @@ function threadIndexPath(root, agentId, sessionKey) {
|
|
|
36688
36959
|
}
|
|
36689
36960
|
async function readThreadId(path) {
|
|
36690
36961
|
try {
|
|
36691
|
-
const parsed = JSON.parse(await
|
|
36962
|
+
const parsed = JSON.parse(await readFile9(path, "utf8"));
|
|
36692
36963
|
return typeof parsed.threadId === "string" && /^[A-Za-z0-9-]{1,120}$/.test(parsed.threadId) ? parsed.threadId : null;
|
|
36693
36964
|
} catch {
|
|
36694
36965
|
return null;
|
|
@@ -36820,8 +37091,8 @@ ${value}` : value;
|
|
|
36820
37091
|
var RUNTIME_READ_ATTEMPTS = 5;
|
|
36821
37092
|
var RUNTIME_READ_INTERVAL_MS = 2e3;
|
|
36822
37093
|
function delay3(ms) {
|
|
36823
|
-
return new Promise((
|
|
36824
|
-
const timer = setTimeout(
|
|
37094
|
+
return new Promise((resolve16) => {
|
|
37095
|
+
const timer = setTimeout(resolve16, ms);
|
|
36825
37096
|
timer.unref?.();
|
|
36826
37097
|
});
|
|
36827
37098
|
}
|
|
@@ -36860,7 +37131,7 @@ function createCodexAppServerParser(onStream, options) {
|
|
|
36860
37131
|
const turnReadyWaiters = /* @__PURE__ */ new Set();
|
|
36861
37132
|
const usage = () => ({ inputTokens, outputTokens });
|
|
36862
37133
|
const settleTurnReadiness = (ready) => {
|
|
36863
|
-
for (const
|
|
37134
|
+
for (const resolve16 of turnReadyWaiters) resolve16(ready);
|
|
36864
37135
|
turnReadyWaiters.clear();
|
|
36865
37136
|
};
|
|
36866
37137
|
const send = async (message) => {
|
|
@@ -37041,12 +37312,12 @@ function createCodexAppServerParser(onStream, options) {
|
|
|
37041
37312
|
async steer(input) {
|
|
37042
37313
|
if (stopped) return false;
|
|
37043
37314
|
if (!activeTurnId) {
|
|
37044
|
-
const ready = await new Promise((
|
|
37315
|
+
const ready = await new Promise((resolve16) => turnReadyWaiters.add(resolve16));
|
|
37045
37316
|
if (!ready || stopped) return false;
|
|
37046
37317
|
}
|
|
37047
37318
|
if (!threadId || !activeTurnId) return false;
|
|
37048
|
-
return await new Promise((
|
|
37049
|
-
steerWaiters.set(input.inputId,
|
|
37319
|
+
return await new Promise((resolve16) => {
|
|
37320
|
+
steerWaiters.set(input.inputId, resolve16);
|
|
37050
37321
|
void send({
|
|
37051
37322
|
id: `steer:${input.inputId}`,
|
|
37052
37323
|
method: "turn/steer",
|
|
@@ -37057,7 +37328,7 @@ function createCodexAppServerParser(onStream, options) {
|
|
|
37057
37328
|
clientUserMessageId: input.inputId
|
|
37058
37329
|
}
|
|
37059
37330
|
}).catch(() => {
|
|
37060
|
-
if (steerWaiters.delete(input.inputId))
|
|
37331
|
+
if (steerWaiters.delete(input.inputId)) resolve16(false);
|
|
37061
37332
|
});
|
|
37062
37333
|
});
|
|
37063
37334
|
},
|
|
@@ -37065,7 +37336,7 @@ function createCodexAppServerParser(onStream, options) {
|
|
|
37065
37336
|
stopped = true;
|
|
37066
37337
|
write = null;
|
|
37067
37338
|
settleTurnReadiness(false);
|
|
37068
|
-
for (const
|
|
37339
|
+
for (const resolve16 of steerWaiters.values()) resolve16(false);
|
|
37069
37340
|
steerWaiters.clear();
|
|
37070
37341
|
},
|
|
37071
37342
|
push(chunk) {
|
|
@@ -37243,8 +37514,8 @@ function improveCodexErrorMessage(error52) {
|
|
|
37243
37514
|
|
|
37244
37515
|
// src/runners/git-preflight.ts
|
|
37245
37516
|
import { spawn as spawn9 } from "node:child_process";
|
|
37246
|
-
import { realpath as
|
|
37247
|
-
import { isAbsolute as
|
|
37517
|
+
import { realpath as realpath10 } from "node:fs/promises";
|
|
37518
|
+
import { isAbsolute as isAbsolute15, resolve as resolve10 } from "node:path";
|
|
37248
37519
|
var OUTPUT_LIMIT = 8192;
|
|
37249
37520
|
var DEFAULT_TIMEOUT_MS4 = 1e4;
|
|
37250
37521
|
var VERSION_PATTERN = /^git version [^\r\n]{1,108}$/;
|
|
@@ -37260,10 +37531,10 @@ function unavailable(error52, checkedAt, executablePath = null) {
|
|
|
37260
37531
|
async function preflightGit(options = {}) {
|
|
37261
37532
|
const checkedAt = (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString();
|
|
37262
37533
|
const configured = options.command;
|
|
37263
|
-
if (configured !== void 0 && !
|
|
37534
|
+
if (configured !== void 0 && !isAbsolute15(configured)) {
|
|
37264
37535
|
return unavailable("configured git command must be an absolute file", checkedAt);
|
|
37265
37536
|
}
|
|
37266
|
-
const trustedCwd = await
|
|
37537
|
+
const trustedCwd = await realpath10(resolve10(options.trustedCwd ?? process.cwd())).catch(() => null);
|
|
37267
37538
|
if (!trustedCwd)
|
|
37268
37539
|
return unavailable("Host-owned git preflight directory is unavailable", checkedAt);
|
|
37269
37540
|
const executablePath = await resolveTrustedCliCommand(configured ?? "git", {
|
|
@@ -37485,7 +37756,7 @@ function parseAuth(result) {
|
|
|
37485
37756
|
return "unknown";
|
|
37486
37757
|
}
|
|
37487
37758
|
function run2(command, args) {
|
|
37488
|
-
return new Promise((
|
|
37759
|
+
return new Promise((resolve16) => {
|
|
37489
37760
|
const child = spawnCli(command, args, {
|
|
37490
37761
|
stdio: ["ignore", "pipe", "pipe"],
|
|
37491
37762
|
windowsHide: true
|
|
@@ -37501,7 +37772,7 @@ function run2(command, args) {
|
|
|
37501
37772
|
if (settled) return;
|
|
37502
37773
|
settled = true;
|
|
37503
37774
|
clearTimeout(timeout);
|
|
37504
|
-
|
|
37775
|
+
resolve16(result);
|
|
37505
37776
|
};
|
|
37506
37777
|
const timeout = setTimeout(() => {
|
|
37507
37778
|
child.kill();
|
|
@@ -37517,7 +37788,7 @@ import { spawn as spawn10 } from "node:child_process";
|
|
|
37517
37788
|
import { constants as constants2 } from "node:fs";
|
|
37518
37789
|
import { access as access4, chmod as chmod7, mkdir as mkdir12, open as open7, rename as rename6, rm as rm8 } from "node:fs/promises";
|
|
37519
37790
|
import { homedir as homedir7, userInfo } from "node:os";
|
|
37520
|
-
import { basename as
|
|
37791
|
+
import { basename as basename4, dirname as dirname8, join as join17, relative as relative9, resolve as resolve11, sep as sep5 } from "node:path";
|
|
37521
37792
|
var SERVICE_NAME = "zixt-host.service";
|
|
37522
37793
|
var SYSTEM_SERVICE_COMMAND_TIMEOUT_MS = 7e4;
|
|
37523
37794
|
var SERVICE_STABILITY_DELAY_MS = 2e3;
|
|
@@ -37545,7 +37816,7 @@ function boundedAppend(current, chunk) {
|
|
|
37545
37816
|
}
|
|
37546
37817
|
async function defaultRunCommand(command, args) {
|
|
37547
37818
|
const commandEnvironment3 = systemServiceCommandEnvironment();
|
|
37548
|
-
return new Promise((
|
|
37819
|
+
return new Promise((resolve16) => {
|
|
37549
37820
|
const child = spawn10(command, [...args], {
|
|
37550
37821
|
stdio: ["ignore", "pipe", "pipe"],
|
|
37551
37822
|
env: commandEnvironment3,
|
|
@@ -37559,7 +37830,7 @@ async function defaultRunCommand(command, args) {
|
|
|
37559
37830
|
if (settled) return;
|
|
37560
37831
|
settled = true;
|
|
37561
37832
|
if (timer) clearTimeout(timer);
|
|
37562
|
-
|
|
37833
|
+
resolve16(result);
|
|
37563
37834
|
};
|
|
37564
37835
|
child.stdout?.on("data", (chunk) => {
|
|
37565
37836
|
stdout = boundedAppend(stdout, chunk);
|
|
@@ -37620,12 +37891,12 @@ async function defaultSyncDirectory(path) {
|
|
|
37620
37891
|
async function ensureDirectory(path, mode, syncDirectory7) {
|
|
37621
37892
|
const firstCreated = await mkdir12(path, { recursive: true, mode });
|
|
37622
37893
|
if (!firstCreated) return;
|
|
37623
|
-
const first =
|
|
37624
|
-
const target =
|
|
37894
|
+
const first = resolve11(firstCreated);
|
|
37895
|
+
const target = resolve11(path);
|
|
37625
37896
|
await syncDirectory7(dirname8(first));
|
|
37626
37897
|
let current = first;
|
|
37627
|
-
const descendants =
|
|
37628
|
-
for (const part of descendants ? descendants.split(
|
|
37898
|
+
const descendants = relative9(first, target);
|
|
37899
|
+
for (const part of descendants ? descendants.split(sep5) : []) {
|
|
37629
37900
|
await syncDirectory7(current);
|
|
37630
37901
|
current = join17(current, part);
|
|
37631
37902
|
}
|
|
@@ -37633,7 +37904,7 @@ async function ensureDirectory(path, mode, syncDirectory7) {
|
|
|
37633
37904
|
async function replacePrivateFile(path, contents, mode, syncDirectory7) {
|
|
37634
37905
|
const parent = dirname8(path);
|
|
37635
37906
|
await ensureDirectory(parent, 448, syncDirectory7);
|
|
37636
|
-
const temporary = join17(parent, `.${
|
|
37907
|
+
const temporary = join17(parent, `.${basename4(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
|
|
37637
37908
|
const handle = await open7(temporary, "wx", mode);
|
|
37638
37909
|
try {
|
|
37639
37910
|
await handle.writeFile(contents, "utf8");
|
|
@@ -37695,7 +37966,7 @@ async function installLinuxService(options) {
|
|
|
37695
37966
|
const resolveCommand = options.resolveCommand ?? defaultResolveCommand;
|
|
37696
37967
|
const run3 = options.runCommand ?? defaultRunCommand;
|
|
37697
37968
|
const syncDirectory7 = options.syncDirectory ?? defaultSyncDirectory;
|
|
37698
|
-
const stabilityDelay = options.delay ?? ((ms) => new Promise((
|
|
37969
|
+
const stabilityDelay = options.delay ?? ((ms) => new Promise((resolve16) => setTimeout(resolve16, ms)));
|
|
37699
37970
|
const [systemctl, loginctl] = await Promise.all([
|
|
37700
37971
|
resolveCommand("systemctl"),
|
|
37701
37972
|
resolveCommand("loginctl")
|
|
@@ -37810,7 +38081,7 @@ import { spawn as spawn11 } from "node:child_process";
|
|
|
37810
38081
|
import { constants as constants3 } from "node:fs";
|
|
37811
38082
|
import { access as access5, chmod as chmod8, mkdir as mkdir13, open as open8, rename as rename7, rm as rm9 } from "node:fs/promises";
|
|
37812
38083
|
import { homedir as homedir8, userInfo as userInfo2 } from "node:os";
|
|
37813
|
-
import { basename as
|
|
38084
|
+
import { basename as basename5, dirname as dirname9, join as join18, relative as relative10, resolve as resolve12, sep as sep6 } from "node:path";
|
|
37814
38085
|
var LAUNCH_AGENT_LABEL = "ai.zixt.host";
|
|
37815
38086
|
var SERVICE_STABILITY_DELAY_MS2 = 2e3;
|
|
37816
38087
|
var COMMAND_TIMEOUT_MS2 = 7e4;
|
|
@@ -37836,11 +38107,11 @@ async function syncDirectory4(path) {
|
|
|
37836
38107
|
async function ensureDirectory2(path, sync) {
|
|
37837
38108
|
const firstCreated = await mkdir13(path, { recursive: true, mode: 448 });
|
|
37838
38109
|
if (!firstCreated) return;
|
|
37839
|
-
const first =
|
|
37840
|
-
const target =
|
|
38110
|
+
const first = resolve12(firstCreated);
|
|
38111
|
+
const target = resolve12(path);
|
|
37841
38112
|
await sync(dirname9(first));
|
|
37842
38113
|
let current = first;
|
|
37843
|
-
for (const part of
|
|
38114
|
+
for (const part of relative10(first, target).split(sep6).filter(Boolean)) {
|
|
37844
38115
|
await sync(current);
|
|
37845
38116
|
current = join18(current, part);
|
|
37846
38117
|
}
|
|
@@ -37848,7 +38119,7 @@ async function ensureDirectory2(path, sync) {
|
|
|
37848
38119
|
async function replacePrivateFile2(path, contents, mode, sync) {
|
|
37849
38120
|
const parent = dirname9(path);
|
|
37850
38121
|
await ensureDirectory2(parent, sync);
|
|
37851
|
-
const temporary = join18(parent, `.${
|
|
38122
|
+
const temporary = join18(parent, `.${basename5(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
|
|
37852
38123
|
const handle = await open8(temporary, "wx", mode);
|
|
37853
38124
|
try {
|
|
37854
38125
|
await handle.writeFile(contents, "utf8");
|
|
@@ -38039,9 +38310,9 @@ async function installMacosService(options) {
|
|
|
38039
38310
|
// src/windows-service.ts
|
|
38040
38311
|
import { spawn as spawn12 } from "node:child_process";
|
|
38041
38312
|
import { constants as constants4 } from "node:fs";
|
|
38042
|
-
import { access as access6, mkdir as mkdir14, open as open9, readFile as
|
|
38313
|
+
import { access as access6, mkdir as mkdir14, open as open9, readFile as readFile10, rename as rename8, rm as rm10 } from "node:fs/promises";
|
|
38043
38314
|
import { homedir as homedir9 } from "node:os";
|
|
38044
|
-
import { basename as
|
|
38315
|
+
import { basename as basename6, dirname as dirname10, isAbsolute as isAbsolute16, join as join19, relative as relative11, resolve as resolve13, sep as sep7 } from "node:path";
|
|
38045
38316
|
var TASK_NAME = "Zixt Host";
|
|
38046
38317
|
var COMMAND_TIMEOUT_MS3 = 7e4;
|
|
38047
38318
|
var SERVICE_STABILITY_DELAY_MS3 = 2e3;
|
|
@@ -38069,11 +38340,11 @@ async function syncDirectory5(path) {
|
|
|
38069
38340
|
async function ensureDirectory3(path, sync) {
|
|
38070
38341
|
const firstCreated = await mkdir14(path, { recursive: true, mode: 448 });
|
|
38071
38342
|
if (!firstCreated) return;
|
|
38072
|
-
const first =
|
|
38073
|
-
const target =
|
|
38343
|
+
const first = resolve13(firstCreated);
|
|
38344
|
+
const target = resolve13(path);
|
|
38074
38345
|
await sync(dirname10(first));
|
|
38075
38346
|
let current = first;
|
|
38076
|
-
for (const part of
|
|
38347
|
+
for (const part of relative11(first, target).split(sep7).filter(Boolean)) {
|
|
38077
38348
|
await sync(current);
|
|
38078
38349
|
current = join19(current, part);
|
|
38079
38350
|
}
|
|
@@ -38081,7 +38352,7 @@ async function ensureDirectory3(path, sync) {
|
|
|
38081
38352
|
async function replacePrivateFile3(path, contents, sync) {
|
|
38082
38353
|
const parent = dirname10(path);
|
|
38083
38354
|
await ensureDirectory3(parent, sync);
|
|
38084
|
-
const temporary = join19(parent, `.${
|
|
38355
|
+
const temporary = join19(parent, `.${basename6(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
|
|
38085
38356
|
const handle = await open9(temporary, "wx", 384);
|
|
38086
38357
|
try {
|
|
38087
38358
|
await handle.writeFile(contents, "utf8");
|
|
@@ -38135,7 +38406,7 @@ async function runChild(command, args, env, input) {
|
|
|
38135
38406
|
}
|
|
38136
38407
|
async function defaultResolveCommand3(name, env) {
|
|
38137
38408
|
const root = env.SYSTEMROOT ?? env.WINDIR;
|
|
38138
|
-
if (!root || !
|
|
38409
|
+
if (!root || !isAbsolute16(root)) return null;
|
|
38139
38410
|
const candidate = name === "powershell" ? join19(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe") : join19(root, "System32", `${name}.exe`);
|
|
38140
38411
|
return access6(candidate, constants4.X_OK).then(
|
|
38141
38412
|
() => candidate,
|
|
@@ -38224,7 +38495,7 @@ exit $code
|
|
|
38224
38495
|
}
|
|
38225
38496
|
async function defaultObserveStatus(path, generation) {
|
|
38226
38497
|
try {
|
|
38227
|
-
const text = (await
|
|
38498
|
+
const text = (await readFile10(path, "utf8")).replace(/^\uFEFF/, "");
|
|
38228
38499
|
const value = JSON.parse(text);
|
|
38229
38500
|
if (value.schema !== 1 || value.generation !== generation || typeof value.pid !== "number" || !Number.isSafeInteger(value.pid) || value.pid <= 0) {
|
|
38230
38501
|
return null;
|
|
@@ -38267,7 +38538,7 @@ async function installWindowsService(options) {
|
|
|
38267
38538
|
const env = options.env ?? process.env;
|
|
38268
38539
|
const home = options.home ?? homedir9();
|
|
38269
38540
|
const localAppData = options.localAppData ?? env.LOCALAPPDATA;
|
|
38270
|
-
if (!localAppData || !
|
|
38541
|
+
if (!localAppData || !isAbsolute16(localAppData)) {
|
|
38271
38542
|
throw new Error("Windows local application data path is unavailable.");
|
|
38272
38543
|
}
|
|
38273
38544
|
const token2 = oneLine3(options.token, "pairing code");
|
|
@@ -38378,9 +38649,9 @@ async function installSystemService(options) {
|
|
|
38378
38649
|
}
|
|
38379
38650
|
|
|
38380
38651
|
// src/terminal-outcomes.ts
|
|
38381
|
-
import { chmod as chmod9, lstat as
|
|
38652
|
+
import { chmod as chmod9, lstat as lstat12, mkdir as mkdir15, open as open10, readdir as readdir5, readFile as readFile11, rename as rename9, rm as rm11 } from "node:fs/promises";
|
|
38382
38653
|
import { homedir as homedir10 } from "node:os";
|
|
38383
|
-
import { dirname as dirname11, join as join20, relative as
|
|
38654
|
+
import { dirname as dirname11, join as join20, relative as relative12, resolve as resolve14, sep as sep8 } from "node:path";
|
|
38384
38655
|
var DIRECTORY_MODE5 = 448;
|
|
38385
38656
|
var FILE_MODE4 = 384;
|
|
38386
38657
|
var MAX_OUTCOME_BYTES = 4 * 1024 * 1024;
|
|
@@ -38408,16 +38679,16 @@ async function syncDirectory6(root) {
|
|
|
38408
38679
|
async function requirePrivateRoot(root, sync = syncDirectory6) {
|
|
38409
38680
|
const firstCreated = await mkdir15(root, { recursive: true, mode: DIRECTORY_MODE5 });
|
|
38410
38681
|
if (firstCreated) {
|
|
38411
|
-
const first =
|
|
38412
|
-
const target =
|
|
38682
|
+
const first = resolve14(firstCreated);
|
|
38683
|
+
const target = resolve14(root);
|
|
38413
38684
|
await sync(dirname11(first));
|
|
38414
38685
|
let current = first;
|
|
38415
|
-
for (const part of
|
|
38686
|
+
for (const part of relative12(first, target).split(sep8).filter(Boolean)) {
|
|
38416
38687
|
await sync(current);
|
|
38417
38688
|
current = join20(current, part);
|
|
38418
38689
|
}
|
|
38419
38690
|
}
|
|
38420
|
-
const stat3 = await
|
|
38691
|
+
const stat3 = await lstat12(root);
|
|
38421
38692
|
if (stat3.isSymbolicLink() || !stat3.isDirectory()) {
|
|
38422
38693
|
throw new Error("terminal outcome journal root is not a trusted directory");
|
|
38423
38694
|
}
|
|
@@ -38445,7 +38716,7 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
|
|
|
38445
38716
|
const destination = outcomePath(root, hostId, outcome.taskId, outcome.epoch);
|
|
38446
38717
|
try {
|
|
38447
38718
|
const existing = parseCommittedOutcome(
|
|
38448
|
-
await
|
|
38719
|
+
await readFile11(destination, { encoding: "utf8", flag: "r" }),
|
|
38449
38720
|
outcome.taskId,
|
|
38450
38721
|
outcome.epoch
|
|
38451
38722
|
);
|
|
@@ -38478,7 +38749,7 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
|
|
|
38478
38749
|
async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
|
|
38479
38750
|
let rootStat;
|
|
38480
38751
|
try {
|
|
38481
|
-
rootStat = await
|
|
38752
|
+
rootStat = await lstat12(root);
|
|
38482
38753
|
} catch (error52) {
|
|
38483
38754
|
if (error52.code === "ENOENT") return [];
|
|
38484
38755
|
throw new Error("terminal outcome journal could not be observed");
|
|
@@ -38495,7 +38766,7 @@ async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
|
|
|
38495
38766
|
throw new Error("terminal outcome Host scope is not a trusted directory");
|
|
38496
38767
|
}
|
|
38497
38768
|
const scopedRoot = hostOutcomeRoot(root, hostEntry.name);
|
|
38498
|
-
const scopedStat = await
|
|
38769
|
+
const scopedStat = await lstat12(scopedRoot);
|
|
38499
38770
|
if (scopedStat.isSymbolicLink() || !scopedStat.isDirectory()) {
|
|
38500
38771
|
throw new Error("terminal outcome Host scope is not a trusted directory");
|
|
38501
38772
|
}
|
|
@@ -38508,12 +38779,12 @@ async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
|
|
|
38508
38779
|
throw new Error("committed terminal outcome is not a trusted regular file");
|
|
38509
38780
|
}
|
|
38510
38781
|
const path = join20(scopedRoot, entry.name);
|
|
38511
|
-
const stat3 = await
|
|
38782
|
+
const stat3 = await lstat12(path);
|
|
38512
38783
|
if (!stat3.isFile() || stat3.isSymbolicLink() || stat3.size > MAX_OUTCOME_BYTES) {
|
|
38513
38784
|
throw new Error("committed terminal outcome is not a trusted regular file");
|
|
38514
38785
|
}
|
|
38515
38786
|
const outcome = parseCommittedOutcome(
|
|
38516
|
-
await
|
|
38787
|
+
await readFile11(path, "utf8"),
|
|
38517
38788
|
match[1],
|
|
38518
38789
|
Number(match[2])
|
|
38519
38790
|
);
|
|
@@ -38660,13 +38931,13 @@ function createHostLogger(options = {}) {
|
|
|
38660
38931
|
}
|
|
38661
38932
|
|
|
38662
38933
|
// src/demo-state.ts
|
|
38663
|
-
import { isAbsolute as
|
|
38934
|
+
import { isAbsolute as isAbsolute17, join as join21, parse as parse3, resolve as resolve15 } from "node:path";
|
|
38664
38935
|
var DEMO_STATE_ROOT_ENV = "ZIXT_DEMO_STATE_ROOT";
|
|
38665
38936
|
function resolveDemoHostStatePaths(env = process.env) {
|
|
38666
38937
|
const configured = env.ZIXT_RUNNER === "demo" ? env[DEMO_STATE_ROOT_ENV] : void 0;
|
|
38667
38938
|
if (!configured) return null;
|
|
38668
|
-
const root =
|
|
38669
|
-
if (!
|
|
38939
|
+
const root = resolve15(configured);
|
|
38940
|
+
if (!isAbsolute17(configured) || root === parse3(root).root) {
|
|
38670
38941
|
throw new Error(`${DEMO_STATE_ROOT_ENV} must be a dedicated absolute directory`);
|
|
38671
38942
|
}
|
|
38672
38943
|
return {
|