@zixt/host 0.0.48 → 0.0.50
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 +629 -316
- 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.50",
|
|
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). */
|
|
@@ -14657,6 +14659,8 @@ var ID_PREFIXES = {
|
|
|
14657
14659
|
conversation: "cnv",
|
|
14658
14660
|
/** One immutable Conversation timeline entry. */
|
|
14659
14661
|
conversationEvent: "cve",
|
|
14662
|
+
/** One human-confirmed integration action prepared by the Manager. */
|
|
14663
|
+
managerIntegrationAction: "mia",
|
|
14660
14664
|
/** One Manager inference call's token-metering row (MG-8). */
|
|
14661
14665
|
managerUsage: "mgu",
|
|
14662
14666
|
/** One ordered Manager reply awaiting Slack delivery. */
|
|
@@ -14692,11 +14696,16 @@ var OrgSkillId = idSchema(ID_PREFIXES.orgSkill, "organization skill id");
|
|
|
14692
14696
|
var OrgRoutineId = idSchema(ID_PREFIXES.orgRoutine, "organization routine id");
|
|
14693
14697
|
var BrowserSessionId = idSchema(ID_PREFIXES.browserSession, "browser session id");
|
|
14694
14698
|
var AttachmentId = idSchema(ID_PREFIXES.attachment, "attachment id");
|
|
14699
|
+
var TaskArtifactId = idSchema(ID_PREFIXES.artifact, "task artifact id");
|
|
14695
14700
|
var MemoryId = idSchema(ID_PREFIXES.memory, "memory id");
|
|
14696
14701
|
var ManagerId = idSchema(ID_PREFIXES.manager, "manager id");
|
|
14697
14702
|
var ManagerMemoryId = idSchema(ID_PREFIXES.managerMemory, "manager memory id");
|
|
14698
14703
|
var ConversationId = idSchema(ID_PREFIXES.conversation, "conversation id");
|
|
14699
14704
|
var ConversationEventId = idSchema(ID_PREFIXES.conversationEvent, "conversation event id");
|
|
14705
|
+
var ManagerIntegrationActionId = idSchema(
|
|
14706
|
+
ID_PREFIXES.managerIntegrationAction,
|
|
14707
|
+
"Manager integration action id"
|
|
14708
|
+
);
|
|
14700
14709
|
var VoiceLineId = idSchema(ID_PREFIXES.voiceLine, "voice line id");
|
|
14701
14710
|
var VoiceCallerId = idSchema(ID_PREFIXES.voiceCaller, "voice caller id");
|
|
14702
14711
|
var VoiceCallId = idSchema(ID_PREFIXES.voiceCall, "voice call id");
|
|
@@ -16013,6 +16022,28 @@ var UploadAttachmentRequest = external_exports.object({
|
|
|
16013
16022
|
data: external_exports.string().min(1).max(Math.ceil(TASK_ATTACHMENT_MAX_BYTES / 3 * 4) + 4)
|
|
16014
16023
|
});
|
|
16015
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
|
+
});
|
|
16016
16047
|
var TaskDisposition = external_exports.object({
|
|
16017
16048
|
outcome: external_exports.enum(["done", "nothing_to_do", "escalated", "cancelled", "failed"]),
|
|
16018
16049
|
summary: external_exports.string().max(5e4)
|
|
@@ -16445,6 +16476,7 @@ var TaskWorkingContextObservation = TaskWorkingContextBase.omit({
|
|
|
16445
16476
|
var TaskDetailResponse = external_exports.object({
|
|
16446
16477
|
task: TaskProjection,
|
|
16447
16478
|
events: external_exports.array(TaskEventRecord),
|
|
16479
|
+
artifacts: external_exports.array(TaskArtifact),
|
|
16448
16480
|
/** Newest assignment epoch first. */
|
|
16449
16481
|
attempts: external_exports.array(TaskAttemptProjection),
|
|
16450
16482
|
/** Only unresolved asks for this task; decisions still use the typed approval endpoint. */
|
|
@@ -16976,6 +17008,39 @@ var AgentOp = external_exports.union([
|
|
|
16976
17008
|
}),
|
|
16977
17009
|
/** The channels a teammate can actually post to: the ones the bot is in. */
|
|
16978
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
|
+
}),
|
|
16979
17044
|
/** Claim a cloud-side intent before a direct host → Linear mutation. */
|
|
16980
17045
|
ProviderIntent,
|
|
16981
17046
|
/** Record provider-confirmed success after the direct mutation returns. */
|
|
@@ -18823,7 +18888,9 @@ var ConversationEventProjection = external_exports.discriminatedUnion("kind", [
|
|
|
18823
18888
|
tool: external_exports.string(),
|
|
18824
18889
|
summary: external_exports.string(),
|
|
18825
18890
|
taskId: TaskId.nullable(),
|
|
18826
|
-
agentId: AgentId.nullable()
|
|
18891
|
+
agentId: AgentId.nullable(),
|
|
18892
|
+
/** Present only for a confirmation card; OAuth authority never appears here. */
|
|
18893
|
+
integrationActionId: ManagerIntegrationActionId.nullable().optional()
|
|
18827
18894
|
}).strict(),
|
|
18828
18895
|
/** A mirrored child-Task event: what the teammate wrote or became. */
|
|
18829
18896
|
external_exports.object({
|
|
@@ -18845,6 +18912,40 @@ var ConversationEventProjection = external_exports.discriminatedUnion("kind", [
|
|
|
18845
18912
|
/** A Manager loop failure a person should see (provider outage, refusal). */
|
|
18846
18913
|
external_exports.object({ ...conversationEventBase, kind: external_exports.literal("error"), message: external_exports.string() }).strict()
|
|
18847
18914
|
]);
|
|
18915
|
+
var ManagerIntegrationProvider = external_exports.enum(["slack"]);
|
|
18916
|
+
var ManagerIntegrationOperation = external_exports.enum(["connect", "reconnect", "check", "remove"]);
|
|
18917
|
+
var ManagerIntegrationActionStatus = external_exports.enum([
|
|
18918
|
+
"awaiting_confirmation",
|
|
18919
|
+
"working",
|
|
18920
|
+
"authorizing",
|
|
18921
|
+
"completed",
|
|
18922
|
+
"cancelled",
|
|
18923
|
+
"failed",
|
|
18924
|
+
"expired"
|
|
18925
|
+
]);
|
|
18926
|
+
var ManagerIntegrationActionProjection = external_exports.object({
|
|
18927
|
+
id: ManagerIntegrationActionId,
|
|
18928
|
+
conversationId: ConversationId,
|
|
18929
|
+
provider: ManagerIntegrationProvider,
|
|
18930
|
+
providerName: external_exports.string().min(1).max(80),
|
|
18931
|
+
operation: ManagerIntegrationOperation,
|
|
18932
|
+
status: ManagerIntegrationActionStatus,
|
|
18933
|
+
title: external_exports.string().min(1).max(200),
|
|
18934
|
+
description: external_exports.string().min(1).max(1e3),
|
|
18935
|
+
confirmLabel: external_exports.string().min(1).max(100),
|
|
18936
|
+
outcome: external_exports.string().max(1e3).nullable(),
|
|
18937
|
+
createdAt: external_exports.string(),
|
|
18938
|
+
expiresAt: external_exports.string()
|
|
18939
|
+
}).strict();
|
|
18940
|
+
var ManagerIntegrationOAuthStart = external_exports.object({
|
|
18941
|
+
authorizeUrl: external_exports.url().max(4e3),
|
|
18942
|
+
callbackOrigin: external_exports.url().max(2e3)
|
|
18943
|
+
}).strict();
|
|
18944
|
+
var ConfirmManagerIntegrationActionRequest = external_exports.object({ requestId: external_exports.string().uuid() }).strict();
|
|
18945
|
+
var ManagerIntegrationActionResponse = external_exports.object({
|
|
18946
|
+
action: ManagerIntegrationActionProjection,
|
|
18947
|
+
oauth: ManagerIntegrationOAuthStart.nullable()
|
|
18948
|
+
}).strict();
|
|
18848
18949
|
var NonEmptyTaskRunnerSelection = TaskRunnerSelection.refine(
|
|
18849
18950
|
(selection) => selection.type !== void 0 || selection.model !== void 0 || selection.effort !== void 0,
|
|
18850
18951
|
"choose at least one runtime preference"
|
|
@@ -19852,10 +19953,77 @@ async function discoverTools(params, fetchFn = fetch) {
|
|
|
19852
19953
|
})).filter((t) => t.name.length > 0);
|
|
19853
19954
|
}
|
|
19854
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
|
+
|
|
19855
20023
|
// src/runners/exec.ts
|
|
19856
20024
|
import { spawn } from "node:child_process";
|
|
19857
|
-
import { realpath, stat } from "node:fs/promises";
|
|
19858
|
-
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";
|
|
19859
20027
|
function spawnCli(command, args, options = {}) {
|
|
19860
20028
|
if (process.platform === "win32") {
|
|
19861
20029
|
return spawn([quoteForCmd(command), ...args.map(quoteForCmd)].join(" "), {
|
|
@@ -19867,26 +20035,26 @@ function spawnCli(command, args, options = {}) {
|
|
|
19867
20035
|
}
|
|
19868
20036
|
async function resolveTrustedCliCommand(command, options = {}) {
|
|
19869
20037
|
const platform = options.platform ?? process.platform;
|
|
19870
|
-
const trustedCwd =
|
|
20038
|
+
const trustedCwd = resolve2(options.trustedCwd ?? process.cwd());
|
|
19871
20039
|
const hasSeparator = command.includes("/") || command.includes("\\");
|
|
19872
20040
|
const bases = [];
|
|
19873
|
-
if (
|
|
20041
|
+
if (isAbsolute2(command)) {
|
|
19874
20042
|
bases.push(command);
|
|
19875
20043
|
} else if (hasSeparator) {
|
|
19876
|
-
bases.push(
|
|
20044
|
+
bases.push(resolve2(trustedCwd, command));
|
|
19877
20045
|
} else {
|
|
19878
20046
|
for (const entry of (options.searchPath ?? process.env.PATH ?? "").split(delimiter)) {
|
|
19879
20047
|
if (!entry) continue;
|
|
19880
|
-
bases.push(join(
|
|
20048
|
+
bases.push(join(isAbsolute2(entry) ? entry : resolve2(trustedCwd, entry), command));
|
|
19881
20049
|
}
|
|
19882
20050
|
}
|
|
19883
|
-
const extensions = platform === "win32" &&
|
|
20051
|
+
const extensions = platform === "win32" && extname2(command) === "" ? (options.pathExt ?? process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
19884
20052
|
for (const base of bases) {
|
|
19885
20053
|
for (const extension of extensions) {
|
|
19886
20054
|
try {
|
|
19887
|
-
const candidate = await
|
|
20055
|
+
const candidate = await realpath2(`${base}${extension}`);
|
|
19888
20056
|
const entry = await stat(candidate);
|
|
19889
|
-
if (entry.isFile() &&
|
|
20057
|
+
if (entry.isFile() && isAbsolute2(candidate)) return candidate;
|
|
19890
20058
|
} catch {
|
|
19891
20059
|
}
|
|
19892
20060
|
}
|
|
@@ -19919,7 +20087,7 @@ async function generateTaskTitle(instructions, runner) {
|
|
|
19919
20087
|
instructions.slice(0, INSTRUCTIONS_BUDGET),
|
|
19920
20088
|
"</task_request>"
|
|
19921
20089
|
].join("\n");
|
|
19922
|
-
return new Promise((
|
|
20090
|
+
return new Promise((resolve16) => {
|
|
19923
20091
|
const child = spawnCli(
|
|
19924
20092
|
command,
|
|
19925
20093
|
[
|
|
@@ -19942,7 +20110,7 @@ async function generateTaskTitle(instructions, runner) {
|
|
|
19942
20110
|
if (settled) return;
|
|
19943
20111
|
settled = true;
|
|
19944
20112
|
clearTimeout(timer);
|
|
19945
|
-
|
|
20113
|
+
resolve16(value);
|
|
19946
20114
|
};
|
|
19947
20115
|
const timer = setTimeout(() => {
|
|
19948
20116
|
child.kill();
|
|
@@ -19980,7 +20148,7 @@ function isPlausibleTaskTitle(title) {
|
|
|
19980
20148
|
// src/worker-watchdog.ts
|
|
19981
20149
|
import { randomUUID } from "node:crypto";
|
|
19982
20150
|
import { writeFileSync as writeFileSync2 } from "node:fs";
|
|
19983
|
-
import { isAbsolute as
|
|
20151
|
+
import { isAbsolute as isAbsolute4 } from "node:path";
|
|
19984
20152
|
|
|
19985
20153
|
// src/worker-ownership.ts
|
|
19986
20154
|
import {
|
|
@@ -19993,8 +20161,8 @@ import {
|
|
|
19993
20161
|
rmSync,
|
|
19994
20162
|
writeFileSync
|
|
19995
20163
|
} from "node:fs";
|
|
19996
|
-
import { chmod, lstat, mkdir, open, readFile, readdir, rm, rmdir } from "node:fs/promises";
|
|
19997
|
-
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";
|
|
19998
20166
|
var LAUNCHER_OWNERSHIP_DIR_ENV = "ZIXT_HOST_LAUNCHER_OWNERSHIP_DIR";
|
|
19999
20167
|
var WORKER_OWNERSHIP_FILE_ENV = "ZIXT_HOST_WORKER_OWNERSHIP_FILE";
|
|
20000
20168
|
var SUPERVISOR_OWNERSHIP_FILE_ENV = "ZIXT_HOST_SUPERVISOR_OWNERSHIP_FILE";
|
|
@@ -20004,7 +20172,7 @@ var MAX_OWNERSHIP_RECORD_BYTES = 4 * 1024;
|
|
|
20004
20172
|
var MAX_OWNERSHIP_RECORDS = 32;
|
|
20005
20173
|
var MAX_OWNERSHIP_GENERATIONS = 32;
|
|
20006
20174
|
function workerOwnershipFile(directory, nonce) {
|
|
20007
|
-
if (!
|
|
20175
|
+
if (!isAbsolute3(directory) || !SAFE_WORKER_OWNERSHIP_NONCE.test(nonce)) return null;
|
|
20008
20176
|
return join2(directory, `${nonce}.json`);
|
|
20009
20177
|
}
|
|
20010
20178
|
function workerOwnershipArguments(nonce) {
|
|
@@ -20014,7 +20182,7 @@ function consumeWorkerOwnershipArguments(argv, env) {
|
|
|
20014
20182
|
const file2 = env[WORKER_OWNERSHIP_FILE_ENV];
|
|
20015
20183
|
const nonce = env.ZIXT_HOST_WORKER_WATCHDOG_NONCE;
|
|
20016
20184
|
if (typeof file2 !== "string") return { argv: [...argv], requested: false, valid: true };
|
|
20017
|
-
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`) {
|
|
20018
20186
|
return { argv: [...argv], requested: true, valid: false };
|
|
20019
20187
|
}
|
|
20020
20188
|
const result = [];
|
|
@@ -20041,7 +20209,7 @@ function syncDirectorySync(path) {
|
|
|
20041
20209
|
}
|
|
20042
20210
|
}
|
|
20043
20211
|
function recordWorkerOwnership(path, nonce, pid = process.pid) {
|
|
20044
|
-
if (!
|
|
20212
|
+
if (!isAbsolute3(path) || !SAFE_WORKER_OWNERSHIP_NONCE.test(nonce) || basename2(path) !== `${nonce}.json` || !Number.isSafeInteger(pid) || pid <= 1) {
|
|
20045
20213
|
return false;
|
|
20046
20214
|
}
|
|
20047
20215
|
const directory = dirname(path);
|
|
@@ -20099,19 +20267,19 @@ async function syncDirectory(path) {
|
|
|
20099
20267
|
}
|
|
20100
20268
|
}
|
|
20101
20269
|
async function ensurePrivateOwnershipRoot(root) {
|
|
20102
|
-
if (!
|
|
20270
|
+
if (!isAbsolute3(root)) throw new Error("launcher ownership root is invalid");
|
|
20103
20271
|
const firstCreated = await mkdir(root, { recursive: true, mode: 448 });
|
|
20104
20272
|
if (firstCreated && process.platform !== "win32") {
|
|
20105
|
-
const first =
|
|
20106
|
-
const target =
|
|
20273
|
+
const first = resolve3(firstCreated);
|
|
20274
|
+
const target = resolve3(root);
|
|
20107
20275
|
await syncDirectory(dirname(first));
|
|
20108
20276
|
let current = first;
|
|
20109
|
-
for (const part of
|
|
20277
|
+
for (const part of relative2(first, target).split(sep2).filter(Boolean)) {
|
|
20110
20278
|
await syncDirectory(current);
|
|
20111
20279
|
current = join2(current, part);
|
|
20112
20280
|
}
|
|
20113
20281
|
}
|
|
20114
|
-
const metadata = await
|
|
20282
|
+
const metadata = await lstat2(root);
|
|
20115
20283
|
if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
|
|
20116
20284
|
throw new Error("launcher ownership root is not a trusted directory");
|
|
20117
20285
|
}
|
|
@@ -20148,7 +20316,7 @@ async function readLauncherOwnershipGenerations(root) {
|
|
|
20148
20316
|
throw new Error("launcher ownership root is malformed");
|
|
20149
20317
|
}
|
|
20150
20318
|
const directory = join2(root, entry.name);
|
|
20151
|
-
const metadata = await
|
|
20319
|
+
const metadata = await lstat2(directory);
|
|
20152
20320
|
if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
|
|
20153
20321
|
throw new Error("launcher ownership generation is not a trusted directory");
|
|
20154
20322
|
}
|
|
@@ -20170,7 +20338,7 @@ function parseRecord(value, path, expectedNonce) {
|
|
|
20170
20338
|
return { schema: 1, nonce: expectedNonce, pid: record2.pid, path };
|
|
20171
20339
|
}
|
|
20172
20340
|
async function readWorkerOwnershipRecords(directory) {
|
|
20173
|
-
if (!
|
|
20341
|
+
if (!isAbsolute3(directory)) throw new Error("worker ownership directory is invalid");
|
|
20174
20342
|
const entries = await readdir(directory, { withFileTypes: true }).catch(
|
|
20175
20343
|
(error52) => {
|
|
20176
20344
|
if (error52.code === "ENOENT") return [];
|
|
@@ -20189,13 +20357,13 @@ async function readWorkerOwnershipRecords(directory) {
|
|
|
20189
20357
|
}
|
|
20190
20358
|
const match = /^([A-Za-z0-9_-]{16,200})\.json$/.exec(entry.name);
|
|
20191
20359
|
if (!entry.isFile() || !match) throw new Error("worker ownership directory is malformed");
|
|
20192
|
-
const metadata = await
|
|
20360
|
+
const metadata = await lstat2(path);
|
|
20193
20361
|
if (!metadata.isFile() || metadata.size > MAX_OWNERSHIP_RECORD_BYTES) {
|
|
20194
20362
|
throw new Error("worker ownership record is invalid");
|
|
20195
20363
|
}
|
|
20196
20364
|
let value;
|
|
20197
20365
|
try {
|
|
20198
|
-
value = JSON.parse(await
|
|
20366
|
+
value = JSON.parse(await readFile2(path, "utf8"));
|
|
20199
20367
|
} catch {
|
|
20200
20368
|
throw new Error("worker ownership record is invalid");
|
|
20201
20369
|
}
|
|
@@ -20204,7 +20372,7 @@ async function readWorkerOwnershipRecords(directory) {
|
|
|
20204
20372
|
return records;
|
|
20205
20373
|
}
|
|
20206
20374
|
async function forgetWorkerOwnership(path) {
|
|
20207
|
-
if (!
|
|
20375
|
+
if (!isAbsolute3(path)) throw new Error("worker ownership path is invalid");
|
|
20208
20376
|
const directory = dirname(path);
|
|
20209
20377
|
await rm(path, { force: true });
|
|
20210
20378
|
await syncDirectory(directory);
|
|
@@ -20264,11 +20432,11 @@ function createWorkerWatchdogSendDrain() {
|
|
|
20264
20432
|
if (completed) return;
|
|
20265
20433
|
completed = true;
|
|
20266
20434
|
pending--;
|
|
20267
|
-
if (pending === 0) drained.splice(0).forEach((
|
|
20435
|
+
if (pending === 0) drained.splice(0).forEach((resolve16) => resolve16());
|
|
20268
20436
|
};
|
|
20269
20437
|
},
|
|
20270
20438
|
drain: async () => {
|
|
20271
|
-
if (pending > 0) await new Promise((
|
|
20439
|
+
if (pending > 0) await new Promise((resolve16) => drained.push(resolve16));
|
|
20272
20440
|
}
|
|
20273
20441
|
};
|
|
20274
20442
|
}
|
|
@@ -20294,7 +20462,7 @@ function startWorkerWatchdogHeartbeat(env = process.env, argv = process.argv.sli
|
|
|
20294
20462
|
}
|
|
20295
20463
|
const heartbeatFile = env[WORKER_WATCHDOG_FILE_ENV];
|
|
20296
20464
|
const ipc = typeof process.send === "function" && process.connected;
|
|
20297
|
-
const file2 = !ipc && typeof heartbeatFile === "string" &&
|
|
20465
|
+
const file2 = !ipc && typeof heartbeatFile === "string" && isAbsolute4(heartbeatFile) ? heartbeatFile : null;
|
|
20298
20466
|
if (!ipc && !file2) {
|
|
20299
20467
|
heartbeatActive = false;
|
|
20300
20468
|
heartbeatUsesIpc = false;
|
|
@@ -20513,7 +20681,7 @@ async function waitForOperationGrantRetry(retryAt, signal) {
|
|
|
20513
20681
|
const deadline = Date.parse(retryAt);
|
|
20514
20682
|
if (!Number.isFinite(deadline) || signal.aborted) return false;
|
|
20515
20683
|
if (deadline <= Date.now()) return true;
|
|
20516
|
-
return await new Promise((
|
|
20684
|
+
return await new Promise((resolve16) => {
|
|
20517
20685
|
let settled = false;
|
|
20518
20686
|
let timer;
|
|
20519
20687
|
const finish = (ready) => {
|
|
@@ -20521,7 +20689,7 @@ async function waitForOperationGrantRetry(retryAt, signal) {
|
|
|
20521
20689
|
settled = true;
|
|
20522
20690
|
if (timer) clearTimeout(timer);
|
|
20523
20691
|
signal.removeEventListener("abort", onAbort);
|
|
20524
|
-
|
|
20692
|
+
resolve16(ready);
|
|
20525
20693
|
};
|
|
20526
20694
|
const onAbort = () => finish(false);
|
|
20527
20695
|
const schedule = () => {
|
|
@@ -20789,22 +20957,22 @@ var HostClient = class _HostClient {
|
|
|
20789
20957
|
const unwindingAssignments = [...this.activeAssignments.values()];
|
|
20790
20958
|
for (const cancel of this.cancels.values()) cancel(stopReason);
|
|
20791
20959
|
for (const entry of this.secretGrants.values()) {
|
|
20792
|
-
for (const
|
|
20960
|
+
for (const resolve16 of entry.resolvers) resolve16({});
|
|
20793
20961
|
entry.resolvers = [];
|
|
20794
20962
|
delete entry.value;
|
|
20795
20963
|
}
|
|
20796
20964
|
for (const entry of this.connectionGrants.values()) {
|
|
20797
|
-
for (const
|
|
20965
|
+
for (const resolve16 of entry.resolvers) resolve16([]);
|
|
20798
20966
|
entry.resolvers = [];
|
|
20799
20967
|
delete entry.value;
|
|
20800
20968
|
}
|
|
20801
20969
|
for (const entry of this.providerGrants.values()) {
|
|
20802
|
-
for (const
|
|
20970
|
+
for (const resolve16 of entry.resolvers) resolve16([]);
|
|
20803
20971
|
entry.resolvers = [];
|
|
20804
20972
|
delete entry.value;
|
|
20805
20973
|
}
|
|
20806
20974
|
for (const waiters of this.approvalWaiters.values()) {
|
|
20807
|
-
for (const
|
|
20975
|
+
for (const resolve16 of waiters.values()) resolve16({ approved: false, guidance: reason });
|
|
20808
20976
|
}
|
|
20809
20977
|
for (const waiters of this.agentOpWaiters.values()) {
|
|
20810
20978
|
for (const waiter of waiters.values()) {
|
|
@@ -20830,9 +20998,9 @@ var HostClient = class _HostClient {
|
|
|
20830
20998
|
let drainTimer;
|
|
20831
20999
|
const drained = await Promise.race([
|
|
20832
21000
|
Promise.allSettled(runs).then(() => true),
|
|
20833
|
-
new Promise((
|
|
21001
|
+
new Promise((resolve16) => {
|
|
20834
21002
|
drainTimer = setTimeout(
|
|
20835
|
-
() =>
|
|
21003
|
+
() => resolve16(false),
|
|
20836
21004
|
this.opts.unwindTimeoutMs ?? _HostClient.DEFAULT_UNWIND_TIMEOUT_MS
|
|
20837
21005
|
);
|
|
20838
21006
|
drainTimer.unref?.();
|
|
@@ -20976,9 +21144,9 @@ var HostClient = class _HostClient {
|
|
|
20976
21144
|
let frameDrainTimer;
|
|
20977
21145
|
const framesDrained = await Promise.race([
|
|
20978
21146
|
frameTail.then(() => true),
|
|
20979
|
-
new Promise((
|
|
21147
|
+
new Promise((resolve16) => {
|
|
20980
21148
|
frameDrainTimer = setTimeout(
|
|
20981
|
-
() =>
|
|
21149
|
+
() => resolve16(false),
|
|
20982
21150
|
this.opts.unwindTimeoutMs ?? _HostClient.DEFAULT_UNWIND_TIMEOUT_MS
|
|
20983
21151
|
);
|
|
20984
21152
|
frameDrainTimer.unref?.();
|
|
@@ -21522,7 +21690,7 @@ var HostClient = class _HostClient {
|
|
|
21522
21690
|
const entry = this.secretGrants.get(key) ?? { resolvers: [] };
|
|
21523
21691
|
entry.value = message.secrets;
|
|
21524
21692
|
entry.expiresAt = expiresAt;
|
|
21525
|
-
for (const
|
|
21693
|
+
for (const resolve16 of entry.resolvers) resolve16(message.secrets);
|
|
21526
21694
|
entry.resolvers = [];
|
|
21527
21695
|
this.secretGrants.set(key, entry);
|
|
21528
21696
|
return;
|
|
@@ -21553,13 +21721,13 @@ var HostClient = class _HostClient {
|
|
|
21553
21721
|
const entry = this.connectionGrants.get(key) ?? { resolvers: [] };
|
|
21554
21722
|
entry.value = message.connections;
|
|
21555
21723
|
entry.expiresAt = expiresAt;
|
|
21556
|
-
for (const
|
|
21724
|
+
for (const resolve16 of entry.resolvers) resolve16(message.connections);
|
|
21557
21725
|
entry.resolvers = [];
|
|
21558
21726
|
this.connectionGrants.set(key, entry);
|
|
21559
21727
|
const providerEntry = this.providerGrants.get(key) ?? { resolvers: [] };
|
|
21560
21728
|
providerEntry.value = providers;
|
|
21561
21729
|
providerEntry.expiresAt = authorityExpiresAt;
|
|
21562
|
-
for (const
|
|
21730
|
+
for (const resolve16 of providerEntry.resolvers) resolve16(providers);
|
|
21563
21731
|
providerEntry.resolvers = [];
|
|
21564
21732
|
this.providerGrants.set(key, providerEntry);
|
|
21565
21733
|
return;
|
|
@@ -21693,8 +21861,8 @@ var HostClient = class _HostClient {
|
|
|
21693
21861
|
return redactCredentialText(text, sensitiveSnapshot()).slice(0, maxLength);
|
|
21694
21862
|
};
|
|
21695
21863
|
let resolveCancelled;
|
|
21696
|
-
const cancelledPromise = new Promise((
|
|
21697
|
-
resolveCancelled =
|
|
21864
|
+
const cancelledPromise = new Promise((resolve16) => {
|
|
21865
|
+
resolveCancelled = resolve16;
|
|
21698
21866
|
});
|
|
21699
21867
|
const endAuthority = (reason = "cloud_cancel") => {
|
|
21700
21868
|
if (stopReason) return;
|
|
@@ -21703,21 +21871,21 @@ var HostClient = class _HostClient {
|
|
|
21703
21871
|
authorityController.abort(reason);
|
|
21704
21872
|
const secretEntry = this.secretGrants.get(cancelKey);
|
|
21705
21873
|
if (secretEntry) {
|
|
21706
|
-
for (const
|
|
21874
|
+
for (const resolve16 of secretEntry.resolvers) resolve16({});
|
|
21707
21875
|
secretEntry.resolvers = [];
|
|
21708
21876
|
delete secretEntry.value;
|
|
21709
21877
|
}
|
|
21710
21878
|
this.secretGrants.delete(cancelKey);
|
|
21711
21879
|
const connectionEntry = this.connectionGrants.get(cancelKey);
|
|
21712
21880
|
if (connectionEntry) {
|
|
21713
|
-
for (const
|
|
21881
|
+
for (const resolve16 of connectionEntry.resolvers) resolve16([]);
|
|
21714
21882
|
connectionEntry.resolvers = [];
|
|
21715
21883
|
delete connectionEntry.value;
|
|
21716
21884
|
}
|
|
21717
21885
|
this.connectionGrants.delete(cancelKey);
|
|
21718
21886
|
const providerEntry = this.providerGrants.get(cancelKey);
|
|
21719
21887
|
if (providerEntry) {
|
|
21720
|
-
for (const
|
|
21888
|
+
for (const resolve16 of providerEntry.resolvers) resolve16([]);
|
|
21721
21889
|
providerEntry.resolvers = [];
|
|
21722
21890
|
delete providerEntry.value;
|
|
21723
21891
|
}
|
|
@@ -21725,8 +21893,8 @@ var HostClient = class _HostClient {
|
|
|
21725
21893
|
this.clearAuthorityExpiry(cancelKey);
|
|
21726
21894
|
const approvalWaiters = this.approvalWaiters.get(cancelKey);
|
|
21727
21895
|
if (approvalWaiters) {
|
|
21728
|
-
for (const
|
|
21729
|
-
|
|
21896
|
+
for (const resolve16 of approvalWaiters.values()) {
|
|
21897
|
+
resolve16({ approved: false, guidance: "task was cancelled" });
|
|
21730
21898
|
}
|
|
21731
21899
|
approvalWaiters.clear();
|
|
21732
21900
|
}
|
|
@@ -21852,9 +22020,9 @@ var HostClient = class _HostClient {
|
|
|
21852
22020
|
return value;
|
|
21853
22021
|
};
|
|
21854
22022
|
if (entry.value) return Promise.resolve(capture(entry.value));
|
|
21855
|
-
return new Promise((
|
|
21856
|
-
entry.resolvers.push((value) =>
|
|
21857
|
-
setTimeout(() =>
|
|
22023
|
+
return new Promise((resolve16) => {
|
|
22024
|
+
entry.resolvers.push((value) => resolve16(capture(value)));
|
|
22025
|
+
setTimeout(() => resolve16(capture(entry.value ?? {})), _HostClient.SECRETS_WAIT_MS);
|
|
21858
22026
|
});
|
|
21859
22027
|
};
|
|
21860
22028
|
const connections = () => {
|
|
@@ -21871,9 +22039,9 @@ var HostClient = class _HostClient {
|
|
|
21871
22039
|
return value;
|
|
21872
22040
|
};
|
|
21873
22041
|
if (entry.value) return Promise.resolve(capture(entry.value));
|
|
21874
|
-
return new Promise((
|
|
21875
|
-
entry.resolvers.push((value) =>
|
|
21876
|
-
setTimeout(() =>
|
|
22042
|
+
return new Promise((resolve16) => {
|
|
22043
|
+
entry.resolvers.push((value) => resolve16(capture(value)));
|
|
22044
|
+
setTimeout(() => resolve16(capture(entry.value ?? [])), _HostClient.SECRETS_WAIT_MS);
|
|
21877
22045
|
});
|
|
21878
22046
|
};
|
|
21879
22047
|
const providers = () => {
|
|
@@ -21890,9 +22058,9 @@ var HostClient = class _HostClient {
|
|
|
21890
22058
|
return value;
|
|
21891
22059
|
};
|
|
21892
22060
|
if (entry.value !== void 0) return Promise.resolve(capture(entry.value));
|
|
21893
|
-
return new Promise((
|
|
21894
|
-
entry.resolvers.push((value) =>
|
|
21895
|
-
setTimeout(() =>
|
|
22061
|
+
return new Promise((resolve16) => {
|
|
22062
|
+
entry.resolvers.push((value) => resolve16(capture(value)));
|
|
22063
|
+
setTimeout(() => resolve16(capture(entry.value ?? [])), _HostClient.SECRETS_WAIT_MS);
|
|
21896
22064
|
});
|
|
21897
22065
|
};
|
|
21898
22066
|
const linear = async () => {
|
|
@@ -21918,13 +22086,13 @@ var HostClient = class _HostClient {
|
|
|
21918
22086
|
payload: safe(payload, 5e4),
|
|
21919
22087
|
...questionChoices ? { questionChoices: [...questionChoices] } : {}
|
|
21920
22088
|
});
|
|
21921
|
-
return new Promise((
|
|
22089
|
+
return new Promise((resolve16) => {
|
|
21922
22090
|
const waiters = this.approvalWaiters.get(cancelKey) ?? /* @__PURE__ */ new Map();
|
|
21923
22091
|
this.approvalWaiters.set(cancelKey, waiters);
|
|
21924
|
-
waiters.set(requestId,
|
|
22092
|
+
waiters.set(requestId, resolve16);
|
|
21925
22093
|
void cancelledPromise.then(() => {
|
|
21926
22094
|
if (waiters.delete(requestId)) {
|
|
21927
|
-
|
|
22095
|
+
resolve16({ approved: false, guidance: "task was cancelled" });
|
|
21928
22096
|
}
|
|
21929
22097
|
});
|
|
21930
22098
|
});
|
|
@@ -21935,6 +22103,14 @@ var HostClient = class _HostClient {
|
|
|
21935
22103
|
const detail = parsed.error.issues.map((i) => `${i.path.join(".") || "op"}: ${i.message}`).join("; ");
|
|
21936
22104
|
return Promise.resolve({ ok: false, error: `invalid arguments: ${detail}` });
|
|
21937
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
|
+
}
|
|
21938
22114
|
if (requestId.length < 1 || requestId.length > 200) {
|
|
21939
22115
|
return Promise.resolve({ ok: false, error: "invalid provider settlement request id" });
|
|
21940
22116
|
}
|
|
@@ -21962,11 +22138,11 @@ var HostClient = class _HostClient {
|
|
|
21962
22138
|
if (existing) message = existing;
|
|
21963
22139
|
else terminalMessages.set(requestId, message);
|
|
21964
22140
|
}
|
|
21965
|
-
return new Promise((
|
|
22141
|
+
return new Promise((resolve16) => {
|
|
21966
22142
|
const waiters = this.agentOpWaiters.get(cancelKey) ?? /* @__PURE__ */ new Map();
|
|
21967
22143
|
this.agentOpWaiters.set(cancelKey, waiters);
|
|
21968
22144
|
if (waiters.has(requestId)) {
|
|
21969
|
-
|
|
22145
|
+
resolve16({ ok: false, error: "provider settlement request is already in flight" });
|
|
21970
22146
|
return;
|
|
21971
22147
|
}
|
|
21972
22148
|
const timer = setTimeout(() => {
|
|
@@ -21977,7 +22153,7 @@ var HostClient = class _HostClient {
|
|
|
21977
22153
|
(pending) => !(pending.type === "agent.op" && pending.requestId === requestId)
|
|
21978
22154
|
);
|
|
21979
22155
|
}
|
|
21980
|
-
|
|
22156
|
+
resolve16({
|
|
21981
22157
|
ok: false,
|
|
21982
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"
|
|
21983
22159
|
});
|
|
@@ -21985,7 +22161,7 @@ var HostClient = class _HostClient {
|
|
|
21985
22161
|
}, _HostClient.AGENT_OP_TIMEOUT_MS);
|
|
21986
22162
|
timer.unref?.();
|
|
21987
22163
|
waiters.set(requestId, {
|
|
21988
|
-
resolve:
|
|
22164
|
+
resolve: resolve16,
|
|
21989
22165
|
timer,
|
|
21990
22166
|
...terminal ? { terminalMessage: message } : {}
|
|
21991
22167
|
});
|
|
@@ -22031,12 +22207,12 @@ var HostClient = class _HostClient {
|
|
|
22031
22207
|
"No GitHub change was attempted; the authority grant request was invalid."
|
|
22032
22208
|
);
|
|
22033
22209
|
}
|
|
22034
|
-
const outcome = await new Promise((
|
|
22210
|
+
const outcome = await new Promise((resolve16) => {
|
|
22035
22211
|
const timer = setTimeout(() => {
|
|
22036
22212
|
const waiter = this.operationGrantWaiters.get(requestId);
|
|
22037
22213
|
if (!waiter) return;
|
|
22038
22214
|
this.operationGrantWaiters.delete(requestId);
|
|
22039
|
-
|
|
22215
|
+
resolve16({ grant: null, retryable: true, reason: "no_reply_from_zixt" });
|
|
22040
22216
|
}, this.operationGrantTimeoutMs);
|
|
22041
22217
|
timer.unref?.();
|
|
22042
22218
|
this.operationGrantWaiters.set(requestId, {
|
|
@@ -22049,9 +22225,9 @@ var HostClient = class _HostClient {
|
|
|
22049
22225
|
timer,
|
|
22050
22226
|
accept: (grant) => {
|
|
22051
22227
|
addSensitiveValues(providerGrantSensitiveValues(grant));
|
|
22052
|
-
|
|
22228
|
+
resolve16({ grant });
|
|
22053
22229
|
},
|
|
22054
|
-
deny: (retryable, reason, detail, retryAt, retryCode) =>
|
|
22230
|
+
deny: (retryable, reason, detail, retryAt, retryCode) => resolve16({
|
|
22055
22231
|
grant: null,
|
|
22056
22232
|
retryable,
|
|
22057
22233
|
reason,
|
|
@@ -22065,7 +22241,7 @@ var HostClient = class _HostClient {
|
|
|
22065
22241
|
} catch {
|
|
22066
22242
|
clearTimeout(timer);
|
|
22067
22243
|
this.operationGrantWaiters.delete(requestId);
|
|
22068
|
-
|
|
22244
|
+
resolve16({ grant: null, retryable: false, reason: "connection_unavailable" });
|
|
22069
22245
|
}
|
|
22070
22246
|
});
|
|
22071
22247
|
if (outcome.grant) {
|
|
@@ -22121,7 +22297,7 @@ var HostClient = class _HostClient {
|
|
|
22121
22297
|
)
|
|
22122
22298
|
);
|
|
22123
22299
|
}
|
|
22124
|
-
return new Promise((
|
|
22300
|
+
return new Promise((resolve16, reject3) => {
|
|
22125
22301
|
const timer = setTimeout(() => {
|
|
22126
22302
|
if (this.browserCredentialWaiters.delete(requestId)) {
|
|
22127
22303
|
reject3(
|
|
@@ -22140,7 +22316,7 @@ var HostClient = class _HostClient {
|
|
|
22140
22316
|
timer,
|
|
22141
22317
|
accept: (credential) => {
|
|
22142
22318
|
addSensitiveValues(webLoginSensitiveValues(credential));
|
|
22143
|
-
|
|
22319
|
+
resolve16(credential);
|
|
22144
22320
|
},
|
|
22145
22321
|
deny: (reason) => reject3(new Error(reason))
|
|
22146
22322
|
});
|
|
@@ -22428,8 +22604,8 @@ function watchForUpdates(options) {
|
|
|
22428
22604
|
|
|
22429
22605
|
// src/runners/process-tree.ts
|
|
22430
22606
|
import { spawn as spawn2 } from "node:child_process";
|
|
22431
|
-
import { readFile as
|
|
22432
|
-
import { isAbsolute as
|
|
22607
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
22608
|
+
import { isAbsolute as isAbsolute5, join as join4 } from "node:path";
|
|
22433
22609
|
var windowsProcessTreeModule = process.platform === "win32" ? import("@vscode/windows-process-tree").catch(() => null) : null;
|
|
22434
22610
|
var PROCESS_TERM_GRACE_MS = 500;
|
|
22435
22611
|
var PROCESS_EXIT_POLL_MS = 20;
|
|
@@ -22461,14 +22637,14 @@ async function observeWindowsGuardianNonce(pid, nonce) {
|
|
|
22461
22637
|
"Windows runner identity could not be observed"
|
|
22462
22638
|
);
|
|
22463
22639
|
}
|
|
22464
|
-
return new Promise((
|
|
22640
|
+
return new Promise((resolve16, reject3) => {
|
|
22465
22641
|
let done = false;
|
|
22466
22642
|
const finish = (result) => {
|
|
22467
22643
|
if (done) return;
|
|
22468
22644
|
done = true;
|
|
22469
22645
|
clearTimeout(timeout);
|
|
22470
22646
|
if (result instanceof Error) reject3(result);
|
|
22471
|
-
else
|
|
22647
|
+
else resolve16(result);
|
|
22472
22648
|
};
|
|
22473
22649
|
const timeout = setTimeout(
|
|
22474
22650
|
() => finish(
|
|
@@ -22502,7 +22678,7 @@ async function observeWindowsGuardianNonce(pid, nonce) {
|
|
|
22502
22678
|
async function observePosixGuardianNonce(pid, nonce) {
|
|
22503
22679
|
if (process.platform === "linux") {
|
|
22504
22680
|
try {
|
|
22505
|
-
const command = await
|
|
22681
|
+
const command = await readFile3(`/proc/${pid}/cmdline`);
|
|
22506
22682
|
const args = command.toString("utf8").split("\0");
|
|
22507
22683
|
return args.includes(nonce) ? "match" : "mismatch";
|
|
22508
22684
|
} catch (error52) {
|
|
@@ -22513,7 +22689,7 @@ async function observePosixGuardianNonce(pid, nonce) {
|
|
|
22513
22689
|
);
|
|
22514
22690
|
}
|
|
22515
22691
|
}
|
|
22516
|
-
return new Promise((
|
|
22692
|
+
return new Promise((resolve16, reject3) => {
|
|
22517
22693
|
const observer = spawn2("/bin/ps", ["-ww", "-o", "command=", "-p", String(pid)], {
|
|
22518
22694
|
stdio: ["ignore", "pipe", "ignore"]
|
|
22519
22695
|
});
|
|
@@ -22524,7 +22700,7 @@ async function observePosixGuardianNonce(pid, nonce) {
|
|
|
22524
22700
|
done = true;
|
|
22525
22701
|
clearTimeout(timeout);
|
|
22526
22702
|
if (result instanceof Error) reject3(result);
|
|
22527
|
-
else
|
|
22703
|
+
else resolve16(result);
|
|
22528
22704
|
};
|
|
22529
22705
|
const timeout = setTimeout(() => {
|
|
22530
22706
|
observer.kill("SIGKILL");
|
|
@@ -22571,7 +22747,7 @@ async function observeGuardianIdentity(pid, identity) {
|
|
|
22571
22747
|
return process.platform === "win32" ? observeWindowsGuardianNonce(pid, identity.nonce) : observePosixGuardianNonce(pid, identity.nonce);
|
|
22572
22748
|
}
|
|
22573
22749
|
function delay(ms) {
|
|
22574
|
-
return new Promise((
|
|
22750
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
22575
22751
|
}
|
|
22576
22752
|
function posixProcessRecordsFromPs(output) {
|
|
22577
22753
|
const records = [];
|
|
@@ -22604,7 +22780,7 @@ function posixProcessRecordsFromPs(output) {
|
|
|
22604
22780
|
return records;
|
|
22605
22781
|
}
|
|
22606
22782
|
async function snapshotPosixProcesses() {
|
|
22607
|
-
return new Promise((
|
|
22783
|
+
return new Promise((resolve16, reject3) => {
|
|
22608
22784
|
const observer = spawn2("/bin/ps", ["-axo", "uid=,pid=,ppid=,pgid=,stat="], {
|
|
22609
22785
|
stdio: ["ignore", "pipe", "ignore"]
|
|
22610
22786
|
});
|
|
@@ -22617,7 +22793,7 @@ async function snapshotPosixProcesses() {
|
|
|
22617
22793
|
if (error52) reject3(error52);
|
|
22618
22794
|
else {
|
|
22619
22795
|
try {
|
|
22620
|
-
|
|
22796
|
+
resolve16(posixProcessRecordsFromPs(output));
|
|
22621
22797
|
} catch (caught) {
|
|
22622
22798
|
reject3(caught);
|
|
22623
22799
|
}
|
|
@@ -22885,7 +23061,7 @@ async function observePosixGroupIdentity(records, pgid, identity) {
|
|
|
22885
23061
|
}
|
|
22886
23062
|
function defaultTaskkillCommand() {
|
|
22887
23063
|
const windowsRoot = process.env.SystemRoot ?? process.env.WINDIR;
|
|
22888
|
-
if (!windowsRoot || !
|
|
23064
|
+
if (!windowsRoot || !isAbsolute5(windowsRoot)) {
|
|
22889
23065
|
throw new ProcessTreeTerminationError(
|
|
22890
23066
|
"termination_failed",
|
|
22891
23067
|
"Windows runner tree termination authority is unavailable"
|
|
@@ -22952,7 +23128,7 @@ async function snapshotWindowsDescendants(rootPid) {
|
|
|
22952
23128
|
"Windows process-tree observation could not start"
|
|
22953
23129
|
);
|
|
22954
23130
|
}
|
|
22955
|
-
return new Promise((
|
|
23131
|
+
return new Promise((resolve16, reject3) => {
|
|
22956
23132
|
let done = false;
|
|
22957
23133
|
const timeout = setTimeout(() => {
|
|
22958
23134
|
if (done) return;
|
|
@@ -22979,7 +23155,7 @@ async function snapshotWindowsDescendants(rootPid) {
|
|
|
22979
23155
|
return;
|
|
22980
23156
|
}
|
|
22981
23157
|
try {
|
|
22982
|
-
|
|
23158
|
+
resolve16(completeWindowsDescendantPids(rootPid, processes));
|
|
22983
23159
|
} catch (caught) {
|
|
22984
23160
|
reject3(caught);
|
|
22985
23161
|
}
|
|
@@ -23026,7 +23202,7 @@ async function waitForProcessesExit(pids, timeoutMs) {
|
|
|
23026
23202
|
}
|
|
23027
23203
|
async function runTaskkill(pid, command, timeoutMs = TASKKILL_TIMEOUT_MS, independentlyTrackedPids = []) {
|
|
23028
23204
|
const trustedCommand = command ?? defaultTaskkillCommand();
|
|
23029
|
-
const result = await new Promise((
|
|
23205
|
+
const result = await new Promise((resolve16, reject3) => {
|
|
23030
23206
|
const killer = spawn2(trustedCommand, ["/PID", String(pid), "/T", "/F"], {
|
|
23031
23207
|
stdio: ["ignore", "pipe", "pipe"],
|
|
23032
23208
|
windowsHide: true
|
|
@@ -23061,7 +23237,7 @@ async function runTaskkill(pid, command, timeoutMs = TASKKILL_TIMEOUT_MS, indepe
|
|
|
23061
23237
|
done = true;
|
|
23062
23238
|
clearTimeout(timeout);
|
|
23063
23239
|
if (error52) reject3(error52);
|
|
23064
|
-
else
|
|
23240
|
+
else resolve16({ code: killer.exitCode, output, outputTruncated });
|
|
23065
23241
|
};
|
|
23066
23242
|
killer.once(
|
|
23067
23243
|
"error",
|
|
@@ -23273,7 +23449,7 @@ async function terminateProcessTree(child, childExited, options = {}) {
|
|
|
23273
23449
|
}
|
|
23274
23450
|
|
|
23275
23451
|
// src/release-state.ts
|
|
23276
|
-
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";
|
|
23277
23453
|
import { dirname as dirname2, join as join5 } from "node:path";
|
|
23278
23454
|
var STATE_FILE = "release-state.json";
|
|
23279
23455
|
var STATE_SCHEMA = 1;
|
|
@@ -23313,7 +23489,7 @@ function createReleaseStateStore(root) {
|
|
|
23313
23489
|
const path = releaseStatePath(root);
|
|
23314
23490
|
return {
|
|
23315
23491
|
async load() {
|
|
23316
|
-
const metadata = await
|
|
23492
|
+
const metadata = await lstat3(path).catch((error52) => {
|
|
23317
23493
|
if (error52.code === "ENOENT") return null;
|
|
23318
23494
|
throw error52;
|
|
23319
23495
|
});
|
|
@@ -23323,7 +23499,7 @@ function createReleaseStateStore(root) {
|
|
|
23323
23499
|
}
|
|
23324
23500
|
let value;
|
|
23325
23501
|
try {
|
|
23326
|
-
value = JSON.parse(await
|
|
23502
|
+
value = JSON.parse(await readFile4(path, "utf8"));
|
|
23327
23503
|
} catch {
|
|
23328
23504
|
throw new Error("Host release state cannot be read");
|
|
23329
23505
|
}
|
|
@@ -23348,7 +23524,7 @@ function createReleaseStateStore(root) {
|
|
|
23348
23524
|
}
|
|
23349
23525
|
},
|
|
23350
23526
|
async clear() {
|
|
23351
|
-
const present = await
|
|
23527
|
+
const present = await lstat3(path).then(
|
|
23352
23528
|
() => true,
|
|
23353
23529
|
(error52) => {
|
|
23354
23530
|
if (error52.code === "ENOENT") return false;
|
|
@@ -23365,7 +23541,7 @@ function createReleaseStateStore(root) {
|
|
|
23365
23541
|
// src/windows-job.ts
|
|
23366
23542
|
import { spawn as spawn3 } from "node:child_process";
|
|
23367
23543
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
23368
|
-
import { isAbsolute as
|
|
23544
|
+
import { isAbsolute as isAbsolute6, win32 } from "node:path";
|
|
23369
23545
|
var WINDOWS_CONTAINMENT_GATE_ENV = "ZIXT_WINDOWS_CONTAINMENT_GATE";
|
|
23370
23546
|
var WINDOWS_CONTAINMENT_GATE_PREFIX = "__ZIXT_WINDOWS_CONTAINMENT_READY__";
|
|
23371
23547
|
var WINDOWS_POST_CONTAINMENT_CWD_ENV = "ZIXT_WINDOWS_POST_CONTAINMENT_CWD";
|
|
@@ -23738,12 +23914,12 @@ async function createWindowsJobContainment(pid, options) {
|
|
|
23738
23914
|
stderr = `${stderr}${String(chunk)}`.slice(-HELPER_OUTPUT_LIMIT);
|
|
23739
23915
|
});
|
|
23740
23916
|
const helperEvents = helper;
|
|
23741
|
-
const exited = new Promise((
|
|
23917
|
+
const exited = new Promise((resolve16) => {
|
|
23742
23918
|
let completed = false;
|
|
23743
23919
|
const complete = (code, signal) => {
|
|
23744
23920
|
if (completed) return;
|
|
23745
23921
|
completed = true;
|
|
23746
|
-
|
|
23922
|
+
resolve16({ code, signal });
|
|
23747
23923
|
};
|
|
23748
23924
|
helperEvents.once("error", () => {
|
|
23749
23925
|
failProtocol(new Error("Windows Job Object helper could not start"));
|
|
@@ -23756,7 +23932,7 @@ async function createWindowsJobContainment(pid, options) {
|
|
|
23756
23932
|
});
|
|
23757
23933
|
const nextLine = async (expected) => {
|
|
23758
23934
|
if (protocolFailure) throw protocolFailure;
|
|
23759
|
-
const line = lines.shift() ?? await new Promise((
|
|
23935
|
+
const line = lines.shift() ?? await new Promise((resolve16, reject3) => {
|
|
23760
23936
|
const timer = setTimeout(
|
|
23761
23937
|
() => reject3(timeoutError("Windows Job Object helper did not answer in time")),
|
|
23762
23938
|
timeoutMs
|
|
@@ -23764,7 +23940,7 @@ async function createWindowsJobContainment(pid, options) {
|
|
|
23764
23940
|
timer.unref?.();
|
|
23765
23941
|
lineWaiters.push((value) => {
|
|
23766
23942
|
clearTimeout(timer);
|
|
23767
|
-
|
|
23943
|
+
resolve16(value);
|
|
23768
23944
|
});
|
|
23769
23945
|
});
|
|
23770
23946
|
if (protocolFailure) throw protocolFailure;
|
|
@@ -23777,8 +23953,8 @@ async function createWindowsJobContainment(pid, options) {
|
|
|
23777
23953
|
}
|
|
23778
23954
|
const stopped = await Promise.race([
|
|
23779
23955
|
exited.then(() => true),
|
|
23780
|
-
new Promise((
|
|
23781
|
-
const timer = setTimeout(() =>
|
|
23956
|
+
new Promise((resolve16) => {
|
|
23957
|
+
const timer = setTimeout(() => resolve16(false), timeoutMs);
|
|
23782
23958
|
timer.unref?.();
|
|
23783
23959
|
})
|
|
23784
23960
|
]);
|
|
@@ -23837,7 +24013,7 @@ async function awaitWindowsContainmentGate(env = process.env, input = process.st
|
|
|
23837
24013
|
if (nonce === void 0) return true;
|
|
23838
24014
|
if (!SAFE_NONCE2.test(nonce)) return false;
|
|
23839
24015
|
const expected = windowsContainmentGate(nonce).trimEnd();
|
|
23840
|
-
return new Promise((
|
|
24016
|
+
return new Promise((resolve16) => {
|
|
23841
24017
|
let pending = Buffer.alloc(0);
|
|
23842
24018
|
let settled = false;
|
|
23843
24019
|
const finish = (result) => {
|
|
@@ -23848,7 +24024,7 @@ async function awaitWindowsContainmentGate(env = process.env, input = process.st
|
|
|
23848
24024
|
input.off("end", onEnd);
|
|
23849
24025
|
input.off("error", onEnd);
|
|
23850
24026
|
if (result) input.pause();
|
|
23851
|
-
|
|
24027
|
+
resolve16(result);
|
|
23852
24028
|
};
|
|
23853
24029
|
const onData = (chunk) => {
|
|
23854
24030
|
pending = Buffer.concat([pending, chunk]);
|
|
@@ -23861,7 +24037,7 @@ async function awaitWindowsContainmentGate(env = process.env, input = process.st
|
|
|
23861
24037
|
const postContainmentCwd = env[WINDOWS_POST_CONTAINMENT_CWD_ENV];
|
|
23862
24038
|
delete env[WINDOWS_POST_CONTAINMENT_CWD_ENV];
|
|
23863
24039
|
if (postContainmentCwd !== void 0) {
|
|
23864
|
-
if (!
|
|
24040
|
+
if (!isAbsolute6(postContainmentCwd)) return finish(false);
|
|
23865
24041
|
try {
|
|
23866
24042
|
process.chdir(postContainmentCwd);
|
|
23867
24043
|
} catch {
|
|
@@ -23937,8 +24113,8 @@ function releaseManifestAtPrefix(prefix) {
|
|
|
23937
24113
|
async function validReleaseAtPrefix(prefix, version2) {
|
|
23938
24114
|
try {
|
|
23939
24115
|
const [entry, manifestText] = await Promise.all([
|
|
23940
|
-
|
|
23941
|
-
|
|
24116
|
+
lstat4(releaseEntryAtPrefix(prefix)),
|
|
24117
|
+
readFile5(releaseManifestAtPrefix(prefix), "utf8")
|
|
23942
24118
|
]);
|
|
23943
24119
|
if (!entry.isFile()) return false;
|
|
23944
24120
|
const manifest = JSON.parse(manifestText);
|
|
@@ -23957,14 +24133,14 @@ async function syncDirectory3(path) {
|
|
|
23957
24133
|
}
|
|
23958
24134
|
}
|
|
23959
24135
|
function installedReleaseVersion(entry, root = versionsRoot()) {
|
|
23960
|
-
if (!
|
|
23961
|
-
const relativeEntry =
|
|
23962
|
-
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)) {
|
|
23963
24139
|
return null;
|
|
23964
24140
|
}
|
|
23965
|
-
const version2 = relativeEntry.split(
|
|
24141
|
+
const version2 = relativeEntry.split(sep3)[0];
|
|
23966
24142
|
if (!version2 || !VERSION_DIR.test(version2)) return null;
|
|
23967
|
-
return
|
|
24143
|
+
return resolve4(entry) === resolve4(installedReleaseEntry(version2, root)) ? version2 : null;
|
|
23968
24144
|
}
|
|
23969
24145
|
function currentReleaseEntry(root = versionsRoot(), platform = process.platform) {
|
|
23970
24146
|
return join6(root, platform === "win32" ? "current-launcher.cjs" : CURRENT_RELEASE_ENTRY);
|
|
@@ -24029,7 +24205,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
|
|
|
24029
24205
|
if (platform === "win32") {
|
|
24030
24206
|
await mkdir3(root, { recursive: true, mode: 448 });
|
|
24031
24207
|
const launcher = currentReleaseEntry(root, platform);
|
|
24032
|
-
const existingLauncher = await
|
|
24208
|
+
const existingLauncher = await lstat4(launcher).catch((error52) => {
|
|
24033
24209
|
if (error52.code === "ENOENT") return null;
|
|
24034
24210
|
throw error52;
|
|
24035
24211
|
});
|
|
@@ -24037,7 +24213,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
|
|
|
24037
24213
|
if (!existingLauncher.isFile()) {
|
|
24038
24214
|
throw new Error("the Zixt Host Windows launcher is not a regular file");
|
|
24039
24215
|
}
|
|
24040
|
-
const contents = await
|
|
24216
|
+
const contents = await readFile5(launcher, "utf8");
|
|
24041
24217
|
if (!contents.startsWith(WINDOWS_LAUNCHER_OWNED_MARKER)) {
|
|
24042
24218
|
throw new Error("the Zixt Host Windows launcher is not owned by Zixt");
|
|
24043
24219
|
}
|
|
@@ -24048,7 +24224,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
|
|
|
24048
24224
|
await replaceDurableFile(launcher, WINDOWS_STABLE_LAUNCHER, sync);
|
|
24049
24225
|
}
|
|
24050
24226
|
const pointerPath = windowsReleasePointer(root);
|
|
24051
|
-
const existingPointer = await
|
|
24227
|
+
const existingPointer = await lstat4(pointerPath).catch((error52) => {
|
|
24052
24228
|
if (error52.code === "ENOENT") return null;
|
|
24053
24229
|
throw error52;
|
|
24054
24230
|
});
|
|
@@ -24058,7 +24234,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
|
|
|
24058
24234
|
}
|
|
24059
24235
|
let prior;
|
|
24060
24236
|
try {
|
|
24061
|
-
prior = JSON.parse(await
|
|
24237
|
+
prior = JSON.parse(await readFile5(pointerPath, "utf8"));
|
|
24062
24238
|
} catch {
|
|
24063
24239
|
throw new Error("the Zixt Host Windows release pointer is invalid");
|
|
24064
24240
|
}
|
|
@@ -24069,7 +24245,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
|
|
|
24069
24245
|
}
|
|
24070
24246
|
await replaceDurableFile(
|
|
24071
24247
|
pointerPath,
|
|
24072
|
-
`${JSON.stringify({ schema: 1, entry:
|
|
24248
|
+
`${JSON.stringify({ schema: 1, entry: resolve4(entry) })}
|
|
24073
24249
|
`,
|
|
24074
24250
|
sync
|
|
24075
24251
|
);
|
|
@@ -24078,7 +24254,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
|
|
|
24078
24254
|
if (platform !== "linux" && platform !== "darwin") return entry;
|
|
24079
24255
|
await mkdir3(root, { recursive: true, mode: 448 });
|
|
24080
24256
|
const current = currentReleaseEntry(root, platform);
|
|
24081
|
-
const existing = await
|
|
24257
|
+
const existing = await lstat4(current).catch((error52) => {
|
|
24082
24258
|
if (error52.code === "ENOENT") return null;
|
|
24083
24259
|
throw error52;
|
|
24084
24260
|
});
|
|
@@ -24100,9 +24276,9 @@ async function activatedReleaseVersion(root = versionsRoot(), platform = process
|
|
|
24100
24276
|
if (platform === "win32") {
|
|
24101
24277
|
try {
|
|
24102
24278
|
const pointerPath = windowsReleasePointer(root);
|
|
24103
|
-
const metadata = await
|
|
24279
|
+
const metadata = await lstat4(pointerPath);
|
|
24104
24280
|
if (!metadata.isFile() || metadata.size > 4 * 1024) return null;
|
|
24105
|
-
const value = JSON.parse(await
|
|
24281
|
+
const value = JSON.parse(await readFile5(pointerPath, "utf8"));
|
|
24106
24282
|
return value.schema === 1 && typeof value.entry === "string" ? installedReleaseVersion(value.entry, root) : null;
|
|
24107
24283
|
} catch {
|
|
24108
24284
|
return null;
|
|
@@ -24112,7 +24288,7 @@ async function activatedReleaseVersion(root = versionsRoot(), platform = process
|
|
|
24112
24288
|
try {
|
|
24113
24289
|
const current = currentReleaseEntry(root, platform);
|
|
24114
24290
|
const target = await readlink(current);
|
|
24115
|
-
return installedReleaseVersion(
|
|
24291
|
+
return installedReleaseVersion(resolve4(dirname3(current), target), root);
|
|
24116
24292
|
} catch {
|
|
24117
24293
|
return null;
|
|
24118
24294
|
}
|
|
@@ -24273,7 +24449,7 @@ async function installRelease(version2, options = {}) {
|
|
|
24273
24449
|
installerContainmentSetupError = error52;
|
|
24274
24450
|
return null;
|
|
24275
24451
|
}) : Promise.resolve(null);
|
|
24276
|
-
const installed = await new Promise((
|
|
24452
|
+
const installed = await new Promise((resolve16, reject3) => {
|
|
24277
24453
|
let finished = false;
|
|
24278
24454
|
let cleanupStarted = false;
|
|
24279
24455
|
let exitObserved = false;
|
|
@@ -24289,7 +24465,7 @@ async function installRelease(version2, options = {}) {
|
|
|
24289
24465
|
finished = true;
|
|
24290
24466
|
clearTimeout(timer);
|
|
24291
24467
|
options.signal?.removeEventListener("abort", requestCleanup);
|
|
24292
|
-
|
|
24468
|
+
resolve16(result);
|
|
24293
24469
|
};
|
|
24294
24470
|
const requestCleanup = () => {
|
|
24295
24471
|
if (cleanupStarted || finished) return;
|
|
@@ -24386,7 +24562,7 @@ async function installRelease(version2, options = {}) {
|
|
|
24386
24562
|
return null;
|
|
24387
24563
|
}
|
|
24388
24564
|
if (await validReleaseAtPrefix(prefix, version2)) return entry;
|
|
24389
|
-
const existing = await
|
|
24565
|
+
const existing = await lstat4(prefix).catch((error52) => {
|
|
24390
24566
|
if (error52.code === "ENOENT") return null;
|
|
24391
24567
|
throw error52;
|
|
24392
24568
|
});
|
|
@@ -24405,7 +24581,7 @@ async function installRelease(version2, options = {}) {
|
|
|
24405
24581
|
}
|
|
24406
24582
|
async function pruneInstalledVersions(keep, root = versionsRoot()) {
|
|
24407
24583
|
const protectedDirs = new Set(keep);
|
|
24408
|
-
const running = process.argv[1] ?
|
|
24584
|
+
const running = process.argv[1] ? resolve4(process.argv[1]) : null;
|
|
24409
24585
|
let entries;
|
|
24410
24586
|
try {
|
|
24411
24587
|
entries = await readdir2(root);
|
|
@@ -24416,7 +24592,7 @@ async function pruneInstalledVersions(keep, root = versionsRoot()) {
|
|
|
24416
24592
|
for (const name of entries) {
|
|
24417
24593
|
if (protectedDirs.has(name) || !VERSION_DIR.test(name)) continue;
|
|
24418
24594
|
const dir = join6(root, name);
|
|
24419
|
-
if (running && running.startsWith(`${dir}${
|
|
24595
|
+
if (running && running.startsWith(`${dir}${sep3}`)) continue;
|
|
24420
24596
|
try {
|
|
24421
24597
|
await rm3(dir, { recursive: true, force: true });
|
|
24422
24598
|
removed.push(name);
|
|
@@ -24577,7 +24753,7 @@ async function runWorkerCompatibilityProxy(env = process.env, argv = process.arg
|
|
|
24577
24753
|
const ownership = consumeWorkerOwnershipArguments(argv, env);
|
|
24578
24754
|
const nonce = env[WORKER_WATCHDOG_NONCE_ENV];
|
|
24579
24755
|
const ownershipFile = env[WORKER_OWNERSHIP_FILE_ENV];
|
|
24580
|
-
if (typeof target !== "string" || !
|
|
24756
|
+
if (typeof target !== "string" || !isAbsolute7(target) || typeof nonce !== "string" || typeof ownershipFile !== "string" || !ownership.requested || !ownership.valid) {
|
|
24581
24757
|
return 1;
|
|
24582
24758
|
}
|
|
24583
24759
|
if (!recordWorkerOwnership(ownershipFile, nonce)) return 1;
|
|
@@ -24602,11 +24778,11 @@ async function runWorkerCompatibilityProxy(env = process.env, argv = process.arg
|
|
|
24602
24778
|
child.stdin?.on("error", () => {
|
|
24603
24779
|
});
|
|
24604
24780
|
process.stdin.pipe(child.stdin);
|
|
24605
|
-
return new Promise((
|
|
24606
|
-
child.once("error", () =>
|
|
24781
|
+
return new Promise((resolve16) => {
|
|
24782
|
+
child.once("error", () => resolve16(1));
|
|
24607
24783
|
child.once("exit", (code) => {
|
|
24608
24784
|
process.stdin.unpipe(child.stdin);
|
|
24609
|
-
|
|
24785
|
+
resolve16(code ?? 1);
|
|
24610
24786
|
});
|
|
24611
24787
|
});
|
|
24612
24788
|
}
|
|
@@ -24644,7 +24820,7 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24644
24820
|
delete env[WORKER_WATCHDOG_FILE_ENV];
|
|
24645
24821
|
delete env[WORKER_OWNERSHIP_FILE_ENV];
|
|
24646
24822
|
delete env[SUPERVISOR_OWNERSHIP_FILE_ENV];
|
|
24647
|
-
const generationNonce = ownershipDirectory ?
|
|
24823
|
+
const generationNonce = ownershipDirectory ? basename3(ownershipDirectory) : null;
|
|
24648
24824
|
if (ownershipDirectory && generationNonce) {
|
|
24649
24825
|
env[LAUNCHER_OWNERSHIP_DIR_ENV] = ownershipDirectory;
|
|
24650
24826
|
env[SUPERVISOR_OWNERSHIP_FILE_ENV] = join6(ownershipDirectory, `${generationNonce}.json`);
|
|
@@ -24684,11 +24860,11 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24684
24860
|
const waitOrStop = async (ms) => {
|
|
24685
24861
|
if (stopping) return false;
|
|
24686
24862
|
if (!customDelay) {
|
|
24687
|
-
await new Promise((
|
|
24863
|
+
await new Promise((resolve16) => {
|
|
24688
24864
|
const finish = () => {
|
|
24689
24865
|
clearTimeout(timer);
|
|
24690
24866
|
stopController.signal.removeEventListener("abort", finish);
|
|
24691
|
-
|
|
24867
|
+
resolve16();
|
|
24692
24868
|
};
|
|
24693
24869
|
const timer = setTimeout(finish, ms);
|
|
24694
24870
|
stopController.signal.addEventListener("abort", finish, { once: true });
|
|
@@ -24696,8 +24872,8 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24696
24872
|
return !stopping;
|
|
24697
24873
|
}
|
|
24698
24874
|
let finishStop;
|
|
24699
|
-
const stopped = new Promise((
|
|
24700
|
-
finishStop = () =>
|
|
24875
|
+
const stopped = new Promise((resolve16) => {
|
|
24876
|
+
finishStop = () => resolve16();
|
|
24701
24877
|
stopController.signal.addEventListener("abort", finishStop, { once: true });
|
|
24702
24878
|
});
|
|
24703
24879
|
await Promise.race([customDelay(ms), stopped]);
|
|
@@ -24722,7 +24898,7 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24722
24898
|
return false;
|
|
24723
24899
|
};
|
|
24724
24900
|
const cleanupOwnershipGeneration = async (directory) => {
|
|
24725
|
-
const generationNonce =
|
|
24901
|
+
const generationNonce = basename3(directory);
|
|
24726
24902
|
const firstRecords = await readWorkerOwnershipRecords(directory);
|
|
24727
24903
|
const supervisorRecord = firstRecords.find((record2) => record2.nonce === generationNonce);
|
|
24728
24904
|
if (firstRecords.length > 0 && !supervisorRecord) {
|
|
@@ -24820,19 +24996,19 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24820
24996
|
child = spawnSupervisor(entry, version2, ownershipDirectory, containmentGateNonce);
|
|
24821
24997
|
const launchedSupervisor = child;
|
|
24822
24998
|
let resolveChildExited;
|
|
24823
|
-
const childExited = new Promise((
|
|
24824
|
-
resolveChildExited =
|
|
24999
|
+
const childExited = new Promise((resolve16) => {
|
|
25000
|
+
resolveChildExited = resolve16;
|
|
24825
25001
|
});
|
|
24826
25002
|
const supervisorContainmentAbort = new AbortController();
|
|
24827
25003
|
void childExited.then(() => supervisorContainmentAbort.abort());
|
|
24828
25004
|
const outcomePromise = new Promise(
|
|
24829
|
-
(
|
|
25005
|
+
(resolve16) => {
|
|
24830
25006
|
let observed = false;
|
|
24831
25007
|
const finish = (code, signal) => {
|
|
24832
25008
|
if (observed) return;
|
|
24833
25009
|
observed = true;
|
|
24834
25010
|
resolveChildExited();
|
|
24835
|
-
|
|
25011
|
+
resolve16({ code, signal });
|
|
24836
25012
|
};
|
|
24837
25013
|
child.once("error", () => finish(1, null));
|
|
24838
25014
|
child.once("exit", finish);
|
|
@@ -24841,7 +25017,7 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24841
25017
|
let supervisorContainment = null;
|
|
24842
25018
|
try {
|
|
24843
25019
|
if (containmentGateNonce) {
|
|
24844
|
-
const supervisorIdentity = ownershipDirectory ?
|
|
25020
|
+
const supervisorIdentity = ownershipDirectory ? basename3(ownershipDirectory) : null;
|
|
24845
25021
|
if (!supervisorIdentity) {
|
|
24846
25022
|
throw new Error("supervisor containment identity is unavailable");
|
|
24847
25023
|
}
|
|
@@ -24853,12 +25029,12 @@ async function launchHostSupervisor(options = {}) {
|
|
|
24853
25029
|
if (!supervisorContainment || !launchedSupervisor.stdin) {
|
|
24854
25030
|
throw new Error("supervisor Job Object gate is unavailable");
|
|
24855
25031
|
}
|
|
24856
|
-
await new Promise((
|
|
25032
|
+
await new Promise((resolve16, reject3) => {
|
|
24857
25033
|
launchedSupervisor.stdin.write(
|
|
24858
25034
|
windowsContainmentGate(containmentGateNonce),
|
|
24859
25035
|
(error52) => {
|
|
24860
25036
|
if (error52) reject3(error52);
|
|
24861
|
-
else
|
|
25037
|
+
else resolve16();
|
|
24862
25038
|
}
|
|
24863
25039
|
);
|
|
24864
25040
|
});
|
|
@@ -24930,9 +25106,9 @@ async function superviseHost(options = {}) {
|
|
|
24930
25106
|
const log2 = options.log ?? ((message) => console.error(message));
|
|
24931
25107
|
const signalWorker = options.signalWorker ?? signalWorkerGroup;
|
|
24932
25108
|
const inheritedOwnershipDirectory = process.env[LAUNCHER_OWNERSHIP_DIR_ENV];
|
|
24933
|
-
const launcherOwnershipDirectory = productionLifecycle && typeof inheritedOwnershipDirectory === "string" &&
|
|
25109
|
+
const launcherOwnershipDirectory = productionLifecycle && typeof inheritedOwnershipDirectory === "string" && isAbsolute7(inheritedOwnershipDirectory) ? inheritedOwnershipDirectory : null;
|
|
24934
25110
|
if (productionLifecycle && isSupervisorRole() && launcherOwnershipDirectory) {
|
|
24935
|
-
const generationNonce =
|
|
25111
|
+
const generationNonce = basename3(launcherOwnershipDirectory);
|
|
24936
25112
|
const expectedOwnershipFile = join6(launcherOwnershipDirectory, `${generationNonce}.json`);
|
|
24937
25113
|
const configuredOwnershipFile = process.env[SUPERVISOR_OWNERSHIP_FILE_ENV];
|
|
24938
25114
|
if (process.argv0 !== generationNonce || configuredOwnershipFile !== expectedOwnershipFile || !recordWorkerOwnership(expectedOwnershipFile, generationNonce)) {
|
|
@@ -25000,18 +25176,18 @@ async function superviseHost(options = {}) {
|
|
|
25000
25176
|
}
|
|
25001
25177
|
}
|
|
25002
25178
|
let announceShutdown;
|
|
25003
|
-
const shutdownAnnounced = new Promise((
|
|
25004
|
-
announceShutdown =
|
|
25179
|
+
const shutdownAnnounced = new Promise((resolve16) => {
|
|
25180
|
+
announceShutdown = resolve16;
|
|
25005
25181
|
});
|
|
25006
25182
|
const attempted = /* @__PURE__ */ new Set();
|
|
25007
25183
|
const waitOrShutdown = async (ms) => {
|
|
25008
25184
|
if (shuttingDown2) return false;
|
|
25009
25185
|
if (!customDelay) {
|
|
25010
|
-
await new Promise((
|
|
25186
|
+
await new Promise((resolve16) => {
|
|
25011
25187
|
const finish = () => {
|
|
25012
25188
|
clearTimeout(timer);
|
|
25013
25189
|
shutdownController.signal.removeEventListener("abort", finish);
|
|
25014
|
-
|
|
25190
|
+
resolve16();
|
|
25015
25191
|
};
|
|
25016
25192
|
const timer = setTimeout(finish, ms);
|
|
25017
25193
|
shutdownController.signal.addEventListener("abort", finish, { once: true });
|
|
@@ -25154,19 +25330,19 @@ async function superviseHost(options = {}) {
|
|
|
25154
25330
|
child = spawnWorker(command, watchdogLaunch, compatibilityOwnership, containmentGateNonce);
|
|
25155
25331
|
const watchedChild = child;
|
|
25156
25332
|
let resolveChildExited;
|
|
25157
|
-
const childExited = new Promise((
|
|
25158
|
-
resolveChildExited =
|
|
25333
|
+
const childExited = new Promise((resolve16) => {
|
|
25334
|
+
resolveChildExited = resolve16;
|
|
25159
25335
|
});
|
|
25160
25336
|
const workerContainmentAbort = new AbortController();
|
|
25161
25337
|
void childExited.then(() => workerContainmentAbort.abort());
|
|
25162
25338
|
const outcomePromise = new Promise(
|
|
25163
|
-
(
|
|
25339
|
+
(resolve16) => {
|
|
25164
25340
|
let observed = false;
|
|
25165
25341
|
const finish = (result) => {
|
|
25166
25342
|
if (observed) return;
|
|
25167
25343
|
observed = true;
|
|
25168
25344
|
resolveChildExited();
|
|
25169
|
-
|
|
25345
|
+
resolve16(result);
|
|
25170
25346
|
};
|
|
25171
25347
|
watchedChild.once("error", () => finish({ code: 1, signal: null }));
|
|
25172
25348
|
watchedChild.once(
|
|
@@ -25188,10 +25364,10 @@ async function superviseHost(options = {}) {
|
|
|
25188
25364
|
if (!workerContainment || !watchedChild.stdin) {
|
|
25189
25365
|
throw new Error("worker Job Object gate is unavailable");
|
|
25190
25366
|
}
|
|
25191
|
-
await new Promise((
|
|
25367
|
+
await new Promise((resolve16, reject3) => {
|
|
25192
25368
|
watchedChild.stdin.write(windowsContainmentGate(containmentGateNonce), (error52) => {
|
|
25193
25369
|
if (error52) reject3(error52);
|
|
25194
|
-
else
|
|
25370
|
+
else resolve16();
|
|
25195
25371
|
});
|
|
25196
25372
|
});
|
|
25197
25373
|
}
|
|
@@ -25644,9 +25820,9 @@ function createDemoBrowserAdapterFactory() {
|
|
|
25644
25820
|
}
|
|
25645
25821
|
|
|
25646
25822
|
// src/browser/manager.ts
|
|
25647
|
-
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";
|
|
25648
25824
|
import { homedir as homedir2 } from "node:os";
|
|
25649
|
-
import { dirname as dirname4, join as join7, resolve as
|
|
25825
|
+
import { dirname as dirname4, join as join7, resolve as resolve5 } from "node:path";
|
|
25650
25826
|
var SAFE_SEGMENT = /^[A-Za-z0-9_-]{1,200}$/;
|
|
25651
25827
|
var FRAME_MIN_INTERVAL_MS = 100;
|
|
25652
25828
|
var IDLE_TIMEOUT_MS = 15 * 6e4;
|
|
@@ -25744,8 +25920,8 @@ var BrowserManager = class {
|
|
|
25744
25920
|
}
|
|
25745
25921
|
}
|
|
25746
25922
|
exactChild(root, child) {
|
|
25747
|
-
const canonicalRoot =
|
|
25748
|
-
const target =
|
|
25923
|
+
const canonicalRoot = resolve5(root);
|
|
25924
|
+
const target = resolve5(canonicalRoot, child);
|
|
25749
25925
|
if (dirname4(target) !== canonicalRoot) {
|
|
25750
25926
|
throw new Error("browser profile path escaped its owned root");
|
|
25751
25927
|
}
|
|
@@ -25753,7 +25929,7 @@ var BrowserManager = class {
|
|
|
25753
25929
|
}
|
|
25754
25930
|
async ensureOwnedDirectory(path) {
|
|
25755
25931
|
await mkdir4(path, { recursive: true, mode: 448 });
|
|
25756
|
-
const stat3 = await
|
|
25932
|
+
const stat3 = await lstat5(path);
|
|
25757
25933
|
if (!stat3.isDirectory() || stat3.isSymbolicLink()) {
|
|
25758
25934
|
throw new Error("browser profile root must be an owned directory, not a symbolic link");
|
|
25759
25935
|
}
|
|
@@ -25788,7 +25964,7 @@ var BrowserManager = class {
|
|
|
25788
25964
|
}
|
|
25789
25965
|
async readProfileState(agentId) {
|
|
25790
25966
|
try {
|
|
25791
|
-
const raw = JSON.parse(await
|
|
25967
|
+
const raw = JSON.parse(await readFile6(this.statePath(agentId), "utf8"));
|
|
25792
25968
|
if (typeof raw !== "object" || raw === null || !Number.isInteger(raw.revision) || Number(raw.revision) < 0 || !["allowed", "purged"].includes(String(raw.state))) {
|
|
25793
25969
|
throw new Error("browser profile lifecycle marker is invalid");
|
|
25794
25970
|
}
|
|
@@ -25887,7 +26063,7 @@ var BrowserManager = class {
|
|
|
25887
26063
|
await this.ensureOwnedDirectory(this.profileRoot);
|
|
25888
26064
|
const profileDir = this.profilePath(agentId);
|
|
25889
26065
|
try {
|
|
25890
|
-
const existingProfile = await
|
|
26066
|
+
const existingProfile = await lstat5(profileDir);
|
|
25891
26067
|
if (existingProfile.isSymbolicLink() || !existingProfile.isDirectory()) {
|
|
25892
26068
|
throw new Error("browser profile path is not an owned directory");
|
|
25893
26069
|
}
|
|
@@ -26654,9 +26830,9 @@ function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
|
|
|
26654
26830
|
// src/runners/cli-runner.ts
|
|
26655
26831
|
import { spawn as spawn8 } from "node:child_process";
|
|
26656
26832
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
26657
|
-
import { lstat as
|
|
26833
|
+
import { lstat as lstat11, mkdir as mkdir10, realpath as realpath8 } from "node:fs/promises";
|
|
26658
26834
|
import { homedir as homedir4 } from "node:os";
|
|
26659
|
-
import { dirname as dirname7, isAbsolute as
|
|
26835
|
+
import { dirname as dirname7, isAbsolute as isAbsolute14, join as join14, resolve as resolve9 } from "node:path";
|
|
26660
26836
|
|
|
26661
26837
|
// src/tool-packs/browser/tool-definitions.ts
|
|
26662
26838
|
function definition(name, description, properties, required2 = []) {
|
|
@@ -26911,7 +27087,7 @@ function createBrowserToolPack(deps) {
|
|
|
26911
27087
|
}
|
|
26912
27088
|
|
|
26913
27089
|
// src/tool-packs/provider-intents.ts
|
|
26914
|
-
import { createHash, randomUUID as randomUUID3 } from "node:crypto";
|
|
27090
|
+
import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
|
|
26915
27091
|
|
|
26916
27092
|
// src/tool-packs/github/rest-transport.ts
|
|
26917
27093
|
var MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
@@ -27157,7 +27333,7 @@ function canonicalJson(value) {
|
|
|
27157
27333
|
return `{${Object.entries(value).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([key, child]) => `${JSON.stringify(key)}:${canonicalJson(child)}`).join(",")}}`;
|
|
27158
27334
|
}
|
|
27159
27335
|
function payloadFingerprint(value) {
|
|
27160
|
-
return
|
|
27336
|
+
return createHash2("sha256").update(canonicalJson(value)).digest("hex");
|
|
27161
27337
|
}
|
|
27162
27338
|
function claimResult(result) {
|
|
27163
27339
|
if (!result.ok || !result.result || typeof result.result !== "object") return null;
|
|
@@ -29349,14 +29525,14 @@ function createGithubPushOrchestrator(input) {
|
|
|
29349
29525
|
// src/tool-packs/github/git-bridge.ts
|
|
29350
29526
|
import { spawn as spawn5 } from "node:child_process";
|
|
29351
29527
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
29352
|
-
import { chmod as chmod3, lstat as
|
|
29353
|
-
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";
|
|
29354
29530
|
|
|
29355
29531
|
// src/tool-packs/github/git-credential-broker.ts
|
|
29356
29532
|
import { createServer } from "node:http";
|
|
29357
29533
|
import { randomBytes, randomUUID as randomUUID6, timingSafeEqual } from "node:crypto";
|
|
29358
|
-
import { chmod as chmod2, lstat as
|
|
29359
|
-
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";
|
|
29360
29536
|
var MAX_REQUEST_BYTES = 16 * 1024;
|
|
29361
29537
|
var FILE_MODE = 384;
|
|
29362
29538
|
var HELPER_SOURCE = String.raw`'use strict';
|
|
@@ -29469,8 +29645,8 @@ async function readBoundedBody2(request) {
|
|
|
29469
29645
|
return Buffer.concat(chunks, size);
|
|
29470
29646
|
}
|
|
29471
29647
|
function assertChildPath(parent, child) {
|
|
29472
|
-
const path =
|
|
29473
|
-
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") ||
|
|
29648
|
+
const path = relative4(parent, child);
|
|
29649
|
+
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute8(path)) {
|
|
29474
29650
|
throw new Error("Git credential helper path escaped its private run directory");
|
|
29475
29651
|
}
|
|
29476
29652
|
}
|
|
@@ -29480,11 +29656,11 @@ async function createGithubGitCredentialBroker(input) {
|
|
|
29480
29656
|
throw new Error("GitHub credential authority has expired");
|
|
29481
29657
|
}
|
|
29482
29658
|
assertRepositoryFullName(input.repositoryFullName);
|
|
29483
|
-
const rootEntry = await
|
|
29659
|
+
const rootEntry = await lstat6(input.runArtifactsRoot);
|
|
29484
29660
|
if (!rootEntry.isDirectory() || rootEntry.isSymbolicLink()) {
|
|
29485
29661
|
throw new Error("Git credential broker requires a private real run directory");
|
|
29486
29662
|
}
|
|
29487
|
-
const runRoot = await
|
|
29663
|
+
const runRoot = await realpath3(input.runArtifactsRoot);
|
|
29488
29664
|
const helperPath = join8(runRoot, `git-credential-${randomUUID6()}.cjs`);
|
|
29489
29665
|
assertChildPath(runRoot, helperPath);
|
|
29490
29666
|
await writeFile(helperPath, HELPER_SOURCE, { flag: "wx", mode: FILE_MODE });
|
|
@@ -29584,26 +29760,26 @@ ${stderr}`;
|
|
|
29584
29760
|
return explicitGithubRefusal ? "provider_rejected" : "command_failed";
|
|
29585
29761
|
}
|
|
29586
29762
|
function assertBelow(parent, child, label) {
|
|
29587
|
-
const path =
|
|
29588
|
-
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") ||
|
|
29763
|
+
const path = relative5(parent, child);
|
|
29764
|
+
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute9(path)) {
|
|
29589
29765
|
throw new GithubGitProcessError("invalid_input");
|
|
29590
29766
|
}
|
|
29591
29767
|
void label;
|
|
29592
29768
|
}
|
|
29593
29769
|
async function requireRealDirectory(path, label) {
|
|
29594
|
-
const entry = await
|
|
29770
|
+
const entry = await lstat7(path).catch(() => null);
|
|
29595
29771
|
if (!entry || !entry.isDirectory() || entry.isSymbolicLink()) {
|
|
29596
29772
|
void label;
|
|
29597
29773
|
throw new GithubGitProcessError("invalid_input");
|
|
29598
29774
|
}
|
|
29599
|
-
return
|
|
29775
|
+
return realpath4(path);
|
|
29600
29776
|
}
|
|
29601
29777
|
async function validateTokenlessPaths(command) {
|
|
29602
29778
|
if (command.kind === "clone-from-bridge") {
|
|
29603
|
-
if (!
|
|
29779
|
+
if (!isAbsolute9(command.destination)) throw new GithubGitProcessError("invalid_input");
|
|
29604
29780
|
const parent = await requireRealDirectory(dirname5(command.destination), "clone parent");
|
|
29605
29781
|
assertBelow(parent, command.destination, "clone destination");
|
|
29606
|
-
const destination = await
|
|
29782
|
+
const destination = await lstat7(command.destination).catch((error52) => {
|
|
29607
29783
|
if (error52.code === "ENOENT") return null;
|
|
29608
29784
|
throw error52;
|
|
29609
29785
|
});
|
|
@@ -29611,7 +29787,7 @@ async function validateTokenlessPaths(command) {
|
|
|
29611
29787
|
return;
|
|
29612
29788
|
}
|
|
29613
29789
|
if ("repositoryPath" in command) {
|
|
29614
|
-
if (!
|
|
29790
|
+
if (!isAbsolute9(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
|
|
29615
29791
|
const repositoryPath5 = await requireRealDirectory(command.repositoryPath, "repository path");
|
|
29616
29792
|
if (repositoryPath5 !== command.repositoryPath) throw new GithubGitProcessError("invalid_input");
|
|
29617
29793
|
}
|
|
@@ -29691,7 +29867,7 @@ async function runGit(input, args, env) {
|
|
|
29691
29867
|
if (input.authoritySignal.aborted || input.cancelledNow()) {
|
|
29692
29868
|
throw new GithubGitProcessError("cancelled");
|
|
29693
29869
|
}
|
|
29694
|
-
if (!
|
|
29870
|
+
if (!isAbsolute9(input.executablePath)) throw new GithubGitProcessError("invalid_input");
|
|
29695
29871
|
const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
29696
29872
|
if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > DEFAULT_TIMEOUT_MS2) {
|
|
29697
29873
|
throw new GithubGitProcessError("invalid_input");
|
|
@@ -29711,8 +29887,8 @@ async function runGit(input, args, env) {
|
|
|
29711
29887
|
let settled = false;
|
|
29712
29888
|
let stopping = false;
|
|
29713
29889
|
let resolveExited;
|
|
29714
|
-
const exited = new Promise((
|
|
29715
|
-
resolveExited =
|
|
29890
|
+
const exited = new Promise((resolve16) => {
|
|
29891
|
+
resolveExited = resolve16;
|
|
29716
29892
|
});
|
|
29717
29893
|
child.once("exit", resolveExited);
|
|
29718
29894
|
const cleanup = () => {
|
|
@@ -29797,7 +29973,7 @@ function tokenlessArgs(command) {
|
|
|
29797
29973
|
switch (command.kind) {
|
|
29798
29974
|
case "clone-from-bridge":
|
|
29799
29975
|
assertRef(command.branch);
|
|
29800
|
-
if (!
|
|
29976
|
+
if (!isAbsolute9(command.destination)) throw new GithubGitProcessError("invalid_input");
|
|
29801
29977
|
return [
|
|
29802
29978
|
"clone",
|
|
29803
29979
|
"--no-recurse-submodules",
|
|
@@ -29809,7 +29985,7 @@ function tokenlessArgs(command) {
|
|
|
29809
29985
|
];
|
|
29810
29986
|
case "fetch-from-bridge":
|
|
29811
29987
|
assertFetchRefspecs(command.refspecs);
|
|
29812
|
-
if (!
|
|
29988
|
+
if (!isAbsolute9(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
|
|
29813
29989
|
return [
|
|
29814
29990
|
"-C",
|
|
29815
29991
|
command.repositoryPath,
|
|
@@ -29821,7 +29997,7 @@ function tokenlessArgs(command) {
|
|
|
29821
29997
|
...command.refspecs
|
|
29822
29998
|
];
|
|
29823
29999
|
case "copy-commit-to-bridge":
|
|
29824
|
-
if (!
|
|
30000
|
+
if (!isAbsolute9(command.repositoryPath) || !SHA.test(command.sha)) {
|
|
29825
30001
|
throw new GithubGitProcessError("invalid_input");
|
|
29826
30002
|
}
|
|
29827
30003
|
return [
|
|
@@ -29833,11 +30009,11 @@ function tokenlessArgs(command) {
|
|
|
29833
30009
|
`${command.sha}:refs/zixt/push-source`
|
|
29834
30010
|
];
|
|
29835
30011
|
case "rev-parse":
|
|
29836
|
-
if (!
|
|
30012
|
+
if (!isAbsolute9(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
|
|
29837
30013
|
assertRef(command.ref);
|
|
29838
30014
|
return ["-C", command.repositoryPath, "rev-parse", "--verify", `${command.ref}^{commit}`];
|
|
29839
30015
|
case "remote-configure":
|
|
29840
|
-
if (!
|
|
30016
|
+
if (!isAbsolute9(command.repositoryPath) || !REPOSITORY.test(command.repositoryFullName)) {
|
|
29841
30017
|
throw new GithubGitProcessError("invalid_input");
|
|
29842
30018
|
}
|
|
29843
30019
|
return [
|
|
@@ -29849,7 +30025,7 @@ function tokenlessArgs(command) {
|
|
|
29849
30025
|
`https://github.com/${command.repositoryFullName}.git`
|
|
29850
30026
|
];
|
|
29851
30027
|
case "status":
|
|
29852
|
-
if (!
|
|
30028
|
+
if (!isAbsolute9(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
|
|
29853
30029
|
return [
|
|
29854
30030
|
"-C",
|
|
29855
30031
|
command.repositoryPath,
|
|
@@ -29879,7 +30055,7 @@ function createGithubGitBridge(input) {
|
|
|
29879
30055
|
})();
|
|
29880
30056
|
const requireBridge = async (value) => {
|
|
29881
30057
|
const current = await roots();
|
|
29882
|
-
if (!
|
|
30058
|
+
if (!isAbsolute9(value) || !active.has(value)) throw new GithubGitProcessError("invalid_input");
|
|
29883
30059
|
const real = await requireRealDirectory(value, "git bridge");
|
|
29884
30060
|
assertBelow(current.bridges, real, "git bridge");
|
|
29885
30061
|
if (real !== value) throw new GithubGitProcessError("invalid_input");
|
|
@@ -30359,8 +30535,8 @@ function createRepositoryTools(runtime) {
|
|
|
30359
30535
|
|
|
30360
30536
|
// src/tool-packs/github/workspace.ts
|
|
30361
30537
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
30362
|
-
import { chmod as chmod4, lstat as
|
|
30363
|
-
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";
|
|
30364
30540
|
var SAFE_LOCAL_ID = /^[A-Za-z0-9_-]{1,200}$/;
|
|
30365
30541
|
var FULL_NAME2 = /^[A-Za-z0-9_.-]{1,100}\/[A-Za-z0-9_.-]{1,100}$/;
|
|
30366
30542
|
var DIRECTORY_MODE2 = 448;
|
|
@@ -30377,20 +30553,20 @@ function hasControlCharacter2(value) {
|
|
|
30377
30553
|
});
|
|
30378
30554
|
}
|
|
30379
30555
|
function assertBelow2(parent, child, label) {
|
|
30380
|
-
const path =
|
|
30381
|
-
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") ||
|
|
30556
|
+
const path = relative6(parent, child);
|
|
30557
|
+
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute10(path)) {
|
|
30382
30558
|
throw new Error(`${label} escaped the task workspace`);
|
|
30383
30559
|
}
|
|
30384
30560
|
}
|
|
30385
30561
|
function samePath(left, right) {
|
|
30386
|
-
return process.platform === "win32" ?
|
|
30562
|
+
return process.platform === "win32" ? resolve6(left).toLowerCase() === resolve6(right).toLowerCase() : resolve6(left) === resolve6(right);
|
|
30387
30563
|
}
|
|
30388
30564
|
async function requireRealDirectory2(path, label) {
|
|
30389
|
-
const entry = await
|
|
30565
|
+
const entry = await lstat8(path).catch(() => null);
|
|
30390
30566
|
if (!entry || !entry.isDirectory() || entry.isSymbolicLink()) {
|
|
30391
30567
|
throw new Error(`${label} must be a real directory, not a symbolic link or junction`);
|
|
30392
30568
|
}
|
|
30393
|
-
const real = await
|
|
30569
|
+
const real = await realpath5(path);
|
|
30394
30570
|
if (!samePath(real, path)) {
|
|
30395
30571
|
throw new Error(`${label} must not traverse a symbolic link or junction`);
|
|
30396
30572
|
}
|
|
@@ -30423,7 +30599,7 @@ function parseMetadata(text) {
|
|
|
30423
30599
|
}
|
|
30424
30600
|
async function pathExists(path) {
|
|
30425
30601
|
try {
|
|
30426
|
-
await
|
|
30602
|
+
await lstat8(path);
|
|
30427
30603
|
return true;
|
|
30428
30604
|
} catch (error52) {
|
|
30429
30605
|
if (error52.code === "ENOENT") return false;
|
|
@@ -30485,11 +30661,11 @@ async function createGithubWorkspaceService(input) {
|
|
|
30485
30661
|
if (!await pathExists(destination) || !await pathExists(metadataPath)) {
|
|
30486
30662
|
throw new Error("GitHub repository workspace has not been prepared");
|
|
30487
30663
|
}
|
|
30488
|
-
const metadataEntry = await
|
|
30664
|
+
const metadataEntry = await lstat8(metadataPath);
|
|
30489
30665
|
if (!metadataEntry.isFile() || metadataEntry.isSymbolicLink()) {
|
|
30490
30666
|
throw new Error("GitHub workspace metadata is invalid");
|
|
30491
30667
|
}
|
|
30492
|
-
const metadata = parseMetadata(await
|
|
30668
|
+
const metadata = parseMetadata(await readFile7(metadataPath, "utf8"));
|
|
30493
30669
|
if (metadata.repositoryId !== parsed.data || metadata.fullName !== repository.fullName || !samePath(metadata.path, destination)) {
|
|
30494
30670
|
throw new Error("GitHub workspace metadata does not match this repository");
|
|
30495
30671
|
}
|
|
@@ -30587,11 +30763,11 @@ async function createGithubWorkspaceService(input) {
|
|
|
30587
30763
|
expiresAt: authority.expiresAt
|
|
30588
30764
|
});
|
|
30589
30765
|
}
|
|
30590
|
-
const metadataEntry = await
|
|
30766
|
+
const metadataEntry = await lstat8(metadataPath);
|
|
30591
30767
|
if (!metadataEntry.isFile() || metadataEntry.isSymbolicLink()) {
|
|
30592
30768
|
throw new Error("GitHub workspace metadata is invalid");
|
|
30593
30769
|
}
|
|
30594
|
-
const metadata = parseMetadata(await
|
|
30770
|
+
const metadata = parseMetadata(await readFile7(metadataPath, "utf8"));
|
|
30595
30771
|
if (metadata.repositoryId !== repository.repositoryId || metadata.fullName !== repository.fullName || !samePath(metadata.path, destination)) {
|
|
30596
30772
|
throw new Error("GitHub workspace metadata does not match this repository");
|
|
30597
30773
|
}
|
|
@@ -31138,7 +31314,7 @@ function createGithubToolPackFactory(options = {}) {
|
|
|
31138
31314
|
var githubToolPackFactory = createGithubToolPackFactory();
|
|
31139
31315
|
|
|
31140
31316
|
// src/runners/linear-api.ts
|
|
31141
|
-
import { createHash as
|
|
31317
|
+
import { createHash as createHash3, randomUUID as randomUUID9 } from "node:crypto";
|
|
31142
31318
|
var MAX_RESPONSE_BYTES2 = 2 * 1024 * 1024;
|
|
31143
31319
|
var MAX_RESULT_STRING = 1e5;
|
|
31144
31320
|
var MAX_RESULT_ARRAY = 100;
|
|
@@ -31709,7 +31885,7 @@ function operationFor(name, args, appUserId, heldBy) {
|
|
|
31709
31885
|
}
|
|
31710
31886
|
}
|
|
31711
31887
|
function fingerprint(value) {
|
|
31712
|
-
return
|
|
31888
|
+
return createHash3("sha256").update(canonicalLinearMutationPayload(value)).digest("hex");
|
|
31713
31889
|
}
|
|
31714
31890
|
function providerIntentFor(mutation, payloadFingerprint2) {
|
|
31715
31891
|
const common = {
|
|
@@ -32200,8 +32376,8 @@ var linearToolPackFactory = {
|
|
|
32200
32376
|
async create(grant, context) {
|
|
32201
32377
|
let resolveCancelled;
|
|
32202
32378
|
let closed = false;
|
|
32203
|
-
const cancelled = new Promise((
|
|
32204
|
-
resolveCancelled =
|
|
32379
|
+
const cancelled = new Promise((resolve16) => {
|
|
32380
|
+
resolveCancelled = resolve16;
|
|
32205
32381
|
});
|
|
32206
32382
|
const cancel = () => {
|
|
32207
32383
|
if (closed) return;
|
|
@@ -32391,6 +32567,56 @@ var TOOLS = [
|
|
|
32391
32567
|
additionalProperties: false
|
|
32392
32568
|
}
|
|
32393
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
|
+
},
|
|
32394
32620
|
{
|
|
32395
32621
|
name: "schedule_task",
|
|
32396
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.',
|
|
@@ -32869,6 +33095,23 @@ function opFor(name, args) {
|
|
|
32869
33095
|
};
|
|
32870
33096
|
case "list_channels":
|
|
32871
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
|
+
};
|
|
32872
33115
|
case "send_message":
|
|
32873
33116
|
return {
|
|
32874
33117
|
kind: "comm.send",
|
|
@@ -32887,7 +33130,7 @@ function createAskUserServer() {
|
|
|
32887
33130
|
let server;
|
|
32888
33131
|
let listening;
|
|
32889
33132
|
function ensureListening() {
|
|
32890
|
-
listening ??= new Promise((
|
|
33133
|
+
listening ??= new Promise((resolve16, reject3) => {
|
|
32891
33134
|
server = createServer2((req, res) => {
|
|
32892
33135
|
res.on("error", () => {
|
|
32893
33136
|
});
|
|
@@ -32903,7 +33146,7 @@ function createAskUserServer() {
|
|
|
32903
33146
|
server.on("error", reject3);
|
|
32904
33147
|
server.listen(0, "127.0.0.1", () => {
|
|
32905
33148
|
const address = server.address();
|
|
32906
|
-
if (address && typeof address === "object")
|
|
33149
|
+
if (address && typeof address === "object") resolve16(address.port);
|
|
32907
33150
|
else reject3(new Error("ask_user server failed to bind"));
|
|
32908
33151
|
});
|
|
32909
33152
|
server.unref();
|
|
@@ -33004,6 +33247,26 @@ function createAskUserServer() {
|
|
|
33004
33247
|
}
|
|
33005
33248
|
return;
|
|
33006
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
|
+
}
|
|
33007
33270
|
const toolPack = run3.toolOwners.get(name);
|
|
33008
33271
|
if (toolPack) {
|
|
33009
33272
|
try {
|
|
@@ -33042,7 +33305,40 @@ function createAskUserServer() {
|
|
|
33042
33305
|
return;
|
|
33043
33306
|
}
|
|
33044
33307
|
try {
|
|
33045
|
-
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);
|
|
33046
33342
|
if (outcome.ok) toolText(JSON.stringify(outcome.result ?? { ok: true }, null, 2));
|
|
33047
33343
|
else toolText(outcome.error ?? "the operation failed", true);
|
|
33048
33344
|
} catch (err) {
|
|
@@ -33064,6 +33360,8 @@ function createAskUserServer() {
|
|
|
33064
33360
|
const handlers = {
|
|
33065
33361
|
askUser: input.askUser,
|
|
33066
33362
|
agentOp: input.agentOp,
|
|
33363
|
+
..."requestApproval" in input && input.requestApproval ? { requestApproval: input.requestApproval } : {},
|
|
33364
|
+
..."publishFile" in input && input.publishFile ? { publishFile: input.publishFile } : {},
|
|
33067
33365
|
...toolPacks.length > 0 ? { toolPacks } : {}
|
|
33068
33366
|
};
|
|
33069
33367
|
const toolOwners = /* @__PURE__ */ new Map();
|
|
@@ -33095,7 +33393,7 @@ function createAskUserServer() {
|
|
|
33095
33393
|
}
|
|
33096
33394
|
|
|
33097
33395
|
// src/runners/runner-env.ts
|
|
33098
|
-
import { delimiter as delimiter2, isAbsolute as
|
|
33396
|
+
import { delimiter as delimiter2, isAbsolute as isAbsolute11 } from "node:path";
|
|
33099
33397
|
var PROVIDER_AUTHORITY_PREFIXES = ["GH_", "GITHUB_", "GIT_", "SSH_"];
|
|
33100
33398
|
var HOST_AUTHORITY_PREFIXES = [
|
|
33101
33399
|
"ZIXT_",
|
|
@@ -33154,7 +33452,7 @@ function inheritedValue(env, name) {
|
|
|
33154
33452
|
}
|
|
33155
33453
|
function sanitizeInheritedSearchPath(path) {
|
|
33156
33454
|
if (!path) return "";
|
|
33157
|
-
return path.split(delimiter2).filter((entry) => entry !== "" &&
|
|
33455
|
+
return path.split(delimiter2).filter((entry) => entry !== "" && isAbsolute11(entry)).join(delimiter2);
|
|
33158
33456
|
}
|
|
33159
33457
|
function buildRunnerEnv(input) {
|
|
33160
33458
|
const env = {};
|
|
@@ -33235,9 +33533,9 @@ function buildRunnerEnv(input) {
|
|
|
33235
33533
|
// src/runners/github-shell-auth.ts
|
|
33236
33534
|
import { execFile } from "node:child_process";
|
|
33237
33535
|
import { randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
33238
|
-
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";
|
|
33239
33537
|
import { createServer as createServer3 } from "node:http";
|
|
33240
|
-
import { isAbsolute as
|
|
33538
|
+
import { isAbsolute as isAbsolute12, join as join12, relative as relative7 } from "node:path";
|
|
33241
33539
|
var MAX_REQUEST_BYTES2 = 16 * 1024;
|
|
33242
33540
|
var DIRECTORY_MODE3 = 448;
|
|
33243
33541
|
var PRIVATE_FILE_MODE = 384;
|
|
@@ -33443,7 +33741,7 @@ function parseGhInvocation(body) {
|
|
|
33443
33741
|
}
|
|
33444
33742
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
33445
33743
|
const { args, cwd } = value;
|
|
33446
|
-
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)) {
|
|
33447
33745
|
return null;
|
|
33448
33746
|
}
|
|
33449
33747
|
return { args, cwd };
|
|
@@ -33601,8 +33899,8 @@ function activationCredential(grant, now = Date.now()) {
|
|
|
33601
33899
|
return expiresAt.getTime() <= now ? null : { accessToken: grant.accessToken, expiresAt };
|
|
33602
33900
|
}
|
|
33603
33901
|
function assertChildPath2(parent, child) {
|
|
33604
|
-
const path =
|
|
33605
|
-
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") ||
|
|
33902
|
+
const path = relative7(parent, child);
|
|
33903
|
+
if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute12(path)) {
|
|
33606
33904
|
throw new Error("GitHub shell helper path escaped its private run directory");
|
|
33607
33905
|
}
|
|
33608
33906
|
}
|
|
@@ -33620,11 +33918,11 @@ async function writePrivate(path, content, executable = false) {
|
|
|
33620
33918
|
await chmod5(path, executable ? EXECUTABLE_FILE_MODE : PRIVATE_FILE_MODE);
|
|
33621
33919
|
}
|
|
33622
33920
|
async function prepareHelpers(input) {
|
|
33623
|
-
const rootEntry = await
|
|
33921
|
+
const rootEntry = await lstat9(input.runRoot);
|
|
33624
33922
|
if (!rootEntry.isDirectory() || rootEntry.isSymbolicLink()) {
|
|
33625
33923
|
throw new Error("GitHub shell authentication requires a private real run directory");
|
|
33626
33924
|
}
|
|
33627
|
-
const runRoot = await
|
|
33925
|
+
const runRoot = await realpath6(input.runRoot);
|
|
33628
33926
|
const helperPath = join12(runRoot, "github-shell-git-credential.cjs");
|
|
33629
33927
|
assertChildPath2(runRoot, helperPath);
|
|
33630
33928
|
await writePrivate(helperPath, GIT_HELPER_SOURCE);
|
|
@@ -33867,7 +34165,7 @@ password=${credential.accessToken}
|
|
|
33867
34165
|
|
|
33868
34166
|
// src/runners/working-context.ts
|
|
33869
34167
|
import { spawn as spawn6 } from "node:child_process";
|
|
33870
|
-
import { resolve as
|
|
34168
|
+
import { resolve as resolve7 } from "node:path";
|
|
33871
34169
|
var COMMAND_TIMEOUT_MS = 5e3;
|
|
33872
34170
|
var OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
33873
34171
|
var COMMAND_STOP_TIMEOUT_MS = 2e4;
|
|
@@ -34225,8 +34523,8 @@ async function repositoryState(directory, git, env, signal) {
|
|
|
34225
34523
|
const pathLines = paths.trim().split(/\r?\n/);
|
|
34226
34524
|
if (pathLines.length < 3 || !pathLines[0] || !pathLines[1] || !pathLines[2]) return null;
|
|
34227
34525
|
const root = pathLines[0];
|
|
34228
|
-
const gitDirectory =
|
|
34229
|
-
const commonDirectory =
|
|
34526
|
+
const gitDirectory = resolve7(directory, pathLines[1]);
|
|
34527
|
+
const commonDirectory = resolve7(directory, pathLines[2]);
|
|
34230
34528
|
const records = status.split(/\0|\r?\n/).filter(Boolean);
|
|
34231
34529
|
const rawBranch = statusField(records, "branch.head");
|
|
34232
34530
|
if (!rawBranch || rawBranch.length > 512 || !isSafeSingleLineDisplayText(rawBranch)) return null;
|
|
@@ -34373,18 +34671,18 @@ var WorkingContextPullRequestCache = class {
|
|
|
34373
34671
|
import { spawn as spawn7 } from "node:child_process";
|
|
34374
34672
|
import {
|
|
34375
34673
|
chmod as chmod6,
|
|
34376
|
-
lstat as
|
|
34674
|
+
lstat as lstat10,
|
|
34377
34675
|
mkdir as mkdir9,
|
|
34378
34676
|
open as open5,
|
|
34379
34677
|
readdir as readdir3,
|
|
34380
|
-
readFile as
|
|
34381
|
-
realpath as
|
|
34678
|
+
readFile as readFile8,
|
|
34679
|
+
realpath as realpath7,
|
|
34382
34680
|
rename as rename5,
|
|
34383
34681
|
rm as rm7,
|
|
34384
34682
|
writeFile as writeFile5
|
|
34385
34683
|
} from "node:fs/promises";
|
|
34386
34684
|
import { homedir as homedir3 } from "node:os";
|
|
34387
|
-
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";
|
|
34388
34686
|
var SAFE_SEGMENT2 = /^[A-Za-z0-9_-]{1,200}$/;
|
|
34389
34687
|
var DIRECTORY_MODE4 = 448;
|
|
34390
34688
|
var FILE_MODE3 = 384;
|
|
@@ -34612,15 +34910,15 @@ function isMissing(error52) {
|
|
|
34612
34910
|
return error52.code === "ENOENT";
|
|
34613
34911
|
}
|
|
34614
34912
|
function assertBelow3(parent, child) {
|
|
34615
|
-
const path =
|
|
34616
|
-
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);
|
|
34617
34915
|
if (escapes) throw new Error("run artifact path escapes its private root");
|
|
34618
34916
|
}
|
|
34619
34917
|
async function requireRealDirectory3(path, label) {
|
|
34620
|
-
const entry = await
|
|
34918
|
+
const entry = await lstat10(path);
|
|
34621
34919
|
if (entry.isSymbolicLink()) throw new Error(`${label} must not be a symbolic link`);
|
|
34622
34920
|
if (!entry.isDirectory()) throw new Error(`${label} must be a directory`);
|
|
34623
|
-
return
|
|
34921
|
+
return realpath7(path);
|
|
34624
34922
|
}
|
|
34625
34923
|
function assertWindowsProfileBoundary(profile, target) {
|
|
34626
34924
|
const path = win322.relative(win322.resolve(profile), win322.resolve(target));
|
|
@@ -34634,7 +34932,7 @@ async function rejectWindowsSymlinkAncestors(profile, target) {
|
|
|
34634
34932
|
for (const segment of path.split("\\").filter(Boolean)) {
|
|
34635
34933
|
current = win322.join(current, segment);
|
|
34636
34934
|
try {
|
|
34637
|
-
const entry = await
|
|
34935
|
+
const entry = await lstat10(current);
|
|
34638
34936
|
if (entry.isSymbolicLink()) {
|
|
34639
34937
|
throw new Error("run artifact path must not contain symbolic links or junctions");
|
|
34640
34938
|
}
|
|
@@ -34645,16 +34943,16 @@ async function rejectWindowsSymlinkAncestors(profile, target) {
|
|
|
34645
34943
|
}
|
|
34646
34944
|
}
|
|
34647
34945
|
async function prepareRoot(root) {
|
|
34648
|
-
const absolute =
|
|
34946
|
+
const absolute = resolve8(root);
|
|
34649
34947
|
let realProfile;
|
|
34650
34948
|
if (process.platform === "win32") {
|
|
34651
|
-
const profile =
|
|
34949
|
+
const profile = resolve8(homedir3());
|
|
34652
34950
|
assertWindowsProfileBoundary(profile, absolute);
|
|
34653
34951
|
await rejectWindowsSymlinkAncestors(profile, absolute);
|
|
34654
|
-
realProfile = await
|
|
34952
|
+
realProfile = await realpath7(profile);
|
|
34655
34953
|
}
|
|
34656
34954
|
try {
|
|
34657
|
-
await
|
|
34955
|
+
await lstat10(absolute);
|
|
34658
34956
|
} catch (error52) {
|
|
34659
34957
|
if (!isMissing(error52)) throw error52;
|
|
34660
34958
|
await mkdir9(absolute, { recursive: true, mode: DIRECTORY_MODE4 });
|
|
@@ -34668,7 +34966,7 @@ async function prepareAgentRoot(root, agentId) {
|
|
|
34668
34966
|
const path = join13(root, agentId);
|
|
34669
34967
|
assertBelow3(root, path);
|
|
34670
34968
|
try {
|
|
34671
|
-
await
|
|
34969
|
+
await lstat10(path);
|
|
34672
34970
|
} catch (error52) {
|
|
34673
34971
|
if (!isMissing(error52)) throw error52;
|
|
34674
34972
|
try {
|
|
@@ -34734,7 +35032,7 @@ async function createPrivateDirectory(parent, name) {
|
|
|
34734
35032
|
assertBelow3(parent, path);
|
|
34735
35033
|
await mkdir9(path, { mode: DIRECTORY_MODE4 });
|
|
34736
35034
|
await chmod6(path, DIRECTORY_MODE4);
|
|
34737
|
-
const real = await
|
|
35035
|
+
const real = await realpath7(path);
|
|
34738
35036
|
assertBelow3(parent, real);
|
|
34739
35037
|
return real;
|
|
34740
35038
|
}
|
|
@@ -34768,7 +35066,7 @@ async function createRunArtifacts(input) {
|
|
|
34768
35066
|
try {
|
|
34769
35067
|
await mkdir9(runRoot, { mode: DIRECTORY_MODE4 });
|
|
34770
35068
|
await chmod6(runRoot, DIRECTORY_MODE4);
|
|
34771
|
-
const realRunRoot = await
|
|
35069
|
+
const realRunRoot = await realpath7(runRoot);
|
|
34772
35070
|
assertBelow3(agentRoot, realRunRoot);
|
|
34773
35071
|
const emptyGithubConfigDirectory = await createPrivateDirectory(realRunRoot, "gh-config");
|
|
34774
35072
|
const emptyGitHooksDirectory = await createPrivateDirectory(realRunRoot, "git-hooks");
|
|
@@ -34818,13 +35116,13 @@ async function removePrivateTreeWithRetries(path, removeTree, retryDelayMs) {
|
|
|
34818
35116
|
}
|
|
34819
35117
|
}
|
|
34820
35118
|
async function sweepOrphanedRunArtifacts(root) {
|
|
34821
|
-
const absolute =
|
|
35119
|
+
const absolute = resolve8(root);
|
|
34822
35120
|
let realProfile;
|
|
34823
35121
|
if (process.platform === "win32") {
|
|
34824
|
-
const profile =
|
|
35122
|
+
const profile = resolve8(homedir3());
|
|
34825
35123
|
assertWindowsProfileBoundary(profile, absolute);
|
|
34826
35124
|
await rejectWindowsSymlinkAncestors(profile, absolute);
|
|
34827
|
-
realProfile = await
|
|
35125
|
+
realProfile = await realpath7(profile);
|
|
34828
35126
|
}
|
|
34829
35127
|
let realRoot;
|
|
34830
35128
|
try {
|
|
@@ -34866,11 +35164,11 @@ async function syncRunRegistryDirectory(path) {
|
|
|
34866
35164
|
async function ensureDurableRunRegistryRoot(registryRoot, syncDirectory7) {
|
|
34867
35165
|
const firstCreated = await mkdir9(registryRoot, { recursive: true, mode: DIRECTORY_MODE4 });
|
|
34868
35166
|
if (firstCreated && process.platform !== "win32") {
|
|
34869
|
-
const first =
|
|
34870
|
-
const target =
|
|
35167
|
+
const first = resolve8(firstCreated);
|
|
35168
|
+
const target = resolve8(registryRoot);
|
|
34871
35169
|
await syncDirectory7(dirname6(first));
|
|
34872
35170
|
let current = first;
|
|
34873
|
-
for (const part of
|
|
35171
|
+
for (const part of relative8(first, target).split(sep4).filter(Boolean)) {
|
|
34874
35172
|
await syncDirectory7(current);
|
|
34875
35173
|
current = join13(current, part);
|
|
34876
35174
|
}
|
|
@@ -34957,7 +35255,7 @@ async function readRecordedRunAssignmentEntries(registryRoot = defaultRunRegistr
|
|
|
34957
35255
|
if (!SAFE_SEGMENT2.test(runToken)) continue;
|
|
34958
35256
|
let text;
|
|
34959
35257
|
try {
|
|
34960
|
-
text = await
|
|
35258
|
+
text = await readFile8(join13(registryRoot, entry.name), "utf8");
|
|
34961
35259
|
} catch {
|
|
34962
35260
|
continue;
|
|
34963
35261
|
}
|
|
@@ -34969,7 +35267,7 @@ async function readRecordedRunAssignmentEntries(registryRoot = defaultRunRegistr
|
|
|
34969
35267
|
async function readRecordedRunAssignmentEntriesStrict(registryRoot = defaultRunRegistryRoot()) {
|
|
34970
35268
|
let rootStat;
|
|
34971
35269
|
try {
|
|
34972
|
-
rootStat = await
|
|
35270
|
+
rootStat = await lstat10(registryRoot);
|
|
34973
35271
|
} catch (error52) {
|
|
34974
35272
|
if (isMissing(error52)) return [];
|
|
34975
35273
|
throw new Error("run registry state could not be observed");
|
|
@@ -34993,7 +35291,7 @@ async function readRecordedRunAssignmentEntriesStrict(registryRoot = defaultRunR
|
|
|
34993
35291
|
}
|
|
34994
35292
|
let text;
|
|
34995
35293
|
try {
|
|
34996
|
-
text = await
|
|
35294
|
+
text = await readFile8(join13(registryRoot, entry.name), "utf8");
|
|
34997
35295
|
} catch {
|
|
34998
35296
|
throw new Error("committed run registry witness could not be read");
|
|
34999
35297
|
}
|
|
@@ -35087,11 +35385,11 @@ function truncateThought(text) {
|
|
|
35087
35385
|
}
|
|
35088
35386
|
var MAX_APPROVAL_PAYLOAD = 5e4;
|
|
35089
35387
|
async function requireRealDirectory4(path, label) {
|
|
35090
|
-
const entry = await
|
|
35388
|
+
const entry = await lstat11(path).catch(() => null);
|
|
35091
35389
|
if (!entry) throw new Error(`${label} does not exist`);
|
|
35092
35390
|
if (entry.isSymbolicLink()) throw new Error(`${label} must not be a symbolic link`);
|
|
35093
35391
|
if (!entry.isDirectory()) throw new Error(`${label} must be a directory`);
|
|
35094
|
-
return
|
|
35392
|
+
return realpath8(path);
|
|
35095
35393
|
}
|
|
35096
35394
|
function createCliRunner(adapter, opts = {}) {
|
|
35097
35395
|
const command = opts.command ?? adapter.defaultCommand;
|
|
@@ -35310,6 +35608,21 @@ function createCliRunner(adapter, opts = {}) {
|
|
|
35310
35608
|
pendingAsks--;
|
|
35311
35609
|
}
|
|
35312
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
|
+
}),
|
|
35313
35626
|
agentOp: (op) => task.agentOp(op),
|
|
35314
35627
|
// GitHub repository work belongs in the installed `git` and `gh`
|
|
35315
35628
|
// commands backed by GithubShellAuth. Do not advertise the bundled
|
|
@@ -35441,7 +35754,7 @@ ${attachmentSection}` : prompt;
|
|
|
35441
35754
|
let changed = false;
|
|
35442
35755
|
for (const path of paths) {
|
|
35443
35756
|
if (!path || path.length > 4096) continue;
|
|
35444
|
-
const absolutePath =
|
|
35757
|
+
const absolutePath = isAbsolute14(path) ? path : resolve9(cwd, path);
|
|
35445
35758
|
const directory = dirname7(absolutePath);
|
|
35446
35759
|
observedWorkingDirectories.delete(directory);
|
|
35447
35760
|
observedWorkingDirectories.add(directory);
|
|
@@ -35864,7 +36177,7 @@ function runCliProcess(options) {
|
|
|
35864
36177
|
usage: { inputTokens: 0, outputTokens: 0 }
|
|
35865
36178
|
});
|
|
35866
36179
|
}
|
|
35867
|
-
return new Promise((
|
|
36180
|
+
return new Promise((resolve16) => {
|
|
35868
36181
|
const platform = options.platform ?? process.platform;
|
|
35869
36182
|
const containmentGateNonce = options.guardian && platform === "win32" ? randomUUID10() : void 0;
|
|
35870
36183
|
const child = options.guardian ? spawn8(
|
|
@@ -35925,7 +36238,7 @@ function runCliProcess(options) {
|
|
|
35925
36238
|
clearInterval(timer);
|
|
35926
36239
|
unregisterFollowUps?.();
|
|
35927
36240
|
parser.stop?.();
|
|
35928
|
-
|
|
36241
|
+
resolve16(result);
|
|
35929
36242
|
};
|
|
35930
36243
|
const terminate = (result) => {
|
|
35931
36244
|
if (settled || forcedResult) return;
|
|
@@ -36156,7 +36469,7 @@ function runCliProcess(options) {
|
|
|
36156
36469
|
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
36157
36470
|
|
|
36158
36471
|
// src/runners/runtime-observation.ts
|
|
36159
|
-
import { open as open6, readdir as readdir4, realpath as
|
|
36472
|
+
import { open as open6, readdir as readdir4, realpath as realpath9 } from "node:fs/promises";
|
|
36160
36473
|
import { homedir as homedir5 } from "node:os";
|
|
36161
36474
|
import { join as join15 } from "node:path";
|
|
36162
36475
|
var READ_WINDOW_BYTES = 1024 * 1024;
|
|
@@ -36223,7 +36536,7 @@ function claudeTranscriptPath(input) {
|
|
|
36223
36536
|
return join15(configDir, "projects", slug, `${input.sessionId}.jsonl`);
|
|
36224
36537
|
}
|
|
36225
36538
|
async function readClaudeSessionEffort(input) {
|
|
36226
|
-
const resolvedCwd = await
|
|
36539
|
+
const resolvedCwd = await realpath9(input.cwd).catch(() => input.cwd);
|
|
36227
36540
|
const path = claudeTranscriptPath({ env: input.env, resolvedCwd, sessionId: input.sessionId });
|
|
36228
36541
|
const records = parseLines(await readTail(path));
|
|
36229
36542
|
for (let index = records.length - 1; index >= 0; index -= 1) {
|
|
@@ -36270,7 +36583,7 @@ async function readCodexSessionRuntime(input) {
|
|
|
36270
36583
|
}
|
|
36271
36584
|
var codexCatalogCache = /* @__PURE__ */ new Map();
|
|
36272
36585
|
async function loadCodexModelCatalog(command, prefixArgs, env) {
|
|
36273
|
-
const output = await new Promise((
|
|
36586
|
+
const output = await new Promise((resolve16) => {
|
|
36274
36587
|
const child = spawnCli(command, [...prefixArgs, "debug", "models"], {
|
|
36275
36588
|
stdio: ["ignore", "pipe", "ignore"],
|
|
36276
36589
|
windowsHide: true,
|
|
@@ -36285,7 +36598,7 @@ async function loadCodexModelCatalog(command, prefixArgs, env) {
|
|
|
36285
36598
|
if (settled) return;
|
|
36286
36599
|
settled = true;
|
|
36287
36600
|
clearTimeout(timer);
|
|
36288
|
-
|
|
36601
|
+
resolve16(value);
|
|
36289
36602
|
};
|
|
36290
36603
|
const timer = setTimeout(() => {
|
|
36291
36604
|
child.kill();
|
|
@@ -36390,8 +36703,8 @@ function createRuntimeReporter(input, sessionId) {
|
|
|
36390
36703
|
var EFFORT_READ_ATTEMPTS = 5;
|
|
36391
36704
|
var EFFORT_READ_INTERVAL_MS = 3e3;
|
|
36392
36705
|
function delay2(ms) {
|
|
36393
|
-
return new Promise((
|
|
36394
|
-
const timer = setTimeout(
|
|
36706
|
+
return new Promise((resolve16) => {
|
|
36707
|
+
const timer = setTimeout(resolve16, ms);
|
|
36395
36708
|
timer.unref?.();
|
|
36396
36709
|
});
|
|
36397
36710
|
}
|
|
@@ -36468,10 +36781,10 @@ function createClaudeLiveParser(onStream, onSessionModel) {
|
|
|
36468
36781
|
},
|
|
36469
36782
|
async steer(followUp) {
|
|
36470
36783
|
if (!write) return false;
|
|
36471
|
-
return await new Promise((
|
|
36472
|
-
acknowledgements.set(followUp.inputId,
|
|
36784
|
+
return await new Promise((resolve16) => {
|
|
36785
|
+
acknowledgements.set(followUp.inputId, resolve16);
|
|
36473
36786
|
void write(input(followUp.inputId, followUp.text)).catch(() => {
|
|
36474
|
-
if (acknowledgements.delete(followUp.inputId))
|
|
36787
|
+
if (acknowledgements.delete(followUp.inputId)) resolve16(false);
|
|
36475
36788
|
});
|
|
36476
36789
|
});
|
|
36477
36790
|
},
|
|
@@ -36631,7 +36944,7 @@ function improveErrorMessage(error52) {
|
|
|
36631
36944
|
}
|
|
36632
36945
|
|
|
36633
36946
|
// src/runners/codex.ts
|
|
36634
|
-
import { mkdir as mkdir11, readFile as
|
|
36947
|
+
import { mkdir as mkdir11, readFile as readFile9, writeFile as writeFile6 } from "node:fs/promises";
|
|
36635
36948
|
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
36636
36949
|
import { homedir as homedir6 } from "node:os";
|
|
36637
36950
|
import { join as join16 } from "node:path";
|
|
@@ -36646,7 +36959,7 @@ function threadIndexPath(root, agentId, sessionKey) {
|
|
|
36646
36959
|
}
|
|
36647
36960
|
async function readThreadId(path) {
|
|
36648
36961
|
try {
|
|
36649
|
-
const parsed = JSON.parse(await
|
|
36962
|
+
const parsed = JSON.parse(await readFile9(path, "utf8"));
|
|
36650
36963
|
return typeof parsed.threadId === "string" && /^[A-Za-z0-9-]{1,120}$/.test(parsed.threadId) ? parsed.threadId : null;
|
|
36651
36964
|
} catch {
|
|
36652
36965
|
return null;
|
|
@@ -36778,8 +37091,8 @@ ${value}` : value;
|
|
|
36778
37091
|
var RUNTIME_READ_ATTEMPTS = 5;
|
|
36779
37092
|
var RUNTIME_READ_INTERVAL_MS = 2e3;
|
|
36780
37093
|
function delay3(ms) {
|
|
36781
|
-
return new Promise((
|
|
36782
|
-
const timer = setTimeout(
|
|
37094
|
+
return new Promise((resolve16) => {
|
|
37095
|
+
const timer = setTimeout(resolve16, ms);
|
|
36783
37096
|
timer.unref?.();
|
|
36784
37097
|
});
|
|
36785
37098
|
}
|
|
@@ -36818,7 +37131,7 @@ function createCodexAppServerParser(onStream, options) {
|
|
|
36818
37131
|
const turnReadyWaiters = /* @__PURE__ */ new Set();
|
|
36819
37132
|
const usage = () => ({ inputTokens, outputTokens });
|
|
36820
37133
|
const settleTurnReadiness = (ready) => {
|
|
36821
|
-
for (const
|
|
37134
|
+
for (const resolve16 of turnReadyWaiters) resolve16(ready);
|
|
36822
37135
|
turnReadyWaiters.clear();
|
|
36823
37136
|
};
|
|
36824
37137
|
const send = async (message) => {
|
|
@@ -36999,12 +37312,12 @@ function createCodexAppServerParser(onStream, options) {
|
|
|
36999
37312
|
async steer(input) {
|
|
37000
37313
|
if (stopped) return false;
|
|
37001
37314
|
if (!activeTurnId) {
|
|
37002
|
-
const ready = await new Promise((
|
|
37315
|
+
const ready = await new Promise((resolve16) => turnReadyWaiters.add(resolve16));
|
|
37003
37316
|
if (!ready || stopped) return false;
|
|
37004
37317
|
}
|
|
37005
37318
|
if (!threadId || !activeTurnId) return false;
|
|
37006
|
-
return await new Promise((
|
|
37007
|
-
steerWaiters.set(input.inputId,
|
|
37319
|
+
return await new Promise((resolve16) => {
|
|
37320
|
+
steerWaiters.set(input.inputId, resolve16);
|
|
37008
37321
|
void send({
|
|
37009
37322
|
id: `steer:${input.inputId}`,
|
|
37010
37323
|
method: "turn/steer",
|
|
@@ -37015,7 +37328,7 @@ function createCodexAppServerParser(onStream, options) {
|
|
|
37015
37328
|
clientUserMessageId: input.inputId
|
|
37016
37329
|
}
|
|
37017
37330
|
}).catch(() => {
|
|
37018
|
-
if (steerWaiters.delete(input.inputId))
|
|
37331
|
+
if (steerWaiters.delete(input.inputId)) resolve16(false);
|
|
37019
37332
|
});
|
|
37020
37333
|
});
|
|
37021
37334
|
},
|
|
@@ -37023,7 +37336,7 @@ function createCodexAppServerParser(onStream, options) {
|
|
|
37023
37336
|
stopped = true;
|
|
37024
37337
|
write = null;
|
|
37025
37338
|
settleTurnReadiness(false);
|
|
37026
|
-
for (const
|
|
37339
|
+
for (const resolve16 of steerWaiters.values()) resolve16(false);
|
|
37027
37340
|
steerWaiters.clear();
|
|
37028
37341
|
},
|
|
37029
37342
|
push(chunk) {
|
|
@@ -37201,8 +37514,8 @@ function improveCodexErrorMessage(error52) {
|
|
|
37201
37514
|
|
|
37202
37515
|
// src/runners/git-preflight.ts
|
|
37203
37516
|
import { spawn as spawn9 } from "node:child_process";
|
|
37204
|
-
import { realpath as
|
|
37205
|
-
import { isAbsolute as
|
|
37517
|
+
import { realpath as realpath10 } from "node:fs/promises";
|
|
37518
|
+
import { isAbsolute as isAbsolute15, resolve as resolve10 } from "node:path";
|
|
37206
37519
|
var OUTPUT_LIMIT = 8192;
|
|
37207
37520
|
var DEFAULT_TIMEOUT_MS4 = 1e4;
|
|
37208
37521
|
var VERSION_PATTERN = /^git version [^\r\n]{1,108}$/;
|
|
@@ -37218,10 +37531,10 @@ function unavailable(error52, checkedAt, executablePath = null) {
|
|
|
37218
37531
|
async function preflightGit(options = {}) {
|
|
37219
37532
|
const checkedAt = (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString();
|
|
37220
37533
|
const configured = options.command;
|
|
37221
|
-
if (configured !== void 0 && !
|
|
37534
|
+
if (configured !== void 0 && !isAbsolute15(configured)) {
|
|
37222
37535
|
return unavailable("configured git command must be an absolute file", checkedAt);
|
|
37223
37536
|
}
|
|
37224
|
-
const trustedCwd = await
|
|
37537
|
+
const trustedCwd = await realpath10(resolve10(options.trustedCwd ?? process.cwd())).catch(() => null);
|
|
37225
37538
|
if (!trustedCwd)
|
|
37226
37539
|
return unavailable("Host-owned git preflight directory is unavailable", checkedAt);
|
|
37227
37540
|
const executablePath = await resolveTrustedCliCommand(configured ?? "git", {
|
|
@@ -37443,7 +37756,7 @@ function parseAuth(result) {
|
|
|
37443
37756
|
return "unknown";
|
|
37444
37757
|
}
|
|
37445
37758
|
function run2(command, args) {
|
|
37446
|
-
return new Promise((
|
|
37759
|
+
return new Promise((resolve16) => {
|
|
37447
37760
|
const child = spawnCli(command, args, {
|
|
37448
37761
|
stdio: ["ignore", "pipe", "pipe"],
|
|
37449
37762
|
windowsHide: true
|
|
@@ -37459,7 +37772,7 @@ function run2(command, args) {
|
|
|
37459
37772
|
if (settled) return;
|
|
37460
37773
|
settled = true;
|
|
37461
37774
|
clearTimeout(timeout);
|
|
37462
|
-
|
|
37775
|
+
resolve16(result);
|
|
37463
37776
|
};
|
|
37464
37777
|
const timeout = setTimeout(() => {
|
|
37465
37778
|
child.kill();
|
|
@@ -37475,7 +37788,7 @@ import { spawn as spawn10 } from "node:child_process";
|
|
|
37475
37788
|
import { constants as constants2 } from "node:fs";
|
|
37476
37789
|
import { access as access4, chmod as chmod7, mkdir as mkdir12, open as open7, rename as rename6, rm as rm8 } from "node:fs/promises";
|
|
37477
37790
|
import { homedir as homedir7, userInfo } from "node:os";
|
|
37478
|
-
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";
|
|
37479
37792
|
var SERVICE_NAME = "zixt-host.service";
|
|
37480
37793
|
var SYSTEM_SERVICE_COMMAND_TIMEOUT_MS = 7e4;
|
|
37481
37794
|
var SERVICE_STABILITY_DELAY_MS = 2e3;
|
|
@@ -37503,7 +37816,7 @@ function boundedAppend(current, chunk) {
|
|
|
37503
37816
|
}
|
|
37504
37817
|
async function defaultRunCommand(command, args) {
|
|
37505
37818
|
const commandEnvironment3 = systemServiceCommandEnvironment();
|
|
37506
|
-
return new Promise((
|
|
37819
|
+
return new Promise((resolve16) => {
|
|
37507
37820
|
const child = spawn10(command, [...args], {
|
|
37508
37821
|
stdio: ["ignore", "pipe", "pipe"],
|
|
37509
37822
|
env: commandEnvironment3,
|
|
@@ -37517,7 +37830,7 @@ async function defaultRunCommand(command, args) {
|
|
|
37517
37830
|
if (settled) return;
|
|
37518
37831
|
settled = true;
|
|
37519
37832
|
if (timer) clearTimeout(timer);
|
|
37520
|
-
|
|
37833
|
+
resolve16(result);
|
|
37521
37834
|
};
|
|
37522
37835
|
child.stdout?.on("data", (chunk) => {
|
|
37523
37836
|
stdout = boundedAppend(stdout, chunk);
|
|
@@ -37578,12 +37891,12 @@ async function defaultSyncDirectory(path) {
|
|
|
37578
37891
|
async function ensureDirectory(path, mode, syncDirectory7) {
|
|
37579
37892
|
const firstCreated = await mkdir12(path, { recursive: true, mode });
|
|
37580
37893
|
if (!firstCreated) return;
|
|
37581
|
-
const first =
|
|
37582
|
-
const target =
|
|
37894
|
+
const first = resolve11(firstCreated);
|
|
37895
|
+
const target = resolve11(path);
|
|
37583
37896
|
await syncDirectory7(dirname8(first));
|
|
37584
37897
|
let current = first;
|
|
37585
|
-
const descendants =
|
|
37586
|
-
for (const part of descendants ? descendants.split(
|
|
37898
|
+
const descendants = relative9(first, target);
|
|
37899
|
+
for (const part of descendants ? descendants.split(sep5) : []) {
|
|
37587
37900
|
await syncDirectory7(current);
|
|
37588
37901
|
current = join17(current, part);
|
|
37589
37902
|
}
|
|
@@ -37591,7 +37904,7 @@ async function ensureDirectory(path, mode, syncDirectory7) {
|
|
|
37591
37904
|
async function replacePrivateFile(path, contents, mode, syncDirectory7) {
|
|
37592
37905
|
const parent = dirname8(path);
|
|
37593
37906
|
await ensureDirectory(parent, 448, syncDirectory7);
|
|
37594
|
-
const temporary = join17(parent, `.${
|
|
37907
|
+
const temporary = join17(parent, `.${basename4(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
|
|
37595
37908
|
const handle = await open7(temporary, "wx", mode);
|
|
37596
37909
|
try {
|
|
37597
37910
|
await handle.writeFile(contents, "utf8");
|
|
@@ -37653,7 +37966,7 @@ async function installLinuxService(options) {
|
|
|
37653
37966
|
const resolveCommand = options.resolveCommand ?? defaultResolveCommand;
|
|
37654
37967
|
const run3 = options.runCommand ?? defaultRunCommand;
|
|
37655
37968
|
const syncDirectory7 = options.syncDirectory ?? defaultSyncDirectory;
|
|
37656
|
-
const stabilityDelay = options.delay ?? ((ms) => new Promise((
|
|
37969
|
+
const stabilityDelay = options.delay ?? ((ms) => new Promise((resolve16) => setTimeout(resolve16, ms)));
|
|
37657
37970
|
const [systemctl, loginctl] = await Promise.all([
|
|
37658
37971
|
resolveCommand("systemctl"),
|
|
37659
37972
|
resolveCommand("loginctl")
|
|
@@ -37768,7 +38081,7 @@ import { spawn as spawn11 } from "node:child_process";
|
|
|
37768
38081
|
import { constants as constants3 } from "node:fs";
|
|
37769
38082
|
import { access as access5, chmod as chmod8, mkdir as mkdir13, open as open8, rename as rename7, rm as rm9 } from "node:fs/promises";
|
|
37770
38083
|
import { homedir as homedir8, userInfo as userInfo2 } from "node:os";
|
|
37771
|
-
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";
|
|
37772
38085
|
var LAUNCH_AGENT_LABEL = "ai.zixt.host";
|
|
37773
38086
|
var SERVICE_STABILITY_DELAY_MS2 = 2e3;
|
|
37774
38087
|
var COMMAND_TIMEOUT_MS2 = 7e4;
|
|
@@ -37794,11 +38107,11 @@ async function syncDirectory4(path) {
|
|
|
37794
38107
|
async function ensureDirectory2(path, sync) {
|
|
37795
38108
|
const firstCreated = await mkdir13(path, { recursive: true, mode: 448 });
|
|
37796
38109
|
if (!firstCreated) return;
|
|
37797
|
-
const first =
|
|
37798
|
-
const target =
|
|
38110
|
+
const first = resolve12(firstCreated);
|
|
38111
|
+
const target = resolve12(path);
|
|
37799
38112
|
await sync(dirname9(first));
|
|
37800
38113
|
let current = first;
|
|
37801
|
-
for (const part of
|
|
38114
|
+
for (const part of relative10(first, target).split(sep6).filter(Boolean)) {
|
|
37802
38115
|
await sync(current);
|
|
37803
38116
|
current = join18(current, part);
|
|
37804
38117
|
}
|
|
@@ -37806,7 +38119,7 @@ async function ensureDirectory2(path, sync) {
|
|
|
37806
38119
|
async function replacePrivateFile2(path, contents, mode, sync) {
|
|
37807
38120
|
const parent = dirname9(path);
|
|
37808
38121
|
await ensureDirectory2(parent, sync);
|
|
37809
|
-
const temporary = join18(parent, `.${
|
|
38122
|
+
const temporary = join18(parent, `.${basename5(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
|
|
37810
38123
|
const handle = await open8(temporary, "wx", mode);
|
|
37811
38124
|
try {
|
|
37812
38125
|
await handle.writeFile(contents, "utf8");
|
|
@@ -37997,9 +38310,9 @@ async function installMacosService(options) {
|
|
|
37997
38310
|
// src/windows-service.ts
|
|
37998
38311
|
import { spawn as spawn12 } from "node:child_process";
|
|
37999
38312
|
import { constants as constants4 } from "node:fs";
|
|
38000
|
-
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";
|
|
38001
38314
|
import { homedir as homedir9 } from "node:os";
|
|
38002
|
-
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";
|
|
38003
38316
|
var TASK_NAME = "Zixt Host";
|
|
38004
38317
|
var COMMAND_TIMEOUT_MS3 = 7e4;
|
|
38005
38318
|
var SERVICE_STABILITY_DELAY_MS3 = 2e3;
|
|
@@ -38027,11 +38340,11 @@ async function syncDirectory5(path) {
|
|
|
38027
38340
|
async function ensureDirectory3(path, sync) {
|
|
38028
38341
|
const firstCreated = await mkdir14(path, { recursive: true, mode: 448 });
|
|
38029
38342
|
if (!firstCreated) return;
|
|
38030
|
-
const first =
|
|
38031
|
-
const target =
|
|
38343
|
+
const first = resolve13(firstCreated);
|
|
38344
|
+
const target = resolve13(path);
|
|
38032
38345
|
await sync(dirname10(first));
|
|
38033
38346
|
let current = first;
|
|
38034
|
-
for (const part of
|
|
38347
|
+
for (const part of relative11(first, target).split(sep7).filter(Boolean)) {
|
|
38035
38348
|
await sync(current);
|
|
38036
38349
|
current = join19(current, part);
|
|
38037
38350
|
}
|
|
@@ -38039,7 +38352,7 @@ async function ensureDirectory3(path, sync) {
|
|
|
38039
38352
|
async function replacePrivateFile3(path, contents, sync) {
|
|
38040
38353
|
const parent = dirname10(path);
|
|
38041
38354
|
await ensureDirectory3(parent, sync);
|
|
38042
|
-
const temporary = join19(parent, `.${
|
|
38355
|
+
const temporary = join19(parent, `.${basename6(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
|
|
38043
38356
|
const handle = await open9(temporary, "wx", 384);
|
|
38044
38357
|
try {
|
|
38045
38358
|
await handle.writeFile(contents, "utf8");
|
|
@@ -38093,7 +38406,7 @@ async function runChild(command, args, env, input) {
|
|
|
38093
38406
|
}
|
|
38094
38407
|
async function defaultResolveCommand3(name, env) {
|
|
38095
38408
|
const root = env.SYSTEMROOT ?? env.WINDIR;
|
|
38096
|
-
if (!root || !
|
|
38409
|
+
if (!root || !isAbsolute16(root)) return null;
|
|
38097
38410
|
const candidate = name === "powershell" ? join19(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe") : join19(root, "System32", `${name}.exe`);
|
|
38098
38411
|
return access6(candidate, constants4.X_OK).then(
|
|
38099
38412
|
() => candidate,
|
|
@@ -38182,7 +38495,7 @@ exit $code
|
|
|
38182
38495
|
}
|
|
38183
38496
|
async function defaultObserveStatus(path, generation) {
|
|
38184
38497
|
try {
|
|
38185
|
-
const text = (await
|
|
38498
|
+
const text = (await readFile10(path, "utf8")).replace(/^\uFEFF/, "");
|
|
38186
38499
|
const value = JSON.parse(text);
|
|
38187
38500
|
if (value.schema !== 1 || value.generation !== generation || typeof value.pid !== "number" || !Number.isSafeInteger(value.pid) || value.pid <= 0) {
|
|
38188
38501
|
return null;
|
|
@@ -38225,7 +38538,7 @@ async function installWindowsService(options) {
|
|
|
38225
38538
|
const env = options.env ?? process.env;
|
|
38226
38539
|
const home = options.home ?? homedir9();
|
|
38227
38540
|
const localAppData = options.localAppData ?? env.LOCALAPPDATA;
|
|
38228
|
-
if (!localAppData || !
|
|
38541
|
+
if (!localAppData || !isAbsolute16(localAppData)) {
|
|
38229
38542
|
throw new Error("Windows local application data path is unavailable.");
|
|
38230
38543
|
}
|
|
38231
38544
|
const token2 = oneLine3(options.token, "pairing code");
|
|
@@ -38336,9 +38649,9 @@ async function installSystemService(options) {
|
|
|
38336
38649
|
}
|
|
38337
38650
|
|
|
38338
38651
|
// src/terminal-outcomes.ts
|
|
38339
|
-
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";
|
|
38340
38653
|
import { homedir as homedir10 } from "node:os";
|
|
38341
|
-
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";
|
|
38342
38655
|
var DIRECTORY_MODE5 = 448;
|
|
38343
38656
|
var FILE_MODE4 = 384;
|
|
38344
38657
|
var MAX_OUTCOME_BYTES = 4 * 1024 * 1024;
|
|
@@ -38366,16 +38679,16 @@ async function syncDirectory6(root) {
|
|
|
38366
38679
|
async function requirePrivateRoot(root, sync = syncDirectory6) {
|
|
38367
38680
|
const firstCreated = await mkdir15(root, { recursive: true, mode: DIRECTORY_MODE5 });
|
|
38368
38681
|
if (firstCreated) {
|
|
38369
|
-
const first =
|
|
38370
|
-
const target =
|
|
38682
|
+
const first = resolve14(firstCreated);
|
|
38683
|
+
const target = resolve14(root);
|
|
38371
38684
|
await sync(dirname11(first));
|
|
38372
38685
|
let current = first;
|
|
38373
|
-
for (const part of
|
|
38686
|
+
for (const part of relative12(first, target).split(sep8).filter(Boolean)) {
|
|
38374
38687
|
await sync(current);
|
|
38375
38688
|
current = join20(current, part);
|
|
38376
38689
|
}
|
|
38377
38690
|
}
|
|
38378
|
-
const stat3 = await
|
|
38691
|
+
const stat3 = await lstat12(root);
|
|
38379
38692
|
if (stat3.isSymbolicLink() || !stat3.isDirectory()) {
|
|
38380
38693
|
throw new Error("terminal outcome journal root is not a trusted directory");
|
|
38381
38694
|
}
|
|
@@ -38403,7 +38716,7 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
|
|
|
38403
38716
|
const destination = outcomePath(root, hostId, outcome.taskId, outcome.epoch);
|
|
38404
38717
|
try {
|
|
38405
38718
|
const existing = parseCommittedOutcome(
|
|
38406
|
-
await
|
|
38719
|
+
await readFile11(destination, { encoding: "utf8", flag: "r" }),
|
|
38407
38720
|
outcome.taskId,
|
|
38408
38721
|
outcome.epoch
|
|
38409
38722
|
);
|
|
@@ -38436,7 +38749,7 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
|
|
|
38436
38749
|
async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
|
|
38437
38750
|
let rootStat;
|
|
38438
38751
|
try {
|
|
38439
|
-
rootStat = await
|
|
38752
|
+
rootStat = await lstat12(root);
|
|
38440
38753
|
} catch (error52) {
|
|
38441
38754
|
if (error52.code === "ENOENT") return [];
|
|
38442
38755
|
throw new Error("terminal outcome journal could not be observed");
|
|
@@ -38453,7 +38766,7 @@ async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
|
|
|
38453
38766
|
throw new Error("terminal outcome Host scope is not a trusted directory");
|
|
38454
38767
|
}
|
|
38455
38768
|
const scopedRoot = hostOutcomeRoot(root, hostEntry.name);
|
|
38456
|
-
const scopedStat = await
|
|
38769
|
+
const scopedStat = await lstat12(scopedRoot);
|
|
38457
38770
|
if (scopedStat.isSymbolicLink() || !scopedStat.isDirectory()) {
|
|
38458
38771
|
throw new Error("terminal outcome Host scope is not a trusted directory");
|
|
38459
38772
|
}
|
|
@@ -38466,12 +38779,12 @@ async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
|
|
|
38466
38779
|
throw new Error("committed terminal outcome is not a trusted regular file");
|
|
38467
38780
|
}
|
|
38468
38781
|
const path = join20(scopedRoot, entry.name);
|
|
38469
|
-
const stat3 = await
|
|
38782
|
+
const stat3 = await lstat12(path);
|
|
38470
38783
|
if (!stat3.isFile() || stat3.isSymbolicLink() || stat3.size > MAX_OUTCOME_BYTES) {
|
|
38471
38784
|
throw new Error("committed terminal outcome is not a trusted regular file");
|
|
38472
38785
|
}
|
|
38473
38786
|
const outcome = parseCommittedOutcome(
|
|
38474
|
-
await
|
|
38787
|
+
await readFile11(path, "utf8"),
|
|
38475
38788
|
match[1],
|
|
38476
38789
|
Number(match[2])
|
|
38477
38790
|
);
|
|
@@ -38618,13 +38931,13 @@ function createHostLogger(options = {}) {
|
|
|
38618
38931
|
}
|
|
38619
38932
|
|
|
38620
38933
|
// src/demo-state.ts
|
|
38621
|
-
import { isAbsolute as
|
|
38934
|
+
import { isAbsolute as isAbsolute17, join as join21, parse as parse3, resolve as resolve15 } from "node:path";
|
|
38622
38935
|
var DEMO_STATE_ROOT_ENV = "ZIXT_DEMO_STATE_ROOT";
|
|
38623
38936
|
function resolveDemoHostStatePaths(env = process.env) {
|
|
38624
38937
|
const configured = env.ZIXT_RUNNER === "demo" ? env[DEMO_STATE_ROOT_ENV] : void 0;
|
|
38625
38938
|
if (!configured) return null;
|
|
38626
|
-
const root =
|
|
38627
|
-
if (!
|
|
38939
|
+
const root = resolve15(configured);
|
|
38940
|
+
if (!isAbsolute17(configured) || root === parse3(root).root) {
|
|
38628
38941
|
throw new Error(`${DEMO_STATE_ROOT_ENV} must be a dedicated absolute directory`);
|
|
38629
38942
|
}
|
|
38630
38943
|
return {
|