@amaster.ai/employee-runtime-connector 0.1.0-beta.41 → 0.1.0-beta.43
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/amaster-runtime-daemon.mjs +914 -458
- package/dist/amaster-runtime.mjs +1 -1
- package/package.json +1 -1
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
// MirrorX runtime connector daemon bundle.
|
|
3
3
|
|
|
4
4
|
// src/amaster-runtime-daemon.mjs
|
|
5
|
-
import { createHash as
|
|
6
|
-
import { chmodSync as
|
|
5
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
6
|
+
import { chmodSync as chmodSync6, copyFileSync as copyFileSync3, existsSync as existsSync12, lstatSync as lstatSync7, mkdirSync as mkdirSync8, readFileSync as readFileSync10, readdirSync as readdirSync8, realpathSync as realpathSync3, renameSync as renameSync5, rmSync as rmSync7, statSync as statSync7, symlinkSync as symlinkSync4, unlinkSync, writeFileSync as writeFileSync8 } from "node:fs";
|
|
7
7
|
import { arch as arch3, homedir as homedir3, hostname as hostname2, platform as platform3 } from "node:os";
|
|
8
|
-
import { basename as basename6, delimiter as delimiter2, dirname as
|
|
8
|
+
import { basename as basename6, delimiter as delimiter2, dirname as dirname9, extname as extname2, isAbsolute as isAbsolute8, join as join13, relative as relative8, resolve as resolve11 } from "node:path";
|
|
9
9
|
import { spawn, spawnSync as spawnSync5 } from "node:child_process";
|
|
10
10
|
|
|
11
11
|
// src/amaster-runtime-daemon/common.mjs
|
|
@@ -1876,7 +1876,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1876
1876
|
const PROFILE_MARKER2 = ".amaster-managed-pi-profile.json";
|
|
1877
1877
|
const SESSION_ROLLOUT_MARKER2 = ".amaster-pi-session-rollout.json";
|
|
1878
1878
|
const DEFAULT_SESSION_ROLLOUT_TTL_MS2 = 24 * 60 * 60 * 1e3;
|
|
1879
|
-
function
|
|
1879
|
+
function record4(value) {
|
|
1880
1880
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1881
1881
|
}
|
|
1882
1882
|
function npmPackageName(source) {
|
|
@@ -1889,7 +1889,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1889
1889
|
if (typeof value !== "string" || value.trim() === "") throw new Error(`pi_managed_mcp_invalid: ${label} is required`);
|
|
1890
1890
|
return value.trim();
|
|
1891
1891
|
}
|
|
1892
|
-
function
|
|
1892
|
+
function within4(candidate, root) {
|
|
1893
1893
|
const rel = relative2(root, candidate);
|
|
1894
1894
|
return rel === "" || !rel.startsWith("..") && !isAbsolute2(rel);
|
|
1895
1895
|
}
|
|
@@ -1932,7 +1932,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1932
1932
|
return matches[0];
|
|
1933
1933
|
}
|
|
1934
1934
|
function restoreManagedPiSessionRollout(input, sessionsRoot, runDir, executorHome, authority) {
|
|
1935
|
-
const session =
|
|
1935
|
+
const session = record4(input.nativeSession);
|
|
1936
1936
|
if (session.mode !== "governed_action_approval" || session.required !== true) return null;
|
|
1937
1937
|
const sessionId = nonEmpty2(session.sessionId, "nativeSession.sessionId");
|
|
1938
1938
|
const sourceRunId = nonEmpty2(session.sourceRunId, "nativeSession.sourceRunId");
|
|
@@ -1956,11 +1956,11 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1956
1956
|
throw new Error("pi_managed_mcp_session_rollout_authority_mismatch: source rollout does not match the approved continuation");
|
|
1957
1957
|
}
|
|
1958
1958
|
const sourceRollout = resolve2(cacheRoot, nonEmpty2(marker.rolloutRelativePath, "rolloutRelativePath"));
|
|
1959
|
-
if (!
|
|
1959
|
+
if (!within4(sourceRollout, cacheRoot) || lstatSync2(sourceRollout).isSymbolicLink() || !lstatSync2(sourceRollout).isFile()) {
|
|
1960
1960
|
throw new Error("pi_managed_mcp_session_rollout_unsafe: source rollout path is invalid");
|
|
1961
1961
|
}
|
|
1962
1962
|
const targetRollout = resolve2(sessionsRoot, marker.rolloutRelativePath);
|
|
1963
|
-
if (!
|
|
1963
|
+
if (!within4(targetRollout, sessionsRoot)) {
|
|
1964
1964
|
throw new Error("pi_managed_mcp_session_rollout_unsafe: target rollout path is invalid");
|
|
1965
1965
|
}
|
|
1966
1966
|
mkdirSync3(dirname3(targetRollout), { recursive: true, mode: 448 });
|
|
@@ -1982,8 +1982,8 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1982
1982
|
return tuple.join(".");
|
|
1983
1983
|
}
|
|
1984
1984
|
function validateAuthority2(input) {
|
|
1985
|
-
const runtimeAuth =
|
|
1986
|
-
const gateway =
|
|
1985
|
+
const runtimeAuth = record4(input.runtimeAuth);
|
|
1986
|
+
const gateway = record4(runtimeAuth.governedMcp);
|
|
1987
1987
|
const runId = nonEmpty2(input.runId, "runId");
|
|
1988
1988
|
if (runtimeAuth.runId !== runId) throw new Error("pi_managed_mcp_owner_mismatch: command runId does not match runtime authority");
|
|
1989
1989
|
if (gateway.schemaVersion !== SUPPORTED_SCHEMA_VERSION2) throw new Error("pi_managed_mcp_invalid: unsupported schema version");
|
|
@@ -1999,7 +1999,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1999
1999
|
if (!Number.isFinite(expiresAt) || expiresAt <= Date.now() + 3e4) {
|
|
2000
2000
|
throw new Error("pi_managed_mcp_session_expired: Gateway session must remain valid through spawn preflight");
|
|
2001
2001
|
}
|
|
2002
|
-
const headers =
|
|
2002
|
+
const headers = record4(gateway.headers);
|
|
2003
2003
|
for (const name of REQUIRED_AUTHORITY_HEADERS2) nonEmpty2(headers[name], `headers.${name}`);
|
|
2004
2004
|
const allowedHeaderNames = /* @__PURE__ */ new Set([...REQUIRED_AUTHORITY_HEADERS2, ...runtimeAuth.issueId ? ["x-amaster-issue-id"] : []]);
|
|
2005
2005
|
if (Object.keys(headers).some((name) => !allowedHeaderNames.has(name)) || Object.keys(headers).length !== allowedHeaderNames.size) {
|
|
@@ -2028,7 +2028,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
2028
2028
|
return output;
|
|
2029
2029
|
}
|
|
2030
2030
|
function assertInvocationIsolation2(input) {
|
|
2031
|
-
for (const name of Object.keys(
|
|
2031
|
+
for (const name of Object.keys(record4(input.commandEnv))) {
|
|
2032
2032
|
if (FORBIDDEN_COMMAND_ENV2.has(name)) throw new Error(`pi_managed_mcp_env_override_blocked: ${name}`);
|
|
2033
2033
|
if (!ALLOWED_COMMAND_ENV2.has(name)) throw new Error(`pi_managed_mcp_env_injection_blocked: ${name}`);
|
|
2034
2034
|
}
|
|
@@ -2060,7 +2060,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
2060
2060
|
const value = safeProxyValue2(baseEnv?.[name], name);
|
|
2061
2061
|
if (value) env[name] = value;
|
|
2062
2062
|
}
|
|
2063
|
-
return { ...env, ...
|
|
2063
|
+
return { ...env, ...record4(commandEnv) };
|
|
2064
2064
|
}
|
|
2065
2065
|
function projectMcpConfigHasContent(filePath) {
|
|
2066
2066
|
if (!existsSync3(filePath)) return false;
|
|
@@ -2070,14 +2070,14 @@ var piManagedMcpProfileApi = (() => {
|
|
|
2070
2070
|
} catch {
|
|
2071
2071
|
return true;
|
|
2072
2072
|
}
|
|
2073
|
-
const config =
|
|
2074
|
-
return Object.keys(
|
|
2073
|
+
const config = record4(parsed);
|
|
2074
|
+
return Object.keys(record4(config.mcpServers)).length > 0 || Object.keys(record4(config.servers)).length > 0 || Array.isArray(config.imports) && config.imports.length > 0;
|
|
2075
2075
|
}
|
|
2076
2076
|
function assertNoProjectMcpOverride(cwd, runDir) {
|
|
2077
2077
|
let cursor = resolve2(cwd);
|
|
2078
2078
|
const boundary = resolve2(runDir);
|
|
2079
|
-
if (!
|
|
2080
|
-
while (
|
|
2079
|
+
if (!within4(cursor, boundary)) throw new Error("pi_managed_mcp_owner_mismatch: cwd is outside the managed run");
|
|
2080
|
+
while (within4(cursor, boundary)) {
|
|
2081
2081
|
for (const relativePath of [".mcp.json", join4(".pi", "mcp.json")]) {
|
|
2082
2082
|
const configPath = join4(cursor, relativePath);
|
|
2083
2083
|
if (projectMcpConfigHasContent(configPath)) throw new Error(`pi_managed_mcp_project_override_blocked: ${configPath}`);
|
|
@@ -2087,7 +2087,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
2087
2087
|
}
|
|
2088
2088
|
}
|
|
2089
2089
|
function selectManagedBrowserUse(sourceSettings, npmSource) {
|
|
2090
|
-
const plugin =
|
|
2090
|
+
const plugin = record4(record4(sourceSettings.plugins)[MANAGED_BROWSER_USE_PLUGIN]);
|
|
2091
2091
|
if (plugin.enabled !== true || plugin.package !== MANAGED_BROWSER_USE_PACKAGE) return null;
|
|
2092
2092
|
const packageSpec = Array.isArray(sourceSettings.packages) ? sourceSettings.packages.find((entry) => npmPackageName(entry) === MANAGED_BROWSER_USE_PACKAGE) : null;
|
|
2093
2093
|
if (typeof packageSpec !== "string") return null;
|
|
@@ -2104,7 +2104,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
2104
2104
|
if (packageMetadata.name !== MANAGED_BROWSER_USE_PACKAGE) {
|
|
2105
2105
|
throw new Error(`pi_managed_mcp_attestation_failed: enabled ${MANAGED_BROWSER_USE_PACKAGE} package identity mismatch`);
|
|
2106
2106
|
}
|
|
2107
|
-
const sourceConfig =
|
|
2107
|
+
const sourceConfig = record4(sourceSettings["pi-browser-use"]);
|
|
2108
2108
|
const config = {};
|
|
2109
2109
|
for (const key of MANAGED_BROWSER_USE_BOOLEAN_SETTINGS) {
|
|
2110
2110
|
if (typeof sourceConfig[key] === "boolean") config[key] = sourceConfig[key];
|
|
@@ -2148,7 +2148,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
2148
2148
|
}
|
|
2149
2149
|
return {
|
|
2150
2150
|
packageSpec,
|
|
2151
|
-
config:
|
|
2151
|
+
config: record4(sourceSettings["pi-telemetry"])
|
|
2152
2152
|
};
|
|
2153
2153
|
}
|
|
2154
2154
|
function seedPiRuntime(sourceHome, agentDir) {
|
|
@@ -2169,7 +2169,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
2169
2169
|
let sourceSettings = {};
|
|
2170
2170
|
if (existsSync3(settingsSource)) {
|
|
2171
2171
|
try {
|
|
2172
|
-
sourceSettings =
|
|
2172
|
+
sourceSettings = record4(JSON.parse(readFileSync3(settingsSource, "utf8")));
|
|
2173
2173
|
} catch {
|
|
2174
2174
|
throw new Error("pi_managed_mcp_attestation_failed: source Pi settings are invalid");
|
|
2175
2175
|
}
|
|
@@ -2238,7 +2238,7 @@ ${result2.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
2238
2238
|
const { gateway, gatewayUrl, sessionToken, headers, runId } = validateAuthority2(input);
|
|
2239
2239
|
const runDir = resolve2(nonEmpty2(input.runDir, "runDir"));
|
|
2240
2240
|
const executorHome = resolve2(nonEmpty2(input.executorHome, "executorHome"));
|
|
2241
|
-
if (!
|
|
2241
|
+
if (!within4(executorHome, join4(runDir, "executors"))) throw new Error("pi_managed_mcp_owner_mismatch: executorHome is outside the managed run");
|
|
2242
2242
|
assertNoProjectMcpOverride(nonEmpty2(input.cwd, "cwd"), runDir);
|
|
2243
2243
|
const profileRoot = join4(executorHome, "managed-mcp");
|
|
2244
2244
|
if (existsSync3(profileRoot)) throw new Error(`pi_managed_mcp_profile_exists: ${profileRoot}`);
|
|
@@ -2253,7 +2253,7 @@ ${result2.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
2253
2253
|
const owner = Object.freeze({ commandId: input.commandId, runId });
|
|
2254
2254
|
writePrivateFile2(markerPath, `${JSON.stringify({ version: 1, ...owner, profileRoot })}
|
|
2255
2255
|
`);
|
|
2256
|
-
const runtimeAuth =
|
|
2256
|
+
const runtimeAuth = record4(input.runtimeAuth);
|
|
2257
2257
|
const authority = Object.freeze({
|
|
2258
2258
|
companyId: nonEmpty2(runtimeAuth.companyId, "runtimeAuth.companyId"),
|
|
2259
2259
|
agentId: nonEmpty2(runtimeAuth.agentId, "runtimeAuth.agentId"),
|
|
@@ -2408,7 +2408,7 @@ ${result2.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
2408
2408
|
const profileRoot = dirname3(markerPath);
|
|
2409
2409
|
try {
|
|
2410
2410
|
const marker = JSON.parse(readFileSync3(markerPath, "utf8"));
|
|
2411
|
-
if (!
|
|
2411
|
+
if (!within4(profileRoot, root) || marker?.profileRoot !== profileRoot) throw new Error("ownership marker root mismatch");
|
|
2412
2412
|
cleanupManagedPiMcpProfile2({ profileRoot }, { commandId: marker.commandId, runId: marker.runId });
|
|
2413
2413
|
removedProfiles += 1;
|
|
2414
2414
|
} catch (error) {
|
|
@@ -2423,7 +2423,7 @@ ${result2.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
2423
2423
|
const markerStat = lstatSync2(markerPath);
|
|
2424
2424
|
const cacheStat = lstatSync2(cacheRoot);
|
|
2425
2425
|
const marker = JSON.parse(readFileSync3(markerPath, "utf8"));
|
|
2426
|
-
if (!
|
|
2426
|
+
if (!within4(cacheRoot, root) || basename2(cacheRoot) !== "session-rollout" || markerStat.isSymbolicLink() || !markerStat.isFile() || cacheStat.isSymbolicLink() || !cacheStat.isDirectory() || marker?.version !== 1 || typeof marker?.companyId !== "string" || typeof marker?.agentId !== "string" || typeof marker?.sourceRunId !== "string" || typeof marker?.sourceCommandId !== "string" || typeof marker?.sessionId !== "string" || marker?.cacheRoot !== cacheRoot) throw new Error("session rollout ownership marker mismatch");
|
|
2427
2427
|
const preservedAtMs = typeof marker.preservedAt === "string" ? Date.parse(marker.preservedAt) : Number.NaN;
|
|
2428
2428
|
const markerAgeMs = nowMs - (Number.isFinite(preservedAtMs) ? preservedAtMs : markerStat.mtimeMs);
|
|
2429
2429
|
if (markerAgeMs < rolloutTtlMs) continue;
|
|
@@ -2511,14 +2511,42 @@ function signalExecutorProcess(child, signal, processGroupId = processGroupIdFor
|
|
|
2511
2511
|
return false;
|
|
2512
2512
|
}
|
|
2513
2513
|
|
|
2514
|
+
// src/amaster-runtime-daemon/executor-spawn.mjs
|
|
2515
|
+
function record2(value) {
|
|
2516
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2517
|
+
}
|
|
2518
|
+
function managedChildSpawnInvocation(command, args, requestedIdentity) {
|
|
2519
|
+
const identity = record2(requestedIdentity);
|
|
2520
|
+
const childUmask = identity.umask;
|
|
2521
|
+
if (childUmask !== void 0 && (!Number.isInteger(childUmask) || childUmask < 0 || childUmask > 511)) {
|
|
2522
|
+
throw new Error("executor_spawn_umask_invalid");
|
|
2523
|
+
}
|
|
2524
|
+
const spawnIdentity = { ...identity };
|
|
2525
|
+
delete spawnIdentity.umask;
|
|
2526
|
+
if (childUmask === void 0) {
|
|
2527
|
+
return { command, args, spawnIdentity };
|
|
2528
|
+
}
|
|
2529
|
+
return {
|
|
2530
|
+
command: "/bin/sh",
|
|
2531
|
+
args: [
|
|
2532
|
+
"-c",
|
|
2533
|
+
`umask ${childUmask.toString(8).padStart(4, "0")}; exec "$@"`,
|
|
2534
|
+
"amaster-managed-child",
|
|
2535
|
+
command,
|
|
2536
|
+
...args
|
|
2537
|
+
],
|
|
2538
|
+
spawnIdentity
|
|
2539
|
+
};
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2514
2542
|
// src/amaster-runtime-daemon/durability.mjs
|
|
2515
2543
|
function resultOutboxFileName(commandId, now = Date.now()) {
|
|
2516
2544
|
const safeCommandId = String(commandId ?? "command").replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
2517
2545
|
return `${now}-${safeCommandId}.json`;
|
|
2518
2546
|
}
|
|
2519
2547
|
function isValidResultOutboxEntry(entry) {
|
|
2520
|
-
const
|
|
2521
|
-
return
|
|
2548
|
+
const record4 = asRecord(entry);
|
|
2549
|
+
return record4.version === 1 && Boolean(readString(record4.path)) && Object.keys(asRecord(record4.payload)).length > 0;
|
|
2522
2550
|
}
|
|
2523
2551
|
function resultOutboxEntryAgeMs(entry, nowMs) {
|
|
2524
2552
|
const createdAt = Date.parse(readString(entry.createdAt) ?? "");
|
|
@@ -2539,6 +2567,15 @@ var RECOVERY_WAKE_REASONS = /* @__PURE__ */ new Set([
|
|
|
2539
2567
|
function isRecoveryWakeReason(wakeReason) {
|
|
2540
2568
|
return RECOVERY_WAKE_REASONS.has(wakeReason);
|
|
2541
2569
|
}
|
|
2570
|
+
function stringifyBoundedJson(value, maxChars = 24e3) {
|
|
2571
|
+
let text = "";
|
|
2572
|
+
try {
|
|
2573
|
+
text = JSON.stringify(value, null, 2);
|
|
2574
|
+
} catch {
|
|
2575
|
+
text = String(value);
|
|
2576
|
+
}
|
|
2577
|
+
return truncateText(text, maxChars);
|
|
2578
|
+
}
|
|
2542
2579
|
function jsonText(value) {
|
|
2543
2580
|
return JSON.stringify(value, null, 2);
|
|
2544
2581
|
}
|
|
@@ -2596,8 +2633,8 @@ function governedReadSection(context) {
|
|
|
2596
2633
|
const reads = Array.isArray(context.governedReadResults) ? context.governedReadResults : [];
|
|
2597
2634
|
if (reads.length === 0) return { content: "", provenance: [] };
|
|
2598
2635
|
const normalized = reads.map((entry, index) => {
|
|
2599
|
-
const
|
|
2600
|
-
const receipt = asRecord(
|
|
2636
|
+
const record4 = asRecord(entry);
|
|
2637
|
+
const receipt = asRecord(record4.receipt);
|
|
2601
2638
|
const provider = readString(receipt.provider) ?? readString(receipt.transport);
|
|
2602
2639
|
const operation = readString(receipt.operation);
|
|
2603
2640
|
const observedAt = readString(receipt.retrievedAt) ?? readString(receipt.observedAt);
|
|
@@ -2607,7 +2644,7 @@ function governedReadSection(context) {
|
|
|
2607
2644
|
throw new Error(`governed_read_context_provenance_invalid: entry ${index} requires provider, operation, observedAt, and source`);
|
|
2608
2645
|
}
|
|
2609
2646
|
return {
|
|
2610
|
-
content:
|
|
2647
|
+
content: record4.content,
|
|
2611
2648
|
receipt: {
|
|
2612
2649
|
provider,
|
|
2613
2650
|
operation,
|
|
@@ -2640,6 +2677,7 @@ function fixedRules(input, includeIssueLine) {
|
|
|
2640
2677
|
`- command id: ${input.commandId}`,
|
|
2641
2678
|
`- run id: ${input.runId ?? "unknown"}`,
|
|
2642
2679
|
`- issue id: ${input.issueId ?? "unknown"}`,
|
|
2680
|
+
input.currentDate ? `- current date: ${input.currentDate}` : "",
|
|
2643
2681
|
includeIssueLine && input.issueLine ? `- issue: ${input.issueLine}` : "",
|
|
2644
2682
|
`- workspace: ${input.cwd}`,
|
|
2645
2683
|
input.managed ? `- source workspace: ${input.sourceWorkspacePath}` : "",
|
|
@@ -2656,6 +2694,17 @@ function approvalContinuationText(input) {
|
|
|
2656
2694
|
"Do not advance to another write action until that exact call returns status succeeded."
|
|
2657
2695
|
].join("\n");
|
|
2658
2696
|
}
|
|
2697
|
+
function interactionResolutionText(context) {
|
|
2698
|
+
const direct = asRecord(context.interactionResolution);
|
|
2699
|
+
const wakeResolution = asRecord(asRecord(context.paperclipWake).interactionResolution);
|
|
2700
|
+
const resolution = Object.keys(direct).length > 0 ? direct : wakeResolution;
|
|
2701
|
+
if (Object.keys(resolution).length === 0) return "";
|
|
2702
|
+
return [
|
|
2703
|
+
"Treat this resolved interaction as the authoritative delta for this run.",
|
|
2704
|
+
readString(resolution.status) === "changes_requested" ? "Apply every requested change before creating a replacement review." : "",
|
|
2705
|
+
stringifyBoundedJson(resolution, 8e3)
|
|
2706
|
+
].filter(Boolean).join("\n");
|
|
2707
|
+
}
|
|
2659
2708
|
function recoveryInstructionText(input) {
|
|
2660
2709
|
const context = asRecord(input.context);
|
|
2661
2710
|
if (input.wakeReason === "finish_successful_run_handoff" && context.handoffRequired === true) {
|
|
@@ -2663,6 +2712,8 @@ function recoveryInstructionText(input) {
|
|
|
2663
2712
|
"The prior successful run did not leave a terminal task disposition.",
|
|
2664
2713
|
"Do not repeat the original source work or create or revise deliverables.",
|
|
2665
2714
|
"Inspect the existing task and run evidence, then choose exactly one explicit disposition: done, in_review, input, blocked, delegated, or queued.",
|
|
2715
|
+
"If more work remains on this issue, call `update_parent` with `status: todo`, preserve the current agent owner, and record the concrete next action.",
|
|
2716
|
+
"Do not keep or write `in_progress`: only the actual `todo` issue update is a recognized resume disposition and lets the control plane queue a normal-model continuation.",
|
|
2666
2717
|
"Record the disposition with its concrete owner or next action and update the task accordingly."
|
|
2667
2718
|
].join("\n");
|
|
2668
2719
|
}
|
|
@@ -2697,6 +2748,28 @@ function runtimeAuthorizationText(context) {
|
|
|
2697
2748
|
"Never use request_confirmation to authorize a runtime action class."
|
|
2698
2749
|
].join("\n");
|
|
2699
2750
|
}
|
|
2751
|
+
function runtimeDecompositionRequirementText(context) {
|
|
2752
|
+
const issue = asRecord(context.paperclipIssue);
|
|
2753
|
+
const requirements = asRecord(issue.taskRequirements);
|
|
2754
|
+
const decomposition = asRecord(requirements.decomposition);
|
|
2755
|
+
if (decomposition.mode !== "required") return "";
|
|
2756
|
+
const children = Array.isArray(context.childIssueSummaries) ? context.childIssueSummaries : [];
|
|
2757
|
+
if (children.length > 0) return "";
|
|
2758
|
+
const source = asRecord(decomposition.source);
|
|
2759
|
+
const sourceType = readString(source.type);
|
|
2760
|
+
const sourceId = readString(source.id);
|
|
2761
|
+
const sourceRevision = readString(source.revision);
|
|
2762
|
+
if (!sourceType || !sourceId || !sourceRevision) {
|
|
2763
|
+
throw new Error("runtime_decomposition_requirement_invalid: required mode needs typed source provenance");
|
|
2764
|
+
}
|
|
2765
|
+
return [
|
|
2766
|
+
"This issue has a server-enforced typed decomposition requirement.",
|
|
2767
|
+
"Create real direct child tasks before continuing substantial source work.",
|
|
2768
|
+
"Each executable child must have an owner, dependencies where needed, and acceptance criteria. Do not create probe or test children.",
|
|
2769
|
+
"Preserve every parent safety and approval boundary in each child title, description, and acceptance criteria. If the parent prohibits registration, payment, booking, or external contact without later explicit authorization, create preparation or approval only children and do not assign the prohibited action.",
|
|
2770
|
+
`Requirement source: ${sourceType}:${sourceId}@${sourceRevision}`
|
|
2771
|
+
].join("\n");
|
|
2772
|
+
}
|
|
2700
2773
|
function sectionText(section) {
|
|
2701
2774
|
if (!section.content) return "";
|
|
2702
2775
|
return section.title ? `## ${section.title}
|
|
@@ -2766,6 +2839,15 @@ function compileCommandPromptWithManifest(input, options = {}) {
|
|
|
2766
2839
|
const wakeBodies = commentBodies(context);
|
|
2767
2840
|
const commentsDuplicatedByTask = hasTask && wakeBodies.length > 0 && wakeBodies.every((body) => taskText.includes(body));
|
|
2768
2841
|
const commentsSelected = mode !== "cold" || !commentsDuplicatedByTask;
|
|
2842
|
+
const interactionResolution = interactionResolutionText(context);
|
|
2843
|
+
const selectedComments = commentsSelected ? readString(input.comments) ?? "" : "";
|
|
2844
|
+
const wakeDeltaContent = [interactionResolution, selectedComments].filter(Boolean).join("\n\n");
|
|
2845
|
+
const wakeDeltaOriginal = [interactionResolution, readString(input.comments) ?? ""].filter(Boolean).join("\n\n");
|
|
2846
|
+
const wakeDeltaTitle = interactionResolution ? selectedComments ? "Wake Delta" : "Resolved Interaction Input" : "Wake Comment Delta";
|
|
2847
|
+
const wakeDeltaSourceRefs = [
|
|
2848
|
+
...readString(context.interactionId) ? [`interaction:${readString(context.interactionId)}`] : [],
|
|
2849
|
+
...commentRefs(context).map((id) => `comment:${id}`)
|
|
2850
|
+
];
|
|
2769
2851
|
const contextScope = {
|
|
2770
2852
|
companyId: readString(asRecord(context.paperclipCompany).id),
|
|
2771
2853
|
issueId: input.issueId ?? null
|
|
@@ -2776,8 +2858,9 @@ function compileCommandPromptWithManifest(input, options = {}) {
|
|
|
2776
2858
|
{ name: "recovery_instruction", title: "Recovery Instruction", priority: 99, sourceRef: `run:${input.runId ?? "unknown"}`, content: recoveryInstructionText(input), truncationReason: isRecoveryWakeReason(input.wakeReason) ? null : "mode_selection" },
|
|
2777
2859
|
{ name: "approval_continuation", title: "Approved Runtime Action Continuation", priority: 99, sourceRef: `run:${input.runId ?? "unknown"}`, content: approvalContinuationText(input), truncationReason: mode === "continuation" ? null : "mode_selection" },
|
|
2778
2860
|
{ name: "runtime_authorization", title: "Runtime Action Authorization", priority: 98, sourceRef: `run:${input.runId ?? "unknown"}`, content: runtimeAuthorizationText(context) },
|
|
2861
|
+
{ name: "runtime_decomposition_requirement", title: "Required Task Decomposition", priority: 98, sourceRef: `issue:${input.issueId ?? "unknown"}`, content: runtimeDecompositionRequirementText(context) },
|
|
2779
2862
|
{ name: "continuation_summary", title: "Continuation Summary", priority: 97, sourceRef: readString(asRecord(context.paperclipContinuationSummary).key) ?? `issue:${input.issueId ?? "unknown"}`, observedAt: readString(asRecord(context.paperclipContinuationSummary).updatedAt), originalContent: continuationSummary, content: mode === "cold" ? "" : continuationSummary, truncationReason: mode === "cold" ? "mode_selection" : null },
|
|
2780
|
-
{ name: "wake_comments", title:
|
|
2863
|
+
{ name: "wake_comments", title: wakeDeltaTitle, priority: interactionResolution ? 99 : 95, sourceRef: wakeDeltaSourceRefs, originalContent: wakeDeltaOriginal, content: wakeDeltaContent, truncationReason: commentsSelected ? null : "duplicate_task_context" },
|
|
2781
2864
|
{ name: "task", title: "Task Context", priority: 90, sourceRef: `issue:${input.issueId ?? "unknown"}`, originalContent: taskText, content: includeTask ? taskText : "", truncationReason: includeTask ? null : "mode_selection" },
|
|
2782
2865
|
{ name: "governed_reads", title: "Governed External Reads", priority: 88, sourceRef: governedReads.provenance.map((entry) => entry.sourceRef), observedAt: governedReads.provenance.map((entry) => entry.observedAt), freshness: governedReads.provenance.map((entry) => entry.freshness), scope: governedReads.provenance.map((entry) => entry.scope), content: governedReads.content },
|
|
2783
2866
|
{ name: "agent_instructions", title: "Agent Instructions", priority: 85, sourceRef: "agent_instructions_bundle", content: readString(input.agentInstructions) ?? "" },
|
|
@@ -3147,10 +3230,10 @@ function compactExecutorJsonlForTranscript(event) {
|
|
|
3147
3230
|
const text = JSON.stringify(compactExecutorJsonValue(event, stringMaxChars));
|
|
3148
3231
|
if (text.length <= 15e3) return text;
|
|
3149
3232
|
}
|
|
3150
|
-
const
|
|
3151
|
-
const item = tcAsRecord(
|
|
3233
|
+
const record4 = tcAsRecord(event);
|
|
3234
|
+
const item = tcAsRecord(record4.item);
|
|
3152
3235
|
return JSON.stringify({
|
|
3153
|
-
type: tcReadString(
|
|
3236
|
+
type: tcReadString(record4.type) ?? "executor.event",
|
|
3154
3237
|
item: item.type ? {
|
|
3155
3238
|
id: tcReadString(item.id),
|
|
3156
3239
|
type: tcReadString(item.type),
|
|
@@ -3163,10 +3246,10 @@ function compactExecutorJsonlForTranscript(event) {
|
|
|
3163
3246
|
});
|
|
3164
3247
|
}
|
|
3165
3248
|
function summarizeTokenUsage(usage) {
|
|
3166
|
-
const
|
|
3167
|
-
const inputTokens = tcReadNumber(
|
|
3168
|
-
const cachedInputTokens = tcReadNumber(
|
|
3169
|
-
const outputTokens = tcReadNumber(
|
|
3249
|
+
const record4 = tcAsRecord(usage);
|
|
3250
|
+
const inputTokens = tcReadNumber(record4.input_tokens ?? record4.inputTokens, 0);
|
|
3251
|
+
const cachedInputTokens = tcReadNumber(record4.cached_input_tokens ?? record4.cachedInputTokens, 0);
|
|
3252
|
+
const outputTokens = tcReadNumber(record4.output_tokens ?? record4.outputTokens, 0);
|
|
3170
3253
|
const parts = [];
|
|
3171
3254
|
if (inputTokens > 0) parts.push(`\u8F93\u5165 ${inputTokens}`);
|
|
3172
3255
|
if (cachedInputTokens > 0) parts.push(`\u7F13\u5B58 ${cachedInputTokens}`);
|
|
@@ -3421,8 +3504,8 @@ function summarizeClaudeEvent(event) {
|
|
|
3421
3504
|
return null;
|
|
3422
3505
|
}
|
|
3423
3506
|
function tcPiMessageText(message) {
|
|
3424
|
-
const
|
|
3425
|
-
const content =
|
|
3507
|
+
const record4 = tcAsRecord(message);
|
|
3508
|
+
const content = record4.content;
|
|
3426
3509
|
if (typeof content === "string" && content.trim().length > 0) return content.trim();
|
|
3427
3510
|
if (!Array.isArray(content)) return "";
|
|
3428
3511
|
return content.map((entry) => {
|
|
@@ -3436,14 +3519,14 @@ function tcPiAssistantMessageEventText(assistantMessageEvent) {
|
|
|
3436
3519
|
return tcReadString(event.content) ?? "";
|
|
3437
3520
|
}
|
|
3438
3521
|
function tcPiMessageStopReason(message) {
|
|
3439
|
-
const
|
|
3440
|
-
return tcReadString(
|
|
3522
|
+
const record4 = tcAsRecord(message);
|
|
3523
|
+
return tcReadString(record4.stopReason ?? record4.stop_reason);
|
|
3441
3524
|
}
|
|
3442
3525
|
function tcPiMessageErrorText(message) {
|
|
3443
|
-
const
|
|
3444
|
-
const explicitError = tcReadString(
|
|
3526
|
+
const record4 = tcAsRecord(message);
|
|
3527
|
+
const explicitError = tcReadString(record4.errorMessage ?? record4.error_message)?.trim();
|
|
3445
3528
|
if (explicitError) return explicitError;
|
|
3446
|
-
const stopReason = tcPiMessageStopReason(
|
|
3529
|
+
const stopReason = tcPiMessageStopReason(record4);
|
|
3447
3530
|
if (stopReason === "error" || stopReason === "failed" || stopReason === "exception") {
|
|
3448
3531
|
return `Pi Agent message ended with stopReason=${stopReason}`;
|
|
3449
3532
|
}
|
|
@@ -3603,6 +3686,11 @@ function shouldPreserveExecutorJsonlForTranscript(executorKind, event) {
|
|
|
3603
3686
|
var CODEX_TRANSIENT_UPSTREAM_RE = /(?:we(?:'|’)re\s+currently\s+experiencing\s+high\s+demand|temporary\s+errors|rate[-\s]?limit(?:ed)?|too\s+many\s+requests|\b429\b|server\s+overloaded|service\s+unavailable|try\s+again\s+later)/i;
|
|
3604
3687
|
var CODEX_REMOTE_COMPACTION_RE = /remote\s+compact\s+task/i;
|
|
3605
3688
|
var CODEX_USAGE_LIMIT_RE = /you(?:'|’)ve hit your usage limit for .+\.\s+switch to another model now,\s+or try again at\s+([^.!\n]+)(?:[.!]|\n|$)/i;
|
|
3689
|
+
var PI_PROVIDER_AUTH_RE = /(?:(?:\b401\b|\b403\b)[^\n]*(?:unauthorized|forbidden|auth(?:entication|orization)?|api[_\s-]?key)|(?:invalid|missing|expired|revoked)\s+(?:provider\s+)?api[_\s-]?key|provider\s+authentication\s+required)/i;
|
|
3690
|
+
var PI_PROVIDER_QUOTA_EXHAUSTED_RE = /(?:\binsufficient[_\s-]?user[_\s-]?quota\b|河狸币余额不足|\b402\b[^\n]*(?:余额不足|payment\s+required))/i;
|
|
3691
|
+
var PI_PROVIDER_TRANSIENT_RE = /(?:\b(?:429|5\d{2})\b|rate[-\s]?limit(?:ed)?|too\s+many\s+requests|billing\s+admission\s+failed|service\s+unavailable|upstream[^\n]*(?:unavailable|failed|timeout)|connect(?:ion)?[^\n]*refused|temporar(?:y|ily)[^\n]*(?:unavailable|failed)|try\s+again\s+later)/i;
|
|
3692
|
+
var PI_PROVIDER_RETRY_AFTER_SECONDS_RE = /retry[-\s]?after\s*[:=]?\s*(\d{1,6})\s*(?:seconds?|secs?|s)\b/i;
|
|
3693
|
+
var MAX_PI_PROVIDER_RETRY_AFTER_SECONDS = 7 * 24 * 60 * 60;
|
|
3606
3694
|
function approvedMcpInvocationSucceeded(results, invocationId) {
|
|
3607
3695
|
const approvedInvocationId = readString(invocationId);
|
|
3608
3696
|
return Boolean(approvedInvocationId && (Array.isArray(results) ? results : []).some((rawResult) => {
|
|
@@ -3817,6 +3905,39 @@ function classifyCodexTransientUpstreamError(input, now = /* @__PURE__ */ new Da
|
|
|
3817
3905
|
...retryNotBefore ? { retryNotBefore: retryNotBefore.toISOString() } : {}
|
|
3818
3906
|
};
|
|
3819
3907
|
}
|
|
3908
|
+
function extractPiProviderRetryNotBefore(errorMessage, now) {
|
|
3909
|
+
const retryAfter = errorMessage.match(PI_PROVIDER_RETRY_AFTER_SECONDS_RE);
|
|
3910
|
+
if (!retryAfter) return null;
|
|
3911
|
+
const seconds = Number.parseInt(retryAfter[1] ?? "", 10);
|
|
3912
|
+
if (!Number.isSafeInteger(seconds) || seconds < 0 || seconds > MAX_PI_PROVIDER_RETRY_AFTER_SECONDS) {
|
|
3913
|
+
return null;
|
|
3914
|
+
}
|
|
3915
|
+
return new Date(now.getTime() + seconds * 1e3);
|
|
3916
|
+
}
|
|
3917
|
+
function classifyPiProviderError(input, now = /* @__PURE__ */ new Date()) {
|
|
3918
|
+
const errorMessage = readString(asRecord(input).errorMessage);
|
|
3919
|
+
if (!errorMessage) return null;
|
|
3920
|
+
if (PI_PROVIDER_QUOTA_EXHAUSTED_RE.test(errorMessage)) {
|
|
3921
|
+
return {
|
|
3922
|
+
errorCode: "pi_provider_quota_exhausted",
|
|
3923
|
+
errorFamily: "provider_quota",
|
|
3924
|
+
nextAction: "\u6CB3\u72F8\u5E01\u4F59\u989D\u4E0D\u8DB3\uFF0C\u7CFB\u7EDF\u5DF2\u505C\u6B62\u81EA\u52A8\u91CD\u8BD5\u3002\u8BF7\u5145\u503C\u6216\u6062\u590D\u989D\u5EA6\u540E\u624B\u52A8\u91CD\u8DD1\u8BE5\u4EFB\u52A1\u3002"
|
|
3925
|
+
};
|
|
3926
|
+
}
|
|
3927
|
+
if (PI_PROVIDER_AUTH_RE.test(errorMessage)) {
|
|
3928
|
+
return {
|
|
3929
|
+
errorCode: "pi_provider_auth_required",
|
|
3930
|
+
errorFamily: "configuration"
|
|
3931
|
+
};
|
|
3932
|
+
}
|
|
3933
|
+
if (!PI_PROVIDER_TRANSIENT_RE.test(errorMessage)) return null;
|
|
3934
|
+
const retryNotBefore = extractPiProviderRetryNotBefore(errorMessage, now);
|
|
3935
|
+
return {
|
|
3936
|
+
errorCode: "pi_transient_upstream",
|
|
3937
|
+
errorFamily: "transient_upstream",
|
|
3938
|
+
...retryNotBefore ? { retryNotBefore: retryNotBefore.toISOString() } : {}
|
|
3939
|
+
};
|
|
3940
|
+
}
|
|
3820
3941
|
function parseClaudeStreamJson(stdout) {
|
|
3821
3942
|
let sessionId = null;
|
|
3822
3943
|
let summary = "";
|
|
@@ -3863,13 +3984,13 @@ function parseClaudeStreamJson(stdout) {
|
|
|
3863
3984
|
}
|
|
3864
3985
|
function openCodeErrorText(value) {
|
|
3865
3986
|
if (typeof value === "string") return value;
|
|
3866
|
-
const
|
|
3867
|
-
const message = readString(
|
|
3987
|
+
const record4 = asRecord(value);
|
|
3988
|
+
const message = readString(record4.message);
|
|
3868
3989
|
if (message) return message;
|
|
3869
|
-
const data = asRecord(
|
|
3990
|
+
const data = asRecord(record4.data);
|
|
3870
3991
|
const nestedMessage = readString(data.message);
|
|
3871
3992
|
if (nestedMessage) return nestedMessage;
|
|
3872
|
-
return readString(
|
|
3993
|
+
return readString(record4.name) ?? readString(record4.code) ?? "";
|
|
3873
3994
|
}
|
|
3874
3995
|
function parseOpenCodeJsonl(stdout) {
|
|
3875
3996
|
let sessionId = null;
|
|
@@ -3907,8 +4028,8 @@ function parseOpenCodeJsonl(stdout) {
|
|
|
3907
4028
|
return { sessionId, summary, usage, errorMessage };
|
|
3908
4029
|
}
|
|
3909
4030
|
function piMessageText(message) {
|
|
3910
|
-
const
|
|
3911
|
-
const content =
|
|
4031
|
+
const record4 = asRecord(message);
|
|
4032
|
+
const content = record4.content;
|
|
3912
4033
|
if (typeof content === "string") return content.trim();
|
|
3913
4034
|
if (!Array.isArray(content)) return "";
|
|
3914
4035
|
return content.map((entry) => {
|
|
@@ -3933,10 +4054,10 @@ function piTextValue(value) {
|
|
|
3933
4054
|
return typeof value === "string" && value.length > 0 ? value : "";
|
|
3934
4055
|
}
|
|
3935
4056
|
function piAssistantEventText(assistantEvent) {
|
|
3936
|
-
const
|
|
3937
|
-
const type = readString(
|
|
3938
|
-
if (type === "text_delta") return piTextValue(
|
|
3939
|
-
if (type === "text_end") return piTextValue(
|
|
4057
|
+
const record4 = asRecord(assistantEvent);
|
|
4058
|
+
const type = readString(record4.type);
|
|
4059
|
+
if (type === "text_delta") return piTextValue(record4.delta);
|
|
4060
|
+
if (type === "text_end") return piTextValue(record4.content);
|
|
3940
4061
|
return "";
|
|
3941
4062
|
}
|
|
3942
4063
|
function piMessageUsage(message) {
|
|
@@ -3957,14 +4078,14 @@ function assignPiUsage(target, source) {
|
|
|
3957
4078
|
if (source.costUsd > 0) target.costUsd = source.costUsd;
|
|
3958
4079
|
}
|
|
3959
4080
|
function piMessageStopReason(message) {
|
|
3960
|
-
const
|
|
3961
|
-
return readString(
|
|
4081
|
+
const record4 = asRecord(message);
|
|
4082
|
+
return readString(record4.stopReason ?? record4.stop_reason);
|
|
3962
4083
|
}
|
|
3963
4084
|
function piMessageErrorText(message) {
|
|
3964
|
-
const
|
|
3965
|
-
const explicitError = readString(
|
|
4085
|
+
const record4 = asRecord(message);
|
|
4086
|
+
const explicitError = readString(record4.errorMessage ?? record4.error_message)?.trim();
|
|
3966
4087
|
if (explicitError) return explicitError;
|
|
3967
|
-
const stopReason = piMessageStopReason(
|
|
4088
|
+
const stopReason = piMessageStopReason(record4);
|
|
3968
4089
|
if (stopReason === "error" || stopReason === "failed" || stopReason === "exception") {
|
|
3969
4090
|
return `Pi Agent message ended with stopReason=${stopReason}`;
|
|
3970
4091
|
}
|
|
@@ -4256,7 +4377,7 @@ async function postRuntimeConnectorJsonWithRetry(config, path, payload, options
|
|
|
4256
4377
|
} catch (error) {
|
|
4257
4378
|
lastError = error;
|
|
4258
4379
|
if (attempt >= maxAttempts || !retryableRuntimeConnectorPost(error)) throw error;
|
|
4259
|
-
if (delayMs > 0) await new Promise((
|
|
4380
|
+
if (delayMs > 0) await new Promise((resolve12) => setTimeout(resolve12, delayMs));
|
|
4260
4381
|
}
|
|
4261
4382
|
}
|
|
4262
4383
|
throw lastError;
|
|
@@ -4340,14 +4461,25 @@ function prepareRuntimeArtifactUploads(cwd, mcpToolResults) {
|
|
|
4340
4461
|
}
|
|
4341
4462
|
|
|
4342
4463
|
// src/amaster-runtime-daemon/runtime-artifact-ingest-queue.mjs
|
|
4464
|
+
function normalizedError(caught) {
|
|
4465
|
+
return caught instanceof Error ? caught : new Error(String(caught));
|
|
4466
|
+
}
|
|
4467
|
+
var RuntimeArtifactIngestAggregateError = class extends AggregateError {
|
|
4468
|
+
constructor(errors, receipts) {
|
|
4469
|
+
super(errors, `${errors.length} Runtime Artifact ingest operation(s) failed`);
|
|
4470
|
+
this.name = "RuntimeArtifactIngestAggregateError";
|
|
4471
|
+
this.code = errors.some((error) => error.code === "runtime_artifact_rejected") ? "runtime_artifact_rejected" : "runtime_artifact_ingest_failed";
|
|
4472
|
+
this.failures = [...errors];
|
|
4473
|
+
this.receipts = [...receipts];
|
|
4474
|
+
}
|
|
4475
|
+
};
|
|
4343
4476
|
function createRuntimeArtifactIngestQueue({ ingest, onError }) {
|
|
4344
4477
|
const handledIntentIds = /* @__PURE__ */ new Set();
|
|
4345
4478
|
const artifacts = [];
|
|
4346
|
-
|
|
4479
|
+
const errors = [];
|
|
4347
4480
|
let queue = Promise.resolve();
|
|
4348
4481
|
return {
|
|
4349
4482
|
enqueue(results) {
|
|
4350
|
-
if (error) return;
|
|
4351
4483
|
const pending = results.filter((result2) => {
|
|
4352
4484
|
const intentId = readString(asRecord(result2).artifactIntent?.intentId);
|
|
4353
4485
|
if (!intentId || handledIntentIds.has(intentId)) return false;
|
|
@@ -4356,8 +4488,12 @@ function createRuntimeArtifactIngestQueue({ ingest, onError }) {
|
|
|
4356
4488
|
});
|
|
4357
4489
|
if (pending.length === 0) return;
|
|
4358
4490
|
queue = queue.then(async () => artifacts.push(...await ingest(pending))).catch((caught) => {
|
|
4359
|
-
|
|
4360
|
-
|
|
4491
|
+
const aggregate = caught instanceof RuntimeArtifactIngestAggregateError ? caught : null;
|
|
4492
|
+
artifacts.push(...aggregate?.receipts ?? []);
|
|
4493
|
+
for (const error of aggregate?.failures ?? [normalizedError(caught)]) {
|
|
4494
|
+
errors.push(error);
|
|
4495
|
+
onError?.(error);
|
|
4496
|
+
}
|
|
4361
4497
|
});
|
|
4362
4498
|
},
|
|
4363
4499
|
hasHandled(intentId) {
|
|
@@ -4365,7 +4501,9 @@ function createRuntimeArtifactIngestQueue({ ingest, onError }) {
|
|
|
4365
4501
|
},
|
|
4366
4502
|
async flush() {
|
|
4367
4503
|
await queue;
|
|
4368
|
-
if (
|
|
4504
|
+
if (errors.length > 0) {
|
|
4505
|
+
throw new RuntimeArtifactIngestAggregateError(errors, artifacts);
|
|
4506
|
+
}
|
|
4369
4507
|
return [...artifacts];
|
|
4370
4508
|
}
|
|
4371
4509
|
};
|
|
@@ -4895,18 +5033,24 @@ function createPiChildIdentityAllocator(input = {}) {
|
|
|
4895
5033
|
const runAssignments = /* @__PURE__ */ new Map();
|
|
4896
5034
|
const uidAssignments = /* @__PURE__ */ new Map();
|
|
4897
5035
|
return {
|
|
4898
|
-
acquire(runId) {
|
|
5036
|
+
acquire(runId, options = {}) {
|
|
4899
5037
|
if (typeof runId !== "string" || runId.trim().length === 0) {
|
|
4900
5038
|
throw new Error("pi_child_isolation_run_id_required");
|
|
4901
5039
|
}
|
|
4902
5040
|
const normalizedRunId = runId.trim();
|
|
4903
5041
|
const existing = runAssignments.get(normalizedRunId);
|
|
4904
|
-
|
|
5042
|
+
const requestedGid = options.gid === void 0 ? null : positiveInteger(options.gid, "gid");
|
|
5043
|
+
if (existing) {
|
|
5044
|
+
if (requestedGid !== null && existing.gid !== requestedGid) {
|
|
5045
|
+
throw new Error("pi_child_isolation_run_gid_mismatch");
|
|
5046
|
+
}
|
|
5047
|
+
return { ...existing };
|
|
5048
|
+
}
|
|
4905
5049
|
const initialOffset = Math.abs(hashRunId(normalizedRunId)) % uidSpan;
|
|
4906
5050
|
for (let attempt = 0; attempt < uidSpan; attempt += 1) {
|
|
4907
5051
|
const uid = uidBase + (initialOffset + attempt) % uidSpan;
|
|
4908
5052
|
if (uidAssignments.has(uid)) continue;
|
|
4909
|
-
const assignment = { uid, gid: uid };
|
|
5053
|
+
const assignment = { uid, gid: requestedGid ?? uid };
|
|
4910
5054
|
runAssignments.set(normalizedRunId, assignment);
|
|
4911
5055
|
uidAssignments.set(uid, normalizedRunId);
|
|
4912
5056
|
return { ...assignment };
|
|
@@ -4945,7 +5089,9 @@ function preparePiChildIsolation(input) {
|
|
|
4945
5089
|
if (!isWithin(input.profileRoot, input.allowedRoot) || !isWithin(input.workspaceRoot, input.allowedRoot)) {
|
|
4946
5090
|
throw new Error("pi_child_isolation_path_outside_run_root");
|
|
4947
5091
|
}
|
|
4948
|
-
const assignment = input.allocator.acquire(input.runId
|
|
5092
|
+
const assignment = input.allocator.acquire(input.runId, {
|
|
5093
|
+
...input.gid === void 0 ? {} : { gid: input.gid }
|
|
5094
|
+
});
|
|
4949
5095
|
const isolatePath = input.isolatePath ?? isolatePiChildPath;
|
|
4950
5096
|
try {
|
|
4951
5097
|
for (const path of [resolve7(input.profileRoot), resolve7(input.workspaceRoot)]) {
|
|
@@ -4956,7 +5102,7 @@ function preparePiChildIsolation(input) {
|
|
|
4956
5102
|
throw error;
|
|
4957
5103
|
}
|
|
4958
5104
|
return {
|
|
4959
|
-
spawn: { uid: assignment.uid, gid: assignment.gid },
|
|
5105
|
+
spawn: { uid: assignment.uid, gid: assignment.gid, umask: 7 },
|
|
4960
5106
|
attestation: {
|
|
4961
5107
|
schemaVersion: "amaster.pi-child-isolation.v1",
|
|
4962
5108
|
commandId: input.commandId,
|
|
@@ -4969,21 +5115,248 @@ function preparePiChildIsolation(input) {
|
|
|
4969
5115
|
};
|
|
4970
5116
|
}
|
|
4971
5117
|
|
|
4972
|
-
// src/amaster-runtime-daemon/pi-
|
|
5118
|
+
// src/amaster-runtime-daemon/pi-company-memory.mjs
|
|
4973
5119
|
import { createHash as createHash6 } from "node:crypto";
|
|
4974
5120
|
import {
|
|
4975
5121
|
chmodSync as chmodSync4,
|
|
4976
|
-
|
|
5122
|
+
chownSync as chownSync2,
|
|
4977
5123
|
existsSync as existsSync9,
|
|
5124
|
+
lchownSync as lchownSync2,
|
|
4978
5125
|
lstatSync as lstatSync5,
|
|
4979
5126
|
mkdirSync as mkdirSync6,
|
|
4980
5127
|
readFileSync as readFileSync7,
|
|
4981
|
-
|
|
5128
|
+
renameSync as renameSync4,
|
|
4982
5129
|
rmSync as rmSync5,
|
|
4983
5130
|
symlinkSync as symlinkSync2,
|
|
4984
5131
|
writeFileSync as writeFileSync6
|
|
4985
5132
|
} from "node:fs";
|
|
4986
5133
|
import { dirname as dirname7, isAbsolute as isAbsolute5, join as join10, relative as relative5, resolve as resolve8 } from "node:path";
|
|
5134
|
+
var REGISTRY_FILENAME = ".amaster-company-memory-groups.json";
|
|
5135
|
+
var COMPANY_MARKER_FILENAME = ".amaster-company-memory.json";
|
|
5136
|
+
var REGISTRY_VERSION = 1;
|
|
5137
|
+
var COMPANY_MARKER_VERSION = 1;
|
|
5138
|
+
var DEFAULT_GID_BASE = 1e5;
|
|
5139
|
+
var DEFAULT_GID_SPAN = 1e6;
|
|
5140
|
+
var defaultFs2 = {
|
|
5141
|
+
chmodSync: chmodSync4,
|
|
5142
|
+
chownSync: chownSync2,
|
|
5143
|
+
existsSync: existsSync9,
|
|
5144
|
+
lchownSync: lchownSync2,
|
|
5145
|
+
lstatSync: lstatSync5,
|
|
5146
|
+
mkdirSync: mkdirSync6,
|
|
5147
|
+
readFileSync: readFileSync7,
|
|
5148
|
+
renameSync: renameSync4,
|
|
5149
|
+
rmSync: rmSync5,
|
|
5150
|
+
symlinkSync: symlinkSync2,
|
|
5151
|
+
writeFileSync: writeFileSync6
|
|
5152
|
+
};
|
|
5153
|
+
function requiredString2(value, label) {
|
|
5154
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
5155
|
+
throw new Error(`pi_company_memory_invalid:${label}`);
|
|
5156
|
+
}
|
|
5157
|
+
return value.trim();
|
|
5158
|
+
}
|
|
5159
|
+
function positiveInteger2(value, label) {
|
|
5160
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
5161
|
+
throw new Error(`pi_company_memory_invalid:${label}`);
|
|
5162
|
+
}
|
|
5163
|
+
return value;
|
|
5164
|
+
}
|
|
5165
|
+
function within2(candidate, root) {
|
|
5166
|
+
const rel = relative5(root, candidate);
|
|
5167
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute5(rel);
|
|
5168
|
+
}
|
|
5169
|
+
function assertDirectory(path, label, fs) {
|
|
5170
|
+
const stat = fs.lstatSync(path);
|
|
5171
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
5172
|
+
throw new Error(`pi_company_memory_unsafe:${label}`);
|
|
5173
|
+
}
|
|
5174
|
+
}
|
|
5175
|
+
function readJson(path, label, fs) {
|
|
5176
|
+
try {
|
|
5177
|
+
const value = JSON.parse(fs.readFileSync(path, "utf8"));
|
|
5178
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5179
|
+
throw new Error("not an object");
|
|
5180
|
+
}
|
|
5181
|
+
return value;
|
|
5182
|
+
} catch {
|
|
5183
|
+
throw new Error(`pi_company_memory_invalid:${label}`);
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
5186
|
+
function writeJsonAtomic(path, value, mode, fs) {
|
|
5187
|
+
const tempPath = `${path}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
5188
|
+
try {
|
|
5189
|
+
fs.writeFileSync(tempPath, `${JSON.stringify(value, null, 2)}
|
|
5190
|
+
`, {
|
|
5191
|
+
mode,
|
|
5192
|
+
flag: "wx"
|
|
5193
|
+
});
|
|
5194
|
+
fs.chmodSync(tempPath, mode);
|
|
5195
|
+
fs.renameSync(tempPath, path);
|
|
5196
|
+
} catch (error) {
|
|
5197
|
+
fs.rmSync(tempPath, { force: true });
|
|
5198
|
+
throw error;
|
|
5199
|
+
}
|
|
5200
|
+
}
|
|
5201
|
+
function safeCompanyPiHomeSegment(companyId) {
|
|
5202
|
+
const raw = requiredString2(companyId, "companyId");
|
|
5203
|
+
if (/^[A-Za-z0-9][A-Za-z0-9._-]{0,119}$/.test(raw)) return raw;
|
|
5204
|
+
const normalized = raw.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[._-]+|[._-]+$/g, "").slice(0, 80);
|
|
5205
|
+
const hash = createHash6("sha256").update(raw).digest("hex").slice(0, 12);
|
|
5206
|
+
return normalized ? `${normalized}-${hash}` : `company-${hash}`;
|
|
5207
|
+
}
|
|
5208
|
+
function ensureMemoryRoot(root, fs) {
|
|
5209
|
+
if (!fs.existsSync(root)) fs.mkdirSync(root, { recursive: true, mode: 457 });
|
|
5210
|
+
assertDirectory(root, "root", fs);
|
|
5211
|
+
fs.chownSync(root, 0, 0);
|
|
5212
|
+
fs.chmodSync(root, 457);
|
|
5213
|
+
}
|
|
5214
|
+
function readGroupRegistry(root, fs) {
|
|
5215
|
+
const path = join10(root, REGISTRY_FILENAME);
|
|
5216
|
+
if (!fs.existsSync(path)) {
|
|
5217
|
+
return { path, groups: {} };
|
|
5218
|
+
}
|
|
5219
|
+
const registryStat = fs.lstatSync(path);
|
|
5220
|
+
if (!registryStat.isFile() || registryStat.isSymbolicLink()) {
|
|
5221
|
+
throw new Error("pi_company_memory_unsafe:group_registry");
|
|
5222
|
+
}
|
|
5223
|
+
const registry = readJson(path, "group_registry", fs);
|
|
5224
|
+
if (registry.version !== REGISTRY_VERSION || !registry.groups || typeof registry.groups !== "object" || Array.isArray(registry.groups)) {
|
|
5225
|
+
throw new Error("pi_company_memory_invalid:group_registry");
|
|
5226
|
+
}
|
|
5227
|
+
const groups = {};
|
|
5228
|
+
const used = /* @__PURE__ */ new Set();
|
|
5229
|
+
for (const [companyId, rawGid] of Object.entries(registry.groups)) {
|
|
5230
|
+
const gid = positiveInteger2(rawGid, "registeredGid");
|
|
5231
|
+
if (used.has(gid)) throw new Error("pi_company_memory_invalid:duplicate_registered_gid");
|
|
5232
|
+
groups[requiredString2(companyId, "registeredCompanyId")] = gid;
|
|
5233
|
+
used.add(gid);
|
|
5234
|
+
}
|
|
5235
|
+
return { path, groups };
|
|
5236
|
+
}
|
|
5237
|
+
function allocateCompanyGid(root, companyId, input, fs) {
|
|
5238
|
+
const gidBase = positiveInteger2(input.gidBase ?? DEFAULT_GID_BASE, "gidBase");
|
|
5239
|
+
const gidSpan = positiveInteger2(input.gidSpan ?? DEFAULT_GID_SPAN, "gidSpan");
|
|
5240
|
+
const { path, groups } = readGroupRegistry(root, fs);
|
|
5241
|
+
if (groups[companyId]) return groups[companyId];
|
|
5242
|
+
const used = new Set(Object.values(groups));
|
|
5243
|
+
const initialOffset = Number.parseInt(
|
|
5244
|
+
createHash6("sha256").update(companyId).digest("hex").slice(0, 12),
|
|
5245
|
+
16
|
|
5246
|
+
) % gidSpan;
|
|
5247
|
+
let gid = null;
|
|
5248
|
+
for (let attempt = 0; attempt < gidSpan; attempt += 1) {
|
|
5249
|
+
const candidate = gidBase + (initialOffset + attempt) % gidSpan;
|
|
5250
|
+
if (!used.has(candidate)) {
|
|
5251
|
+
gid = candidate;
|
|
5252
|
+
break;
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5255
|
+
if (!gid) throw new Error("pi_company_memory_gid_pool_exhausted");
|
|
5256
|
+
writeJsonAtomic(path, {
|
|
5257
|
+
version: REGISTRY_VERSION,
|
|
5258
|
+
groups: {
|
|
5259
|
+
...groups,
|
|
5260
|
+
[companyId]: gid
|
|
5261
|
+
}
|
|
5262
|
+
}, 384, fs);
|
|
5263
|
+
return gid;
|
|
5264
|
+
}
|
|
5265
|
+
function resolveCompanyPiMemoryGroup(input, fs = defaultFs2) {
|
|
5266
|
+
const root = resolve8(requiredString2(input.root, "root"));
|
|
5267
|
+
const companyId = requiredString2(input.companyId, "companyId");
|
|
5268
|
+
ensureMemoryRoot(root, fs);
|
|
5269
|
+
return {
|
|
5270
|
+
root,
|
|
5271
|
+
companyId,
|
|
5272
|
+
gid: allocateCompanyGid(root, companyId, input, fs)
|
|
5273
|
+
};
|
|
5274
|
+
}
|
|
5275
|
+
function ensurePrivateDirectory(path, mode, uid, gid, fs) {
|
|
5276
|
+
if (!fs.existsSync(path)) fs.mkdirSync(path, { recursive: false, mode });
|
|
5277
|
+
assertDirectory(path, "directory", fs);
|
|
5278
|
+
fs.chownSync(path, uid, gid);
|
|
5279
|
+
fs.chmodSync(path, mode);
|
|
5280
|
+
}
|
|
5281
|
+
function prepareCompanyPiMemory(input, fs = defaultFs2) {
|
|
5282
|
+
const root = resolve8(requiredString2(input.root, "root"));
|
|
5283
|
+
const profileRoot = resolve8(requiredString2(input.profileRoot, "profileRoot"));
|
|
5284
|
+
const profileHome = resolve8(requiredString2(input.profileHome, "profileHome"));
|
|
5285
|
+
const companyId = requiredString2(input.companyId, "companyId");
|
|
5286
|
+
const childUid = positiveInteger2(input.childUid, "childUid");
|
|
5287
|
+
if (!within2(profileHome, profileRoot)) {
|
|
5288
|
+
throw new Error("pi_company_memory_profile_path_escape");
|
|
5289
|
+
}
|
|
5290
|
+
assertDirectory(profileRoot, "profile_root", fs);
|
|
5291
|
+
assertDirectory(profileHome, "profile_home", fs);
|
|
5292
|
+
const group = resolveCompanyPiMemoryGroup({ ...input, root, companyId }, fs);
|
|
5293
|
+
const gid = group.gid;
|
|
5294
|
+
if (input.gid !== void 0 && positiveInteger2(input.gid, "gid") !== gid) {
|
|
5295
|
+
throw new Error("pi_company_memory_gid_mismatch");
|
|
5296
|
+
}
|
|
5297
|
+
const companyDir = join10(root, safeCompanyPiHomeSegment(companyId));
|
|
5298
|
+
const companyPiHome = join10(companyDir, ".pi");
|
|
5299
|
+
const memoryDir = join10(companyPiHome, "memories");
|
|
5300
|
+
ensurePrivateDirectory(companyDir, 456, 0, gid, fs);
|
|
5301
|
+
const markerPath = join10(companyDir, COMPANY_MARKER_FILENAME);
|
|
5302
|
+
if (fs.existsSync(markerPath)) {
|
|
5303
|
+
const markerStat = fs.lstatSync(markerPath);
|
|
5304
|
+
if (!markerStat.isFile() || markerStat.isSymbolicLink()) {
|
|
5305
|
+
throw new Error("pi_company_memory_unsafe:company_marker");
|
|
5306
|
+
}
|
|
5307
|
+
const marker = readJson(markerPath, "company_marker", fs);
|
|
5308
|
+
if (marker.version !== COMPANY_MARKER_VERSION || marker.companyId !== companyId || marker.gid !== gid) {
|
|
5309
|
+
throw new Error("pi_company_memory_authority_mismatch");
|
|
5310
|
+
}
|
|
5311
|
+
} else {
|
|
5312
|
+
writeJsonAtomic(markerPath, {
|
|
5313
|
+
version: COMPANY_MARKER_VERSION,
|
|
5314
|
+
companyId,
|
|
5315
|
+
gid,
|
|
5316
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5317
|
+
}, 384, fs);
|
|
5318
|
+
}
|
|
5319
|
+
fs.chownSync(markerPath, 0, 0);
|
|
5320
|
+
fs.chmodSync(markerPath, 384);
|
|
5321
|
+
ensurePrivateDirectory(companyPiHome, 456, 0, gid, fs);
|
|
5322
|
+
if (!fs.existsSync(memoryDir)) fs.mkdirSync(memoryDir, { recursive: false, mode: 1528 });
|
|
5323
|
+
assertDirectory(memoryDir, "memories", fs);
|
|
5324
|
+
fs.chownSync(memoryDir, 0, gid);
|
|
5325
|
+
fs.chmodSync(memoryDir, 1528);
|
|
5326
|
+
const memoryLink = join10(profileHome, "memories");
|
|
5327
|
+
if (fs.existsSync(memoryLink)) {
|
|
5328
|
+
throw new Error("pi_company_memory_profile_link_exists");
|
|
5329
|
+
}
|
|
5330
|
+
fs.symlinkSync(memoryDir, memoryLink, "dir");
|
|
5331
|
+
fs.lchownSync(memoryLink, childUid, gid);
|
|
5332
|
+
return {
|
|
5333
|
+
gid,
|
|
5334
|
+
memoryDir,
|
|
5335
|
+
memoryLink,
|
|
5336
|
+
attestation: {
|
|
5337
|
+
schemaVersion: "amaster.company-pi-memory.v1",
|
|
5338
|
+
companyId,
|
|
5339
|
+
gid,
|
|
5340
|
+
mode: "run_scoped_home_company_memory"
|
|
5341
|
+
}
|
|
5342
|
+
};
|
|
5343
|
+
}
|
|
5344
|
+
|
|
5345
|
+
// src/amaster-runtime-daemon/pi-trusted-runtime-profile.mjs
|
|
5346
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
5347
|
+
import {
|
|
5348
|
+
chmodSync as chmodSync5,
|
|
5349
|
+
copyFileSync as copyFileSync2,
|
|
5350
|
+
existsSync as existsSync10,
|
|
5351
|
+
lstatSync as lstatSync6,
|
|
5352
|
+
mkdirSync as mkdirSync7,
|
|
5353
|
+
readFileSync as readFileSync8,
|
|
5354
|
+
readdirSync as readdirSync6,
|
|
5355
|
+
rmSync as rmSync6,
|
|
5356
|
+
symlinkSync as symlinkSync3,
|
|
5357
|
+
writeFileSync as writeFileSync7
|
|
5358
|
+
} from "node:fs";
|
|
5359
|
+
import { dirname as dirname8, isAbsolute as isAbsolute6, join as join11, relative as relative6, resolve as resolve9 } from "node:path";
|
|
4987
5360
|
var ASSERTION_VERSION = "2026-07-25.v1";
|
|
4988
5361
|
var SHA256 = /^[a-f0-9]{64}$/;
|
|
4989
5362
|
var COPY_ENTRIES = ["SYSTEM.md", "policy", "skills", "agents", "bundles", "extensions"];
|
|
@@ -4992,23 +5365,23 @@ var SECRET_KEY = /(authorization|cookie|api[_-]?key|password|secret|token)$/i;
|
|
|
4992
5365
|
var SECRET_VALUE = /(?:authorization|cookie|api[_-]?key|password|secret|token)\s*[:=]\s*(?:bearer\s+)?[^\s"',;]+|bearer\s+[^\s"',;]+/i;
|
|
4993
5366
|
var MAX_AUDIT_BYTES = 1024 * 1024;
|
|
4994
5367
|
var MAX_AUDIT_EVENTS = 2e3;
|
|
4995
|
-
function
|
|
5368
|
+
function requiredString3(value, field) {
|
|
4996
5369
|
if (typeof value !== "string" || value.trim() === "") {
|
|
4997
5370
|
throw new Error(`pi_trusted_runtime_assertion_invalid:${field}`);
|
|
4998
5371
|
}
|
|
4999
5372
|
return value.trim();
|
|
5000
5373
|
}
|
|
5001
5374
|
function requiredDigest(value, field) {
|
|
5002
|
-
const digest =
|
|
5375
|
+
const digest = requiredString3(value, field);
|
|
5003
5376
|
if (!SHA256.test(digest)) throw new Error(`pi_trusted_runtime_assertion_invalid:${field}`);
|
|
5004
5377
|
return digest;
|
|
5005
5378
|
}
|
|
5006
5379
|
function sha256File(path, label) {
|
|
5007
|
-
const stat =
|
|
5380
|
+
const stat = lstatSync6(path);
|
|
5008
5381
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
5009
5382
|
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
5010
5383
|
}
|
|
5011
|
-
return
|
|
5384
|
+
return createHash7("sha256").update(readFileSync8(path)).digest("hex");
|
|
5012
5385
|
}
|
|
5013
5386
|
function verifyDeclaredFiles(manifest, root, label, ignoredPaths = [], enforceComplete = true) {
|
|
5014
5387
|
if (!Array.isArray(manifest.files) || manifest.files.length === 0) {
|
|
@@ -5016,10 +5389,10 @@ function verifyDeclaredFiles(manifest, root, label, ignoredPaths = [], enforceCo
|
|
|
5016
5389
|
}
|
|
5017
5390
|
const seen = /* @__PURE__ */ new Set();
|
|
5018
5391
|
for (const entry of manifest.files) {
|
|
5019
|
-
const relativePath =
|
|
5392
|
+
const relativePath = requiredString3(entry?.path, `${label}.files.path`);
|
|
5020
5393
|
const expectedDigest = requiredDigest(entry?.sha256, `${label}.files.sha256`);
|
|
5021
|
-
const filePath =
|
|
5022
|
-
if (!
|
|
5394
|
+
const filePath = resolve9(root, relativePath);
|
|
5395
|
+
if (!within3(filePath, root) || seen.has(relativePath)) {
|
|
5023
5396
|
throw new Error(`pi_trusted_runtime_source_invalid:${label}_files`);
|
|
5024
5397
|
}
|
|
5025
5398
|
seen.add(relativePath);
|
|
@@ -5031,9 +5404,9 @@ function verifyDeclaredFiles(manifest, root, label, ignoredPaths = [], enforceCo
|
|
|
5031
5404
|
const ignored = ignoredPaths.map((path) => path.split("\\").join("/"));
|
|
5032
5405
|
const visit = (directory) => {
|
|
5033
5406
|
for (const entry of readdirSync6(directory)) {
|
|
5034
|
-
const filePath =
|
|
5035
|
-
const relativePath =
|
|
5036
|
-
const stat =
|
|
5407
|
+
const filePath = join11(directory, entry);
|
|
5408
|
+
const relativePath = relative6(root, filePath).split("\\").join("/");
|
|
5409
|
+
const stat = lstatSync6(filePath);
|
|
5037
5410
|
if (stat.isSymbolicLink()) {
|
|
5038
5411
|
throw new Error(`pi_trusted_runtime_source_unsafe:${label}_file`);
|
|
5039
5412
|
}
|
|
@@ -5049,21 +5422,21 @@ function verifyDeclaredFiles(manifest, root, label, ignoredPaths = [], enforceCo
|
|
|
5049
5422
|
};
|
|
5050
5423
|
visit(root);
|
|
5051
5424
|
}
|
|
5052
|
-
function
|
|
5425
|
+
function record3(value) {
|
|
5053
5426
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
5054
5427
|
}
|
|
5055
|
-
function
|
|
5056
|
-
const rel =
|
|
5057
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
5428
|
+
function within3(candidate, root) {
|
|
5429
|
+
const rel = relative6(root, candidate);
|
|
5430
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute6(rel);
|
|
5058
5431
|
}
|
|
5059
5432
|
function readJsonFile2(path, label, fallback = {}) {
|
|
5060
|
-
if (!
|
|
5061
|
-
const stat =
|
|
5433
|
+
if (!existsSync10(path)) return fallback;
|
|
5434
|
+
const stat = lstatSync6(path);
|
|
5062
5435
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
5063
5436
|
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
5064
5437
|
}
|
|
5065
5438
|
try {
|
|
5066
|
-
return JSON.parse(
|
|
5439
|
+
return JSON.parse(readFileSync8(path, "utf8"));
|
|
5067
5440
|
} catch {
|
|
5068
5441
|
throw new Error(`pi_trusted_runtime_source_invalid:${label}`);
|
|
5069
5442
|
}
|
|
@@ -5091,32 +5464,32 @@ function assertNoPersistentSecrets(value, path = []) {
|
|
|
5091
5464
|
}
|
|
5092
5465
|
}
|
|
5093
5466
|
function copyTreeNoLinks(source, target) {
|
|
5094
|
-
const stat =
|
|
5467
|
+
const stat = lstatSync6(source);
|
|
5095
5468
|
if (stat.isSymbolicLink()) throw new Error("pi_trusted_runtime_source_symlink_blocked");
|
|
5096
5469
|
if (stat.isDirectory()) {
|
|
5097
|
-
|
|
5098
|
-
|
|
5470
|
+
mkdirSync7(target, { recursive: true, mode: 448 });
|
|
5471
|
+
chmodSync5(target, 448);
|
|
5099
5472
|
for (const entry of readdirSync6(source)) {
|
|
5100
|
-
copyTreeNoLinks(
|
|
5473
|
+
copyTreeNoLinks(join11(source, entry), join11(target, entry));
|
|
5101
5474
|
}
|
|
5102
5475
|
return;
|
|
5103
5476
|
}
|
|
5104
5477
|
if (!stat.isFile()) throw new Error("pi_trusted_runtime_source_type_blocked");
|
|
5105
|
-
|
|
5478
|
+
mkdirSync7(dirname8(target), { recursive: true, mode: 448 });
|
|
5106
5479
|
copyFileSync2(source, target);
|
|
5107
|
-
|
|
5480
|
+
chmodSync5(target, 384 | stat.mode & 73);
|
|
5108
5481
|
}
|
|
5109
5482
|
function mergeMcp(seedRoot, overlayRoot, governedConfig) {
|
|
5110
|
-
const seed =
|
|
5111
|
-
const overlay =
|
|
5483
|
+
const seed = record3(readJsonFile2(join11(seedRoot, "mcp.json"), "seed_mcp", { mcpServers: {} }));
|
|
5484
|
+
const overlay = record3(readJsonFile2(join11(overlayRoot, "mcp.json"), "overlay_mcp", { mcpServers: {} }));
|
|
5112
5485
|
assertNoPersistentSecrets(seed, ["seed", "mcp.json"]);
|
|
5113
5486
|
assertNoPersistentSecrets(overlay, ["overlay", "mcp.json"]);
|
|
5114
|
-
const seedServers =
|
|
5115
|
-
const overlayServers =
|
|
5487
|
+
const seedServers = record3(seed.mcpServers);
|
|
5488
|
+
const overlayServers = record3(overlay.mcpServers);
|
|
5116
5489
|
if ("amaster" in seedServers || "amaster" in overlayServers) {
|
|
5117
5490
|
throw new Error("pi_trusted_runtime_reserved_mcp_override:amaster");
|
|
5118
5491
|
}
|
|
5119
|
-
const governed =
|
|
5492
|
+
const governed = record3(record3(governedConfig).mcpServers).amaster;
|
|
5120
5493
|
if (!governed) throw new Error("pi_trusted_runtime_governed_mcp_missing");
|
|
5121
5494
|
return {
|
|
5122
5495
|
...deepMerge(seed, overlay),
|
|
@@ -5136,14 +5509,14 @@ function assertEnabledPackagesAvailable(settings, npmRoot) {
|
|
|
5136
5509
|
const requiredNames = new Set(
|
|
5137
5510
|
(Array.isArray(settings.packages) ? settings.packages : []).map(packageName).filter(Boolean)
|
|
5138
5511
|
);
|
|
5139
|
-
for (const plugin of Object.values(
|
|
5140
|
-
const config =
|
|
5512
|
+
for (const plugin of Object.values(record3(settings.plugins))) {
|
|
5513
|
+
const config = record3(plugin);
|
|
5141
5514
|
if (config.enabled === true && typeof config.package === "string") {
|
|
5142
5515
|
requiredNames.add(config.package);
|
|
5143
5516
|
}
|
|
5144
5517
|
}
|
|
5145
5518
|
for (const name of requiredNames) {
|
|
5146
|
-
const metadataPath =
|
|
5519
|
+
const metadataPath = join11(npmRoot, "node_modules", ...name.split("/"), "package.json");
|
|
5147
5520
|
const metadata = readJsonFile2(metadataPath, `package:${name}`, null);
|
|
5148
5521
|
if (!metadata || metadata.name !== name) {
|
|
5149
5522
|
throw new Error(`pi_trusted_runtime_package_unavailable:${name}`);
|
|
@@ -5151,62 +5524,62 @@ function assertEnabledPackagesAvailable(settings, npmRoot) {
|
|
|
5151
5524
|
}
|
|
5152
5525
|
}
|
|
5153
5526
|
function materializeTrustedPiRuntimeProfile(input) {
|
|
5154
|
-
const seedRoot =
|
|
5155
|
-
const overlayRoot =
|
|
5156
|
-
const profileRoot =
|
|
5157
|
-
const agentDir =
|
|
5158
|
-
if (!
|
|
5527
|
+
const seedRoot = resolve9(requiredString3(input.seedRoot, "seedRoot"));
|
|
5528
|
+
const overlayRoot = resolve9(requiredString3(input.overlayRoot, "overlayRoot"));
|
|
5529
|
+
const profileRoot = resolve9(requiredString3(input.profileRoot, "profileRoot"));
|
|
5530
|
+
const agentDir = resolve9(requiredString3(input.agentDir, "agentDir"));
|
|
5531
|
+
if (!within3(agentDir, profileRoot)) throw new Error("pi_trusted_runtime_profile_path_escape");
|
|
5159
5532
|
for (const [root, label] of [[seedRoot, "seed_root"], [overlayRoot, "overlay_root"]]) {
|
|
5160
|
-
const stat =
|
|
5533
|
+
const stat = lstatSync6(root);
|
|
5161
5534
|
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
5162
5535
|
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
5163
5536
|
}
|
|
5164
5537
|
}
|
|
5165
5538
|
for (const entry of COPY_ENTRIES) {
|
|
5166
|
-
const target =
|
|
5167
|
-
|
|
5539
|
+
const target = join11(agentDir, entry);
|
|
5540
|
+
rmSync6(target, { recursive: true, force: true });
|
|
5168
5541
|
for (const sourceRoot of [seedRoot, overlayRoot]) {
|
|
5169
|
-
const source =
|
|
5170
|
-
if (
|
|
5542
|
+
const source = join11(sourceRoot, entry);
|
|
5543
|
+
if (existsSync10(source)) copyTreeNoLinks(source, target);
|
|
5171
5544
|
}
|
|
5172
5545
|
}
|
|
5173
5546
|
const mergedJson = {};
|
|
5174
5547
|
for (const entry of JSON_ENTRIES) {
|
|
5175
|
-
const seed = readJsonFile2(
|
|
5176
|
-
const overlay = readJsonFile2(
|
|
5548
|
+
const seed = readJsonFile2(join11(seedRoot, entry), `seed_${entry}`, {});
|
|
5549
|
+
const overlay = readJsonFile2(join11(overlayRoot, entry), `overlay_${entry}`, {});
|
|
5177
5550
|
const merged = deepMerge(seed, overlay);
|
|
5178
5551
|
if (entry === "settings.json") {
|
|
5179
5552
|
merged["pi-security"] = {
|
|
5180
|
-
...
|
|
5553
|
+
...record3(merged["pi-security"]),
|
|
5181
5554
|
enabled: true,
|
|
5182
5555
|
approvals: {
|
|
5183
|
-
...
|
|
5556
|
+
...record3(record3(merged["pi-security"]).approvals),
|
|
5184
5557
|
allowSessionGrants: false
|
|
5185
5558
|
}
|
|
5186
5559
|
};
|
|
5187
5560
|
}
|
|
5188
5561
|
assertNoPersistentSecrets(merged, [entry]);
|
|
5189
|
-
|
|
5562
|
+
writeFileSync7(join11(agentDir, entry), `${JSON.stringify(merged, null, 2)}
|
|
5190
5563
|
`, {
|
|
5191
5564
|
mode: 384
|
|
5192
5565
|
});
|
|
5193
|
-
|
|
5566
|
+
chmodSync5(join11(agentDir, entry), 384);
|
|
5194
5567
|
mergedJson[entry] = merged;
|
|
5195
5568
|
}
|
|
5196
5569
|
const governedConfig = readJsonFile2(input.governedMcpConfigPath, "governed_mcp");
|
|
5197
5570
|
const mcp = mergeMcp(seedRoot, overlayRoot, governedConfig);
|
|
5198
|
-
|
|
5571
|
+
writeFileSync7(input.governedMcpConfigPath, `${JSON.stringify(mcp, null, 2)}
|
|
5199
5572
|
`, { mode: 384 });
|
|
5200
|
-
|
|
5201
|
-
const npmRoot =
|
|
5573
|
+
chmodSync5(input.governedMcpConfigPath, 384);
|
|
5574
|
+
const npmRoot = join11(seedRoot, "npm");
|
|
5202
5575
|
assertEnabledPackagesAvailable(mergedJson["settings.json"], npmRoot);
|
|
5203
|
-
const npmTarget =
|
|
5204
|
-
|
|
5205
|
-
const npmStat =
|
|
5576
|
+
const npmTarget = join11(agentDir, "npm");
|
|
5577
|
+
rmSync6(npmTarget, { recursive: true, force: true });
|
|
5578
|
+
const npmStat = lstatSync6(npmRoot);
|
|
5206
5579
|
if (!npmStat.isDirectory() || npmStat.isSymbolicLink()) {
|
|
5207
5580
|
throw new Error("pi_trusted_runtime_source_unsafe:seed_npm");
|
|
5208
5581
|
}
|
|
5209
|
-
|
|
5582
|
+
symlinkSync3(npmRoot, npmTarget, "dir");
|
|
5210
5583
|
const facts = {
|
|
5211
5584
|
schemaVersion: "amaster.trusted-pi-profile.v1",
|
|
5212
5585
|
seedManifestDigest: input.verifiedAssertion.digests.seedManifestDigest,
|
|
@@ -5219,7 +5592,7 @@ function materializeTrustedPiRuntimeProfile(input) {
|
|
|
5219
5592
|
};
|
|
5220
5593
|
return {
|
|
5221
5594
|
facts,
|
|
5222
|
-
attestationId:
|
|
5595
|
+
attestationId: createHash7("sha256").update(JSON.stringify(facts)).digest("hex")
|
|
5223
5596
|
};
|
|
5224
5597
|
}
|
|
5225
5598
|
function assertAuditArgsRedacted(value) {
|
|
@@ -5242,16 +5615,16 @@ function assertAuditArgsRedacted(value) {
|
|
|
5242
5615
|
}
|
|
5243
5616
|
}
|
|
5244
5617
|
function readTrustedPiRuntimeAudit(input) {
|
|
5245
|
-
const profileRoot =
|
|
5246
|
-
const auditFile =
|
|
5247
|
-
if (!
|
|
5248
|
-
if (!
|
|
5249
|
-
const stat =
|
|
5618
|
+
const profileRoot = resolve9(requiredString3(input.profileRoot, "profileRoot"));
|
|
5619
|
+
const auditFile = resolve9(requiredString3(input.auditFile, "auditFile"));
|
|
5620
|
+
if (!within3(auditFile, profileRoot)) throw new Error("pi_trusted_runtime_audit_path_escape");
|
|
5621
|
+
if (!existsSync10(auditFile)) throw new Error("pi_trusted_runtime_audit_startup_missing");
|
|
5622
|
+
const stat = lstatSync6(auditFile);
|
|
5250
5623
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
5251
5624
|
throw new Error("pi_trusted_runtime_audit_unsafe");
|
|
5252
5625
|
}
|
|
5253
5626
|
if (stat.size > MAX_AUDIT_BYTES) throw new Error("pi_trusted_runtime_audit_too_large");
|
|
5254
|
-
const lines =
|
|
5627
|
+
const lines = readFileSync8(auditFile, "utf8").split("\n").filter(Boolean);
|
|
5255
5628
|
if (lines.length === 0 || lines.length > MAX_AUDIT_EVENTS) {
|
|
5256
5629
|
throw new Error("pi_trusted_runtime_audit_event_count_invalid");
|
|
5257
5630
|
}
|
|
@@ -5299,20 +5672,20 @@ function readTrustedPiRuntimeAudit(input) {
|
|
|
5299
5672
|
};
|
|
5300
5673
|
}
|
|
5301
5674
|
function readTrustedPiRuntimeLocalDigests(input) {
|
|
5302
|
-
const seedRoot =
|
|
5303
|
-
const overlayRoot =
|
|
5304
|
-
const policyFile =
|
|
5675
|
+
const seedRoot = resolve9(requiredString3(input.seedRoot, "seedRoot"));
|
|
5676
|
+
const overlayRoot = resolve9(requiredString3(input.overlayRoot, "overlayRoot"));
|
|
5677
|
+
const policyFile = resolve9(requiredString3(input.policyFile, "policyFile"));
|
|
5305
5678
|
for (const [path, label] of [[seedRoot, "seed_root"], [overlayRoot, "overlay_root"]]) {
|
|
5306
|
-
const stat =
|
|
5679
|
+
const stat = lstatSync6(path);
|
|
5307
5680
|
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
5308
5681
|
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
5309
5682
|
}
|
|
5310
5683
|
}
|
|
5311
|
-
const seedManifestFile =
|
|
5312
|
-
const overlayManifestFile =
|
|
5313
|
-
const seedManifest = JSON.parse(
|
|
5314
|
-
const overlayManifest = JSON.parse(
|
|
5315
|
-
const policyManifest = JSON.parse(
|
|
5684
|
+
const seedManifestFile = join11(seedRoot, "seed-manifest.json");
|
|
5685
|
+
const overlayManifestFile = join11(overlayRoot, "runtime-overlay-manifest.json");
|
|
5686
|
+
const seedManifest = JSON.parse(readFileSync8(seedManifestFile, "utf8"));
|
|
5687
|
+
const overlayManifest = JSON.parse(readFileSync8(overlayManifestFile, "utf8"));
|
|
5688
|
+
const policyManifest = JSON.parse(readFileSync8(policyFile, "utf8"));
|
|
5316
5689
|
verifyDeclaredFiles(seedManifest, seedRoot, "seed", [
|
|
5317
5690
|
"seed-manifest.json",
|
|
5318
5691
|
"npm/package-lock.json",
|
|
@@ -5321,9 +5694,9 @@ function readTrustedPiRuntimeLocalDigests(input) {
|
|
|
5321
5694
|
verifyDeclaredFiles(overlayManifest, overlayRoot, "overlay", ["runtime-overlay-manifest.json"]);
|
|
5322
5695
|
verifyDeclaredFiles(
|
|
5323
5696
|
policyManifest,
|
|
5324
|
-
|
|
5697
|
+
dirname8(policyFile),
|
|
5325
5698
|
"policy",
|
|
5326
|
-
[
|
|
5699
|
+
[relative6(dirname8(policyFile), policyFile)],
|
|
5327
5700
|
false
|
|
5328
5701
|
);
|
|
5329
5702
|
return {
|
|
@@ -5369,16 +5742,16 @@ function verifyTrustedPiRuntimeAssertion(input) {
|
|
|
5369
5742
|
leaseId: input.leaseId,
|
|
5370
5743
|
executorKind: input.executorKind
|
|
5371
5744
|
};
|
|
5372
|
-
|
|
5745
|
+
requiredString3(assertion.attestationId, "attestationId");
|
|
5373
5746
|
for (const [field, expected] of Object.entries(bindings)) {
|
|
5374
|
-
if (
|
|
5747
|
+
if (requiredString3(assertion[field], field) !== expected) {
|
|
5375
5748
|
throw new Error(`pi_trusted_runtime_assertion_binding_mismatch:${field}`);
|
|
5376
5749
|
}
|
|
5377
5750
|
}
|
|
5378
5751
|
if (assertion.executorKind !== "pi") {
|
|
5379
5752
|
throw new Error("pi_trusted_runtime_assertion_binding_mismatch:executorKind");
|
|
5380
5753
|
}
|
|
5381
|
-
const expiresAt = Date.parse(
|
|
5754
|
+
const expiresAt = Date.parse(requiredString3(assertion.expiresAt, "expiresAt"));
|
|
5382
5755
|
const now = input.now instanceof Date ? input.now : new Date(input.now ?? Date.now());
|
|
5383
5756
|
if (!Number.isFinite(expiresAt) || input.verifyExpiry !== false && expiresAt <= now.getTime()) {
|
|
5384
5757
|
throw new Error("pi_trusted_runtime_assertion_expired");
|
|
@@ -5415,9 +5788,9 @@ function verifyTrustedPiRuntimeAssertion(input) {
|
|
|
5415
5788
|
|
|
5416
5789
|
// src/amaster-runtime-daemon/workspace-status.mjs
|
|
5417
5790
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
5418
|
-
import { createHash as
|
|
5419
|
-
import { existsSync as
|
|
5420
|
-
import { basename as basename5, extname, isAbsolute as
|
|
5791
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
5792
|
+
import { existsSync as existsSync11, readdirSync as readdirSync7, readFileSync as readFileSync9, statSync as statSync6 } from "node:fs";
|
|
5793
|
+
import { basename as basename5, extname, isAbsolute as isAbsolute7, join as join12, relative as relative7, resolve as resolve10 } from "node:path";
|
|
5421
5794
|
var WORKSPACE_RUNTIME_SERVICES_FILENAME = ".amaster-runtime-services.json";
|
|
5422
5795
|
var ARTIFACT_EXTENSIONS = /* @__PURE__ */ new Map([
|
|
5423
5796
|
[".md", "markdown"],
|
|
@@ -5462,11 +5835,11 @@ var SAFE_RUNTIME_SERVICE_STATUSES = /* @__PURE__ */ new Set(["starting", "runnin
|
|
|
5462
5835
|
var SAFE_RUNTIME_SERVICE_HEALTH_STATUSES = /* @__PURE__ */ new Set(["unknown", "healthy", "unhealthy"]);
|
|
5463
5836
|
var SAFE_RUNTIME_SERVICE_LIFECYCLES = /* @__PURE__ */ new Set(["shared", "ephemeral"]);
|
|
5464
5837
|
function statusPathWithin(candidate, root) {
|
|
5465
|
-
const rel =
|
|
5466
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
5838
|
+
const rel = relative7(root, candidate);
|
|
5839
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute7(rel);
|
|
5467
5840
|
}
|
|
5468
5841
|
function normalizeRelativePath(root, filePath) {
|
|
5469
|
-
return
|
|
5842
|
+
return relative7(root, filePath).split(/[\\/]+/).join("/");
|
|
5470
5843
|
}
|
|
5471
5844
|
function isSafeRelativePath(value) {
|
|
5472
5845
|
const text = String(value ?? "").trim().split(/[\\/]+/).join("/");
|
|
@@ -5486,7 +5859,7 @@ function sanitizeTrackedChange(line) {
|
|
|
5486
5859
|
return isSafeRelativePath(path) ? line : null;
|
|
5487
5860
|
}
|
|
5488
5861
|
function sha256File2(filePath) {
|
|
5489
|
-
return
|
|
5862
|
+
return createHash8("sha256").update(readFileSync9(filePath)).digest("hex");
|
|
5490
5863
|
}
|
|
5491
5864
|
function artifactHashCacheKey(relativePath, stat) {
|
|
5492
5865
|
return `${relativePath}\0${stat.size}\0${stat.mtimeMs}`;
|
|
@@ -5514,7 +5887,7 @@ function artifactSha256(filePath, relativePath, stat, opts = {}) {
|
|
|
5514
5887
|
return hash;
|
|
5515
5888
|
}
|
|
5516
5889
|
function scanArtifactCandidates(cwd, opts = {}) {
|
|
5517
|
-
const root =
|
|
5890
|
+
const root = resolve10(cwd);
|
|
5518
5891
|
const maxCandidates = opts.maxCandidates ?? MAX_CANDIDATES;
|
|
5519
5892
|
const maxEntries = opts.maxEntries ?? MAX_SCAN_ENTRIES;
|
|
5520
5893
|
const candidates = [];
|
|
@@ -5535,7 +5908,7 @@ function scanArtifactCandidates(cwd, opts = {}) {
|
|
|
5535
5908
|
if (entry.name.startsWith(".") && entry.name !== ".amaster-runtime.json") {
|
|
5536
5909
|
if (entry.name === ".git") continue;
|
|
5537
5910
|
}
|
|
5538
|
-
const fullPath =
|
|
5911
|
+
const fullPath = join12(current, entry.name);
|
|
5539
5912
|
const relativePath = normalizeRelativePath(root, fullPath);
|
|
5540
5913
|
if (!isSafeRelativePath(relativePath)) continue;
|
|
5541
5914
|
if (basename5(relativePath) === ".amaster-runtime.json") continue;
|
|
@@ -5554,7 +5927,7 @@ function scanArtifactCandidates(cwd, opts = {}) {
|
|
|
5554
5927
|
} catch {
|
|
5555
5928
|
continue;
|
|
5556
5929
|
}
|
|
5557
|
-
if (!statusPathWithin(
|
|
5930
|
+
if (!statusPathWithin(resolve10(fullPath), root) || stat.size > MAX_HASH_BYTES) continue;
|
|
5558
5931
|
candidates.push({
|
|
5559
5932
|
relativePath,
|
|
5560
5933
|
name: basename5(fullPath),
|
|
@@ -5614,10 +5987,10 @@ function sanitizeRuntimeService(entry) {
|
|
|
5614
5987
|
};
|
|
5615
5988
|
}
|
|
5616
5989
|
function readRuntimeServicesSnapshot(cwd) {
|
|
5617
|
-
const snapshotPath =
|
|
5618
|
-
if (!
|
|
5990
|
+
const snapshotPath = join12(resolve10(cwd), WORKSPACE_RUNTIME_SERVICES_FILENAME);
|
|
5991
|
+
if (!existsSync11(snapshotPath)) return [];
|
|
5619
5992
|
try {
|
|
5620
|
-
const parsed = JSON.parse(
|
|
5993
|
+
const parsed = JSON.parse(readFileSync9(snapshotPath, "utf8"));
|
|
5621
5994
|
const rawServices = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.services) ? parsed.services : [];
|
|
5622
5995
|
return rawServices.map((entry) => sanitizeRuntimeService(entry)).filter((entry) => entry !== null).slice(0, 50);
|
|
5623
5996
|
} catch {
|
|
@@ -5688,7 +6061,7 @@ function readWorkspaceStatus(cwd, opts = {}) {
|
|
|
5688
6061
|
}
|
|
5689
6062
|
|
|
5690
6063
|
// src/amaster-runtime-daemon.mjs
|
|
5691
|
-
var CONNECTOR_VERSION = "0.1.0-beta.
|
|
6064
|
+
var CONNECTOR_VERSION = "0.1.0-beta.43";
|
|
5692
6065
|
var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
|
|
5693
6066
|
var MAX_CHECKPOINT_BYTES = 20 * 1024 * 1024;
|
|
5694
6067
|
var CHECKPOINT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -5736,11 +6109,11 @@ function updateActiveRunWorkspaceManifest(commandId, manifestPath, patch = {}) {
|
|
|
5736
6109
|
}
|
|
5737
6110
|
function resultOutboxPendingCount(config) {
|
|
5738
6111
|
const dir = resultOutboxDir(config);
|
|
5739
|
-
if (!
|
|
6112
|
+
if (!existsSync12(dir)) return 0;
|
|
5740
6113
|
try {
|
|
5741
6114
|
let pending = 0;
|
|
5742
6115
|
for (const file of readdirSync8(dir).filter((name) => name.endsWith(".json"))) {
|
|
5743
|
-
if (readValidResultOutboxEntryOrQuarantine(config, file,
|
|
6116
|
+
if (readValidResultOutboxEntryOrQuarantine(config, file, join13(dir, file))) {
|
|
5744
6117
|
pending += 1;
|
|
5745
6118
|
}
|
|
5746
6119
|
}
|
|
@@ -5756,11 +6129,11 @@ function piCompletionOutputType(event) {
|
|
|
5756
6129
|
}
|
|
5757
6130
|
function resultOutboxActiveRunCommands(config) {
|
|
5758
6131
|
const dir = resultOutboxDir(config);
|
|
5759
|
-
if (!
|
|
6132
|
+
if (!existsSync12(dir)) return [];
|
|
5760
6133
|
const outboxPending = resultOutboxPendingCount(config);
|
|
5761
6134
|
const entries = [];
|
|
5762
6135
|
for (const file of readdirSync8(dir).filter((name) => name.endsWith(".json")).sort()) {
|
|
5763
|
-
const entry = readValidResultOutboxEntryOrQuarantine(config, file,
|
|
6136
|
+
const entry = readValidResultOutboxEntryOrQuarantine(config, file, join13(dir, file));
|
|
5764
6137
|
if (!entry) continue;
|
|
5765
6138
|
const activeRun = asRecord(entry.activeRun);
|
|
5766
6139
|
const commandId = readString(activeRun.commandId) ?? readString(entry.commandId);
|
|
@@ -5790,12 +6163,12 @@ function resultOutboxActiveRunCommands(config) {
|
|
|
5790
6163
|
}
|
|
5791
6164
|
function resultOutboxFailedRunCommands(config) {
|
|
5792
6165
|
const dir = resultOutboxInvalidDir(config);
|
|
5793
|
-
if (!
|
|
6166
|
+
if (!existsSync12(dir)) return [];
|
|
5794
6167
|
const entries = [];
|
|
5795
6168
|
for (const file of readdirSync8(dir).filter((name) => name.endsWith(".json")).sort().slice(-100)) {
|
|
5796
6169
|
let entry;
|
|
5797
6170
|
try {
|
|
5798
|
-
entry = asRecord(JSON.parse(
|
|
6171
|
+
entry = asRecord(JSON.parse(readFileSync10(join13(dir, file), "utf8")));
|
|
5799
6172
|
} catch {
|
|
5800
6173
|
continue;
|
|
5801
6174
|
}
|
|
@@ -5855,11 +6228,11 @@ function piExtraArgsDiagnostics(value) {
|
|
|
5855
6228
|
}
|
|
5856
6229
|
function safeExpandPath(value) {
|
|
5857
6230
|
const text = readString(value);
|
|
5858
|
-
return text ?
|
|
6231
|
+
return text ? resolve11(expandHomePath(text)) : null;
|
|
5859
6232
|
}
|
|
5860
6233
|
function safeJsonObjectFromFile(filePath) {
|
|
5861
6234
|
try {
|
|
5862
|
-
const parsed = JSON.parse(
|
|
6235
|
+
const parsed = JSON.parse(readFileSync10(filePath, "utf8"));
|
|
5863
6236
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
5864
6237
|
} catch {
|
|
5865
6238
|
return null;
|
|
@@ -5902,10 +6275,10 @@ function safeSkillRootSummary(kind, source, pathValue) {
|
|
|
5902
6275
|
try {
|
|
5903
6276
|
for (const name of readdirSync8(pathValue)) {
|
|
5904
6277
|
if (name.startsWith(".")) continue;
|
|
5905
|
-
const skillDir =
|
|
6278
|
+
const skillDir = join13(pathValue, name);
|
|
5906
6279
|
try {
|
|
5907
6280
|
if (!statSync7(skillDir).isDirectory()) continue;
|
|
5908
|
-
if (!
|
|
6281
|
+
if (!existsSync12(join13(skillDir, "SKILL.md"))) continue;
|
|
5909
6282
|
skillCount += 1;
|
|
5910
6283
|
if (skillCount >= MAX_PI_CAPABILITY_SOURCE_ENTRIES) {
|
|
5911
6284
|
truncated = true;
|
|
@@ -5956,7 +6329,7 @@ function objectKeyCount(value) {
|
|
|
5956
6329
|
return value && typeof value === "object" && !Array.isArray(value) ? Object.keys(value).length : 0;
|
|
5957
6330
|
}
|
|
5958
6331
|
function defaultPiCodingAgentDir() {
|
|
5959
|
-
return
|
|
6332
|
+
return join13(homedir3(), ".pi", "agent");
|
|
5960
6333
|
}
|
|
5961
6334
|
function piCapabilitySourcesDiagnostics() {
|
|
5962
6335
|
const configuredPiCodingAgentDir = safeExpandPath(process.env.PI_CODING_AGENT_DIR);
|
|
@@ -5965,11 +6338,11 @@ function piCapabilitySourcesDiagnostics() {
|
|
|
5965
6338
|
const configuredPiAgentHome = safeExpandPath(process.env.PI_AGENT_HOME);
|
|
5966
6339
|
const piAgentHome = configuredPiAgentHome ?? piCodingAgentDir;
|
|
5967
6340
|
const piAgentHomeSource = configuredPiAgentHome ? "PI_AGENT_HOME" : piCodingAgentDirSource;
|
|
5968
|
-
const userSkillsPath = piAgentHome ?
|
|
5969
|
-
const marketplaceSkillsPath = safeExpandPath(process.env.PI_AGENT_MARKETPLACE_SKILLS_DIR) ?? (piAgentHome ?
|
|
6341
|
+
const userSkillsPath = piAgentHome ? join13(piAgentHome, "skills") : null;
|
|
6342
|
+
const marketplaceSkillsPath = safeExpandPath(process.env.PI_AGENT_MARKETPLACE_SKILLS_DIR) ?? (piAgentHome ? join13(piAgentHome, "marketplace", "skills") : null);
|
|
5970
6343
|
const builtinSkillsPath = safeExpandPath(process.env.PI_AGENT_BUILTIN_SKILLS_DIR) ?? safeExpandPath(process.env.AMASTER_BUILTIN_SKILLS);
|
|
5971
|
-
const mcpConfigPath = safeExpandPath(process.env.PI_AGENT_MCP_SERVERS_FILE) ?? (piAgentHome ?
|
|
5972
|
-
const settingsConfigPath = piCodingAgentDir ?
|
|
6344
|
+
const mcpConfigPath = safeExpandPath(process.env.PI_AGENT_MCP_SERVERS_FILE) ?? (piAgentHome ? join13(piAgentHome, "mcp.json") : null);
|
|
6345
|
+
const settingsConfigPath = piCodingAgentDir ? join13(piCodingAgentDir, "settings.json") : null;
|
|
5973
6346
|
const skillRoots = [
|
|
5974
6347
|
safeSkillRootSummary("user", `${piAgentHomeSource}/skills`, userSkillsPath),
|
|
5975
6348
|
safeSkillRootSummary(
|
|
@@ -6200,13 +6573,13 @@ function piAgentLocalPlatformRunnerEnabled(config) {
|
|
|
6200
6573
|
}
|
|
6201
6574
|
function piAgentSystemDataDir(config) {
|
|
6202
6575
|
const configured = readString(config.AMASTER_PI_AGENT_SYSTEM_DATA_DIR ?? process.env.AMASTER_PI_AGENT_SYSTEM_DATA_DIR);
|
|
6203
|
-
return configured ?
|
|
6576
|
+
return configured ? resolve11(expandHomePath(configured)) : null;
|
|
6204
6577
|
}
|
|
6205
6578
|
function readPiAgentLocalPlatformCredential(credentialsDir) {
|
|
6206
|
-
const pointer = readJsonFile3(
|
|
6579
|
+
const pointer = readJsonFile3(join13(credentialsDir, "latest.json"));
|
|
6207
6580
|
const credentialRef = readString(pointer.credentialRef);
|
|
6208
6581
|
if (!credentialRef || !/^[a-f0-9]{64}$/i.test(credentialRef)) return null;
|
|
6209
|
-
const credential = readJsonFile3(
|
|
6582
|
+
const credential = readJsonFile3(join13(credentialsDir, `${credentialRef}.json`));
|
|
6210
6583
|
const organizationId = readString(credential.organizationId);
|
|
6211
6584
|
const apiKey = readString(credential.apiKey);
|
|
6212
6585
|
if (credential.version !== 1 || !organizationId || !apiKey) return null;
|
|
@@ -6222,7 +6595,7 @@ function piAgentLocalPlatformCredentials(config) {
|
|
|
6222
6595
|
if (!piAgentLocalPlatformRunnerEnabled(config)) return [];
|
|
6223
6596
|
const systemDataDir = piAgentSystemDataDir(config);
|
|
6224
6597
|
if (!systemDataDir) return [];
|
|
6225
|
-
const companiesDir =
|
|
6598
|
+
const companiesDir = join13(systemDataDir, "companies");
|
|
6226
6599
|
let entries = [];
|
|
6227
6600
|
try {
|
|
6228
6601
|
entries = readdirSync8(companiesDir, { withFileTypes: true });
|
|
@@ -6232,7 +6605,7 @@ function piAgentLocalPlatformCredentials(config) {
|
|
|
6232
6605
|
const credentialsByOrganizationId = /* @__PURE__ */ new Map();
|
|
6233
6606
|
for (const entry of entries) {
|
|
6234
6607
|
if (!entry.isDirectory()) continue;
|
|
6235
|
-
const credential = readPiAgentLocalPlatformCredential(
|
|
6608
|
+
const credential = readPiAgentLocalPlatformCredential(join13(companiesDir, entry.name, "model-credentials"));
|
|
6236
6609
|
if (credential) credentialsByOrganizationId.set(credential.organizationId, credential);
|
|
6237
6610
|
}
|
|
6238
6611
|
return [...credentialsByOrganizationId.values()];
|
|
@@ -6406,7 +6779,7 @@ AMASTER_WORKSPACE_ALLOWLIST=${quoteShell(config.workspaceBindings.join(","))}
|
|
|
6406
6779
|
AMASTER_EXECUTORS=${quoteShell(executorEnv)}
|
|
6407
6780
|
AMASTER_CAPABILITIES=${quoteShell(config.capabilities.join(","))}
|
|
6408
6781
|
AMASTER_NETWORK_DOMAINS=${quoteShell(config.networkDomains.join(","))}
|
|
6409
|
-
AMASTER_DAEMON_STATE_FILE=${quoteShell(
|
|
6782
|
+
AMASTER_DAEMON_STATE_FILE=${quoteShell(join13(homedir3(), ".amaster-employee", "runtime-connector-state.json"))}
|
|
6410
6783
|
EOF
|
|
6411
6784
|
|
|
6412
6785
|
set -a
|
|
@@ -6594,10 +6967,10 @@ function buildActiveRunCommandStatus(config, entry) {
|
|
|
6594
6967
|
const base = {
|
|
6595
6968
|
...entry,
|
|
6596
6969
|
phase: readString(entry.phase) ?? "executing",
|
|
6597
|
-
managedWorkdirPresent: entry.workspacePath ?
|
|
6970
|
+
managedWorkdirPresent: entry.workspacePath ? existsSync12(entry.workspacePath) : false,
|
|
6598
6971
|
outboxPending: resultOutboxPendingCount(config)
|
|
6599
6972
|
};
|
|
6600
|
-
if (!entry.workspacePath || !
|
|
6973
|
+
if (!entry.workspacePath || !existsSync12(entry.workspacePath)) return base;
|
|
6601
6974
|
const manifestPath = entry.manifestPath ?? workspaceManifestPath(entry.workspacePath);
|
|
6602
6975
|
const status = readWorkspaceStatus(entry.workspacePath, { hashCache: workspaceStatusHashCache });
|
|
6603
6976
|
const artifactCandidates = status.artifacts.slice(0, 20);
|
|
@@ -6778,7 +7151,7 @@ function trustedPiRuntimeSources(config) {
|
|
|
6778
7151
|
}
|
|
6779
7152
|
function readJsonFile3(filePath) {
|
|
6780
7153
|
try {
|
|
6781
|
-
const parsed = JSON.parse(
|
|
7154
|
+
const parsed = JSON.parse(readFileSync10(filePath, "utf8"));
|
|
6782
7155
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
6783
7156
|
} catch {
|
|
6784
7157
|
return {};
|
|
@@ -6847,11 +7220,11 @@ function safeAgentInstructionMaterializationTarget(workspace, filePath) {
|
|
|
6847
7220
|
const raw = readString(filePath);
|
|
6848
7221
|
if (!raw || raw.includes("\0")) return null;
|
|
6849
7222
|
const normalized = raw.replace(/\\/g, "/");
|
|
6850
|
-
if (
|
|
7223
|
+
if (isAbsolute8(normalized)) return null;
|
|
6851
7224
|
const segments = normalized.split("/").filter(Boolean);
|
|
6852
7225
|
if (segments.length === 0 || segments.some((segment) => segment === "." || segment === "..")) return null;
|
|
6853
7226
|
const relativePath = segments.join("/");
|
|
6854
|
-
const targetPath =
|
|
7227
|
+
const targetPath = resolve11(workspace.cwd, relativePath);
|
|
6855
7228
|
if (!pathWithin2(targetPath, workspace.cwd)) return null;
|
|
6856
7229
|
return { relativePath, targetPath };
|
|
6857
7230
|
}
|
|
@@ -6865,8 +7238,8 @@ async function materializeAgentInstructionsBundle(config, command, workspace) {
|
|
|
6865
7238
|
if (!content) continue;
|
|
6866
7239
|
const target = safeAgentInstructionMaterializationTarget(workspace, filePath);
|
|
6867
7240
|
if (!target) continue;
|
|
6868
|
-
|
|
6869
|
-
|
|
7241
|
+
mkdirSync8(dirname9(target.targetPath), { recursive: true });
|
|
7242
|
+
writeFileSync8(target.targetPath, content, "utf8");
|
|
6870
7243
|
materialized.push({
|
|
6871
7244
|
path: target.relativePath,
|
|
6872
7245
|
byteSize: Buffer.byteLength(content, "utf8")
|
|
@@ -6916,6 +7289,7 @@ function buildCommandPrompt(command, workspace, materializedAttachments = [], op
|
|
|
6916
7289
|
commandId: command.commandId,
|
|
6917
7290
|
runId: commandRunId(command),
|
|
6918
7291
|
issueId: commandIssueId(command),
|
|
7292
|
+
currentDate: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
6919
7293
|
issueLine,
|
|
6920
7294
|
cwd,
|
|
6921
7295
|
managed: workspaceContext.managed,
|
|
@@ -6930,25 +7304,18 @@ function buildCommandPrompt(command, workspace, materializedAttachments = [], op
|
|
|
6930
7304
|
nativeSession: asRecord(payload.nativeSession)
|
|
6931
7305
|
});
|
|
6932
7306
|
}
|
|
6933
|
-
function safeCompanyPiHomeSegment(companyId) {
|
|
6934
|
-
const raw = readString(companyId)?.trim();
|
|
6935
|
-
if (!raw) return null;
|
|
6936
|
-
if (/^[A-Za-z0-9][A-Za-z0-9._-]{0,119}$/.test(raw)) return raw;
|
|
6937
|
-
const normalized = raw.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[._-]+|[._-]+$/g, "").slice(0, 80);
|
|
6938
|
-
const hash = createHash8("sha256").update(raw).digest("hex").slice(0, 12);
|
|
6939
|
-
return normalized ? `${normalized}-${hash}` : `company-${hash}`;
|
|
6940
|
-
}
|
|
6941
7307
|
function companyPiHomeRoot(baseEnv) {
|
|
6942
7308
|
const explicitRoot = readString(baseEnv.AMASTER_COMPANY_PI_HOME_ROOT);
|
|
6943
|
-
if (explicitRoot) return
|
|
7309
|
+
if (explicitRoot) return resolve11(expandHomePath(explicitRoot));
|
|
6944
7310
|
const configuredPiHome = readString(baseEnv.PI_AGENT_HOME) ?? readString(baseEnv.PI_CODING_AGENT_DIR);
|
|
6945
|
-
if (configuredPiHome) return
|
|
6946
|
-
return
|
|
7311
|
+
if (configuredPiHome) return join13(dirname9(resolve11(expandHomePath(configuredPiHome))), "companies");
|
|
7312
|
+
return join13(homedir3(), ".amaster-employee", "companies");
|
|
6947
7313
|
}
|
|
6948
7314
|
function companyPiAgentHome(baseEnv, companyId) {
|
|
6949
|
-
const
|
|
6950
|
-
if (!
|
|
6951
|
-
|
|
7315
|
+
const rawCompanyId = readString(companyId);
|
|
7316
|
+
if (!rawCompanyId) return null;
|
|
7317
|
+
const segment = safeCompanyPiHomeSegment(rawCompanyId);
|
|
7318
|
+
return join13(companyPiHomeRoot(baseEnv), segment, ".pi");
|
|
6952
7319
|
}
|
|
6953
7320
|
function commandUsesPiExecutor(command) {
|
|
6954
7321
|
return readString(asRecord(command.payload).executorKind) === "pi";
|
|
@@ -7017,7 +7384,7 @@ function resolveNativeSessionRequest(command, workspace) {
|
|
|
7017
7384
|
try {
|
|
7018
7385
|
cwdMatched = realpathSync3(requestedCwd) === realpathSync3(sourceWorkspacePath);
|
|
7019
7386
|
} catch {
|
|
7020
|
-
cwdMatched =
|
|
7387
|
+
cwdMatched = resolve11(requestedCwd) === resolve11(sourceWorkspacePath);
|
|
7021
7388
|
}
|
|
7022
7389
|
}
|
|
7023
7390
|
const used = Boolean(enabled && requested && sessionId && requestedCwd && cwdMatched);
|
|
@@ -7216,6 +7583,7 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
|
|
|
7216
7583
|
let nonProgressEventCount = 0;
|
|
7217
7584
|
let unparsedLineCount = 0;
|
|
7218
7585
|
let lastPiAgentMessage = null;
|
|
7586
|
+
let piTerminalOutput = null;
|
|
7219
7587
|
let executorSessionId = null;
|
|
7220
7588
|
const liveMcpToolResults = [];
|
|
7221
7589
|
let queue = Promise.resolve();
|
|
@@ -7299,9 +7667,20 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
|
|
|
7299
7667
|
const text = redactProtectedText(line, protectedValues).trim();
|
|
7300
7668
|
if (!text) return;
|
|
7301
7669
|
const event = stream === "stdout" ? parseJsonLine(text) : null;
|
|
7302
|
-
|
|
7670
|
+
const eventType = readString(asRecord(event).type);
|
|
7671
|
+
if (executorKind === "pi" && eventType === "session") {
|
|
7303
7672
|
executorSessionId = readString(asRecord(event).sessionId ?? asRecord(event).id) ?? executorSessionId;
|
|
7304
7673
|
}
|
|
7674
|
+
if (executorKind === "pi" && (["message_end", "turn_end", "agent_end"].includes(eventType ?? "") || eventType === "message_update" && readString(asRecord(asRecord(event).assistantMessageEvent).type) === "text_end")) {
|
|
7675
|
+
const parsedTerminalOutput = parsePiJsonl(text);
|
|
7676
|
+
if (parsedTerminalOutput.hasAssistantOutput && readString(parsedTerminalOutput.summary)) {
|
|
7677
|
+
piTerminalOutput = {
|
|
7678
|
+
summary: parsedTerminalOutput.summary,
|
|
7679
|
+
usage: parsedTerminalOutput.usage,
|
|
7680
|
+
hasAssistantOutput: true
|
|
7681
|
+
};
|
|
7682
|
+
}
|
|
7683
|
+
}
|
|
7305
7684
|
if (["codex", "pi"].includes(executorKind) && event) {
|
|
7306
7685
|
const results = executorKind === "codex" ? codexMcpToolResults(event) : piMcpToolResults(event);
|
|
7307
7686
|
liveMcpToolResults.push(...results);
|
|
@@ -7340,6 +7719,12 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
|
|
|
7340
7719
|
mcpToolResults() {
|
|
7341
7720
|
return [...liveMcpToolResults];
|
|
7342
7721
|
},
|
|
7722
|
+
terminalOutput() {
|
|
7723
|
+
return piTerminalOutput ? {
|
|
7724
|
+
...piTerminalOutput,
|
|
7725
|
+
usage: { ...piTerminalOutput.usage }
|
|
7726
|
+
} : null;
|
|
7727
|
+
},
|
|
7343
7728
|
write(stream, chunk) {
|
|
7344
7729
|
const key = stream === "stderr" ? "stderr" : "stdout";
|
|
7345
7730
|
sourceCounts[key] += 1;
|
|
@@ -7444,10 +7829,10 @@ function realOrResolvedPath(value) {
|
|
|
7444
7829
|
try {
|
|
7445
7830
|
return realpathSync3(value);
|
|
7446
7831
|
} catch {
|
|
7447
|
-
return
|
|
7832
|
+
return resolve11(value);
|
|
7448
7833
|
}
|
|
7449
7834
|
}
|
|
7450
|
-
var LSOF_COMMAND = process.platform === "darwin" &&
|
|
7835
|
+
var LSOF_COMMAND = process.platform === "darwin" && existsSync12("/usr/sbin/lsof") ? "/usr/sbin/lsof" : "lsof";
|
|
7451
7836
|
function processCwdForPid(pid) {
|
|
7452
7837
|
if (process.platform === "linux") {
|
|
7453
7838
|
try {
|
|
@@ -7569,7 +7954,7 @@ function killWorkspaceResidentProcesses(cwd, processGroupId, options = {}) {
|
|
|
7569
7954
|
}
|
|
7570
7955
|
function walkManagedWorkdirs(root) {
|
|
7571
7956
|
const workdirs = [];
|
|
7572
|
-
if (!root || !
|
|
7957
|
+
if (!root || !existsSync12(root)) return workdirs;
|
|
7573
7958
|
const stack = [root];
|
|
7574
7959
|
while (stack.length > 0) {
|
|
7575
7960
|
const current = stack.pop();
|
|
@@ -7582,8 +7967,8 @@ function walkManagedWorkdirs(root) {
|
|
|
7582
7967
|
}
|
|
7583
7968
|
for (const entry of entries) {
|
|
7584
7969
|
if (!entry.isDirectory()) continue;
|
|
7585
|
-
const fullPath =
|
|
7586
|
-
if (entry.name === "workdir" &&
|
|
7970
|
+
const fullPath = join13(current, entry.name);
|
|
7971
|
+
if (entry.name === "workdir" && existsSync12(workspaceManifestPath(fullPath))) {
|
|
7587
7972
|
workdirs.push(fullPath);
|
|
7588
7973
|
continue;
|
|
7589
7974
|
}
|
|
@@ -7621,8 +8006,8 @@ function manifestMatchesActiveRuntimeRef(manifest, refs, workdir = null) {
|
|
|
7621
8006
|
}
|
|
7622
8007
|
function buildOrphanReaperSample(root, workdir, manifest, residents) {
|
|
7623
8008
|
const relativeWorkdir = (() => {
|
|
7624
|
-
const value =
|
|
7625
|
-
return value && !value.startsWith("..") && !
|
|
8009
|
+
const value = relative8(root, workdir);
|
|
8010
|
+
return value && !value.startsWith("..") && !isAbsolute8(value) ? value : basename6(workdir);
|
|
7626
8011
|
})();
|
|
7627
8012
|
return {
|
|
7628
8013
|
workdir: relativeWorkdir,
|
|
@@ -7725,12 +8110,13 @@ function runExecutor(command, args, options) {
|
|
|
7725
8110
|
const maxOutputBytes = parsePositiveInteger(options.maxOutputBytes, 50 * 1024 * 1024);
|
|
7726
8111
|
const maxRssMb = parsePositiveInteger(options.maxRssMb, 0);
|
|
7727
8112
|
const maxRssBytes = maxRssMb * 1024 * 1024;
|
|
7728
|
-
const
|
|
8113
|
+
const spawnInvocation = managedChildSpawnInvocation(command, args, options.spawnIdentity);
|
|
8114
|
+
const child = spawn(spawnInvocation.command, spawnInvocation.args, {
|
|
7729
8115
|
cwd: options.cwd,
|
|
7730
8116
|
env: options.env,
|
|
7731
8117
|
detached: process.platform !== "win32",
|
|
7732
8118
|
stdio: options.managedInput ? ["pipe", "pipe", "pipe", "pipe"] : ["pipe", "pipe", "pipe"],
|
|
7733
|
-
...
|
|
8119
|
+
...spawnInvocation.spawnIdentity
|
|
7734
8120
|
});
|
|
7735
8121
|
const processGroupId = processGroupIdForChild(child);
|
|
7736
8122
|
const finish = (result2) => {
|
|
@@ -8012,6 +8398,7 @@ async function ingestRuntimeArtifacts(config, command, cwd, mcpToolResults) {
|
|
|
8012
8398
|
if (!runId) throw new Error("Runtime Artifact ingest requires a correlated runId");
|
|
8013
8399
|
const uploads = prepareRuntimeArtifactUploads(cwd, mcpToolResults);
|
|
8014
8400
|
const receipts = [];
|
|
8401
|
+
const failures = [];
|
|
8015
8402
|
for (const upload of uploads) {
|
|
8016
8403
|
const path = `/api/amaster/runtime-connectors/${connectorId}/artifact-intents/${encodeURIComponent(upload.intentId)}/ingest`;
|
|
8017
8404
|
const sourcePathHeaders = /^[\x20-\x7e]+$/.test(upload.sourceRelativePath) ? { "x-amaster-artifact-source-path": upload.sourceRelativePath } : {
|
|
@@ -8025,8 +8412,13 @@ async function ingestRuntimeArtifacts(config, command, cwd, mcpToolResults) {
|
|
|
8025
8412
|
"x-amaster-artifact-manifest-id": upload.manifestId,
|
|
8026
8413
|
...sourcePathHeaders
|
|
8027
8414
|
}));
|
|
8028
|
-
|
|
8029
|
-
|
|
8415
|
+
const receiptStatus = readString(receipt.status);
|
|
8416
|
+
if (readString(receipt.intentId) !== upload.intentId || receiptStatus !== "finalized") {
|
|
8417
|
+
const error = new Error(`Runtime Artifact ${upload.intentId} was not finalized: ${JSON.stringify(receipt)}`);
|
|
8418
|
+
if (receiptStatus === "rejected") {
|
|
8419
|
+
error.code = "runtime_artifact_rejected";
|
|
8420
|
+
}
|
|
8421
|
+
throw error;
|
|
8030
8422
|
}
|
|
8031
8423
|
receipts.push(receipt);
|
|
8032
8424
|
await ingestLog(config, command, "system", "info", `Finalized Runtime Artifact ${upload.sourceRelativePath}`, {
|
|
@@ -8042,7 +8434,12 @@ async function ingestRuntimeArtifacts(config, command, cwd, mcpToolResults) {
|
|
|
8042
8434
|
});
|
|
8043
8435
|
} catch (err) {
|
|
8044
8436
|
const message = `Runtime Artifact ${upload.intentId} ingest failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
8437
|
+
const failure = new Error(message, err instanceof Error ? { cause: err } : void 0);
|
|
8438
|
+
if (err instanceof Error && err.code === "runtime_artifact_rejected") {
|
|
8439
|
+
failure.code = "runtime_artifact_rejected";
|
|
8440
|
+
}
|
|
8045
8441
|
await ingestLog(config, command, "system", "error", message, {
|
|
8442
|
+
event: "runtime_artifact_ingest_failed",
|
|
8046
8443
|
presentationKind: "runtime_artifact_ingest",
|
|
8047
8444
|
intentId: upload.intentId,
|
|
8048
8445
|
manifestId: upload.manifestId,
|
|
@@ -8051,9 +8448,12 @@ async function ingestRuntimeArtifacts(config, command, cwd, mcpToolResults) {
|
|
|
8051
8448
|
byteSize: upload.byteSize,
|
|
8052
8449
|
status: "failed"
|
|
8053
8450
|
});
|
|
8054
|
-
|
|
8451
|
+
failures.push(failure);
|
|
8055
8452
|
}
|
|
8056
8453
|
}
|
|
8454
|
+
if (failures.length > 0) {
|
|
8455
|
+
throw new RuntimeArtifactIngestAggregateError(failures, receipts);
|
|
8456
|
+
}
|
|
8057
8457
|
return receipts;
|
|
8058
8458
|
}
|
|
8059
8459
|
function resultOutboxActiveRunSnapshot(command) {
|
|
@@ -8106,15 +8506,15 @@ async function completeCommand(config, command, status, result2, error) {
|
|
|
8106
8506
|
}
|
|
8107
8507
|
function resultOutboxDir(config) {
|
|
8108
8508
|
const explicit = readString(process.env.AMASTER_RESULT_OUTBOX_DIR);
|
|
8109
|
-
if (explicit) return
|
|
8110
|
-
return
|
|
8509
|
+
if (explicit) return resolve11(expandHomePath(explicit));
|
|
8510
|
+
return join13(dirname9(stateFilePath(process.env)), "result-outbox");
|
|
8111
8511
|
}
|
|
8112
8512
|
function resultOutboxInvalidDir(config) {
|
|
8113
|
-
return
|
|
8513
|
+
return join13(resultOutboxDir(config), "invalid");
|
|
8114
8514
|
}
|
|
8115
8515
|
function writeResultOutboxEntry(config, entry) {
|
|
8116
8516
|
const dir = resultOutboxDir(config);
|
|
8117
|
-
|
|
8517
|
+
mkdirSync8(dir, { recursive: true });
|
|
8118
8518
|
const body = {
|
|
8119
8519
|
version: 1,
|
|
8120
8520
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -8122,16 +8522,16 @@ function writeResultOutboxEntry(config, entry) {
|
|
|
8122
8522
|
lastAttemptAt: null,
|
|
8123
8523
|
...entry
|
|
8124
8524
|
};
|
|
8125
|
-
|
|
8525
|
+
writeFileSync8(join13(dir, resultOutboxFileName(entry.commandId)), `${JSON.stringify(body, null, 2)}
|
|
8126
8526
|
`, { mode: 384 });
|
|
8127
8527
|
}
|
|
8128
8528
|
function moveResultOutboxEntryToInvalid(config, file, fullPath, reason, detail, original) {
|
|
8129
8529
|
const invalidDir = resultOutboxInvalidDir(config);
|
|
8130
|
-
|
|
8131
|
-
const invalidPath =
|
|
8530
|
+
mkdirSync8(invalidDir, { recursive: true });
|
|
8531
|
+
const invalidPath = join13(invalidDir, file);
|
|
8132
8532
|
if (original === void 0) {
|
|
8133
8533
|
try {
|
|
8134
|
-
|
|
8534
|
+
renameSync5(fullPath, invalidPath);
|
|
8135
8535
|
} catch {
|
|
8136
8536
|
copyFileSync3(fullPath, invalidPath);
|
|
8137
8537
|
unlinkSync(fullPath);
|
|
@@ -8144,14 +8544,14 @@ function moveResultOutboxEntryToInvalid(config, file, fullPath, reason, detail,
|
|
|
8144
8544
|
...detail ? { detail: truncateText(detail, 1e3) } : {},
|
|
8145
8545
|
original
|
|
8146
8546
|
};
|
|
8147
|
-
|
|
8547
|
+
writeFileSync8(invalidPath, `${JSON.stringify(evidence, null, 2)}
|
|
8148
8548
|
`, { mode: 384 });
|
|
8149
8549
|
unlinkSync(fullPath);
|
|
8150
8550
|
}
|
|
8151
8551
|
function readValidResultOutboxEntryOrQuarantine(config, file, fullPath) {
|
|
8152
8552
|
let entry;
|
|
8153
8553
|
try {
|
|
8154
|
-
entry = JSON.parse(
|
|
8554
|
+
entry = JSON.parse(readFileSync10(fullPath, "utf8"));
|
|
8155
8555
|
} catch (err) {
|
|
8156
8556
|
const message = err instanceof Error ? err.message : String(err);
|
|
8157
8557
|
moveResultOutboxEntryToInvalid(config, file, fullPath, "malformed_result_outbox_json", message);
|
|
@@ -8181,13 +8581,13 @@ function updateResultOutboxAttempt(fullPath, entry, err) {
|
|
|
8181
8581
|
...typeof err?.httpStatus === "number" ? { httpStatus: err.httpStatus } : {},
|
|
8182
8582
|
lastError: truncateText(err instanceof Error ? err.message : String(err), 1e3)
|
|
8183
8583
|
};
|
|
8184
|
-
|
|
8584
|
+
writeFileSync8(fullPath, `${JSON.stringify(next, null, 2)}
|
|
8185
8585
|
`, { mode: 384 });
|
|
8186
8586
|
return next;
|
|
8187
8587
|
}
|
|
8188
8588
|
function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err) {
|
|
8189
8589
|
const invalidDir = resultOutboxInvalidDir(config);
|
|
8190
|
-
|
|
8590
|
+
mkdirSync8(invalidDir, { recursive: true });
|
|
8191
8591
|
const body = {
|
|
8192
8592
|
...entry,
|
|
8193
8593
|
invalidReason: reason,
|
|
@@ -8195,8 +8595,8 @@ function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err)
|
|
|
8195
8595
|
...typeof err?.httpStatus === "number" ? { httpStatus: err.httpStatus } : {},
|
|
8196
8596
|
lastError: truncateText(err instanceof Error ? err.message : String(err), 1e3)
|
|
8197
8597
|
};
|
|
8198
|
-
const invalidPath =
|
|
8199
|
-
|
|
8598
|
+
const invalidPath = join13(invalidDir, file);
|
|
8599
|
+
writeFileSync8(invalidPath, `${JSON.stringify(body, null, 2)}
|
|
8200
8600
|
`, { mode: 384 });
|
|
8201
8601
|
try {
|
|
8202
8602
|
unlinkSync(fullPath);
|
|
@@ -8209,11 +8609,11 @@ function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err)
|
|
|
8209
8609
|
}
|
|
8210
8610
|
async function flushResultOutbox(config) {
|
|
8211
8611
|
const dir = resultOutboxDir(config);
|
|
8212
|
-
if (!
|
|
8612
|
+
if (!existsSync12(dir)) return { attempted: 0, completed: 0 };
|
|
8213
8613
|
const files = readdirSync8(dir).filter((name) => name.endsWith(".json")).sort();
|
|
8214
8614
|
let completed = 0;
|
|
8215
8615
|
for (const file of files) {
|
|
8216
|
-
const fullPath =
|
|
8616
|
+
const fullPath = join13(dir, file);
|
|
8217
8617
|
const entry = readValidResultOutboxEntryOrQuarantine(config, file, fullPath);
|
|
8218
8618
|
if (!entry) continue;
|
|
8219
8619
|
try {
|
|
@@ -8410,8 +8810,8 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
8410
8810
|
runtimeAuth,
|
|
8411
8811
|
issueId
|
|
8412
8812
|
);
|
|
8413
|
-
const targetDir =
|
|
8414
|
-
|
|
8813
|
+
const targetDir = join13(workspace.cwd, "input-attachments");
|
|
8814
|
+
mkdirSync8(targetDir, { recursive: true });
|
|
8415
8815
|
const usedFilenames = /* @__PURE__ */ new Set();
|
|
8416
8816
|
const materialized = [];
|
|
8417
8817
|
for (const [index, rawAttachment] of attachments.entries()) {
|
|
@@ -8425,11 +8825,11 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
8425
8825
|
filename = `${stem}-${index + 1}${ext}`;
|
|
8426
8826
|
}
|
|
8427
8827
|
usedFilenames.add(filename);
|
|
8428
|
-
const targetPath =
|
|
8828
|
+
const targetPath = join13(targetDir, filename);
|
|
8429
8829
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
8430
|
-
|
|
8830
|
+
writeFileSync8(targetPath, body);
|
|
8431
8831
|
const attachmentId = readString(attachment.id);
|
|
8432
|
-
const actualSha256 =
|
|
8832
|
+
const actualSha256 = createHash9("sha256").update(body).digest("hex");
|
|
8433
8833
|
const lineageCandidates = lineageCandidatesByAttachmentId.get(attachmentId) ?? [];
|
|
8434
8834
|
const lineage = selectAttachmentLineage(lineageCandidates, actualSha256);
|
|
8435
8835
|
if (lineageCandidates.length > 0 && !lineage) {
|
|
@@ -8452,7 +8852,7 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
8452
8852
|
id: attachmentId,
|
|
8453
8853
|
name: readString(attachment.originalFilename) ?? filename,
|
|
8454
8854
|
path: targetPath,
|
|
8455
|
-
relativePath:
|
|
8855
|
+
relativePath: relative8(workspace.cwd, targetPath),
|
|
8456
8856
|
contentType: readString(attachment.contentType),
|
|
8457
8857
|
byteSize: body.byteLength,
|
|
8458
8858
|
contentPath,
|
|
@@ -8501,9 +8901,9 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
8501
8901
|
if (manifest.version !== 1 || !Array.isArray(manifest.entries)) {
|
|
8502
8902
|
throw new Error("artifact_input_manifest_invalid: expected version 1 entries array");
|
|
8503
8903
|
}
|
|
8504
|
-
const targetRoot =
|
|
8505
|
-
|
|
8506
|
-
|
|
8904
|
+
const targetRoot = join13(workspace.cwd, "input-artifacts");
|
|
8905
|
+
rmSync7(targetRoot, { recursive: true, force: true });
|
|
8906
|
+
mkdirSync8(targetRoot, { recursive: true });
|
|
8507
8907
|
const usedPaths = /* @__PURE__ */ new Set();
|
|
8508
8908
|
const materialized = [];
|
|
8509
8909
|
for (const [index, rawEntry] of manifest.entries.entries()) {
|
|
@@ -8521,7 +8921,7 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
8521
8921
|
throw new Error(`artifact_input_manifest_invalid: entry ${index} contentPath does not match attachmentId`);
|
|
8522
8922
|
}
|
|
8523
8923
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
8524
|
-
const actualSha256 =
|
|
8924
|
+
const actualSha256 = createHash9("sha256").update(body).digest("hex");
|
|
8525
8925
|
if (body.byteLength !== byteSize || actualSha256 !== sha256) {
|
|
8526
8926
|
throw new Error(
|
|
8527
8927
|
`artifact_input_integrity_mismatch: workProductId=${workProductId} expectedBytes=${byteSize} actualBytes=${body.byteLength} expectedSha256=${sha256} actualSha256=${actualSha256}`
|
|
@@ -8532,18 +8932,18 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
8532
8932
|
id: attachmentId,
|
|
8533
8933
|
originalFilename: readString(entry.originalFilename)
|
|
8534
8934
|
}, index);
|
|
8535
|
-
let relativePath =
|
|
8935
|
+
let relativePath = join13("input-artifacts", sourceDir, filename).split(/[\\/]+/).join("/");
|
|
8536
8936
|
if (usedPaths.has(relativePath)) {
|
|
8537
8937
|
const ext = extname2(filename);
|
|
8538
8938
|
const stem = ext ? filename.slice(0, -ext.length) : filename;
|
|
8539
8939
|
filename = `${stem}-${index + 1}${ext}`;
|
|
8540
|
-
relativePath =
|
|
8940
|
+
relativePath = join13("input-artifacts", sourceDir, filename).split(/[\\/]+/).join("/");
|
|
8541
8941
|
}
|
|
8542
8942
|
usedPaths.add(relativePath);
|
|
8543
|
-
const targetPath =
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
|
|
8943
|
+
const targetPath = join13(workspace.cwd, relativePath);
|
|
8944
|
+
mkdirSync8(dirname9(targetPath), { recursive: true });
|
|
8945
|
+
writeFileSync8(targetPath, body);
|
|
8946
|
+
chmodSync6(targetPath, 292);
|
|
8547
8947
|
materialized.push({
|
|
8548
8948
|
id: attachmentId,
|
|
8549
8949
|
workProductId,
|
|
@@ -8562,9 +8962,9 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
8562
8962
|
version: 1,
|
|
8563
8963
|
entries: materialized.map(({ path: _path, relativePath, ...entry }) => ({ ...entry, path: relativePath }))
|
|
8564
8964
|
};
|
|
8565
|
-
const manifestPath =
|
|
8566
|
-
|
|
8567
|
-
|
|
8965
|
+
const manifestPath = join13(targetRoot, "artifact-input-manifest.json");
|
|
8966
|
+
writeFileSync8(manifestPath, JSON.stringify(localManifest, null, 2) + "\n");
|
|
8967
|
+
chmodSync6(manifestPath, 292);
|
|
8568
8968
|
updateWorkspaceManifest(workspaceManifestPath(workspace), { artifactInputManifest: localManifest });
|
|
8569
8969
|
await ingestLog(config, command, "system", "info", `Materialized ${materialized.length} required artifact input(s) into the execution workspace`, {
|
|
8570
8970
|
artifactInputCount: materialized.length,
|
|
@@ -8573,46 +8973,46 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
8573
8973
|
return materialized;
|
|
8574
8974
|
}
|
|
8575
8975
|
function issueCheckpointDir(workspace) {
|
|
8576
|
-
return
|
|
8976
|
+
return join13(dirname9(workspace.runDir), "checkpoint");
|
|
8577
8977
|
}
|
|
8578
8978
|
async function clearIssueCheckpoint(config, command, workspace, reason) {
|
|
8579
8979
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
8580
|
-
if (!
|
|
8581
|
-
|
|
8980
|
+
if (!existsSync12(checkpointDir)) return false;
|
|
8981
|
+
rmSync7(checkpointDir, { recursive: true, force: true });
|
|
8582
8982
|
await ingestLog(config, command, "system", "info", "Cleared issue continuation checkpoint", { reason });
|
|
8583
8983
|
return true;
|
|
8584
8984
|
}
|
|
8585
8985
|
function safeCheckpointRelativePath(rawPath) {
|
|
8586
8986
|
const raw = String(rawPath ?? "").trim();
|
|
8587
|
-
if (
|
|
8987
|
+
if (isAbsolute8(raw) || /^[A-Za-z]:[\\/]/.test(raw)) return null;
|
|
8588
8988
|
const normalized = raw.split(/[\\/]+/).filter(Boolean).join("/");
|
|
8589
8989
|
if (!normalized || normalized.startsWith("../") || normalized.split("/").some((segment) => segment.startsWith("."))) return null;
|
|
8590
8990
|
if (normalized.startsWith("input-attachments/") || isRuntimeMetadataArtifactPath(normalized)) return null;
|
|
8591
8991
|
return normalized;
|
|
8592
8992
|
}
|
|
8593
8993
|
function hashFileSha256(filePath) {
|
|
8594
|
-
return
|
|
8994
|
+
return createHash9("sha256").update(readFileSync10(filePath)).digest("hex");
|
|
8595
8995
|
}
|
|
8596
8996
|
async function materializeIssueCheckpoint(config, command, workspace) {
|
|
8597
8997
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
8598
|
-
const manifestPath =
|
|
8599
|
-
if (!
|
|
8998
|
+
const manifestPath = join13(checkpointDir, "manifest.json");
|
|
8999
|
+
if (!existsSync12(manifestPath)) return [];
|
|
8600
9000
|
let manifest;
|
|
8601
9001
|
try {
|
|
8602
|
-
manifest = asRecord(JSON.parse(
|
|
9002
|
+
manifest = asRecord(JSON.parse(readFileSync10(manifestPath, "utf8")));
|
|
8603
9003
|
} catch (err) {
|
|
8604
|
-
|
|
9004
|
+
rmSync7(checkpointDir, { recursive: true, force: true });
|
|
8605
9005
|
throw new Error(`invalid issue checkpoint manifest: ${err instanceof Error ? err.message : String(err)}`);
|
|
8606
9006
|
}
|
|
8607
9007
|
const expiresAt = Date.parse(readString(manifest.expiresAt) ?? "");
|
|
8608
9008
|
if (!Number.isFinite(expiresAt) || expiresAt <= Date.now() || readString(manifest.issueId) !== commandIssueId(command)) {
|
|
8609
|
-
|
|
9009
|
+
rmSync7(checkpointDir, { recursive: true, force: true });
|
|
8610
9010
|
return [];
|
|
8611
9011
|
}
|
|
8612
9012
|
try {
|
|
8613
9013
|
const files = Array.isArray(manifest.files) ? manifest.files : [];
|
|
8614
9014
|
if (files.length > 20) throw new Error("issue checkpoint manifest exceeds the limit of 20 files");
|
|
8615
|
-
const filesRoot = realpathSync3(
|
|
9015
|
+
const filesRoot = realpathSync3(join13(checkpointDir, "files"));
|
|
8616
9016
|
const workspaceRoot = realpathSync3(workspace.cwd);
|
|
8617
9017
|
const validated = [];
|
|
8618
9018
|
let totalBytes = 0;
|
|
@@ -8620,12 +9020,12 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
8620
9020
|
const file = asRecord(rawFile);
|
|
8621
9021
|
const relativePath = safeCheckpointRelativePath(readString(file.path));
|
|
8622
9022
|
if (!relativePath) throw new Error("issue checkpoint manifest contains an invalid file path");
|
|
8623
|
-
const sourceCandidate =
|
|
8624
|
-
const target =
|
|
9023
|
+
const sourceCandidate = resolve11(filesRoot, relativePath);
|
|
9024
|
+
const target = resolve11(workspaceRoot, relativePath);
|
|
8625
9025
|
if (!pathWithin2(sourceCandidate, filesRoot) || !pathWithin2(target, workspaceRoot)) {
|
|
8626
9026
|
throw new Error(`issue checkpoint path escapes its workspace: ${relativePath}`);
|
|
8627
9027
|
}
|
|
8628
|
-
if (!
|
|
9028
|
+
if (!existsSync12(sourceCandidate)) throw new Error(`issue checkpoint file is missing: ${relativePath}`);
|
|
8629
9029
|
const source = realpathSync3(sourceCandidate);
|
|
8630
9030
|
if (!pathWithin2(source, filesRoot) || !statSync7(source).isFile()) {
|
|
8631
9031
|
throw new Error(`issue checkpoint source escapes its storage root: ${relativePath}`);
|
|
@@ -8645,13 +9045,13 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
8645
9045
|
const materialized = [];
|
|
8646
9046
|
for (const { relativePath, source, target } of validated) {
|
|
8647
9047
|
try {
|
|
8648
|
-
|
|
9048
|
+
lstatSync7(target);
|
|
8649
9049
|
continue;
|
|
8650
9050
|
} catch (err) {
|
|
8651
9051
|
if (err?.code !== "ENOENT") throw err;
|
|
8652
9052
|
}
|
|
8653
|
-
|
|
8654
|
-
const targetParent = realpathSync3(
|
|
9053
|
+
mkdirSync8(dirname9(target), { recursive: true });
|
|
9054
|
+
const targetParent = realpathSync3(dirname9(target));
|
|
8655
9055
|
if (!pathWithin2(targetParent, workspaceRoot)) {
|
|
8656
9056
|
throw new Error(`issue checkpoint target escapes its workspace: ${relativePath}`);
|
|
8657
9057
|
}
|
|
@@ -8679,31 +9079,31 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
8679
9079
|
}
|
|
8680
9080
|
async function saveIssueCheckpoint(config, command, workspace, candidates) {
|
|
8681
9081
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
8682
|
-
const filesDir =
|
|
8683
|
-
|
|
8684
|
-
|
|
9082
|
+
const filesDir = join13(checkpointDir, "files");
|
|
9083
|
+
rmSync7(checkpointDir, { recursive: true, force: true });
|
|
9084
|
+
mkdirSync8(filesDir, { recursive: true });
|
|
8685
9085
|
const files = [];
|
|
8686
9086
|
let totalBytes = 0;
|
|
8687
9087
|
const workspaceRoot = realpathSync3(workspace.cwd);
|
|
8688
9088
|
for (const candidate of candidates.slice(0, 20)) {
|
|
8689
9089
|
const relativePath = safeCheckpointRelativePath(candidate.rawPath);
|
|
8690
9090
|
const source = readString(candidate.filePath);
|
|
8691
|
-
if (!relativePath || !source || !
|
|
9091
|
+
if (!relativePath || !source || !existsSync12(source) || !statSync7(source).isFile()) continue;
|
|
8692
9092
|
const ownedSource = realpathSync3(source);
|
|
8693
9093
|
if (!pathWithin2(ownedSource, workspaceRoot)) {
|
|
8694
9094
|
throw new Error(`issue checkpoint source escapes its execution workspace: ${relativePath}`);
|
|
8695
9095
|
}
|
|
8696
9096
|
const byteSize = statSync7(ownedSource).size;
|
|
8697
9097
|
if (byteSize <= 0 || totalBytes + byteSize > MAX_CHECKPOINT_BYTES) continue;
|
|
8698
|
-
const target =
|
|
9098
|
+
const target = resolve11(filesDir, relativePath);
|
|
8699
9099
|
if (!pathWithin2(target, filesDir)) continue;
|
|
8700
|
-
|
|
9100
|
+
mkdirSync8(dirname9(target), { recursive: true });
|
|
8701
9101
|
copyFileSync3(ownedSource, target);
|
|
8702
9102
|
totalBytes += byteSize;
|
|
8703
9103
|
files.push({ path: relativePath, byteSize, sha256: hashFileSha256(ownedSource) });
|
|
8704
9104
|
}
|
|
8705
9105
|
if (files.length === 0) {
|
|
8706
|
-
|
|
9106
|
+
rmSync7(checkpointDir, { recursive: true, force: true });
|
|
8707
9107
|
return null;
|
|
8708
9108
|
}
|
|
8709
9109
|
const manifest = {
|
|
@@ -8715,7 +9115,7 @@ async function saveIssueCheckpoint(config, command, workspace, candidates) {
|
|
|
8715
9115
|
totalBytes,
|
|
8716
9116
|
files
|
|
8717
9117
|
};
|
|
8718
|
-
|
|
9118
|
+
writeFileSync8(join13(checkpointDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
8719
9119
|
`);
|
|
8720
9120
|
await ingestLog(config, command, "system", "warn", `Saved ${files.length} required deliverable(s) for continuation recovery`, manifest);
|
|
8721
9121
|
return manifest;
|
|
@@ -8789,44 +9189,20 @@ async function executeRunCommand(config, command) {
|
|
|
8789
9189
|
let cleanupManagedMcpProfile = null;
|
|
8790
9190
|
const providerProtectedValues = [];
|
|
8791
9191
|
let piChildIsolation = null;
|
|
9192
|
+
let piChildAssignmentAcquired = false;
|
|
9193
|
+
let piCompanyMemory = null;
|
|
8792
9194
|
let trustedPiRuntime = null;
|
|
8793
9195
|
let trustedPiRuntimeSourcePaths = null;
|
|
8794
9196
|
let trustedPiRuntimeProfile = null;
|
|
8795
9197
|
let trustedPiRuntimeAudit = null;
|
|
8796
9198
|
let piResolvedProviderConfig = null;
|
|
8797
|
-
|
|
8798
|
-
|
|
8799
|
-
|
|
8800
|
-
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
runDir: workspace.runDir,
|
|
8805
|
-
cwd,
|
|
8806
|
-
runtimeAuth: commandRuntimeAuth(command),
|
|
8807
|
-
nativeSession: asRecord(asRecord(command.payload).nativeSession),
|
|
8808
|
-
baseEnv: executorEnv,
|
|
8809
|
-
commandEnv: commandExecutorEnv(command),
|
|
8810
|
-
extraArgs: splitExtraArgs(process.env.AMASTER_CODEX_EXTRA_ARGS)
|
|
8811
|
-
});
|
|
8812
|
-
cleanupManagedMcpProfile = cleanupManagedCodexMcpProfile;
|
|
8813
|
-
}
|
|
8814
|
-
if (executor.kind === "pi") {
|
|
8815
|
-
if (piAgentLocalPlatformRunnerEnabled(config)) {
|
|
8816
|
-
delete executorEnv.AMASTER_API_KEY;
|
|
8817
|
-
delete executorEnv.AMASTER_PROVIDER_BASE_URL;
|
|
8818
|
-
delete executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL;
|
|
8819
|
-
delete executorEnv.AMASTER_PROVIDER_FLASH_MODEL;
|
|
8820
|
-
}
|
|
8821
|
-
piResolvedProviderConfig = resolvePiExecutorProviderConfig(config, command, executorEnv);
|
|
8822
|
-
for (const envName of ["AMASTER_API_KEY", "AMASTER_PLATFORM_OAUTH_TOKEN"]) {
|
|
8823
|
-
const protectedValue = readString(piResolvedProviderConfig.providerConfig[envName]);
|
|
8824
|
-
if (protectedValue && !providerProtectedValues.includes(protectedValue)) {
|
|
8825
|
-
providerProtectedValues.push(protectedValue);
|
|
8826
|
-
}
|
|
8827
|
-
}
|
|
8828
|
-
if (Object.keys(governedMcp).length > 0) {
|
|
8829
|
-
managedMcpProfile = prepareManagedPiMcpProfile({
|
|
9199
|
+
let forgetActiveRunCommand = () => {
|
|
9200
|
+
};
|
|
9201
|
+
let stopActiveRunHeartbeats = () => {
|
|
9202
|
+
};
|
|
9203
|
+
try {
|
|
9204
|
+
if (executor.kind === "codex" && Object.keys(governedMcp).length > 0) {
|
|
9205
|
+
managedMcpProfile = prepareManagedCodexMcpProfile({
|
|
8830
9206
|
commandId: command.commandId,
|
|
8831
9207
|
runId: commandRunId(command),
|
|
8832
9208
|
connectorVersion: CONNECTOR_VERSION,
|
|
@@ -8838,165 +9214,220 @@ async function executeRunCommand(config, command) {
|
|
|
8838
9214
|
nativeSession: asRecord(asRecord(command.payload).nativeSession),
|
|
8839
9215
|
baseEnv: executorEnv,
|
|
8840
9216
|
commandEnv: commandExecutorEnv(command),
|
|
8841
|
-
extraArgs: splitExtraArgs(process.env.
|
|
9217
|
+
extraArgs: splitExtraArgs(process.env.AMASTER_CODEX_EXTRA_ARGS)
|
|
8842
9218
|
});
|
|
8843
|
-
cleanupManagedMcpProfile =
|
|
8844
|
-
for (const protectedValue of providerProtectedValues) {
|
|
8845
|
-
if (!managedMcpProfile.protectedValues.includes(protectedValue)) {
|
|
8846
|
-
managedMcpProfile.protectedValues.push(protectedValue);
|
|
8847
|
-
}
|
|
8848
|
-
}
|
|
9219
|
+
cleanupManagedMcpProfile = cleanupManagedCodexMcpProfile;
|
|
8849
9220
|
}
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
8856
|
-
});
|
|
8857
|
-
}
|
|
8858
|
-
const piChildAllocator = executor.kind === "pi" ? configuredPiChildIdentityAllocator(config) : null;
|
|
8859
|
-
const trustedPiRuntimeAssertion = commandTrustedPiRuntimeAssertion(command);
|
|
8860
|
-
if (Object.keys(trustedPiRuntimeAssertion).length > 0) {
|
|
8861
|
-
try {
|
|
8862
|
-
if (executor.kind !== "pi") {
|
|
8863
|
-
throw new Error("pi_trusted_runtime_assertion_binding_mismatch:executorKind");
|
|
9221
|
+
if (executor.kind === "pi") {
|
|
9222
|
+
if (piAgentLocalPlatformRunnerEnabled(config)) {
|
|
9223
|
+
delete executorEnv.AMASTER_API_KEY;
|
|
9224
|
+
delete executorEnv.AMASTER_PROVIDER_BASE_URL;
|
|
9225
|
+
delete executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL;
|
|
9226
|
+
delete executorEnv.AMASTER_PROVIDER_FLASH_MODEL;
|
|
8864
9227
|
}
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
|
|
8868
|
-
|
|
8869
|
-
|
|
8870
|
-
|
|
8871
|
-
leaseId: command.leaseId,
|
|
8872
|
-
executorKind: executor.kind,
|
|
8873
|
-
localDigests: readTrustedPiRuntimeLocalDigests(trustedPiRuntimeSourcePaths)
|
|
8874
|
-
});
|
|
8875
|
-
if (!managedMcpProfile) {
|
|
8876
|
-
throw new Error("pi_trusted_runtime_governed_profile_required");
|
|
9228
|
+
piResolvedProviderConfig = resolvePiExecutorProviderConfig(config, command, executorEnv);
|
|
9229
|
+
for (const envName of ["AMASTER_API_KEY", "AMASTER_PLATFORM_OAUTH_TOKEN"]) {
|
|
9230
|
+
const protectedValue = readString(piResolvedProviderConfig.providerConfig[envName]);
|
|
9231
|
+
if (protectedValue && !providerProtectedValues.includes(protectedValue)) {
|
|
9232
|
+
providerProtectedValues.push(protectedValue);
|
|
9233
|
+
}
|
|
8877
9234
|
}
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
seedRoot: trustedPiRuntimeSourcePaths.seedRoot,
|
|
8881
|
-
overlayRoot: trustedPiRuntimeSourcePaths.overlayRoot,
|
|
8882
|
-
profileRoot: managedMcpProfile.profileRoot,
|
|
8883
|
-
agentDir: managedMcpProfile.env.PI_CODING_AGENT_DIR,
|
|
8884
|
-
governedMcpConfigPath: managedMcpProfile.configPath,
|
|
8885
|
-
verifiedAssertion: trustedPiRuntime
|
|
8886
|
-
});
|
|
8887
|
-
executorEnv = {
|
|
8888
|
-
...executorEnv,
|
|
8889
|
-
AMASTER_MANAGED_RUNTIME_ASSERTION_FD: "3",
|
|
8890
|
-
AMASTER_MANAGED_RUNTIME_AUDIT_FILE: join12(
|
|
8891
|
-
managedMcpProfile.env.HOME,
|
|
8892
|
-
".amaster-managed-runtime-audit.jsonl"
|
|
8893
|
-
),
|
|
8894
|
-
AMASTER_RUNTIME_LEASE_ID: command.leaseId
|
|
8895
|
-
};
|
|
8896
|
-
} catch (error) {
|
|
8897
|
-
if (managedMcpProfile) {
|
|
8898
|
-
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
9235
|
+
if (Object.keys(governedMcp).length > 0) {
|
|
9236
|
+
managedMcpProfile = prepareManagedPiMcpProfile({
|
|
8899
9237
|
commandId: command.commandId,
|
|
8900
|
-
runId: commandRunId(command)
|
|
9238
|
+
runId: commandRunId(command),
|
|
9239
|
+
connectorVersion: CONNECTOR_VERSION,
|
|
9240
|
+
executorCommand: invocation.command,
|
|
9241
|
+
executorHome: workspace.executorHome,
|
|
9242
|
+
runDir: workspace.runDir,
|
|
9243
|
+
cwd,
|
|
9244
|
+
runtimeAuth: commandRuntimeAuth(command),
|
|
9245
|
+
nativeSession: asRecord(asRecord(command.payload).nativeSession),
|
|
9246
|
+
baseEnv: executorEnv,
|
|
9247
|
+
commandEnv: commandExecutorEnv(command),
|
|
9248
|
+
extraArgs: splitExtraArgs(process.env.AMASTER_PI_EXTRA_ARGS)
|
|
8901
9249
|
});
|
|
9250
|
+
cleanupManagedMcpProfile = cleanupManagedPiMcpProfile;
|
|
9251
|
+
for (const protectedValue of providerProtectedValues) {
|
|
9252
|
+
if (!managedMcpProfile.protectedValues.includes(protectedValue)) {
|
|
9253
|
+
managedMcpProfile.protectedValues.push(protectedValue);
|
|
9254
|
+
}
|
|
9255
|
+
}
|
|
8902
9256
|
}
|
|
8903
|
-
throw error;
|
|
8904
9257
|
}
|
|
8905
|
-
|
|
8906
|
-
|
|
8907
|
-
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
|
|
8919
|
-
config
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
);
|
|
8924
|
-
} catch (error) {
|
|
8925
|
-
if (managedMcpProfile && cleanupManagedMcpProfile) {
|
|
8926
|
-
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
9258
|
+
if (managedMcpProfile) {
|
|
9259
|
+
executorEnv = managedMcpProfile.env;
|
|
9260
|
+
await ingestLog(config, command, "system", "info", `Attested isolated ${executor.kind} managed MCP profile`, {
|
|
9261
|
+
presentationKind: "managed_mcp_attestation",
|
|
9262
|
+
...managedMcpProfile.attestation
|
|
9263
|
+
});
|
|
9264
|
+
}
|
|
9265
|
+
const piChildAllocator2 = executor.kind === "pi" ? configuredPiChildIdentityAllocator(config) : null;
|
|
9266
|
+
const trustedPiRuntimeAssertion = commandTrustedPiRuntimeAssertion(command);
|
|
9267
|
+
if (Object.keys(trustedPiRuntimeAssertion).length > 0) {
|
|
9268
|
+
try {
|
|
9269
|
+
if (executor.kind !== "pi") {
|
|
9270
|
+
throw new Error("pi_trusted_runtime_assertion_binding_mismatch:executorKind");
|
|
9271
|
+
}
|
|
9272
|
+
trustedPiRuntimeSourcePaths = trustedPiRuntimeSources(config);
|
|
9273
|
+
trustedPiRuntime = verifyTrustedPiRuntimeAssertion({
|
|
9274
|
+
assertion: trustedPiRuntimeAssertion,
|
|
9275
|
+
connectorId: requireConnectorId(config),
|
|
8927
9276
|
commandId: command.commandId,
|
|
8928
|
-
runId: commandRunId(command)
|
|
9277
|
+
runId: commandRunId(command),
|
|
9278
|
+
leaseId: command.leaseId,
|
|
9279
|
+
executorKind: executor.kind,
|
|
9280
|
+
localDigests: readTrustedPiRuntimeLocalDigests(trustedPiRuntimeSourcePaths)
|
|
8929
9281
|
});
|
|
8930
|
-
managedMcpProfile
|
|
9282
|
+
if (!managedMcpProfile) {
|
|
9283
|
+
throw new Error("pi_trusted_runtime_governed_profile_required");
|
|
9284
|
+
}
|
|
9285
|
+
requireTrustedPiChildAllocator(piChildAllocator2, true);
|
|
9286
|
+
trustedPiRuntimeProfile = materializeTrustedPiRuntimeProfile({
|
|
9287
|
+
seedRoot: trustedPiRuntimeSourcePaths.seedRoot,
|
|
9288
|
+
overlayRoot: trustedPiRuntimeSourcePaths.overlayRoot,
|
|
9289
|
+
profileRoot: managedMcpProfile.profileRoot,
|
|
9290
|
+
agentDir: managedMcpProfile.env.PI_CODING_AGENT_DIR,
|
|
9291
|
+
governedMcpConfigPath: managedMcpProfile.configPath,
|
|
9292
|
+
verifiedAssertion: trustedPiRuntime
|
|
9293
|
+
});
|
|
9294
|
+
executorEnv = {
|
|
9295
|
+
...executorEnv,
|
|
9296
|
+
AMASTER_MANAGED_RUNTIME_ASSERTION_FD: "3",
|
|
9297
|
+
AMASTER_MANAGED_RUNTIME_AUDIT_FILE: join13(
|
|
9298
|
+
managedMcpProfile.env.HOME,
|
|
9299
|
+
".amaster-managed-runtime-audit.jsonl"
|
|
9300
|
+
),
|
|
9301
|
+
AMASTER_RUNTIME_LEASE_ID: command.leaseId
|
|
9302
|
+
};
|
|
9303
|
+
} catch (error2) {
|
|
9304
|
+
if (managedMcpProfile) {
|
|
9305
|
+
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
9306
|
+
commandId: command.commandId,
|
|
9307
|
+
runId: commandRunId(command)
|
|
9308
|
+
});
|
|
9309
|
+
}
|
|
9310
|
+
throw error2;
|
|
8931
9311
|
}
|
|
8932
|
-
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
});
|
|
8941
|
-
piChildIsolation = preparePiChildIsolation({
|
|
8942
|
-
allocator: piChildAllocator,
|
|
8943
|
-
effectiveUid: typeof process.geteuid === "function" ? process.geteuid() : null,
|
|
8944
|
-
commandId: command.commandId,
|
|
8945
|
-
runId: commandRunId(command),
|
|
8946
|
-
profileRoot,
|
|
8947
|
-
workspaceRoot: cwd,
|
|
8948
|
-
allowedRoot: config.runtimeWorkspacesRoot
|
|
9312
|
+
await ingestLog(config, command, "system", "info", "Verified trusted Pi runtime provenance", {
|
|
9313
|
+
presentationKind: "trusted_pi_runtime_attestation",
|
|
9314
|
+
attestationId: trustedPiRuntime.attestationId,
|
|
9315
|
+
unknownToolMode: trustedPiRuntime.unknownToolMode,
|
|
9316
|
+
directToolBudget: trustedPiRuntime.directToolBudget,
|
|
9317
|
+
digests: trustedPiRuntime.digests,
|
|
9318
|
+
profileAttestationId: trustedPiRuntimeProfile.attestationId,
|
|
9319
|
+
inheritedEntries: trustedPiRuntimeProfile.facts.inheritedEntries
|
|
8949
9320
|
});
|
|
8950
|
-
}
|
|
8951
|
-
|
|
8952
|
-
|
|
9321
|
+
}
|
|
9322
|
+
if (executor.kind === "pi" && piResolvedProviderConfig) {
|
|
9323
|
+
const agentDir = managedMcpProfile ? readString(managedMcpProfile.env.PI_CODING_AGENT_DIR) ?? readString(managedMcpProfile.env.PI_AGENT_HOME) ?? null : piAgentLocalPlatformRunnerEnabled(config) ? readString(executorEnv.PI_AGENT_HOME) ?? readString(executorEnv.PI_CODING_AGENT_DIR) ?? null : readString(executorEnv.PI_CODING_AGENT_DIR) ?? readString(executorEnv.PI_AGENT_HOME) ?? null;
|
|
9324
|
+
try {
|
|
9325
|
+
await syncPiExecutorProviderConfig(
|
|
9326
|
+
config,
|
|
9327
|
+
command,
|
|
9328
|
+
agentDir,
|
|
9329
|
+
piResolvedProviderConfig
|
|
9330
|
+
);
|
|
9331
|
+
} catch (error2) {
|
|
9332
|
+
if (managedMcpProfile && cleanupManagedMcpProfile) {
|
|
9333
|
+
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
9334
|
+
commandId: command.commandId,
|
|
9335
|
+
runId: commandRunId(command)
|
|
9336
|
+
});
|
|
9337
|
+
managedMcpProfile = null;
|
|
9338
|
+
}
|
|
9339
|
+
throw error2;
|
|
9340
|
+
}
|
|
9341
|
+
}
|
|
9342
|
+
if (piChildAllocator2) {
|
|
9343
|
+
try {
|
|
9344
|
+
const companyId = readString(commandRuntimeAuth(command).companyId) ?? readString(asRecord(command.payload).companyId);
|
|
9345
|
+
if (!companyId) throw new Error("pi_company_memory_company_id_required");
|
|
9346
|
+
const companyMemoryGroup = resolveCompanyPiMemoryGroup({
|
|
9347
|
+
root: companyPiHomeRoot(process.env),
|
|
9348
|
+
companyId
|
|
9349
|
+
});
|
|
9350
|
+
const assignment = piChildAllocator2.acquire(commandRunId(command), {
|
|
9351
|
+
gid: companyMemoryGroup.gid
|
|
9352
|
+
});
|
|
9353
|
+
piChildAssignmentAcquired = true;
|
|
9354
|
+
if (managedMcpProfile) {
|
|
9355
|
+
piCompanyMemory = prepareCompanyPiMemory({
|
|
9356
|
+
root: companyMemoryGroup.root,
|
|
9357
|
+
companyId,
|
|
9358
|
+
gid: companyMemoryGroup.gid,
|
|
9359
|
+
profileRoot: managedMcpProfile.profileRoot,
|
|
9360
|
+
profileHome: managedMcpProfile.env.PI_AGENT_HOME,
|
|
9361
|
+
childUid: assignment.uid
|
|
9362
|
+
});
|
|
9363
|
+
}
|
|
9364
|
+
const profileRoot = piChildIsolationProfileRoot({
|
|
9365
|
+
managedMcpProfile,
|
|
9366
|
+
executorHome: workspace.executorHome
|
|
9367
|
+
});
|
|
9368
|
+
piChildIsolation = preparePiChildIsolation({
|
|
9369
|
+
allocator: piChildAllocator2,
|
|
9370
|
+
effectiveUid: typeof process.geteuid === "function" ? process.geteuid() : null,
|
|
8953
9371
|
commandId: command.commandId,
|
|
8954
|
-
runId: commandRunId(command)
|
|
9372
|
+
runId: commandRunId(command),
|
|
9373
|
+
...piCompanyMemory ? { gid: piCompanyMemory.gid } : {},
|
|
9374
|
+
profileRoot,
|
|
9375
|
+
workspaceRoot: cwd,
|
|
9376
|
+
allowedRoot: config.runtimeWorkspacesRoot
|
|
8955
9377
|
});
|
|
9378
|
+
} catch (error2) {
|
|
9379
|
+
if (piChildAssignmentAcquired) {
|
|
9380
|
+
piChildAllocator2.release(commandRunId(command));
|
|
9381
|
+
piChildAssignmentAcquired = false;
|
|
9382
|
+
}
|
|
9383
|
+
if (managedMcpProfile) {
|
|
9384
|
+
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
9385
|
+
commandId: command.commandId,
|
|
9386
|
+
runId: commandRunId(command)
|
|
9387
|
+
});
|
|
9388
|
+
}
|
|
9389
|
+
throw error2;
|
|
8956
9390
|
}
|
|
8957
|
-
|
|
9391
|
+
await ingestLog(config, command, "system", "info", "Prepared isolated Pi child identity", {
|
|
9392
|
+
presentationKind: "pi_child_isolation_attestation",
|
|
9393
|
+
...piChildIsolation.attestation,
|
|
9394
|
+
...piCompanyMemory ? { companyMemory: piCompanyMemory.attestation } : {}
|
|
9395
|
+
});
|
|
8958
9396
|
}
|
|
8959
|
-
await ingestLog(config, command, "system", "info",
|
|
8960
|
-
presentationKind: "
|
|
8961
|
-
|
|
9397
|
+
await ingestLog(config, command, "system", "info", `Compiled ${contextManifest.mode} prompt using ${contextManifest.budget.usedChars}/${contextManifest.budget.totalChars} characters`, {
|
|
9398
|
+
presentationKind: "context_manifest",
|
|
9399
|
+
contextManifest
|
|
8962
9400
|
});
|
|
8963
|
-
|
|
8964
|
-
|
|
8965
|
-
|
|
8966
|
-
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
command,
|
|
8994
|
-
executor.kind,
|
|
8995
|
-
protectedExecutorValues,
|
|
8996
|
-
(results) => runtimeArtifactIngest.enqueue(results)
|
|
8997
|
-
);
|
|
8998
|
-
let execution;
|
|
8999
|
-
try {
|
|
9401
|
+
await ackCommand(config, command, "spawned");
|
|
9402
|
+
await ingestLog(config, command, "system", "info", `Starting ${executor.kind} executor`, {
|
|
9403
|
+
executorKind: executor.kind,
|
|
9404
|
+
cwd,
|
|
9405
|
+
args: invocation.args
|
|
9406
|
+
});
|
|
9407
|
+
forgetActiveRunCommand = rememberActiveRunCommand(command, {
|
|
9408
|
+
executorKind: executor.kind,
|
|
9409
|
+
workspacePath: cwd,
|
|
9410
|
+
sourceWorkspacePath: workspace.sourceWorkspacePath,
|
|
9411
|
+
managedWorkdir: workspace.managed,
|
|
9412
|
+
manifestPath: workspaceManifestPath(workspace),
|
|
9413
|
+
outputFloodLimitBytesPerStream: config.executorMaxOutputBytes,
|
|
9414
|
+
...managedMcpProfile ? { managedMcpAttestation: managedMcpProfile.attestation } : {}
|
|
9415
|
+
});
|
|
9416
|
+
const abortController = new AbortController();
|
|
9417
|
+
stopActiveRunHeartbeats = startActiveRunHeartbeats(config, command, abortController);
|
|
9418
|
+
const protectedExecutorValues = managedMcpProfile?.protectedValues ?? providerProtectedValues;
|
|
9419
|
+
const runtimeArtifacts = [];
|
|
9420
|
+
const runtimeArtifactIngest = createRuntimeArtifactIngestQueue({
|
|
9421
|
+
ingest: (results) => ingestRuntimeArtifacts(config, command, cwd, results)
|
|
9422
|
+
});
|
|
9423
|
+
const liveOutputLogger = createLiveOutputLogger(
|
|
9424
|
+
config,
|
|
9425
|
+
command,
|
|
9426
|
+
executor.kind,
|
|
9427
|
+
protectedExecutorValues,
|
|
9428
|
+
(results) => runtimeArtifactIngest.enqueue(results)
|
|
9429
|
+
);
|
|
9430
|
+
let execution;
|
|
9000
9431
|
try {
|
|
9001
9432
|
execution = await runExecutor(invocation.command, invocation.args, {
|
|
9002
9433
|
cwd,
|
|
@@ -9065,6 +9496,19 @@ async function executeRunCommand(config, command) {
|
|
|
9065
9496
|
errorMessage: null
|
|
9066
9497
|
} : executor.kind === "codex" ? parseCodexJsonl(execution.stdout) : executor.kind === "claude" ? parseClaudeStreamJson(execution.stdout) : executor.kind === "opencode" ? parseOpenCodeJsonl(execution.stdout) : executor.kind === "pi" ? parsePiJsonl(execution.stdout) : parseGenericOutput(execution.stdout, execution.stderr);
|
|
9067
9498
|
parsed.sessionId ??= liveOutputLogger.sessionId();
|
|
9499
|
+
const liveTerminalOutput = executor.kind === "pi" && !hasOutputFlood ? liveOutputLogger.terminalOutput() : null;
|
|
9500
|
+
if (liveTerminalOutput) {
|
|
9501
|
+
const parsedUsage = asRecord(parsed.usage);
|
|
9502
|
+
const liveUsage = asRecord(liveTerminalOutput.usage);
|
|
9503
|
+
parsed.summary = liveTerminalOutput.summary;
|
|
9504
|
+
parsed.hasAssistantOutput = true;
|
|
9505
|
+
parsed.usage = {
|
|
9506
|
+
inputTokens: readNumber(liveUsage.inputTokens, 0) || readNumber(parsedUsage.inputTokens, 0),
|
|
9507
|
+
cachedInputTokens: readNumber(liveUsage.cachedInputTokens, 0) || readNumber(parsedUsage.cachedInputTokens, 0),
|
|
9508
|
+
outputTokens: readNumber(liveUsage.outputTokens, 0) || readNumber(parsedUsage.outputTokens, 0),
|
|
9509
|
+
...readNumber(liveUsage.costUsd, 0) > 0 || readNumber(parsedUsage.costUsd, 0) > 0 ? { costUsd: readNumber(liveUsage.costUsd, 0) || readNumber(parsedUsage.costUsd, 0) } : {}
|
|
9510
|
+
};
|
|
9511
|
+
}
|
|
9068
9512
|
const outputTelemetry = liveOutputLogger.snapshot({
|
|
9069
9513
|
outputBytes: execution.outputBytes,
|
|
9070
9514
|
floodLimitBytes: config.executorMaxOutputBytes,
|
|
@@ -9119,7 +9563,7 @@ async function executeRunCommand(config, command) {
|
|
|
9119
9563
|
workspace,
|
|
9120
9564
|
workspaceStatus.artifacts.map((artifact) => ({
|
|
9121
9565
|
rawPath: artifact.relativePath,
|
|
9122
|
-
filePath:
|
|
9566
|
+
filePath: resolve11(cwd, artifact.relativePath)
|
|
9123
9567
|
}))
|
|
9124
9568
|
);
|
|
9125
9569
|
nativeSessionRollout = {
|
|
@@ -9171,6 +9615,7 @@ async function executeRunCommand(config, command) {
|
|
|
9171
9615
|
allowMissingTurnEnd: completionOutputStopped,
|
|
9172
9616
|
allowMissingAssistantOutput: execution.completionOutputType === "approval_required"
|
|
9173
9617
|
}) : null;
|
|
9618
|
+
const piProviderFailure = executor.kind === "pi" && !cancelled && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError ? classifyPiProviderError(parsed) : null;
|
|
9174
9619
|
const parsedErrorMessage = outputFloodError ?? memoryLimitError ?? piInvalidOutputError ?? nativeSessionRolloutError ?? nativeSessionRolloutCleanupError ?? parsed.errorMessage;
|
|
9175
9620
|
const codexTransientFailure = executor.kind === "codex" && (execution.exitCode ?? 0) !== 0 ? classifyCodexTransientUpstreamError({
|
|
9176
9621
|
stdout: execution.stdout,
|
|
@@ -9246,10 +9691,11 @@ async function executeRunCommand(config, command) {
|
|
|
9246
9691
|
...Array.isArray(execution.killedWorkspaceResidents) && execution.killedWorkspaceResidents.length > 0 ? {
|
|
9247
9692
|
killedWorkspaceResidents: execution.killedWorkspaceResidents
|
|
9248
9693
|
} : {},
|
|
9249
|
-
...piInvalidOutputError && !hasOutputFlood ? {
|
|
9694
|
+
...piInvalidOutputError && !cancelled && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError && !piProviderFailure ? {
|
|
9250
9695
|
errorCode: "pi_executor_invalid_output",
|
|
9251
9696
|
errorFamily: "validation"
|
|
9252
9697
|
} : {},
|
|
9698
|
+
...piProviderFailure ? piProviderFailure : {},
|
|
9253
9699
|
...codexTransientFailure ? codexTransientFailure : {},
|
|
9254
9700
|
...piUsageDiagnostic && !piInvalidOutputError ? {
|
|
9255
9701
|
piDiagnostics: {
|
|
@@ -9267,6 +9713,9 @@ async function executeRunCommand(config, command) {
|
|
|
9267
9713
|
...piChildIsolation ? {
|
|
9268
9714
|
piChildIsolation: piChildIsolation.attestation
|
|
9269
9715
|
} : {},
|
|
9716
|
+
...piCompanyMemory ? {
|
|
9717
|
+
companyMemory: piCompanyMemory.attestation
|
|
9718
|
+
} : {},
|
|
9270
9719
|
...trustedPiRuntimeProfile ? {
|
|
9271
9720
|
trustedPiRuntime: {
|
|
9272
9721
|
attestationId: trustedPiRuntime.attestationId,
|
|
@@ -9297,6 +9746,9 @@ async function executeRunCommand(config, command) {
|
|
|
9297
9746
|
});
|
|
9298
9747
|
}
|
|
9299
9748
|
piChildIsolation?.release();
|
|
9749
|
+
if (!piChildIsolation && piChildAssignmentAcquired) {
|
|
9750
|
+
piChildAllocator?.release(commandRunId(command));
|
|
9751
|
+
}
|
|
9300
9752
|
stopActiveRunHeartbeats();
|
|
9301
9753
|
forgetActiveRunCommand();
|
|
9302
9754
|
}
|
|
@@ -9325,10 +9777,14 @@ async function processCommand(config, command) {
|
|
|
9325
9777
|
});
|
|
9326
9778
|
} catch (err) {
|
|
9327
9779
|
const message = err instanceof Error ? err.message : String(err);
|
|
9780
|
+
const errorCode = readString(asRecord(err).code);
|
|
9781
|
+
const runtimeArtifacts = Array.isArray(asRecord(err).receipts) ? asRecord(err).receipts.map(asRecord) : [];
|
|
9328
9782
|
await ingestLog(config, command, "system", "error", message);
|
|
9329
9783
|
await completeCommand(config, command, "failed", {
|
|
9330
9784
|
summary: message,
|
|
9331
|
-
commandType: command.commandType
|
|
9785
|
+
commandType: command.commandType,
|
|
9786
|
+
...errorCode && /^[a-z][a-z0-9_]{0,127}$/.test(errorCode) ? { errorCode } : {},
|
|
9787
|
+
...runtimeArtifacts.length > 0 ? { runtimeArtifacts } : {}
|
|
9332
9788
|
}, message);
|
|
9333
9789
|
}
|
|
9334
9790
|
}
|
|
@@ -9499,7 +9955,7 @@ async function runLoop(config) {
|
|
|
9499
9955
|
${message}
|
|
9500
9956
|
`);
|
|
9501
9957
|
}
|
|
9502
|
-
await new Promise((
|
|
9958
|
+
await new Promise((resolve12) => setTimeout(resolve12, config.pollIntervalSeconds * 1e3));
|
|
9503
9959
|
}
|
|
9504
9960
|
}
|
|
9505
9961
|
function help() {
|