@amaster.ai/employee-runtime-connector 0.1.0-beta.41 → 0.1.0-beta.42
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 +906 -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,10 @@ 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_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;
|
|
3691
|
+
var PI_PROVIDER_RETRY_AFTER_SECONDS_RE = /retry[-\s]?after\s*[:=]?\s*(\d{1,6})\s*(?:seconds?|secs?|s)\b/i;
|
|
3692
|
+
var MAX_PI_PROVIDER_RETRY_AFTER_SECONDS = 7 * 24 * 60 * 60;
|
|
3606
3693
|
function approvedMcpInvocationSucceeded(results, invocationId) {
|
|
3607
3694
|
const approvedInvocationId = readString(invocationId);
|
|
3608
3695
|
return Boolean(approvedInvocationId && (Array.isArray(results) ? results : []).some((rawResult) => {
|
|
@@ -3817,6 +3904,32 @@ function classifyCodexTransientUpstreamError(input, now = /* @__PURE__ */ new Da
|
|
|
3817
3904
|
...retryNotBefore ? { retryNotBefore: retryNotBefore.toISOString() } : {}
|
|
3818
3905
|
};
|
|
3819
3906
|
}
|
|
3907
|
+
function extractPiProviderRetryNotBefore(errorMessage, now) {
|
|
3908
|
+
const retryAfter = errorMessage.match(PI_PROVIDER_RETRY_AFTER_SECONDS_RE);
|
|
3909
|
+
if (!retryAfter) return null;
|
|
3910
|
+
const seconds = Number.parseInt(retryAfter[1] ?? "", 10);
|
|
3911
|
+
if (!Number.isSafeInteger(seconds) || seconds < 0 || seconds > MAX_PI_PROVIDER_RETRY_AFTER_SECONDS) {
|
|
3912
|
+
return null;
|
|
3913
|
+
}
|
|
3914
|
+
return new Date(now.getTime() + seconds * 1e3);
|
|
3915
|
+
}
|
|
3916
|
+
function classifyPiProviderError(input, now = /* @__PURE__ */ new Date()) {
|
|
3917
|
+
const errorMessage = readString(asRecord(input).errorMessage);
|
|
3918
|
+
if (!errorMessage) return null;
|
|
3919
|
+
if (PI_PROVIDER_AUTH_RE.test(errorMessage)) {
|
|
3920
|
+
return {
|
|
3921
|
+
errorCode: "pi_provider_auth_required",
|
|
3922
|
+
errorFamily: "configuration"
|
|
3923
|
+
};
|
|
3924
|
+
}
|
|
3925
|
+
if (!PI_PROVIDER_TRANSIENT_RE.test(errorMessage)) return null;
|
|
3926
|
+
const retryNotBefore = extractPiProviderRetryNotBefore(errorMessage, now);
|
|
3927
|
+
return {
|
|
3928
|
+
errorCode: "pi_transient_upstream",
|
|
3929
|
+
errorFamily: "transient_upstream",
|
|
3930
|
+
...retryNotBefore ? { retryNotBefore: retryNotBefore.toISOString() } : {}
|
|
3931
|
+
};
|
|
3932
|
+
}
|
|
3820
3933
|
function parseClaudeStreamJson(stdout) {
|
|
3821
3934
|
let sessionId = null;
|
|
3822
3935
|
let summary = "";
|
|
@@ -3863,13 +3976,13 @@ function parseClaudeStreamJson(stdout) {
|
|
|
3863
3976
|
}
|
|
3864
3977
|
function openCodeErrorText(value) {
|
|
3865
3978
|
if (typeof value === "string") return value;
|
|
3866
|
-
const
|
|
3867
|
-
const message = readString(
|
|
3979
|
+
const record4 = asRecord(value);
|
|
3980
|
+
const message = readString(record4.message);
|
|
3868
3981
|
if (message) return message;
|
|
3869
|
-
const data = asRecord(
|
|
3982
|
+
const data = asRecord(record4.data);
|
|
3870
3983
|
const nestedMessage = readString(data.message);
|
|
3871
3984
|
if (nestedMessage) return nestedMessage;
|
|
3872
|
-
return readString(
|
|
3985
|
+
return readString(record4.name) ?? readString(record4.code) ?? "";
|
|
3873
3986
|
}
|
|
3874
3987
|
function parseOpenCodeJsonl(stdout) {
|
|
3875
3988
|
let sessionId = null;
|
|
@@ -3907,8 +4020,8 @@ function parseOpenCodeJsonl(stdout) {
|
|
|
3907
4020
|
return { sessionId, summary, usage, errorMessage };
|
|
3908
4021
|
}
|
|
3909
4022
|
function piMessageText(message) {
|
|
3910
|
-
const
|
|
3911
|
-
const content =
|
|
4023
|
+
const record4 = asRecord(message);
|
|
4024
|
+
const content = record4.content;
|
|
3912
4025
|
if (typeof content === "string") return content.trim();
|
|
3913
4026
|
if (!Array.isArray(content)) return "";
|
|
3914
4027
|
return content.map((entry) => {
|
|
@@ -3933,10 +4046,10 @@ function piTextValue(value) {
|
|
|
3933
4046
|
return typeof value === "string" && value.length > 0 ? value : "";
|
|
3934
4047
|
}
|
|
3935
4048
|
function piAssistantEventText(assistantEvent) {
|
|
3936
|
-
const
|
|
3937
|
-
const type = readString(
|
|
3938
|
-
if (type === "text_delta") return piTextValue(
|
|
3939
|
-
if (type === "text_end") return piTextValue(
|
|
4049
|
+
const record4 = asRecord(assistantEvent);
|
|
4050
|
+
const type = readString(record4.type);
|
|
4051
|
+
if (type === "text_delta") return piTextValue(record4.delta);
|
|
4052
|
+
if (type === "text_end") return piTextValue(record4.content);
|
|
3940
4053
|
return "";
|
|
3941
4054
|
}
|
|
3942
4055
|
function piMessageUsage(message) {
|
|
@@ -3957,14 +4070,14 @@ function assignPiUsage(target, source) {
|
|
|
3957
4070
|
if (source.costUsd > 0) target.costUsd = source.costUsd;
|
|
3958
4071
|
}
|
|
3959
4072
|
function piMessageStopReason(message) {
|
|
3960
|
-
const
|
|
3961
|
-
return readString(
|
|
4073
|
+
const record4 = asRecord(message);
|
|
4074
|
+
return readString(record4.stopReason ?? record4.stop_reason);
|
|
3962
4075
|
}
|
|
3963
4076
|
function piMessageErrorText(message) {
|
|
3964
|
-
const
|
|
3965
|
-
const explicitError = readString(
|
|
4077
|
+
const record4 = asRecord(message);
|
|
4078
|
+
const explicitError = readString(record4.errorMessage ?? record4.error_message)?.trim();
|
|
3966
4079
|
if (explicitError) return explicitError;
|
|
3967
|
-
const stopReason = piMessageStopReason(
|
|
4080
|
+
const stopReason = piMessageStopReason(record4);
|
|
3968
4081
|
if (stopReason === "error" || stopReason === "failed" || stopReason === "exception") {
|
|
3969
4082
|
return `Pi Agent message ended with stopReason=${stopReason}`;
|
|
3970
4083
|
}
|
|
@@ -4256,7 +4369,7 @@ async function postRuntimeConnectorJsonWithRetry(config, path, payload, options
|
|
|
4256
4369
|
} catch (error) {
|
|
4257
4370
|
lastError = error;
|
|
4258
4371
|
if (attempt >= maxAttempts || !retryableRuntimeConnectorPost(error)) throw error;
|
|
4259
|
-
if (delayMs > 0) await new Promise((
|
|
4372
|
+
if (delayMs > 0) await new Promise((resolve12) => setTimeout(resolve12, delayMs));
|
|
4260
4373
|
}
|
|
4261
4374
|
}
|
|
4262
4375
|
throw lastError;
|
|
@@ -4340,14 +4453,25 @@ function prepareRuntimeArtifactUploads(cwd, mcpToolResults) {
|
|
|
4340
4453
|
}
|
|
4341
4454
|
|
|
4342
4455
|
// src/amaster-runtime-daemon/runtime-artifact-ingest-queue.mjs
|
|
4456
|
+
function normalizedError(caught) {
|
|
4457
|
+
return caught instanceof Error ? caught : new Error(String(caught));
|
|
4458
|
+
}
|
|
4459
|
+
var RuntimeArtifactIngestAggregateError = class extends AggregateError {
|
|
4460
|
+
constructor(errors, receipts) {
|
|
4461
|
+
super(errors, `${errors.length} Runtime Artifact ingest operation(s) failed`);
|
|
4462
|
+
this.name = "RuntimeArtifactIngestAggregateError";
|
|
4463
|
+
this.code = errors.some((error) => error.code === "runtime_artifact_rejected") ? "runtime_artifact_rejected" : "runtime_artifact_ingest_failed";
|
|
4464
|
+
this.failures = [...errors];
|
|
4465
|
+
this.receipts = [...receipts];
|
|
4466
|
+
}
|
|
4467
|
+
};
|
|
4343
4468
|
function createRuntimeArtifactIngestQueue({ ingest, onError }) {
|
|
4344
4469
|
const handledIntentIds = /* @__PURE__ */ new Set();
|
|
4345
4470
|
const artifacts = [];
|
|
4346
|
-
|
|
4471
|
+
const errors = [];
|
|
4347
4472
|
let queue = Promise.resolve();
|
|
4348
4473
|
return {
|
|
4349
4474
|
enqueue(results) {
|
|
4350
|
-
if (error) return;
|
|
4351
4475
|
const pending = results.filter((result2) => {
|
|
4352
4476
|
const intentId = readString(asRecord(result2).artifactIntent?.intentId);
|
|
4353
4477
|
if (!intentId || handledIntentIds.has(intentId)) return false;
|
|
@@ -4356,8 +4480,12 @@ function createRuntimeArtifactIngestQueue({ ingest, onError }) {
|
|
|
4356
4480
|
});
|
|
4357
4481
|
if (pending.length === 0) return;
|
|
4358
4482
|
queue = queue.then(async () => artifacts.push(...await ingest(pending))).catch((caught) => {
|
|
4359
|
-
|
|
4360
|
-
|
|
4483
|
+
const aggregate = caught instanceof RuntimeArtifactIngestAggregateError ? caught : null;
|
|
4484
|
+
artifacts.push(...aggregate?.receipts ?? []);
|
|
4485
|
+
for (const error of aggregate?.failures ?? [normalizedError(caught)]) {
|
|
4486
|
+
errors.push(error);
|
|
4487
|
+
onError?.(error);
|
|
4488
|
+
}
|
|
4361
4489
|
});
|
|
4362
4490
|
},
|
|
4363
4491
|
hasHandled(intentId) {
|
|
@@ -4365,7 +4493,9 @@ function createRuntimeArtifactIngestQueue({ ingest, onError }) {
|
|
|
4365
4493
|
},
|
|
4366
4494
|
async flush() {
|
|
4367
4495
|
await queue;
|
|
4368
|
-
if (
|
|
4496
|
+
if (errors.length > 0) {
|
|
4497
|
+
throw new RuntimeArtifactIngestAggregateError(errors, artifacts);
|
|
4498
|
+
}
|
|
4369
4499
|
return [...artifacts];
|
|
4370
4500
|
}
|
|
4371
4501
|
};
|
|
@@ -4895,18 +5025,24 @@ function createPiChildIdentityAllocator(input = {}) {
|
|
|
4895
5025
|
const runAssignments = /* @__PURE__ */ new Map();
|
|
4896
5026
|
const uidAssignments = /* @__PURE__ */ new Map();
|
|
4897
5027
|
return {
|
|
4898
|
-
acquire(runId) {
|
|
5028
|
+
acquire(runId, options = {}) {
|
|
4899
5029
|
if (typeof runId !== "string" || runId.trim().length === 0) {
|
|
4900
5030
|
throw new Error("pi_child_isolation_run_id_required");
|
|
4901
5031
|
}
|
|
4902
5032
|
const normalizedRunId = runId.trim();
|
|
4903
5033
|
const existing = runAssignments.get(normalizedRunId);
|
|
4904
|
-
|
|
5034
|
+
const requestedGid = options.gid === void 0 ? null : positiveInteger(options.gid, "gid");
|
|
5035
|
+
if (existing) {
|
|
5036
|
+
if (requestedGid !== null && existing.gid !== requestedGid) {
|
|
5037
|
+
throw new Error("pi_child_isolation_run_gid_mismatch");
|
|
5038
|
+
}
|
|
5039
|
+
return { ...existing };
|
|
5040
|
+
}
|
|
4905
5041
|
const initialOffset = Math.abs(hashRunId(normalizedRunId)) % uidSpan;
|
|
4906
5042
|
for (let attempt = 0; attempt < uidSpan; attempt += 1) {
|
|
4907
5043
|
const uid = uidBase + (initialOffset + attempt) % uidSpan;
|
|
4908
5044
|
if (uidAssignments.has(uid)) continue;
|
|
4909
|
-
const assignment = { uid, gid: uid };
|
|
5045
|
+
const assignment = { uid, gid: requestedGid ?? uid };
|
|
4910
5046
|
runAssignments.set(normalizedRunId, assignment);
|
|
4911
5047
|
uidAssignments.set(uid, normalizedRunId);
|
|
4912
5048
|
return { ...assignment };
|
|
@@ -4945,7 +5081,9 @@ function preparePiChildIsolation(input) {
|
|
|
4945
5081
|
if (!isWithin(input.profileRoot, input.allowedRoot) || !isWithin(input.workspaceRoot, input.allowedRoot)) {
|
|
4946
5082
|
throw new Error("pi_child_isolation_path_outside_run_root");
|
|
4947
5083
|
}
|
|
4948
|
-
const assignment = input.allocator.acquire(input.runId
|
|
5084
|
+
const assignment = input.allocator.acquire(input.runId, {
|
|
5085
|
+
...input.gid === void 0 ? {} : { gid: input.gid }
|
|
5086
|
+
});
|
|
4949
5087
|
const isolatePath = input.isolatePath ?? isolatePiChildPath;
|
|
4950
5088
|
try {
|
|
4951
5089
|
for (const path of [resolve7(input.profileRoot), resolve7(input.workspaceRoot)]) {
|
|
@@ -4956,7 +5094,7 @@ function preparePiChildIsolation(input) {
|
|
|
4956
5094
|
throw error;
|
|
4957
5095
|
}
|
|
4958
5096
|
return {
|
|
4959
|
-
spawn: { uid: assignment.uid, gid: assignment.gid },
|
|
5097
|
+
spawn: { uid: assignment.uid, gid: assignment.gid, umask: 7 },
|
|
4960
5098
|
attestation: {
|
|
4961
5099
|
schemaVersion: "amaster.pi-child-isolation.v1",
|
|
4962
5100
|
commandId: input.commandId,
|
|
@@ -4969,21 +5107,248 @@ function preparePiChildIsolation(input) {
|
|
|
4969
5107
|
};
|
|
4970
5108
|
}
|
|
4971
5109
|
|
|
4972
|
-
// src/amaster-runtime-daemon/pi-
|
|
5110
|
+
// src/amaster-runtime-daemon/pi-company-memory.mjs
|
|
4973
5111
|
import { createHash as createHash6 } from "node:crypto";
|
|
4974
5112
|
import {
|
|
4975
5113
|
chmodSync as chmodSync4,
|
|
4976
|
-
|
|
5114
|
+
chownSync as chownSync2,
|
|
4977
5115
|
existsSync as existsSync9,
|
|
5116
|
+
lchownSync as lchownSync2,
|
|
4978
5117
|
lstatSync as lstatSync5,
|
|
4979
5118
|
mkdirSync as mkdirSync6,
|
|
4980
5119
|
readFileSync as readFileSync7,
|
|
4981
|
-
|
|
5120
|
+
renameSync as renameSync4,
|
|
4982
5121
|
rmSync as rmSync5,
|
|
4983
5122
|
symlinkSync as symlinkSync2,
|
|
4984
5123
|
writeFileSync as writeFileSync6
|
|
4985
5124
|
} from "node:fs";
|
|
4986
5125
|
import { dirname as dirname7, isAbsolute as isAbsolute5, join as join10, relative as relative5, resolve as resolve8 } from "node:path";
|
|
5126
|
+
var REGISTRY_FILENAME = ".amaster-company-memory-groups.json";
|
|
5127
|
+
var COMPANY_MARKER_FILENAME = ".amaster-company-memory.json";
|
|
5128
|
+
var REGISTRY_VERSION = 1;
|
|
5129
|
+
var COMPANY_MARKER_VERSION = 1;
|
|
5130
|
+
var DEFAULT_GID_BASE = 1e5;
|
|
5131
|
+
var DEFAULT_GID_SPAN = 1e6;
|
|
5132
|
+
var defaultFs2 = {
|
|
5133
|
+
chmodSync: chmodSync4,
|
|
5134
|
+
chownSync: chownSync2,
|
|
5135
|
+
existsSync: existsSync9,
|
|
5136
|
+
lchownSync: lchownSync2,
|
|
5137
|
+
lstatSync: lstatSync5,
|
|
5138
|
+
mkdirSync: mkdirSync6,
|
|
5139
|
+
readFileSync: readFileSync7,
|
|
5140
|
+
renameSync: renameSync4,
|
|
5141
|
+
rmSync: rmSync5,
|
|
5142
|
+
symlinkSync: symlinkSync2,
|
|
5143
|
+
writeFileSync: writeFileSync6
|
|
5144
|
+
};
|
|
5145
|
+
function requiredString2(value, label) {
|
|
5146
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
5147
|
+
throw new Error(`pi_company_memory_invalid:${label}`);
|
|
5148
|
+
}
|
|
5149
|
+
return value.trim();
|
|
5150
|
+
}
|
|
5151
|
+
function positiveInteger2(value, label) {
|
|
5152
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
5153
|
+
throw new Error(`pi_company_memory_invalid:${label}`);
|
|
5154
|
+
}
|
|
5155
|
+
return value;
|
|
5156
|
+
}
|
|
5157
|
+
function within2(candidate, root) {
|
|
5158
|
+
const rel = relative5(root, candidate);
|
|
5159
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute5(rel);
|
|
5160
|
+
}
|
|
5161
|
+
function assertDirectory(path, label, fs) {
|
|
5162
|
+
const stat = fs.lstatSync(path);
|
|
5163
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
5164
|
+
throw new Error(`pi_company_memory_unsafe:${label}`);
|
|
5165
|
+
}
|
|
5166
|
+
}
|
|
5167
|
+
function readJson(path, label, fs) {
|
|
5168
|
+
try {
|
|
5169
|
+
const value = JSON.parse(fs.readFileSync(path, "utf8"));
|
|
5170
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5171
|
+
throw new Error("not an object");
|
|
5172
|
+
}
|
|
5173
|
+
return value;
|
|
5174
|
+
} catch {
|
|
5175
|
+
throw new Error(`pi_company_memory_invalid:${label}`);
|
|
5176
|
+
}
|
|
5177
|
+
}
|
|
5178
|
+
function writeJsonAtomic(path, value, mode, fs) {
|
|
5179
|
+
const tempPath = `${path}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
5180
|
+
try {
|
|
5181
|
+
fs.writeFileSync(tempPath, `${JSON.stringify(value, null, 2)}
|
|
5182
|
+
`, {
|
|
5183
|
+
mode,
|
|
5184
|
+
flag: "wx"
|
|
5185
|
+
});
|
|
5186
|
+
fs.chmodSync(tempPath, mode);
|
|
5187
|
+
fs.renameSync(tempPath, path);
|
|
5188
|
+
} catch (error) {
|
|
5189
|
+
fs.rmSync(tempPath, { force: true });
|
|
5190
|
+
throw error;
|
|
5191
|
+
}
|
|
5192
|
+
}
|
|
5193
|
+
function safeCompanyPiHomeSegment(companyId) {
|
|
5194
|
+
const raw = requiredString2(companyId, "companyId");
|
|
5195
|
+
if (/^[A-Za-z0-9][A-Za-z0-9._-]{0,119}$/.test(raw)) return raw;
|
|
5196
|
+
const normalized = raw.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[._-]+|[._-]+$/g, "").slice(0, 80);
|
|
5197
|
+
const hash = createHash6("sha256").update(raw).digest("hex").slice(0, 12);
|
|
5198
|
+
return normalized ? `${normalized}-${hash}` : `company-${hash}`;
|
|
5199
|
+
}
|
|
5200
|
+
function ensureMemoryRoot(root, fs) {
|
|
5201
|
+
if (!fs.existsSync(root)) fs.mkdirSync(root, { recursive: true, mode: 457 });
|
|
5202
|
+
assertDirectory(root, "root", fs);
|
|
5203
|
+
fs.chownSync(root, 0, 0);
|
|
5204
|
+
fs.chmodSync(root, 457);
|
|
5205
|
+
}
|
|
5206
|
+
function readGroupRegistry(root, fs) {
|
|
5207
|
+
const path = join10(root, REGISTRY_FILENAME);
|
|
5208
|
+
if (!fs.existsSync(path)) {
|
|
5209
|
+
return { path, groups: {} };
|
|
5210
|
+
}
|
|
5211
|
+
const registryStat = fs.lstatSync(path);
|
|
5212
|
+
if (!registryStat.isFile() || registryStat.isSymbolicLink()) {
|
|
5213
|
+
throw new Error("pi_company_memory_unsafe:group_registry");
|
|
5214
|
+
}
|
|
5215
|
+
const registry = readJson(path, "group_registry", fs);
|
|
5216
|
+
if (registry.version !== REGISTRY_VERSION || !registry.groups || typeof registry.groups !== "object" || Array.isArray(registry.groups)) {
|
|
5217
|
+
throw new Error("pi_company_memory_invalid:group_registry");
|
|
5218
|
+
}
|
|
5219
|
+
const groups = {};
|
|
5220
|
+
const used = /* @__PURE__ */ new Set();
|
|
5221
|
+
for (const [companyId, rawGid] of Object.entries(registry.groups)) {
|
|
5222
|
+
const gid = positiveInteger2(rawGid, "registeredGid");
|
|
5223
|
+
if (used.has(gid)) throw new Error("pi_company_memory_invalid:duplicate_registered_gid");
|
|
5224
|
+
groups[requiredString2(companyId, "registeredCompanyId")] = gid;
|
|
5225
|
+
used.add(gid);
|
|
5226
|
+
}
|
|
5227
|
+
return { path, groups };
|
|
5228
|
+
}
|
|
5229
|
+
function allocateCompanyGid(root, companyId, input, fs) {
|
|
5230
|
+
const gidBase = positiveInteger2(input.gidBase ?? DEFAULT_GID_BASE, "gidBase");
|
|
5231
|
+
const gidSpan = positiveInteger2(input.gidSpan ?? DEFAULT_GID_SPAN, "gidSpan");
|
|
5232
|
+
const { path, groups } = readGroupRegistry(root, fs);
|
|
5233
|
+
if (groups[companyId]) return groups[companyId];
|
|
5234
|
+
const used = new Set(Object.values(groups));
|
|
5235
|
+
const initialOffset = Number.parseInt(
|
|
5236
|
+
createHash6("sha256").update(companyId).digest("hex").slice(0, 12),
|
|
5237
|
+
16
|
|
5238
|
+
) % gidSpan;
|
|
5239
|
+
let gid = null;
|
|
5240
|
+
for (let attempt = 0; attempt < gidSpan; attempt += 1) {
|
|
5241
|
+
const candidate = gidBase + (initialOffset + attempt) % gidSpan;
|
|
5242
|
+
if (!used.has(candidate)) {
|
|
5243
|
+
gid = candidate;
|
|
5244
|
+
break;
|
|
5245
|
+
}
|
|
5246
|
+
}
|
|
5247
|
+
if (!gid) throw new Error("pi_company_memory_gid_pool_exhausted");
|
|
5248
|
+
writeJsonAtomic(path, {
|
|
5249
|
+
version: REGISTRY_VERSION,
|
|
5250
|
+
groups: {
|
|
5251
|
+
...groups,
|
|
5252
|
+
[companyId]: gid
|
|
5253
|
+
}
|
|
5254
|
+
}, 384, fs);
|
|
5255
|
+
return gid;
|
|
5256
|
+
}
|
|
5257
|
+
function resolveCompanyPiMemoryGroup(input, fs = defaultFs2) {
|
|
5258
|
+
const root = resolve8(requiredString2(input.root, "root"));
|
|
5259
|
+
const companyId = requiredString2(input.companyId, "companyId");
|
|
5260
|
+
ensureMemoryRoot(root, fs);
|
|
5261
|
+
return {
|
|
5262
|
+
root,
|
|
5263
|
+
companyId,
|
|
5264
|
+
gid: allocateCompanyGid(root, companyId, input, fs)
|
|
5265
|
+
};
|
|
5266
|
+
}
|
|
5267
|
+
function ensurePrivateDirectory(path, mode, uid, gid, fs) {
|
|
5268
|
+
if (!fs.existsSync(path)) fs.mkdirSync(path, { recursive: false, mode });
|
|
5269
|
+
assertDirectory(path, "directory", fs);
|
|
5270
|
+
fs.chownSync(path, uid, gid);
|
|
5271
|
+
fs.chmodSync(path, mode);
|
|
5272
|
+
}
|
|
5273
|
+
function prepareCompanyPiMemory(input, fs = defaultFs2) {
|
|
5274
|
+
const root = resolve8(requiredString2(input.root, "root"));
|
|
5275
|
+
const profileRoot = resolve8(requiredString2(input.profileRoot, "profileRoot"));
|
|
5276
|
+
const profileHome = resolve8(requiredString2(input.profileHome, "profileHome"));
|
|
5277
|
+
const companyId = requiredString2(input.companyId, "companyId");
|
|
5278
|
+
const childUid = positiveInteger2(input.childUid, "childUid");
|
|
5279
|
+
if (!within2(profileHome, profileRoot)) {
|
|
5280
|
+
throw new Error("pi_company_memory_profile_path_escape");
|
|
5281
|
+
}
|
|
5282
|
+
assertDirectory(profileRoot, "profile_root", fs);
|
|
5283
|
+
assertDirectory(profileHome, "profile_home", fs);
|
|
5284
|
+
const group = resolveCompanyPiMemoryGroup({ ...input, root, companyId }, fs);
|
|
5285
|
+
const gid = group.gid;
|
|
5286
|
+
if (input.gid !== void 0 && positiveInteger2(input.gid, "gid") !== gid) {
|
|
5287
|
+
throw new Error("pi_company_memory_gid_mismatch");
|
|
5288
|
+
}
|
|
5289
|
+
const companyDir = join10(root, safeCompanyPiHomeSegment(companyId));
|
|
5290
|
+
const companyPiHome = join10(companyDir, ".pi");
|
|
5291
|
+
const memoryDir = join10(companyPiHome, "memories");
|
|
5292
|
+
ensurePrivateDirectory(companyDir, 456, 0, gid, fs);
|
|
5293
|
+
const markerPath = join10(companyDir, COMPANY_MARKER_FILENAME);
|
|
5294
|
+
if (fs.existsSync(markerPath)) {
|
|
5295
|
+
const markerStat = fs.lstatSync(markerPath);
|
|
5296
|
+
if (!markerStat.isFile() || markerStat.isSymbolicLink()) {
|
|
5297
|
+
throw new Error("pi_company_memory_unsafe:company_marker");
|
|
5298
|
+
}
|
|
5299
|
+
const marker = readJson(markerPath, "company_marker", fs);
|
|
5300
|
+
if (marker.version !== COMPANY_MARKER_VERSION || marker.companyId !== companyId || marker.gid !== gid) {
|
|
5301
|
+
throw new Error("pi_company_memory_authority_mismatch");
|
|
5302
|
+
}
|
|
5303
|
+
} else {
|
|
5304
|
+
writeJsonAtomic(markerPath, {
|
|
5305
|
+
version: COMPANY_MARKER_VERSION,
|
|
5306
|
+
companyId,
|
|
5307
|
+
gid,
|
|
5308
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5309
|
+
}, 384, fs);
|
|
5310
|
+
}
|
|
5311
|
+
fs.chownSync(markerPath, 0, 0);
|
|
5312
|
+
fs.chmodSync(markerPath, 384);
|
|
5313
|
+
ensurePrivateDirectory(companyPiHome, 456, 0, gid, fs);
|
|
5314
|
+
if (!fs.existsSync(memoryDir)) fs.mkdirSync(memoryDir, { recursive: false, mode: 1528 });
|
|
5315
|
+
assertDirectory(memoryDir, "memories", fs);
|
|
5316
|
+
fs.chownSync(memoryDir, 0, gid);
|
|
5317
|
+
fs.chmodSync(memoryDir, 1528);
|
|
5318
|
+
const memoryLink = join10(profileHome, "memories");
|
|
5319
|
+
if (fs.existsSync(memoryLink)) {
|
|
5320
|
+
throw new Error("pi_company_memory_profile_link_exists");
|
|
5321
|
+
}
|
|
5322
|
+
fs.symlinkSync(memoryDir, memoryLink, "dir");
|
|
5323
|
+
fs.lchownSync(memoryLink, childUid, gid);
|
|
5324
|
+
return {
|
|
5325
|
+
gid,
|
|
5326
|
+
memoryDir,
|
|
5327
|
+
memoryLink,
|
|
5328
|
+
attestation: {
|
|
5329
|
+
schemaVersion: "amaster.company-pi-memory.v1",
|
|
5330
|
+
companyId,
|
|
5331
|
+
gid,
|
|
5332
|
+
mode: "run_scoped_home_company_memory"
|
|
5333
|
+
}
|
|
5334
|
+
};
|
|
5335
|
+
}
|
|
5336
|
+
|
|
5337
|
+
// src/amaster-runtime-daemon/pi-trusted-runtime-profile.mjs
|
|
5338
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
5339
|
+
import {
|
|
5340
|
+
chmodSync as chmodSync5,
|
|
5341
|
+
copyFileSync as copyFileSync2,
|
|
5342
|
+
existsSync as existsSync10,
|
|
5343
|
+
lstatSync as lstatSync6,
|
|
5344
|
+
mkdirSync as mkdirSync7,
|
|
5345
|
+
readFileSync as readFileSync8,
|
|
5346
|
+
readdirSync as readdirSync6,
|
|
5347
|
+
rmSync as rmSync6,
|
|
5348
|
+
symlinkSync as symlinkSync3,
|
|
5349
|
+
writeFileSync as writeFileSync7
|
|
5350
|
+
} from "node:fs";
|
|
5351
|
+
import { dirname as dirname8, isAbsolute as isAbsolute6, join as join11, relative as relative6, resolve as resolve9 } from "node:path";
|
|
4987
5352
|
var ASSERTION_VERSION = "2026-07-25.v1";
|
|
4988
5353
|
var SHA256 = /^[a-f0-9]{64}$/;
|
|
4989
5354
|
var COPY_ENTRIES = ["SYSTEM.md", "policy", "skills", "agents", "bundles", "extensions"];
|
|
@@ -4992,23 +5357,23 @@ var SECRET_KEY = /(authorization|cookie|api[_-]?key|password|secret|token)$/i;
|
|
|
4992
5357
|
var SECRET_VALUE = /(?:authorization|cookie|api[_-]?key|password|secret|token)\s*[:=]\s*(?:bearer\s+)?[^\s"',;]+|bearer\s+[^\s"',;]+/i;
|
|
4993
5358
|
var MAX_AUDIT_BYTES = 1024 * 1024;
|
|
4994
5359
|
var MAX_AUDIT_EVENTS = 2e3;
|
|
4995
|
-
function
|
|
5360
|
+
function requiredString3(value, field) {
|
|
4996
5361
|
if (typeof value !== "string" || value.trim() === "") {
|
|
4997
5362
|
throw new Error(`pi_trusted_runtime_assertion_invalid:${field}`);
|
|
4998
5363
|
}
|
|
4999
5364
|
return value.trim();
|
|
5000
5365
|
}
|
|
5001
5366
|
function requiredDigest(value, field) {
|
|
5002
|
-
const digest =
|
|
5367
|
+
const digest = requiredString3(value, field);
|
|
5003
5368
|
if (!SHA256.test(digest)) throw new Error(`pi_trusted_runtime_assertion_invalid:${field}`);
|
|
5004
5369
|
return digest;
|
|
5005
5370
|
}
|
|
5006
5371
|
function sha256File(path, label) {
|
|
5007
|
-
const stat =
|
|
5372
|
+
const stat = lstatSync6(path);
|
|
5008
5373
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
5009
5374
|
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
5010
5375
|
}
|
|
5011
|
-
return
|
|
5376
|
+
return createHash7("sha256").update(readFileSync8(path)).digest("hex");
|
|
5012
5377
|
}
|
|
5013
5378
|
function verifyDeclaredFiles(manifest, root, label, ignoredPaths = [], enforceComplete = true) {
|
|
5014
5379
|
if (!Array.isArray(manifest.files) || manifest.files.length === 0) {
|
|
@@ -5016,10 +5381,10 @@ function verifyDeclaredFiles(manifest, root, label, ignoredPaths = [], enforceCo
|
|
|
5016
5381
|
}
|
|
5017
5382
|
const seen = /* @__PURE__ */ new Set();
|
|
5018
5383
|
for (const entry of manifest.files) {
|
|
5019
|
-
const relativePath =
|
|
5384
|
+
const relativePath = requiredString3(entry?.path, `${label}.files.path`);
|
|
5020
5385
|
const expectedDigest = requiredDigest(entry?.sha256, `${label}.files.sha256`);
|
|
5021
|
-
const filePath =
|
|
5022
|
-
if (!
|
|
5386
|
+
const filePath = resolve9(root, relativePath);
|
|
5387
|
+
if (!within3(filePath, root) || seen.has(relativePath)) {
|
|
5023
5388
|
throw new Error(`pi_trusted_runtime_source_invalid:${label}_files`);
|
|
5024
5389
|
}
|
|
5025
5390
|
seen.add(relativePath);
|
|
@@ -5031,9 +5396,9 @@ function verifyDeclaredFiles(manifest, root, label, ignoredPaths = [], enforceCo
|
|
|
5031
5396
|
const ignored = ignoredPaths.map((path) => path.split("\\").join("/"));
|
|
5032
5397
|
const visit = (directory) => {
|
|
5033
5398
|
for (const entry of readdirSync6(directory)) {
|
|
5034
|
-
const filePath =
|
|
5035
|
-
const relativePath =
|
|
5036
|
-
const stat =
|
|
5399
|
+
const filePath = join11(directory, entry);
|
|
5400
|
+
const relativePath = relative6(root, filePath).split("\\").join("/");
|
|
5401
|
+
const stat = lstatSync6(filePath);
|
|
5037
5402
|
if (stat.isSymbolicLink()) {
|
|
5038
5403
|
throw new Error(`pi_trusted_runtime_source_unsafe:${label}_file`);
|
|
5039
5404
|
}
|
|
@@ -5049,21 +5414,21 @@ function verifyDeclaredFiles(manifest, root, label, ignoredPaths = [], enforceCo
|
|
|
5049
5414
|
};
|
|
5050
5415
|
visit(root);
|
|
5051
5416
|
}
|
|
5052
|
-
function
|
|
5417
|
+
function record3(value) {
|
|
5053
5418
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
5054
5419
|
}
|
|
5055
|
-
function
|
|
5056
|
-
const rel =
|
|
5057
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
5420
|
+
function within3(candidate, root) {
|
|
5421
|
+
const rel = relative6(root, candidate);
|
|
5422
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute6(rel);
|
|
5058
5423
|
}
|
|
5059
5424
|
function readJsonFile2(path, label, fallback = {}) {
|
|
5060
|
-
if (!
|
|
5061
|
-
const stat =
|
|
5425
|
+
if (!existsSync10(path)) return fallback;
|
|
5426
|
+
const stat = lstatSync6(path);
|
|
5062
5427
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
5063
5428
|
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
5064
5429
|
}
|
|
5065
5430
|
try {
|
|
5066
|
-
return JSON.parse(
|
|
5431
|
+
return JSON.parse(readFileSync8(path, "utf8"));
|
|
5067
5432
|
} catch {
|
|
5068
5433
|
throw new Error(`pi_trusted_runtime_source_invalid:${label}`);
|
|
5069
5434
|
}
|
|
@@ -5091,32 +5456,32 @@ function assertNoPersistentSecrets(value, path = []) {
|
|
|
5091
5456
|
}
|
|
5092
5457
|
}
|
|
5093
5458
|
function copyTreeNoLinks(source, target) {
|
|
5094
|
-
const stat =
|
|
5459
|
+
const stat = lstatSync6(source);
|
|
5095
5460
|
if (stat.isSymbolicLink()) throw new Error("pi_trusted_runtime_source_symlink_blocked");
|
|
5096
5461
|
if (stat.isDirectory()) {
|
|
5097
|
-
|
|
5098
|
-
|
|
5462
|
+
mkdirSync7(target, { recursive: true, mode: 448 });
|
|
5463
|
+
chmodSync5(target, 448);
|
|
5099
5464
|
for (const entry of readdirSync6(source)) {
|
|
5100
|
-
copyTreeNoLinks(
|
|
5465
|
+
copyTreeNoLinks(join11(source, entry), join11(target, entry));
|
|
5101
5466
|
}
|
|
5102
5467
|
return;
|
|
5103
5468
|
}
|
|
5104
5469
|
if (!stat.isFile()) throw new Error("pi_trusted_runtime_source_type_blocked");
|
|
5105
|
-
|
|
5470
|
+
mkdirSync7(dirname8(target), { recursive: true, mode: 448 });
|
|
5106
5471
|
copyFileSync2(source, target);
|
|
5107
|
-
|
|
5472
|
+
chmodSync5(target, 384 | stat.mode & 73);
|
|
5108
5473
|
}
|
|
5109
5474
|
function mergeMcp(seedRoot, overlayRoot, governedConfig) {
|
|
5110
|
-
const seed =
|
|
5111
|
-
const overlay =
|
|
5475
|
+
const seed = record3(readJsonFile2(join11(seedRoot, "mcp.json"), "seed_mcp", { mcpServers: {} }));
|
|
5476
|
+
const overlay = record3(readJsonFile2(join11(overlayRoot, "mcp.json"), "overlay_mcp", { mcpServers: {} }));
|
|
5112
5477
|
assertNoPersistentSecrets(seed, ["seed", "mcp.json"]);
|
|
5113
5478
|
assertNoPersistentSecrets(overlay, ["overlay", "mcp.json"]);
|
|
5114
|
-
const seedServers =
|
|
5115
|
-
const overlayServers =
|
|
5479
|
+
const seedServers = record3(seed.mcpServers);
|
|
5480
|
+
const overlayServers = record3(overlay.mcpServers);
|
|
5116
5481
|
if ("amaster" in seedServers || "amaster" in overlayServers) {
|
|
5117
5482
|
throw new Error("pi_trusted_runtime_reserved_mcp_override:amaster");
|
|
5118
5483
|
}
|
|
5119
|
-
const governed =
|
|
5484
|
+
const governed = record3(record3(governedConfig).mcpServers).amaster;
|
|
5120
5485
|
if (!governed) throw new Error("pi_trusted_runtime_governed_mcp_missing");
|
|
5121
5486
|
return {
|
|
5122
5487
|
...deepMerge(seed, overlay),
|
|
@@ -5136,14 +5501,14 @@ function assertEnabledPackagesAvailable(settings, npmRoot) {
|
|
|
5136
5501
|
const requiredNames = new Set(
|
|
5137
5502
|
(Array.isArray(settings.packages) ? settings.packages : []).map(packageName).filter(Boolean)
|
|
5138
5503
|
);
|
|
5139
|
-
for (const plugin of Object.values(
|
|
5140
|
-
const config =
|
|
5504
|
+
for (const plugin of Object.values(record3(settings.plugins))) {
|
|
5505
|
+
const config = record3(plugin);
|
|
5141
5506
|
if (config.enabled === true && typeof config.package === "string") {
|
|
5142
5507
|
requiredNames.add(config.package);
|
|
5143
5508
|
}
|
|
5144
5509
|
}
|
|
5145
5510
|
for (const name of requiredNames) {
|
|
5146
|
-
const metadataPath =
|
|
5511
|
+
const metadataPath = join11(npmRoot, "node_modules", ...name.split("/"), "package.json");
|
|
5147
5512
|
const metadata = readJsonFile2(metadataPath, `package:${name}`, null);
|
|
5148
5513
|
if (!metadata || metadata.name !== name) {
|
|
5149
5514
|
throw new Error(`pi_trusted_runtime_package_unavailable:${name}`);
|
|
@@ -5151,62 +5516,62 @@ function assertEnabledPackagesAvailable(settings, npmRoot) {
|
|
|
5151
5516
|
}
|
|
5152
5517
|
}
|
|
5153
5518
|
function materializeTrustedPiRuntimeProfile(input) {
|
|
5154
|
-
const seedRoot =
|
|
5155
|
-
const overlayRoot =
|
|
5156
|
-
const profileRoot =
|
|
5157
|
-
const agentDir =
|
|
5158
|
-
if (!
|
|
5519
|
+
const seedRoot = resolve9(requiredString3(input.seedRoot, "seedRoot"));
|
|
5520
|
+
const overlayRoot = resolve9(requiredString3(input.overlayRoot, "overlayRoot"));
|
|
5521
|
+
const profileRoot = resolve9(requiredString3(input.profileRoot, "profileRoot"));
|
|
5522
|
+
const agentDir = resolve9(requiredString3(input.agentDir, "agentDir"));
|
|
5523
|
+
if (!within3(agentDir, profileRoot)) throw new Error("pi_trusted_runtime_profile_path_escape");
|
|
5159
5524
|
for (const [root, label] of [[seedRoot, "seed_root"], [overlayRoot, "overlay_root"]]) {
|
|
5160
|
-
const stat =
|
|
5525
|
+
const stat = lstatSync6(root);
|
|
5161
5526
|
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
5162
5527
|
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
5163
5528
|
}
|
|
5164
5529
|
}
|
|
5165
5530
|
for (const entry of COPY_ENTRIES) {
|
|
5166
|
-
const target =
|
|
5167
|
-
|
|
5531
|
+
const target = join11(agentDir, entry);
|
|
5532
|
+
rmSync6(target, { recursive: true, force: true });
|
|
5168
5533
|
for (const sourceRoot of [seedRoot, overlayRoot]) {
|
|
5169
|
-
const source =
|
|
5170
|
-
if (
|
|
5534
|
+
const source = join11(sourceRoot, entry);
|
|
5535
|
+
if (existsSync10(source)) copyTreeNoLinks(source, target);
|
|
5171
5536
|
}
|
|
5172
5537
|
}
|
|
5173
5538
|
const mergedJson = {};
|
|
5174
5539
|
for (const entry of JSON_ENTRIES) {
|
|
5175
|
-
const seed = readJsonFile2(
|
|
5176
|
-
const overlay = readJsonFile2(
|
|
5540
|
+
const seed = readJsonFile2(join11(seedRoot, entry), `seed_${entry}`, {});
|
|
5541
|
+
const overlay = readJsonFile2(join11(overlayRoot, entry), `overlay_${entry}`, {});
|
|
5177
5542
|
const merged = deepMerge(seed, overlay);
|
|
5178
5543
|
if (entry === "settings.json") {
|
|
5179
5544
|
merged["pi-security"] = {
|
|
5180
|
-
...
|
|
5545
|
+
...record3(merged["pi-security"]),
|
|
5181
5546
|
enabled: true,
|
|
5182
5547
|
approvals: {
|
|
5183
|
-
...
|
|
5548
|
+
...record3(record3(merged["pi-security"]).approvals),
|
|
5184
5549
|
allowSessionGrants: false
|
|
5185
5550
|
}
|
|
5186
5551
|
};
|
|
5187
5552
|
}
|
|
5188
5553
|
assertNoPersistentSecrets(merged, [entry]);
|
|
5189
|
-
|
|
5554
|
+
writeFileSync7(join11(agentDir, entry), `${JSON.stringify(merged, null, 2)}
|
|
5190
5555
|
`, {
|
|
5191
5556
|
mode: 384
|
|
5192
5557
|
});
|
|
5193
|
-
|
|
5558
|
+
chmodSync5(join11(agentDir, entry), 384);
|
|
5194
5559
|
mergedJson[entry] = merged;
|
|
5195
5560
|
}
|
|
5196
5561
|
const governedConfig = readJsonFile2(input.governedMcpConfigPath, "governed_mcp");
|
|
5197
5562
|
const mcp = mergeMcp(seedRoot, overlayRoot, governedConfig);
|
|
5198
|
-
|
|
5563
|
+
writeFileSync7(input.governedMcpConfigPath, `${JSON.stringify(mcp, null, 2)}
|
|
5199
5564
|
`, { mode: 384 });
|
|
5200
|
-
|
|
5201
|
-
const npmRoot =
|
|
5565
|
+
chmodSync5(input.governedMcpConfigPath, 384);
|
|
5566
|
+
const npmRoot = join11(seedRoot, "npm");
|
|
5202
5567
|
assertEnabledPackagesAvailable(mergedJson["settings.json"], npmRoot);
|
|
5203
|
-
const npmTarget =
|
|
5204
|
-
|
|
5205
|
-
const npmStat =
|
|
5568
|
+
const npmTarget = join11(agentDir, "npm");
|
|
5569
|
+
rmSync6(npmTarget, { recursive: true, force: true });
|
|
5570
|
+
const npmStat = lstatSync6(npmRoot);
|
|
5206
5571
|
if (!npmStat.isDirectory() || npmStat.isSymbolicLink()) {
|
|
5207
5572
|
throw new Error("pi_trusted_runtime_source_unsafe:seed_npm");
|
|
5208
5573
|
}
|
|
5209
|
-
|
|
5574
|
+
symlinkSync3(npmRoot, npmTarget, "dir");
|
|
5210
5575
|
const facts = {
|
|
5211
5576
|
schemaVersion: "amaster.trusted-pi-profile.v1",
|
|
5212
5577
|
seedManifestDigest: input.verifiedAssertion.digests.seedManifestDigest,
|
|
@@ -5219,7 +5584,7 @@ function materializeTrustedPiRuntimeProfile(input) {
|
|
|
5219
5584
|
};
|
|
5220
5585
|
return {
|
|
5221
5586
|
facts,
|
|
5222
|
-
attestationId:
|
|
5587
|
+
attestationId: createHash7("sha256").update(JSON.stringify(facts)).digest("hex")
|
|
5223
5588
|
};
|
|
5224
5589
|
}
|
|
5225
5590
|
function assertAuditArgsRedacted(value) {
|
|
@@ -5242,16 +5607,16 @@ function assertAuditArgsRedacted(value) {
|
|
|
5242
5607
|
}
|
|
5243
5608
|
}
|
|
5244
5609
|
function readTrustedPiRuntimeAudit(input) {
|
|
5245
|
-
const profileRoot =
|
|
5246
|
-
const auditFile =
|
|
5247
|
-
if (!
|
|
5248
|
-
if (!
|
|
5249
|
-
const stat =
|
|
5610
|
+
const profileRoot = resolve9(requiredString3(input.profileRoot, "profileRoot"));
|
|
5611
|
+
const auditFile = resolve9(requiredString3(input.auditFile, "auditFile"));
|
|
5612
|
+
if (!within3(auditFile, profileRoot)) throw new Error("pi_trusted_runtime_audit_path_escape");
|
|
5613
|
+
if (!existsSync10(auditFile)) throw new Error("pi_trusted_runtime_audit_startup_missing");
|
|
5614
|
+
const stat = lstatSync6(auditFile);
|
|
5250
5615
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
5251
5616
|
throw new Error("pi_trusted_runtime_audit_unsafe");
|
|
5252
5617
|
}
|
|
5253
5618
|
if (stat.size > MAX_AUDIT_BYTES) throw new Error("pi_trusted_runtime_audit_too_large");
|
|
5254
|
-
const lines =
|
|
5619
|
+
const lines = readFileSync8(auditFile, "utf8").split("\n").filter(Boolean);
|
|
5255
5620
|
if (lines.length === 0 || lines.length > MAX_AUDIT_EVENTS) {
|
|
5256
5621
|
throw new Error("pi_trusted_runtime_audit_event_count_invalid");
|
|
5257
5622
|
}
|
|
@@ -5299,20 +5664,20 @@ function readTrustedPiRuntimeAudit(input) {
|
|
|
5299
5664
|
};
|
|
5300
5665
|
}
|
|
5301
5666
|
function readTrustedPiRuntimeLocalDigests(input) {
|
|
5302
|
-
const seedRoot =
|
|
5303
|
-
const overlayRoot =
|
|
5304
|
-
const policyFile =
|
|
5667
|
+
const seedRoot = resolve9(requiredString3(input.seedRoot, "seedRoot"));
|
|
5668
|
+
const overlayRoot = resolve9(requiredString3(input.overlayRoot, "overlayRoot"));
|
|
5669
|
+
const policyFile = resolve9(requiredString3(input.policyFile, "policyFile"));
|
|
5305
5670
|
for (const [path, label] of [[seedRoot, "seed_root"], [overlayRoot, "overlay_root"]]) {
|
|
5306
|
-
const stat =
|
|
5671
|
+
const stat = lstatSync6(path);
|
|
5307
5672
|
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
5308
5673
|
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
5309
5674
|
}
|
|
5310
5675
|
}
|
|
5311
|
-
const seedManifestFile =
|
|
5312
|
-
const overlayManifestFile =
|
|
5313
|
-
const seedManifest = JSON.parse(
|
|
5314
|
-
const overlayManifest = JSON.parse(
|
|
5315
|
-
const policyManifest = JSON.parse(
|
|
5676
|
+
const seedManifestFile = join11(seedRoot, "seed-manifest.json");
|
|
5677
|
+
const overlayManifestFile = join11(overlayRoot, "runtime-overlay-manifest.json");
|
|
5678
|
+
const seedManifest = JSON.parse(readFileSync8(seedManifestFile, "utf8"));
|
|
5679
|
+
const overlayManifest = JSON.parse(readFileSync8(overlayManifestFile, "utf8"));
|
|
5680
|
+
const policyManifest = JSON.parse(readFileSync8(policyFile, "utf8"));
|
|
5316
5681
|
verifyDeclaredFiles(seedManifest, seedRoot, "seed", [
|
|
5317
5682
|
"seed-manifest.json",
|
|
5318
5683
|
"npm/package-lock.json",
|
|
@@ -5321,9 +5686,9 @@ function readTrustedPiRuntimeLocalDigests(input) {
|
|
|
5321
5686
|
verifyDeclaredFiles(overlayManifest, overlayRoot, "overlay", ["runtime-overlay-manifest.json"]);
|
|
5322
5687
|
verifyDeclaredFiles(
|
|
5323
5688
|
policyManifest,
|
|
5324
|
-
|
|
5689
|
+
dirname8(policyFile),
|
|
5325
5690
|
"policy",
|
|
5326
|
-
[
|
|
5691
|
+
[relative6(dirname8(policyFile), policyFile)],
|
|
5327
5692
|
false
|
|
5328
5693
|
);
|
|
5329
5694
|
return {
|
|
@@ -5369,16 +5734,16 @@ function verifyTrustedPiRuntimeAssertion(input) {
|
|
|
5369
5734
|
leaseId: input.leaseId,
|
|
5370
5735
|
executorKind: input.executorKind
|
|
5371
5736
|
};
|
|
5372
|
-
|
|
5737
|
+
requiredString3(assertion.attestationId, "attestationId");
|
|
5373
5738
|
for (const [field, expected] of Object.entries(bindings)) {
|
|
5374
|
-
if (
|
|
5739
|
+
if (requiredString3(assertion[field], field) !== expected) {
|
|
5375
5740
|
throw new Error(`pi_trusted_runtime_assertion_binding_mismatch:${field}`);
|
|
5376
5741
|
}
|
|
5377
5742
|
}
|
|
5378
5743
|
if (assertion.executorKind !== "pi") {
|
|
5379
5744
|
throw new Error("pi_trusted_runtime_assertion_binding_mismatch:executorKind");
|
|
5380
5745
|
}
|
|
5381
|
-
const expiresAt = Date.parse(
|
|
5746
|
+
const expiresAt = Date.parse(requiredString3(assertion.expiresAt, "expiresAt"));
|
|
5382
5747
|
const now = input.now instanceof Date ? input.now : new Date(input.now ?? Date.now());
|
|
5383
5748
|
if (!Number.isFinite(expiresAt) || input.verifyExpiry !== false && expiresAt <= now.getTime()) {
|
|
5384
5749
|
throw new Error("pi_trusted_runtime_assertion_expired");
|
|
@@ -5415,9 +5780,9 @@ function verifyTrustedPiRuntimeAssertion(input) {
|
|
|
5415
5780
|
|
|
5416
5781
|
// src/amaster-runtime-daemon/workspace-status.mjs
|
|
5417
5782
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
5418
|
-
import { createHash as
|
|
5419
|
-
import { existsSync as
|
|
5420
|
-
import { basename as basename5, extname, isAbsolute as
|
|
5783
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
5784
|
+
import { existsSync as existsSync11, readdirSync as readdirSync7, readFileSync as readFileSync9, statSync as statSync6 } from "node:fs";
|
|
5785
|
+
import { basename as basename5, extname, isAbsolute as isAbsolute7, join as join12, relative as relative7, resolve as resolve10 } from "node:path";
|
|
5421
5786
|
var WORKSPACE_RUNTIME_SERVICES_FILENAME = ".amaster-runtime-services.json";
|
|
5422
5787
|
var ARTIFACT_EXTENSIONS = /* @__PURE__ */ new Map([
|
|
5423
5788
|
[".md", "markdown"],
|
|
@@ -5462,11 +5827,11 @@ var SAFE_RUNTIME_SERVICE_STATUSES = /* @__PURE__ */ new Set(["starting", "runnin
|
|
|
5462
5827
|
var SAFE_RUNTIME_SERVICE_HEALTH_STATUSES = /* @__PURE__ */ new Set(["unknown", "healthy", "unhealthy"]);
|
|
5463
5828
|
var SAFE_RUNTIME_SERVICE_LIFECYCLES = /* @__PURE__ */ new Set(["shared", "ephemeral"]);
|
|
5464
5829
|
function statusPathWithin(candidate, root) {
|
|
5465
|
-
const rel =
|
|
5466
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
5830
|
+
const rel = relative7(root, candidate);
|
|
5831
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute7(rel);
|
|
5467
5832
|
}
|
|
5468
5833
|
function normalizeRelativePath(root, filePath) {
|
|
5469
|
-
return
|
|
5834
|
+
return relative7(root, filePath).split(/[\\/]+/).join("/");
|
|
5470
5835
|
}
|
|
5471
5836
|
function isSafeRelativePath(value) {
|
|
5472
5837
|
const text = String(value ?? "").trim().split(/[\\/]+/).join("/");
|
|
@@ -5486,7 +5851,7 @@ function sanitizeTrackedChange(line) {
|
|
|
5486
5851
|
return isSafeRelativePath(path) ? line : null;
|
|
5487
5852
|
}
|
|
5488
5853
|
function sha256File2(filePath) {
|
|
5489
|
-
return
|
|
5854
|
+
return createHash8("sha256").update(readFileSync9(filePath)).digest("hex");
|
|
5490
5855
|
}
|
|
5491
5856
|
function artifactHashCacheKey(relativePath, stat) {
|
|
5492
5857
|
return `${relativePath}\0${stat.size}\0${stat.mtimeMs}`;
|
|
@@ -5514,7 +5879,7 @@ function artifactSha256(filePath, relativePath, stat, opts = {}) {
|
|
|
5514
5879
|
return hash;
|
|
5515
5880
|
}
|
|
5516
5881
|
function scanArtifactCandidates(cwd, opts = {}) {
|
|
5517
|
-
const root =
|
|
5882
|
+
const root = resolve10(cwd);
|
|
5518
5883
|
const maxCandidates = opts.maxCandidates ?? MAX_CANDIDATES;
|
|
5519
5884
|
const maxEntries = opts.maxEntries ?? MAX_SCAN_ENTRIES;
|
|
5520
5885
|
const candidates = [];
|
|
@@ -5535,7 +5900,7 @@ function scanArtifactCandidates(cwd, opts = {}) {
|
|
|
5535
5900
|
if (entry.name.startsWith(".") && entry.name !== ".amaster-runtime.json") {
|
|
5536
5901
|
if (entry.name === ".git") continue;
|
|
5537
5902
|
}
|
|
5538
|
-
const fullPath =
|
|
5903
|
+
const fullPath = join12(current, entry.name);
|
|
5539
5904
|
const relativePath = normalizeRelativePath(root, fullPath);
|
|
5540
5905
|
if (!isSafeRelativePath(relativePath)) continue;
|
|
5541
5906
|
if (basename5(relativePath) === ".amaster-runtime.json") continue;
|
|
@@ -5554,7 +5919,7 @@ function scanArtifactCandidates(cwd, opts = {}) {
|
|
|
5554
5919
|
} catch {
|
|
5555
5920
|
continue;
|
|
5556
5921
|
}
|
|
5557
|
-
if (!statusPathWithin(
|
|
5922
|
+
if (!statusPathWithin(resolve10(fullPath), root) || stat.size > MAX_HASH_BYTES) continue;
|
|
5558
5923
|
candidates.push({
|
|
5559
5924
|
relativePath,
|
|
5560
5925
|
name: basename5(fullPath),
|
|
@@ -5614,10 +5979,10 @@ function sanitizeRuntimeService(entry) {
|
|
|
5614
5979
|
};
|
|
5615
5980
|
}
|
|
5616
5981
|
function readRuntimeServicesSnapshot(cwd) {
|
|
5617
|
-
const snapshotPath =
|
|
5618
|
-
if (!
|
|
5982
|
+
const snapshotPath = join12(resolve10(cwd), WORKSPACE_RUNTIME_SERVICES_FILENAME);
|
|
5983
|
+
if (!existsSync11(snapshotPath)) return [];
|
|
5619
5984
|
try {
|
|
5620
|
-
const parsed = JSON.parse(
|
|
5985
|
+
const parsed = JSON.parse(readFileSync9(snapshotPath, "utf8"));
|
|
5621
5986
|
const rawServices = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.services) ? parsed.services : [];
|
|
5622
5987
|
return rawServices.map((entry) => sanitizeRuntimeService(entry)).filter((entry) => entry !== null).slice(0, 50);
|
|
5623
5988
|
} catch {
|
|
@@ -5688,7 +6053,7 @@ function readWorkspaceStatus(cwd, opts = {}) {
|
|
|
5688
6053
|
}
|
|
5689
6054
|
|
|
5690
6055
|
// src/amaster-runtime-daemon.mjs
|
|
5691
|
-
var CONNECTOR_VERSION = "0.1.0-beta.
|
|
6056
|
+
var CONNECTOR_VERSION = "0.1.0-beta.42";
|
|
5692
6057
|
var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
|
|
5693
6058
|
var MAX_CHECKPOINT_BYTES = 20 * 1024 * 1024;
|
|
5694
6059
|
var CHECKPOINT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -5736,11 +6101,11 @@ function updateActiveRunWorkspaceManifest(commandId, manifestPath, patch = {}) {
|
|
|
5736
6101
|
}
|
|
5737
6102
|
function resultOutboxPendingCount(config) {
|
|
5738
6103
|
const dir = resultOutboxDir(config);
|
|
5739
|
-
if (!
|
|
6104
|
+
if (!existsSync12(dir)) return 0;
|
|
5740
6105
|
try {
|
|
5741
6106
|
let pending = 0;
|
|
5742
6107
|
for (const file of readdirSync8(dir).filter((name) => name.endsWith(".json"))) {
|
|
5743
|
-
if (readValidResultOutboxEntryOrQuarantine(config, file,
|
|
6108
|
+
if (readValidResultOutboxEntryOrQuarantine(config, file, join13(dir, file))) {
|
|
5744
6109
|
pending += 1;
|
|
5745
6110
|
}
|
|
5746
6111
|
}
|
|
@@ -5756,11 +6121,11 @@ function piCompletionOutputType(event) {
|
|
|
5756
6121
|
}
|
|
5757
6122
|
function resultOutboxActiveRunCommands(config) {
|
|
5758
6123
|
const dir = resultOutboxDir(config);
|
|
5759
|
-
if (!
|
|
6124
|
+
if (!existsSync12(dir)) return [];
|
|
5760
6125
|
const outboxPending = resultOutboxPendingCount(config);
|
|
5761
6126
|
const entries = [];
|
|
5762
6127
|
for (const file of readdirSync8(dir).filter((name) => name.endsWith(".json")).sort()) {
|
|
5763
|
-
const entry = readValidResultOutboxEntryOrQuarantine(config, file,
|
|
6128
|
+
const entry = readValidResultOutboxEntryOrQuarantine(config, file, join13(dir, file));
|
|
5764
6129
|
if (!entry) continue;
|
|
5765
6130
|
const activeRun = asRecord(entry.activeRun);
|
|
5766
6131
|
const commandId = readString(activeRun.commandId) ?? readString(entry.commandId);
|
|
@@ -5790,12 +6155,12 @@ function resultOutboxActiveRunCommands(config) {
|
|
|
5790
6155
|
}
|
|
5791
6156
|
function resultOutboxFailedRunCommands(config) {
|
|
5792
6157
|
const dir = resultOutboxInvalidDir(config);
|
|
5793
|
-
if (!
|
|
6158
|
+
if (!existsSync12(dir)) return [];
|
|
5794
6159
|
const entries = [];
|
|
5795
6160
|
for (const file of readdirSync8(dir).filter((name) => name.endsWith(".json")).sort().slice(-100)) {
|
|
5796
6161
|
let entry;
|
|
5797
6162
|
try {
|
|
5798
|
-
entry = asRecord(JSON.parse(
|
|
6163
|
+
entry = asRecord(JSON.parse(readFileSync10(join13(dir, file), "utf8")));
|
|
5799
6164
|
} catch {
|
|
5800
6165
|
continue;
|
|
5801
6166
|
}
|
|
@@ -5855,11 +6220,11 @@ function piExtraArgsDiagnostics(value) {
|
|
|
5855
6220
|
}
|
|
5856
6221
|
function safeExpandPath(value) {
|
|
5857
6222
|
const text = readString(value);
|
|
5858
|
-
return text ?
|
|
6223
|
+
return text ? resolve11(expandHomePath(text)) : null;
|
|
5859
6224
|
}
|
|
5860
6225
|
function safeJsonObjectFromFile(filePath) {
|
|
5861
6226
|
try {
|
|
5862
|
-
const parsed = JSON.parse(
|
|
6227
|
+
const parsed = JSON.parse(readFileSync10(filePath, "utf8"));
|
|
5863
6228
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
5864
6229
|
} catch {
|
|
5865
6230
|
return null;
|
|
@@ -5902,10 +6267,10 @@ function safeSkillRootSummary(kind, source, pathValue) {
|
|
|
5902
6267
|
try {
|
|
5903
6268
|
for (const name of readdirSync8(pathValue)) {
|
|
5904
6269
|
if (name.startsWith(".")) continue;
|
|
5905
|
-
const skillDir =
|
|
6270
|
+
const skillDir = join13(pathValue, name);
|
|
5906
6271
|
try {
|
|
5907
6272
|
if (!statSync7(skillDir).isDirectory()) continue;
|
|
5908
|
-
if (!
|
|
6273
|
+
if (!existsSync12(join13(skillDir, "SKILL.md"))) continue;
|
|
5909
6274
|
skillCount += 1;
|
|
5910
6275
|
if (skillCount >= MAX_PI_CAPABILITY_SOURCE_ENTRIES) {
|
|
5911
6276
|
truncated = true;
|
|
@@ -5956,7 +6321,7 @@ function objectKeyCount(value) {
|
|
|
5956
6321
|
return value && typeof value === "object" && !Array.isArray(value) ? Object.keys(value).length : 0;
|
|
5957
6322
|
}
|
|
5958
6323
|
function defaultPiCodingAgentDir() {
|
|
5959
|
-
return
|
|
6324
|
+
return join13(homedir3(), ".pi", "agent");
|
|
5960
6325
|
}
|
|
5961
6326
|
function piCapabilitySourcesDiagnostics() {
|
|
5962
6327
|
const configuredPiCodingAgentDir = safeExpandPath(process.env.PI_CODING_AGENT_DIR);
|
|
@@ -5965,11 +6330,11 @@ function piCapabilitySourcesDiagnostics() {
|
|
|
5965
6330
|
const configuredPiAgentHome = safeExpandPath(process.env.PI_AGENT_HOME);
|
|
5966
6331
|
const piAgentHome = configuredPiAgentHome ?? piCodingAgentDir;
|
|
5967
6332
|
const piAgentHomeSource = configuredPiAgentHome ? "PI_AGENT_HOME" : piCodingAgentDirSource;
|
|
5968
|
-
const userSkillsPath = piAgentHome ?
|
|
5969
|
-
const marketplaceSkillsPath = safeExpandPath(process.env.PI_AGENT_MARKETPLACE_SKILLS_DIR) ?? (piAgentHome ?
|
|
6333
|
+
const userSkillsPath = piAgentHome ? join13(piAgentHome, "skills") : null;
|
|
6334
|
+
const marketplaceSkillsPath = safeExpandPath(process.env.PI_AGENT_MARKETPLACE_SKILLS_DIR) ?? (piAgentHome ? join13(piAgentHome, "marketplace", "skills") : null);
|
|
5970
6335
|
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 ?
|
|
6336
|
+
const mcpConfigPath = safeExpandPath(process.env.PI_AGENT_MCP_SERVERS_FILE) ?? (piAgentHome ? join13(piAgentHome, "mcp.json") : null);
|
|
6337
|
+
const settingsConfigPath = piCodingAgentDir ? join13(piCodingAgentDir, "settings.json") : null;
|
|
5973
6338
|
const skillRoots = [
|
|
5974
6339
|
safeSkillRootSummary("user", `${piAgentHomeSource}/skills`, userSkillsPath),
|
|
5975
6340
|
safeSkillRootSummary(
|
|
@@ -6200,13 +6565,13 @@ function piAgentLocalPlatformRunnerEnabled(config) {
|
|
|
6200
6565
|
}
|
|
6201
6566
|
function piAgentSystemDataDir(config) {
|
|
6202
6567
|
const configured = readString(config.AMASTER_PI_AGENT_SYSTEM_DATA_DIR ?? process.env.AMASTER_PI_AGENT_SYSTEM_DATA_DIR);
|
|
6203
|
-
return configured ?
|
|
6568
|
+
return configured ? resolve11(expandHomePath(configured)) : null;
|
|
6204
6569
|
}
|
|
6205
6570
|
function readPiAgentLocalPlatformCredential(credentialsDir) {
|
|
6206
|
-
const pointer = readJsonFile3(
|
|
6571
|
+
const pointer = readJsonFile3(join13(credentialsDir, "latest.json"));
|
|
6207
6572
|
const credentialRef = readString(pointer.credentialRef);
|
|
6208
6573
|
if (!credentialRef || !/^[a-f0-9]{64}$/i.test(credentialRef)) return null;
|
|
6209
|
-
const credential = readJsonFile3(
|
|
6574
|
+
const credential = readJsonFile3(join13(credentialsDir, `${credentialRef}.json`));
|
|
6210
6575
|
const organizationId = readString(credential.organizationId);
|
|
6211
6576
|
const apiKey = readString(credential.apiKey);
|
|
6212
6577
|
if (credential.version !== 1 || !organizationId || !apiKey) return null;
|
|
@@ -6222,7 +6587,7 @@ function piAgentLocalPlatformCredentials(config) {
|
|
|
6222
6587
|
if (!piAgentLocalPlatformRunnerEnabled(config)) return [];
|
|
6223
6588
|
const systemDataDir = piAgentSystemDataDir(config);
|
|
6224
6589
|
if (!systemDataDir) return [];
|
|
6225
|
-
const companiesDir =
|
|
6590
|
+
const companiesDir = join13(systemDataDir, "companies");
|
|
6226
6591
|
let entries = [];
|
|
6227
6592
|
try {
|
|
6228
6593
|
entries = readdirSync8(companiesDir, { withFileTypes: true });
|
|
@@ -6232,7 +6597,7 @@ function piAgentLocalPlatformCredentials(config) {
|
|
|
6232
6597
|
const credentialsByOrganizationId = /* @__PURE__ */ new Map();
|
|
6233
6598
|
for (const entry of entries) {
|
|
6234
6599
|
if (!entry.isDirectory()) continue;
|
|
6235
|
-
const credential = readPiAgentLocalPlatformCredential(
|
|
6600
|
+
const credential = readPiAgentLocalPlatformCredential(join13(companiesDir, entry.name, "model-credentials"));
|
|
6236
6601
|
if (credential) credentialsByOrganizationId.set(credential.organizationId, credential);
|
|
6237
6602
|
}
|
|
6238
6603
|
return [...credentialsByOrganizationId.values()];
|
|
@@ -6406,7 +6771,7 @@ AMASTER_WORKSPACE_ALLOWLIST=${quoteShell(config.workspaceBindings.join(","))}
|
|
|
6406
6771
|
AMASTER_EXECUTORS=${quoteShell(executorEnv)}
|
|
6407
6772
|
AMASTER_CAPABILITIES=${quoteShell(config.capabilities.join(","))}
|
|
6408
6773
|
AMASTER_NETWORK_DOMAINS=${quoteShell(config.networkDomains.join(","))}
|
|
6409
|
-
AMASTER_DAEMON_STATE_FILE=${quoteShell(
|
|
6774
|
+
AMASTER_DAEMON_STATE_FILE=${quoteShell(join13(homedir3(), ".amaster-employee", "runtime-connector-state.json"))}
|
|
6410
6775
|
EOF
|
|
6411
6776
|
|
|
6412
6777
|
set -a
|
|
@@ -6594,10 +6959,10 @@ function buildActiveRunCommandStatus(config, entry) {
|
|
|
6594
6959
|
const base = {
|
|
6595
6960
|
...entry,
|
|
6596
6961
|
phase: readString(entry.phase) ?? "executing",
|
|
6597
|
-
managedWorkdirPresent: entry.workspacePath ?
|
|
6962
|
+
managedWorkdirPresent: entry.workspacePath ? existsSync12(entry.workspacePath) : false,
|
|
6598
6963
|
outboxPending: resultOutboxPendingCount(config)
|
|
6599
6964
|
};
|
|
6600
|
-
if (!entry.workspacePath || !
|
|
6965
|
+
if (!entry.workspacePath || !existsSync12(entry.workspacePath)) return base;
|
|
6601
6966
|
const manifestPath = entry.manifestPath ?? workspaceManifestPath(entry.workspacePath);
|
|
6602
6967
|
const status = readWorkspaceStatus(entry.workspacePath, { hashCache: workspaceStatusHashCache });
|
|
6603
6968
|
const artifactCandidates = status.artifacts.slice(0, 20);
|
|
@@ -6778,7 +7143,7 @@ function trustedPiRuntimeSources(config) {
|
|
|
6778
7143
|
}
|
|
6779
7144
|
function readJsonFile3(filePath) {
|
|
6780
7145
|
try {
|
|
6781
|
-
const parsed = JSON.parse(
|
|
7146
|
+
const parsed = JSON.parse(readFileSync10(filePath, "utf8"));
|
|
6782
7147
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
6783
7148
|
} catch {
|
|
6784
7149
|
return {};
|
|
@@ -6847,11 +7212,11 @@ function safeAgentInstructionMaterializationTarget(workspace, filePath) {
|
|
|
6847
7212
|
const raw = readString(filePath);
|
|
6848
7213
|
if (!raw || raw.includes("\0")) return null;
|
|
6849
7214
|
const normalized = raw.replace(/\\/g, "/");
|
|
6850
|
-
if (
|
|
7215
|
+
if (isAbsolute8(normalized)) return null;
|
|
6851
7216
|
const segments = normalized.split("/").filter(Boolean);
|
|
6852
7217
|
if (segments.length === 0 || segments.some((segment) => segment === "." || segment === "..")) return null;
|
|
6853
7218
|
const relativePath = segments.join("/");
|
|
6854
|
-
const targetPath =
|
|
7219
|
+
const targetPath = resolve11(workspace.cwd, relativePath);
|
|
6855
7220
|
if (!pathWithin2(targetPath, workspace.cwd)) return null;
|
|
6856
7221
|
return { relativePath, targetPath };
|
|
6857
7222
|
}
|
|
@@ -6865,8 +7230,8 @@ async function materializeAgentInstructionsBundle(config, command, workspace) {
|
|
|
6865
7230
|
if (!content) continue;
|
|
6866
7231
|
const target = safeAgentInstructionMaterializationTarget(workspace, filePath);
|
|
6867
7232
|
if (!target) continue;
|
|
6868
|
-
|
|
6869
|
-
|
|
7233
|
+
mkdirSync8(dirname9(target.targetPath), { recursive: true });
|
|
7234
|
+
writeFileSync8(target.targetPath, content, "utf8");
|
|
6870
7235
|
materialized.push({
|
|
6871
7236
|
path: target.relativePath,
|
|
6872
7237
|
byteSize: Buffer.byteLength(content, "utf8")
|
|
@@ -6916,6 +7281,7 @@ function buildCommandPrompt(command, workspace, materializedAttachments = [], op
|
|
|
6916
7281
|
commandId: command.commandId,
|
|
6917
7282
|
runId: commandRunId(command),
|
|
6918
7283
|
issueId: commandIssueId(command),
|
|
7284
|
+
currentDate: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
6919
7285
|
issueLine,
|
|
6920
7286
|
cwd,
|
|
6921
7287
|
managed: workspaceContext.managed,
|
|
@@ -6930,25 +7296,18 @@ function buildCommandPrompt(command, workspace, materializedAttachments = [], op
|
|
|
6930
7296
|
nativeSession: asRecord(payload.nativeSession)
|
|
6931
7297
|
});
|
|
6932
7298
|
}
|
|
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
7299
|
function companyPiHomeRoot(baseEnv) {
|
|
6942
7300
|
const explicitRoot = readString(baseEnv.AMASTER_COMPANY_PI_HOME_ROOT);
|
|
6943
|
-
if (explicitRoot) return
|
|
7301
|
+
if (explicitRoot) return resolve11(expandHomePath(explicitRoot));
|
|
6944
7302
|
const configuredPiHome = readString(baseEnv.PI_AGENT_HOME) ?? readString(baseEnv.PI_CODING_AGENT_DIR);
|
|
6945
|
-
if (configuredPiHome) return
|
|
6946
|
-
return
|
|
7303
|
+
if (configuredPiHome) return join13(dirname9(resolve11(expandHomePath(configuredPiHome))), "companies");
|
|
7304
|
+
return join13(homedir3(), ".amaster-employee", "companies");
|
|
6947
7305
|
}
|
|
6948
7306
|
function companyPiAgentHome(baseEnv, companyId) {
|
|
6949
|
-
const
|
|
6950
|
-
if (!
|
|
6951
|
-
|
|
7307
|
+
const rawCompanyId = readString(companyId);
|
|
7308
|
+
if (!rawCompanyId) return null;
|
|
7309
|
+
const segment = safeCompanyPiHomeSegment(rawCompanyId);
|
|
7310
|
+
return join13(companyPiHomeRoot(baseEnv), segment, ".pi");
|
|
6952
7311
|
}
|
|
6953
7312
|
function commandUsesPiExecutor(command) {
|
|
6954
7313
|
return readString(asRecord(command.payload).executorKind) === "pi";
|
|
@@ -7017,7 +7376,7 @@ function resolveNativeSessionRequest(command, workspace) {
|
|
|
7017
7376
|
try {
|
|
7018
7377
|
cwdMatched = realpathSync3(requestedCwd) === realpathSync3(sourceWorkspacePath);
|
|
7019
7378
|
} catch {
|
|
7020
|
-
cwdMatched =
|
|
7379
|
+
cwdMatched = resolve11(requestedCwd) === resolve11(sourceWorkspacePath);
|
|
7021
7380
|
}
|
|
7022
7381
|
}
|
|
7023
7382
|
const used = Boolean(enabled && requested && sessionId && requestedCwd && cwdMatched);
|
|
@@ -7216,6 +7575,7 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
|
|
|
7216
7575
|
let nonProgressEventCount = 0;
|
|
7217
7576
|
let unparsedLineCount = 0;
|
|
7218
7577
|
let lastPiAgentMessage = null;
|
|
7578
|
+
let piTerminalOutput = null;
|
|
7219
7579
|
let executorSessionId = null;
|
|
7220
7580
|
const liveMcpToolResults = [];
|
|
7221
7581
|
let queue = Promise.resolve();
|
|
@@ -7299,9 +7659,20 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
|
|
|
7299
7659
|
const text = redactProtectedText(line, protectedValues).trim();
|
|
7300
7660
|
if (!text) return;
|
|
7301
7661
|
const event = stream === "stdout" ? parseJsonLine(text) : null;
|
|
7302
|
-
|
|
7662
|
+
const eventType = readString(asRecord(event).type);
|
|
7663
|
+
if (executorKind === "pi" && eventType === "session") {
|
|
7303
7664
|
executorSessionId = readString(asRecord(event).sessionId ?? asRecord(event).id) ?? executorSessionId;
|
|
7304
7665
|
}
|
|
7666
|
+
if (executorKind === "pi" && (["message_end", "turn_end", "agent_end"].includes(eventType ?? "") || eventType === "message_update" && readString(asRecord(asRecord(event).assistantMessageEvent).type) === "text_end")) {
|
|
7667
|
+
const parsedTerminalOutput = parsePiJsonl(text);
|
|
7668
|
+
if (parsedTerminalOutput.hasAssistantOutput && readString(parsedTerminalOutput.summary)) {
|
|
7669
|
+
piTerminalOutput = {
|
|
7670
|
+
summary: parsedTerminalOutput.summary,
|
|
7671
|
+
usage: parsedTerminalOutput.usage,
|
|
7672
|
+
hasAssistantOutput: true
|
|
7673
|
+
};
|
|
7674
|
+
}
|
|
7675
|
+
}
|
|
7305
7676
|
if (["codex", "pi"].includes(executorKind) && event) {
|
|
7306
7677
|
const results = executorKind === "codex" ? codexMcpToolResults(event) : piMcpToolResults(event);
|
|
7307
7678
|
liveMcpToolResults.push(...results);
|
|
@@ -7340,6 +7711,12 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
|
|
|
7340
7711
|
mcpToolResults() {
|
|
7341
7712
|
return [...liveMcpToolResults];
|
|
7342
7713
|
},
|
|
7714
|
+
terminalOutput() {
|
|
7715
|
+
return piTerminalOutput ? {
|
|
7716
|
+
...piTerminalOutput,
|
|
7717
|
+
usage: { ...piTerminalOutput.usage }
|
|
7718
|
+
} : null;
|
|
7719
|
+
},
|
|
7343
7720
|
write(stream, chunk) {
|
|
7344
7721
|
const key = stream === "stderr" ? "stderr" : "stdout";
|
|
7345
7722
|
sourceCounts[key] += 1;
|
|
@@ -7444,10 +7821,10 @@ function realOrResolvedPath(value) {
|
|
|
7444
7821
|
try {
|
|
7445
7822
|
return realpathSync3(value);
|
|
7446
7823
|
} catch {
|
|
7447
|
-
return
|
|
7824
|
+
return resolve11(value);
|
|
7448
7825
|
}
|
|
7449
7826
|
}
|
|
7450
|
-
var LSOF_COMMAND = process.platform === "darwin" &&
|
|
7827
|
+
var LSOF_COMMAND = process.platform === "darwin" && existsSync12("/usr/sbin/lsof") ? "/usr/sbin/lsof" : "lsof";
|
|
7451
7828
|
function processCwdForPid(pid) {
|
|
7452
7829
|
if (process.platform === "linux") {
|
|
7453
7830
|
try {
|
|
@@ -7569,7 +7946,7 @@ function killWorkspaceResidentProcesses(cwd, processGroupId, options = {}) {
|
|
|
7569
7946
|
}
|
|
7570
7947
|
function walkManagedWorkdirs(root) {
|
|
7571
7948
|
const workdirs = [];
|
|
7572
|
-
if (!root || !
|
|
7949
|
+
if (!root || !existsSync12(root)) return workdirs;
|
|
7573
7950
|
const stack = [root];
|
|
7574
7951
|
while (stack.length > 0) {
|
|
7575
7952
|
const current = stack.pop();
|
|
@@ -7582,8 +7959,8 @@ function walkManagedWorkdirs(root) {
|
|
|
7582
7959
|
}
|
|
7583
7960
|
for (const entry of entries) {
|
|
7584
7961
|
if (!entry.isDirectory()) continue;
|
|
7585
|
-
const fullPath =
|
|
7586
|
-
if (entry.name === "workdir" &&
|
|
7962
|
+
const fullPath = join13(current, entry.name);
|
|
7963
|
+
if (entry.name === "workdir" && existsSync12(workspaceManifestPath(fullPath))) {
|
|
7587
7964
|
workdirs.push(fullPath);
|
|
7588
7965
|
continue;
|
|
7589
7966
|
}
|
|
@@ -7621,8 +7998,8 @@ function manifestMatchesActiveRuntimeRef(manifest, refs, workdir = null) {
|
|
|
7621
7998
|
}
|
|
7622
7999
|
function buildOrphanReaperSample(root, workdir, manifest, residents) {
|
|
7623
8000
|
const relativeWorkdir = (() => {
|
|
7624
|
-
const value =
|
|
7625
|
-
return value && !value.startsWith("..") && !
|
|
8001
|
+
const value = relative8(root, workdir);
|
|
8002
|
+
return value && !value.startsWith("..") && !isAbsolute8(value) ? value : basename6(workdir);
|
|
7626
8003
|
})();
|
|
7627
8004
|
return {
|
|
7628
8005
|
workdir: relativeWorkdir,
|
|
@@ -7725,12 +8102,13 @@ function runExecutor(command, args, options) {
|
|
|
7725
8102
|
const maxOutputBytes = parsePositiveInteger(options.maxOutputBytes, 50 * 1024 * 1024);
|
|
7726
8103
|
const maxRssMb = parsePositiveInteger(options.maxRssMb, 0);
|
|
7727
8104
|
const maxRssBytes = maxRssMb * 1024 * 1024;
|
|
7728
|
-
const
|
|
8105
|
+
const spawnInvocation = managedChildSpawnInvocation(command, args, options.spawnIdentity);
|
|
8106
|
+
const child = spawn(spawnInvocation.command, spawnInvocation.args, {
|
|
7729
8107
|
cwd: options.cwd,
|
|
7730
8108
|
env: options.env,
|
|
7731
8109
|
detached: process.platform !== "win32",
|
|
7732
8110
|
stdio: options.managedInput ? ["pipe", "pipe", "pipe", "pipe"] : ["pipe", "pipe", "pipe"],
|
|
7733
|
-
...
|
|
8111
|
+
...spawnInvocation.spawnIdentity
|
|
7734
8112
|
});
|
|
7735
8113
|
const processGroupId = processGroupIdForChild(child);
|
|
7736
8114
|
const finish = (result2) => {
|
|
@@ -8012,6 +8390,7 @@ async function ingestRuntimeArtifacts(config, command, cwd, mcpToolResults) {
|
|
|
8012
8390
|
if (!runId) throw new Error("Runtime Artifact ingest requires a correlated runId");
|
|
8013
8391
|
const uploads = prepareRuntimeArtifactUploads(cwd, mcpToolResults);
|
|
8014
8392
|
const receipts = [];
|
|
8393
|
+
const failures = [];
|
|
8015
8394
|
for (const upload of uploads) {
|
|
8016
8395
|
const path = `/api/amaster/runtime-connectors/${connectorId}/artifact-intents/${encodeURIComponent(upload.intentId)}/ingest`;
|
|
8017
8396
|
const sourcePathHeaders = /^[\x20-\x7e]+$/.test(upload.sourceRelativePath) ? { "x-amaster-artifact-source-path": upload.sourceRelativePath } : {
|
|
@@ -8025,8 +8404,13 @@ async function ingestRuntimeArtifacts(config, command, cwd, mcpToolResults) {
|
|
|
8025
8404
|
"x-amaster-artifact-manifest-id": upload.manifestId,
|
|
8026
8405
|
...sourcePathHeaders
|
|
8027
8406
|
}));
|
|
8028
|
-
|
|
8029
|
-
|
|
8407
|
+
const receiptStatus = readString(receipt.status);
|
|
8408
|
+
if (readString(receipt.intentId) !== upload.intentId || receiptStatus !== "finalized") {
|
|
8409
|
+
const error = new Error(`Runtime Artifact ${upload.intentId} was not finalized: ${JSON.stringify(receipt)}`);
|
|
8410
|
+
if (receiptStatus === "rejected") {
|
|
8411
|
+
error.code = "runtime_artifact_rejected";
|
|
8412
|
+
}
|
|
8413
|
+
throw error;
|
|
8030
8414
|
}
|
|
8031
8415
|
receipts.push(receipt);
|
|
8032
8416
|
await ingestLog(config, command, "system", "info", `Finalized Runtime Artifact ${upload.sourceRelativePath}`, {
|
|
@@ -8042,7 +8426,12 @@ async function ingestRuntimeArtifacts(config, command, cwd, mcpToolResults) {
|
|
|
8042
8426
|
});
|
|
8043
8427
|
} catch (err) {
|
|
8044
8428
|
const message = `Runtime Artifact ${upload.intentId} ingest failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
8429
|
+
const failure = new Error(message, err instanceof Error ? { cause: err } : void 0);
|
|
8430
|
+
if (err instanceof Error && err.code === "runtime_artifact_rejected") {
|
|
8431
|
+
failure.code = "runtime_artifact_rejected";
|
|
8432
|
+
}
|
|
8045
8433
|
await ingestLog(config, command, "system", "error", message, {
|
|
8434
|
+
event: "runtime_artifact_ingest_failed",
|
|
8046
8435
|
presentationKind: "runtime_artifact_ingest",
|
|
8047
8436
|
intentId: upload.intentId,
|
|
8048
8437
|
manifestId: upload.manifestId,
|
|
@@ -8051,9 +8440,12 @@ async function ingestRuntimeArtifacts(config, command, cwd, mcpToolResults) {
|
|
|
8051
8440
|
byteSize: upload.byteSize,
|
|
8052
8441
|
status: "failed"
|
|
8053
8442
|
});
|
|
8054
|
-
|
|
8443
|
+
failures.push(failure);
|
|
8055
8444
|
}
|
|
8056
8445
|
}
|
|
8446
|
+
if (failures.length > 0) {
|
|
8447
|
+
throw new RuntimeArtifactIngestAggregateError(failures, receipts);
|
|
8448
|
+
}
|
|
8057
8449
|
return receipts;
|
|
8058
8450
|
}
|
|
8059
8451
|
function resultOutboxActiveRunSnapshot(command) {
|
|
@@ -8106,15 +8498,15 @@ async function completeCommand(config, command, status, result2, error) {
|
|
|
8106
8498
|
}
|
|
8107
8499
|
function resultOutboxDir(config) {
|
|
8108
8500
|
const explicit = readString(process.env.AMASTER_RESULT_OUTBOX_DIR);
|
|
8109
|
-
if (explicit) return
|
|
8110
|
-
return
|
|
8501
|
+
if (explicit) return resolve11(expandHomePath(explicit));
|
|
8502
|
+
return join13(dirname9(stateFilePath(process.env)), "result-outbox");
|
|
8111
8503
|
}
|
|
8112
8504
|
function resultOutboxInvalidDir(config) {
|
|
8113
|
-
return
|
|
8505
|
+
return join13(resultOutboxDir(config), "invalid");
|
|
8114
8506
|
}
|
|
8115
8507
|
function writeResultOutboxEntry(config, entry) {
|
|
8116
8508
|
const dir = resultOutboxDir(config);
|
|
8117
|
-
|
|
8509
|
+
mkdirSync8(dir, { recursive: true });
|
|
8118
8510
|
const body = {
|
|
8119
8511
|
version: 1,
|
|
8120
8512
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -8122,16 +8514,16 @@ function writeResultOutboxEntry(config, entry) {
|
|
|
8122
8514
|
lastAttemptAt: null,
|
|
8123
8515
|
...entry
|
|
8124
8516
|
};
|
|
8125
|
-
|
|
8517
|
+
writeFileSync8(join13(dir, resultOutboxFileName(entry.commandId)), `${JSON.stringify(body, null, 2)}
|
|
8126
8518
|
`, { mode: 384 });
|
|
8127
8519
|
}
|
|
8128
8520
|
function moveResultOutboxEntryToInvalid(config, file, fullPath, reason, detail, original) {
|
|
8129
8521
|
const invalidDir = resultOutboxInvalidDir(config);
|
|
8130
|
-
|
|
8131
|
-
const invalidPath =
|
|
8522
|
+
mkdirSync8(invalidDir, { recursive: true });
|
|
8523
|
+
const invalidPath = join13(invalidDir, file);
|
|
8132
8524
|
if (original === void 0) {
|
|
8133
8525
|
try {
|
|
8134
|
-
|
|
8526
|
+
renameSync5(fullPath, invalidPath);
|
|
8135
8527
|
} catch {
|
|
8136
8528
|
copyFileSync3(fullPath, invalidPath);
|
|
8137
8529
|
unlinkSync(fullPath);
|
|
@@ -8144,14 +8536,14 @@ function moveResultOutboxEntryToInvalid(config, file, fullPath, reason, detail,
|
|
|
8144
8536
|
...detail ? { detail: truncateText(detail, 1e3) } : {},
|
|
8145
8537
|
original
|
|
8146
8538
|
};
|
|
8147
|
-
|
|
8539
|
+
writeFileSync8(invalidPath, `${JSON.stringify(evidence, null, 2)}
|
|
8148
8540
|
`, { mode: 384 });
|
|
8149
8541
|
unlinkSync(fullPath);
|
|
8150
8542
|
}
|
|
8151
8543
|
function readValidResultOutboxEntryOrQuarantine(config, file, fullPath) {
|
|
8152
8544
|
let entry;
|
|
8153
8545
|
try {
|
|
8154
|
-
entry = JSON.parse(
|
|
8546
|
+
entry = JSON.parse(readFileSync10(fullPath, "utf8"));
|
|
8155
8547
|
} catch (err) {
|
|
8156
8548
|
const message = err instanceof Error ? err.message : String(err);
|
|
8157
8549
|
moveResultOutboxEntryToInvalid(config, file, fullPath, "malformed_result_outbox_json", message);
|
|
@@ -8181,13 +8573,13 @@ function updateResultOutboxAttempt(fullPath, entry, err) {
|
|
|
8181
8573
|
...typeof err?.httpStatus === "number" ? { httpStatus: err.httpStatus } : {},
|
|
8182
8574
|
lastError: truncateText(err instanceof Error ? err.message : String(err), 1e3)
|
|
8183
8575
|
};
|
|
8184
|
-
|
|
8576
|
+
writeFileSync8(fullPath, `${JSON.stringify(next, null, 2)}
|
|
8185
8577
|
`, { mode: 384 });
|
|
8186
8578
|
return next;
|
|
8187
8579
|
}
|
|
8188
8580
|
function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err) {
|
|
8189
8581
|
const invalidDir = resultOutboxInvalidDir(config);
|
|
8190
|
-
|
|
8582
|
+
mkdirSync8(invalidDir, { recursive: true });
|
|
8191
8583
|
const body = {
|
|
8192
8584
|
...entry,
|
|
8193
8585
|
invalidReason: reason,
|
|
@@ -8195,8 +8587,8 @@ function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err)
|
|
|
8195
8587
|
...typeof err?.httpStatus === "number" ? { httpStatus: err.httpStatus } : {},
|
|
8196
8588
|
lastError: truncateText(err instanceof Error ? err.message : String(err), 1e3)
|
|
8197
8589
|
};
|
|
8198
|
-
const invalidPath =
|
|
8199
|
-
|
|
8590
|
+
const invalidPath = join13(invalidDir, file);
|
|
8591
|
+
writeFileSync8(invalidPath, `${JSON.stringify(body, null, 2)}
|
|
8200
8592
|
`, { mode: 384 });
|
|
8201
8593
|
try {
|
|
8202
8594
|
unlinkSync(fullPath);
|
|
@@ -8209,11 +8601,11 @@ function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err)
|
|
|
8209
8601
|
}
|
|
8210
8602
|
async function flushResultOutbox(config) {
|
|
8211
8603
|
const dir = resultOutboxDir(config);
|
|
8212
|
-
if (!
|
|
8604
|
+
if (!existsSync12(dir)) return { attempted: 0, completed: 0 };
|
|
8213
8605
|
const files = readdirSync8(dir).filter((name) => name.endsWith(".json")).sort();
|
|
8214
8606
|
let completed = 0;
|
|
8215
8607
|
for (const file of files) {
|
|
8216
|
-
const fullPath =
|
|
8608
|
+
const fullPath = join13(dir, file);
|
|
8217
8609
|
const entry = readValidResultOutboxEntryOrQuarantine(config, file, fullPath);
|
|
8218
8610
|
if (!entry) continue;
|
|
8219
8611
|
try {
|
|
@@ -8410,8 +8802,8 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
8410
8802
|
runtimeAuth,
|
|
8411
8803
|
issueId
|
|
8412
8804
|
);
|
|
8413
|
-
const targetDir =
|
|
8414
|
-
|
|
8805
|
+
const targetDir = join13(workspace.cwd, "input-attachments");
|
|
8806
|
+
mkdirSync8(targetDir, { recursive: true });
|
|
8415
8807
|
const usedFilenames = /* @__PURE__ */ new Set();
|
|
8416
8808
|
const materialized = [];
|
|
8417
8809
|
for (const [index, rawAttachment] of attachments.entries()) {
|
|
@@ -8425,11 +8817,11 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
8425
8817
|
filename = `${stem}-${index + 1}${ext}`;
|
|
8426
8818
|
}
|
|
8427
8819
|
usedFilenames.add(filename);
|
|
8428
|
-
const targetPath =
|
|
8820
|
+
const targetPath = join13(targetDir, filename);
|
|
8429
8821
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
8430
|
-
|
|
8822
|
+
writeFileSync8(targetPath, body);
|
|
8431
8823
|
const attachmentId = readString(attachment.id);
|
|
8432
|
-
const actualSha256 =
|
|
8824
|
+
const actualSha256 = createHash9("sha256").update(body).digest("hex");
|
|
8433
8825
|
const lineageCandidates = lineageCandidatesByAttachmentId.get(attachmentId) ?? [];
|
|
8434
8826
|
const lineage = selectAttachmentLineage(lineageCandidates, actualSha256);
|
|
8435
8827
|
if (lineageCandidates.length > 0 && !lineage) {
|
|
@@ -8452,7 +8844,7 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
8452
8844
|
id: attachmentId,
|
|
8453
8845
|
name: readString(attachment.originalFilename) ?? filename,
|
|
8454
8846
|
path: targetPath,
|
|
8455
|
-
relativePath:
|
|
8847
|
+
relativePath: relative8(workspace.cwd, targetPath),
|
|
8456
8848
|
contentType: readString(attachment.contentType),
|
|
8457
8849
|
byteSize: body.byteLength,
|
|
8458
8850
|
contentPath,
|
|
@@ -8501,9 +8893,9 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
8501
8893
|
if (manifest.version !== 1 || !Array.isArray(manifest.entries)) {
|
|
8502
8894
|
throw new Error("artifact_input_manifest_invalid: expected version 1 entries array");
|
|
8503
8895
|
}
|
|
8504
|
-
const targetRoot =
|
|
8505
|
-
|
|
8506
|
-
|
|
8896
|
+
const targetRoot = join13(workspace.cwd, "input-artifacts");
|
|
8897
|
+
rmSync7(targetRoot, { recursive: true, force: true });
|
|
8898
|
+
mkdirSync8(targetRoot, { recursive: true });
|
|
8507
8899
|
const usedPaths = /* @__PURE__ */ new Set();
|
|
8508
8900
|
const materialized = [];
|
|
8509
8901
|
for (const [index, rawEntry] of manifest.entries.entries()) {
|
|
@@ -8521,7 +8913,7 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
8521
8913
|
throw new Error(`artifact_input_manifest_invalid: entry ${index} contentPath does not match attachmentId`);
|
|
8522
8914
|
}
|
|
8523
8915
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
8524
|
-
const actualSha256 =
|
|
8916
|
+
const actualSha256 = createHash9("sha256").update(body).digest("hex");
|
|
8525
8917
|
if (body.byteLength !== byteSize || actualSha256 !== sha256) {
|
|
8526
8918
|
throw new Error(
|
|
8527
8919
|
`artifact_input_integrity_mismatch: workProductId=${workProductId} expectedBytes=${byteSize} actualBytes=${body.byteLength} expectedSha256=${sha256} actualSha256=${actualSha256}`
|
|
@@ -8532,18 +8924,18 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
8532
8924
|
id: attachmentId,
|
|
8533
8925
|
originalFilename: readString(entry.originalFilename)
|
|
8534
8926
|
}, index);
|
|
8535
|
-
let relativePath =
|
|
8927
|
+
let relativePath = join13("input-artifacts", sourceDir, filename).split(/[\\/]+/).join("/");
|
|
8536
8928
|
if (usedPaths.has(relativePath)) {
|
|
8537
8929
|
const ext = extname2(filename);
|
|
8538
8930
|
const stem = ext ? filename.slice(0, -ext.length) : filename;
|
|
8539
8931
|
filename = `${stem}-${index + 1}${ext}`;
|
|
8540
|
-
relativePath =
|
|
8932
|
+
relativePath = join13("input-artifacts", sourceDir, filename).split(/[\\/]+/).join("/");
|
|
8541
8933
|
}
|
|
8542
8934
|
usedPaths.add(relativePath);
|
|
8543
|
-
const targetPath =
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
|
|
8935
|
+
const targetPath = join13(workspace.cwd, relativePath);
|
|
8936
|
+
mkdirSync8(dirname9(targetPath), { recursive: true });
|
|
8937
|
+
writeFileSync8(targetPath, body);
|
|
8938
|
+
chmodSync6(targetPath, 292);
|
|
8547
8939
|
materialized.push({
|
|
8548
8940
|
id: attachmentId,
|
|
8549
8941
|
workProductId,
|
|
@@ -8562,9 +8954,9 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
8562
8954
|
version: 1,
|
|
8563
8955
|
entries: materialized.map(({ path: _path, relativePath, ...entry }) => ({ ...entry, path: relativePath }))
|
|
8564
8956
|
};
|
|
8565
|
-
const manifestPath =
|
|
8566
|
-
|
|
8567
|
-
|
|
8957
|
+
const manifestPath = join13(targetRoot, "artifact-input-manifest.json");
|
|
8958
|
+
writeFileSync8(manifestPath, JSON.stringify(localManifest, null, 2) + "\n");
|
|
8959
|
+
chmodSync6(manifestPath, 292);
|
|
8568
8960
|
updateWorkspaceManifest(workspaceManifestPath(workspace), { artifactInputManifest: localManifest });
|
|
8569
8961
|
await ingestLog(config, command, "system", "info", `Materialized ${materialized.length} required artifact input(s) into the execution workspace`, {
|
|
8570
8962
|
artifactInputCount: materialized.length,
|
|
@@ -8573,46 +8965,46 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
8573
8965
|
return materialized;
|
|
8574
8966
|
}
|
|
8575
8967
|
function issueCheckpointDir(workspace) {
|
|
8576
|
-
return
|
|
8968
|
+
return join13(dirname9(workspace.runDir), "checkpoint");
|
|
8577
8969
|
}
|
|
8578
8970
|
async function clearIssueCheckpoint(config, command, workspace, reason) {
|
|
8579
8971
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
8580
|
-
if (!
|
|
8581
|
-
|
|
8972
|
+
if (!existsSync12(checkpointDir)) return false;
|
|
8973
|
+
rmSync7(checkpointDir, { recursive: true, force: true });
|
|
8582
8974
|
await ingestLog(config, command, "system", "info", "Cleared issue continuation checkpoint", { reason });
|
|
8583
8975
|
return true;
|
|
8584
8976
|
}
|
|
8585
8977
|
function safeCheckpointRelativePath(rawPath) {
|
|
8586
8978
|
const raw = String(rawPath ?? "").trim();
|
|
8587
|
-
if (
|
|
8979
|
+
if (isAbsolute8(raw) || /^[A-Za-z]:[\\/]/.test(raw)) return null;
|
|
8588
8980
|
const normalized = raw.split(/[\\/]+/).filter(Boolean).join("/");
|
|
8589
8981
|
if (!normalized || normalized.startsWith("../") || normalized.split("/").some((segment) => segment.startsWith("."))) return null;
|
|
8590
8982
|
if (normalized.startsWith("input-attachments/") || isRuntimeMetadataArtifactPath(normalized)) return null;
|
|
8591
8983
|
return normalized;
|
|
8592
8984
|
}
|
|
8593
8985
|
function hashFileSha256(filePath) {
|
|
8594
|
-
return
|
|
8986
|
+
return createHash9("sha256").update(readFileSync10(filePath)).digest("hex");
|
|
8595
8987
|
}
|
|
8596
8988
|
async function materializeIssueCheckpoint(config, command, workspace) {
|
|
8597
8989
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
8598
|
-
const manifestPath =
|
|
8599
|
-
if (!
|
|
8990
|
+
const manifestPath = join13(checkpointDir, "manifest.json");
|
|
8991
|
+
if (!existsSync12(manifestPath)) return [];
|
|
8600
8992
|
let manifest;
|
|
8601
8993
|
try {
|
|
8602
|
-
manifest = asRecord(JSON.parse(
|
|
8994
|
+
manifest = asRecord(JSON.parse(readFileSync10(manifestPath, "utf8")));
|
|
8603
8995
|
} catch (err) {
|
|
8604
|
-
|
|
8996
|
+
rmSync7(checkpointDir, { recursive: true, force: true });
|
|
8605
8997
|
throw new Error(`invalid issue checkpoint manifest: ${err instanceof Error ? err.message : String(err)}`);
|
|
8606
8998
|
}
|
|
8607
8999
|
const expiresAt = Date.parse(readString(manifest.expiresAt) ?? "");
|
|
8608
9000
|
if (!Number.isFinite(expiresAt) || expiresAt <= Date.now() || readString(manifest.issueId) !== commandIssueId(command)) {
|
|
8609
|
-
|
|
9001
|
+
rmSync7(checkpointDir, { recursive: true, force: true });
|
|
8610
9002
|
return [];
|
|
8611
9003
|
}
|
|
8612
9004
|
try {
|
|
8613
9005
|
const files = Array.isArray(manifest.files) ? manifest.files : [];
|
|
8614
9006
|
if (files.length > 20) throw new Error("issue checkpoint manifest exceeds the limit of 20 files");
|
|
8615
|
-
const filesRoot = realpathSync3(
|
|
9007
|
+
const filesRoot = realpathSync3(join13(checkpointDir, "files"));
|
|
8616
9008
|
const workspaceRoot = realpathSync3(workspace.cwd);
|
|
8617
9009
|
const validated = [];
|
|
8618
9010
|
let totalBytes = 0;
|
|
@@ -8620,12 +9012,12 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
8620
9012
|
const file = asRecord(rawFile);
|
|
8621
9013
|
const relativePath = safeCheckpointRelativePath(readString(file.path));
|
|
8622
9014
|
if (!relativePath) throw new Error("issue checkpoint manifest contains an invalid file path");
|
|
8623
|
-
const sourceCandidate =
|
|
8624
|
-
const target =
|
|
9015
|
+
const sourceCandidate = resolve11(filesRoot, relativePath);
|
|
9016
|
+
const target = resolve11(workspaceRoot, relativePath);
|
|
8625
9017
|
if (!pathWithin2(sourceCandidate, filesRoot) || !pathWithin2(target, workspaceRoot)) {
|
|
8626
9018
|
throw new Error(`issue checkpoint path escapes its workspace: ${relativePath}`);
|
|
8627
9019
|
}
|
|
8628
|
-
if (!
|
|
9020
|
+
if (!existsSync12(sourceCandidate)) throw new Error(`issue checkpoint file is missing: ${relativePath}`);
|
|
8629
9021
|
const source = realpathSync3(sourceCandidate);
|
|
8630
9022
|
if (!pathWithin2(source, filesRoot) || !statSync7(source).isFile()) {
|
|
8631
9023
|
throw new Error(`issue checkpoint source escapes its storage root: ${relativePath}`);
|
|
@@ -8645,13 +9037,13 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
8645
9037
|
const materialized = [];
|
|
8646
9038
|
for (const { relativePath, source, target } of validated) {
|
|
8647
9039
|
try {
|
|
8648
|
-
|
|
9040
|
+
lstatSync7(target);
|
|
8649
9041
|
continue;
|
|
8650
9042
|
} catch (err) {
|
|
8651
9043
|
if (err?.code !== "ENOENT") throw err;
|
|
8652
9044
|
}
|
|
8653
|
-
|
|
8654
|
-
const targetParent = realpathSync3(
|
|
9045
|
+
mkdirSync8(dirname9(target), { recursive: true });
|
|
9046
|
+
const targetParent = realpathSync3(dirname9(target));
|
|
8655
9047
|
if (!pathWithin2(targetParent, workspaceRoot)) {
|
|
8656
9048
|
throw new Error(`issue checkpoint target escapes its workspace: ${relativePath}`);
|
|
8657
9049
|
}
|
|
@@ -8679,31 +9071,31 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
8679
9071
|
}
|
|
8680
9072
|
async function saveIssueCheckpoint(config, command, workspace, candidates) {
|
|
8681
9073
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
8682
|
-
const filesDir =
|
|
8683
|
-
|
|
8684
|
-
|
|
9074
|
+
const filesDir = join13(checkpointDir, "files");
|
|
9075
|
+
rmSync7(checkpointDir, { recursive: true, force: true });
|
|
9076
|
+
mkdirSync8(filesDir, { recursive: true });
|
|
8685
9077
|
const files = [];
|
|
8686
9078
|
let totalBytes = 0;
|
|
8687
9079
|
const workspaceRoot = realpathSync3(workspace.cwd);
|
|
8688
9080
|
for (const candidate of candidates.slice(0, 20)) {
|
|
8689
9081
|
const relativePath = safeCheckpointRelativePath(candidate.rawPath);
|
|
8690
9082
|
const source = readString(candidate.filePath);
|
|
8691
|
-
if (!relativePath || !source || !
|
|
9083
|
+
if (!relativePath || !source || !existsSync12(source) || !statSync7(source).isFile()) continue;
|
|
8692
9084
|
const ownedSource = realpathSync3(source);
|
|
8693
9085
|
if (!pathWithin2(ownedSource, workspaceRoot)) {
|
|
8694
9086
|
throw new Error(`issue checkpoint source escapes its execution workspace: ${relativePath}`);
|
|
8695
9087
|
}
|
|
8696
9088
|
const byteSize = statSync7(ownedSource).size;
|
|
8697
9089
|
if (byteSize <= 0 || totalBytes + byteSize > MAX_CHECKPOINT_BYTES) continue;
|
|
8698
|
-
const target =
|
|
9090
|
+
const target = resolve11(filesDir, relativePath);
|
|
8699
9091
|
if (!pathWithin2(target, filesDir)) continue;
|
|
8700
|
-
|
|
9092
|
+
mkdirSync8(dirname9(target), { recursive: true });
|
|
8701
9093
|
copyFileSync3(ownedSource, target);
|
|
8702
9094
|
totalBytes += byteSize;
|
|
8703
9095
|
files.push({ path: relativePath, byteSize, sha256: hashFileSha256(ownedSource) });
|
|
8704
9096
|
}
|
|
8705
9097
|
if (files.length === 0) {
|
|
8706
|
-
|
|
9098
|
+
rmSync7(checkpointDir, { recursive: true, force: true });
|
|
8707
9099
|
return null;
|
|
8708
9100
|
}
|
|
8709
9101
|
const manifest = {
|
|
@@ -8715,7 +9107,7 @@ async function saveIssueCheckpoint(config, command, workspace, candidates) {
|
|
|
8715
9107
|
totalBytes,
|
|
8716
9108
|
files
|
|
8717
9109
|
};
|
|
8718
|
-
|
|
9110
|
+
writeFileSync8(join13(checkpointDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
8719
9111
|
`);
|
|
8720
9112
|
await ingestLog(config, command, "system", "warn", `Saved ${files.length} required deliverable(s) for continuation recovery`, manifest);
|
|
8721
9113
|
return manifest;
|
|
@@ -8789,44 +9181,20 @@ async function executeRunCommand(config, command) {
|
|
|
8789
9181
|
let cleanupManagedMcpProfile = null;
|
|
8790
9182
|
const providerProtectedValues = [];
|
|
8791
9183
|
let piChildIsolation = null;
|
|
9184
|
+
let piChildAssignmentAcquired = false;
|
|
9185
|
+
let piCompanyMemory = null;
|
|
8792
9186
|
let trustedPiRuntime = null;
|
|
8793
9187
|
let trustedPiRuntimeSourcePaths = null;
|
|
8794
9188
|
let trustedPiRuntimeProfile = null;
|
|
8795
9189
|
let trustedPiRuntimeAudit = null;
|
|
8796
9190
|
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({
|
|
9191
|
+
let forgetActiveRunCommand = () => {
|
|
9192
|
+
};
|
|
9193
|
+
let stopActiveRunHeartbeats = () => {
|
|
9194
|
+
};
|
|
9195
|
+
try {
|
|
9196
|
+
if (executor.kind === "codex" && Object.keys(governedMcp).length > 0) {
|
|
9197
|
+
managedMcpProfile = prepareManagedCodexMcpProfile({
|
|
8830
9198
|
commandId: command.commandId,
|
|
8831
9199
|
runId: commandRunId(command),
|
|
8832
9200
|
connectorVersion: CONNECTOR_VERSION,
|
|
@@ -8838,165 +9206,220 @@ async function executeRunCommand(config, command) {
|
|
|
8838
9206
|
nativeSession: asRecord(asRecord(command.payload).nativeSession),
|
|
8839
9207
|
baseEnv: executorEnv,
|
|
8840
9208
|
commandEnv: commandExecutorEnv(command),
|
|
8841
|
-
extraArgs: splitExtraArgs(process.env.
|
|
9209
|
+
extraArgs: splitExtraArgs(process.env.AMASTER_CODEX_EXTRA_ARGS)
|
|
8842
9210
|
});
|
|
8843
|
-
cleanupManagedMcpProfile =
|
|
8844
|
-
for (const protectedValue of providerProtectedValues) {
|
|
8845
|
-
if (!managedMcpProfile.protectedValues.includes(protectedValue)) {
|
|
8846
|
-
managedMcpProfile.protectedValues.push(protectedValue);
|
|
8847
|
-
}
|
|
8848
|
-
}
|
|
9211
|
+
cleanupManagedMcpProfile = cleanupManagedCodexMcpProfile;
|
|
8849
9212
|
}
|
|
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");
|
|
9213
|
+
if (executor.kind === "pi") {
|
|
9214
|
+
if (piAgentLocalPlatformRunnerEnabled(config)) {
|
|
9215
|
+
delete executorEnv.AMASTER_API_KEY;
|
|
9216
|
+
delete executorEnv.AMASTER_PROVIDER_BASE_URL;
|
|
9217
|
+
delete executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL;
|
|
9218
|
+
delete executorEnv.AMASTER_PROVIDER_FLASH_MODEL;
|
|
8864
9219
|
}
|
|
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");
|
|
9220
|
+
piResolvedProviderConfig = resolvePiExecutorProviderConfig(config, command, executorEnv);
|
|
9221
|
+
for (const envName of ["AMASTER_API_KEY", "AMASTER_PLATFORM_OAUTH_TOKEN"]) {
|
|
9222
|
+
const protectedValue = readString(piResolvedProviderConfig.providerConfig[envName]);
|
|
9223
|
+
if (protectedValue && !providerProtectedValues.includes(protectedValue)) {
|
|
9224
|
+
providerProtectedValues.push(protectedValue);
|
|
9225
|
+
}
|
|
8877
9226
|
}
|
|
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, {
|
|
9227
|
+
if (Object.keys(governedMcp).length > 0) {
|
|
9228
|
+
managedMcpProfile = prepareManagedPiMcpProfile({
|
|
8899
9229
|
commandId: command.commandId,
|
|
8900
|
-
runId: commandRunId(command)
|
|
9230
|
+
runId: commandRunId(command),
|
|
9231
|
+
connectorVersion: CONNECTOR_VERSION,
|
|
9232
|
+
executorCommand: invocation.command,
|
|
9233
|
+
executorHome: workspace.executorHome,
|
|
9234
|
+
runDir: workspace.runDir,
|
|
9235
|
+
cwd,
|
|
9236
|
+
runtimeAuth: commandRuntimeAuth(command),
|
|
9237
|
+
nativeSession: asRecord(asRecord(command.payload).nativeSession),
|
|
9238
|
+
baseEnv: executorEnv,
|
|
9239
|
+
commandEnv: commandExecutorEnv(command),
|
|
9240
|
+
extraArgs: splitExtraArgs(process.env.AMASTER_PI_EXTRA_ARGS)
|
|
8901
9241
|
});
|
|
9242
|
+
cleanupManagedMcpProfile = cleanupManagedPiMcpProfile;
|
|
9243
|
+
for (const protectedValue of providerProtectedValues) {
|
|
9244
|
+
if (!managedMcpProfile.protectedValues.includes(protectedValue)) {
|
|
9245
|
+
managedMcpProfile.protectedValues.push(protectedValue);
|
|
9246
|
+
}
|
|
9247
|
+
}
|
|
8902
9248
|
}
|
|
8903
|
-
throw error;
|
|
8904
9249
|
}
|
|
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, {
|
|
9250
|
+
if (managedMcpProfile) {
|
|
9251
|
+
executorEnv = managedMcpProfile.env;
|
|
9252
|
+
await ingestLog(config, command, "system", "info", `Attested isolated ${executor.kind} managed MCP profile`, {
|
|
9253
|
+
presentationKind: "managed_mcp_attestation",
|
|
9254
|
+
...managedMcpProfile.attestation
|
|
9255
|
+
});
|
|
9256
|
+
}
|
|
9257
|
+
const piChildAllocator2 = executor.kind === "pi" ? configuredPiChildIdentityAllocator(config) : null;
|
|
9258
|
+
const trustedPiRuntimeAssertion = commandTrustedPiRuntimeAssertion(command);
|
|
9259
|
+
if (Object.keys(trustedPiRuntimeAssertion).length > 0) {
|
|
9260
|
+
try {
|
|
9261
|
+
if (executor.kind !== "pi") {
|
|
9262
|
+
throw new Error("pi_trusted_runtime_assertion_binding_mismatch:executorKind");
|
|
9263
|
+
}
|
|
9264
|
+
trustedPiRuntimeSourcePaths = trustedPiRuntimeSources(config);
|
|
9265
|
+
trustedPiRuntime = verifyTrustedPiRuntimeAssertion({
|
|
9266
|
+
assertion: trustedPiRuntimeAssertion,
|
|
9267
|
+
connectorId: requireConnectorId(config),
|
|
8927
9268
|
commandId: command.commandId,
|
|
8928
|
-
runId: commandRunId(command)
|
|
9269
|
+
runId: commandRunId(command),
|
|
9270
|
+
leaseId: command.leaseId,
|
|
9271
|
+
executorKind: executor.kind,
|
|
9272
|
+
localDigests: readTrustedPiRuntimeLocalDigests(trustedPiRuntimeSourcePaths)
|
|
8929
9273
|
});
|
|
8930
|
-
managedMcpProfile
|
|
9274
|
+
if (!managedMcpProfile) {
|
|
9275
|
+
throw new Error("pi_trusted_runtime_governed_profile_required");
|
|
9276
|
+
}
|
|
9277
|
+
requireTrustedPiChildAllocator(piChildAllocator2, true);
|
|
9278
|
+
trustedPiRuntimeProfile = materializeTrustedPiRuntimeProfile({
|
|
9279
|
+
seedRoot: trustedPiRuntimeSourcePaths.seedRoot,
|
|
9280
|
+
overlayRoot: trustedPiRuntimeSourcePaths.overlayRoot,
|
|
9281
|
+
profileRoot: managedMcpProfile.profileRoot,
|
|
9282
|
+
agentDir: managedMcpProfile.env.PI_CODING_AGENT_DIR,
|
|
9283
|
+
governedMcpConfigPath: managedMcpProfile.configPath,
|
|
9284
|
+
verifiedAssertion: trustedPiRuntime
|
|
9285
|
+
});
|
|
9286
|
+
executorEnv = {
|
|
9287
|
+
...executorEnv,
|
|
9288
|
+
AMASTER_MANAGED_RUNTIME_ASSERTION_FD: "3",
|
|
9289
|
+
AMASTER_MANAGED_RUNTIME_AUDIT_FILE: join13(
|
|
9290
|
+
managedMcpProfile.env.HOME,
|
|
9291
|
+
".amaster-managed-runtime-audit.jsonl"
|
|
9292
|
+
),
|
|
9293
|
+
AMASTER_RUNTIME_LEASE_ID: command.leaseId
|
|
9294
|
+
};
|
|
9295
|
+
} catch (error2) {
|
|
9296
|
+
if (managedMcpProfile) {
|
|
9297
|
+
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
9298
|
+
commandId: command.commandId,
|
|
9299
|
+
runId: commandRunId(command)
|
|
9300
|
+
});
|
|
9301
|
+
}
|
|
9302
|
+
throw error2;
|
|
8931
9303
|
}
|
|
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
|
|
9304
|
+
await ingestLog(config, command, "system", "info", "Verified trusted Pi runtime provenance", {
|
|
9305
|
+
presentationKind: "trusted_pi_runtime_attestation",
|
|
9306
|
+
attestationId: trustedPiRuntime.attestationId,
|
|
9307
|
+
unknownToolMode: trustedPiRuntime.unknownToolMode,
|
|
9308
|
+
directToolBudget: trustedPiRuntime.directToolBudget,
|
|
9309
|
+
digests: trustedPiRuntime.digests,
|
|
9310
|
+
profileAttestationId: trustedPiRuntimeProfile.attestationId,
|
|
9311
|
+
inheritedEntries: trustedPiRuntimeProfile.facts.inheritedEntries
|
|
8949
9312
|
});
|
|
8950
|
-
}
|
|
8951
|
-
|
|
8952
|
-
|
|
9313
|
+
}
|
|
9314
|
+
if (executor.kind === "pi" && piResolvedProviderConfig) {
|
|
9315
|
+
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;
|
|
9316
|
+
try {
|
|
9317
|
+
await syncPiExecutorProviderConfig(
|
|
9318
|
+
config,
|
|
9319
|
+
command,
|
|
9320
|
+
agentDir,
|
|
9321
|
+
piResolvedProviderConfig
|
|
9322
|
+
);
|
|
9323
|
+
} catch (error2) {
|
|
9324
|
+
if (managedMcpProfile && cleanupManagedMcpProfile) {
|
|
9325
|
+
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
9326
|
+
commandId: command.commandId,
|
|
9327
|
+
runId: commandRunId(command)
|
|
9328
|
+
});
|
|
9329
|
+
managedMcpProfile = null;
|
|
9330
|
+
}
|
|
9331
|
+
throw error2;
|
|
9332
|
+
}
|
|
9333
|
+
}
|
|
9334
|
+
if (piChildAllocator2) {
|
|
9335
|
+
try {
|
|
9336
|
+
const companyId = readString(commandRuntimeAuth(command).companyId) ?? readString(asRecord(command.payload).companyId);
|
|
9337
|
+
if (!companyId) throw new Error("pi_company_memory_company_id_required");
|
|
9338
|
+
const companyMemoryGroup = resolveCompanyPiMemoryGroup({
|
|
9339
|
+
root: companyPiHomeRoot(process.env),
|
|
9340
|
+
companyId
|
|
9341
|
+
});
|
|
9342
|
+
const assignment = piChildAllocator2.acquire(commandRunId(command), {
|
|
9343
|
+
gid: companyMemoryGroup.gid
|
|
9344
|
+
});
|
|
9345
|
+
piChildAssignmentAcquired = true;
|
|
9346
|
+
if (managedMcpProfile) {
|
|
9347
|
+
piCompanyMemory = prepareCompanyPiMemory({
|
|
9348
|
+
root: companyMemoryGroup.root,
|
|
9349
|
+
companyId,
|
|
9350
|
+
gid: companyMemoryGroup.gid,
|
|
9351
|
+
profileRoot: managedMcpProfile.profileRoot,
|
|
9352
|
+
profileHome: managedMcpProfile.env.PI_AGENT_HOME,
|
|
9353
|
+
childUid: assignment.uid
|
|
9354
|
+
});
|
|
9355
|
+
}
|
|
9356
|
+
const profileRoot = piChildIsolationProfileRoot({
|
|
9357
|
+
managedMcpProfile,
|
|
9358
|
+
executorHome: workspace.executorHome
|
|
9359
|
+
});
|
|
9360
|
+
piChildIsolation = preparePiChildIsolation({
|
|
9361
|
+
allocator: piChildAllocator2,
|
|
9362
|
+
effectiveUid: typeof process.geteuid === "function" ? process.geteuid() : null,
|
|
8953
9363
|
commandId: command.commandId,
|
|
8954
|
-
runId: commandRunId(command)
|
|
9364
|
+
runId: commandRunId(command),
|
|
9365
|
+
...piCompanyMemory ? { gid: piCompanyMemory.gid } : {},
|
|
9366
|
+
profileRoot,
|
|
9367
|
+
workspaceRoot: cwd,
|
|
9368
|
+
allowedRoot: config.runtimeWorkspacesRoot
|
|
8955
9369
|
});
|
|
9370
|
+
} catch (error2) {
|
|
9371
|
+
if (piChildAssignmentAcquired) {
|
|
9372
|
+
piChildAllocator2.release(commandRunId(command));
|
|
9373
|
+
piChildAssignmentAcquired = false;
|
|
9374
|
+
}
|
|
9375
|
+
if (managedMcpProfile) {
|
|
9376
|
+
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
9377
|
+
commandId: command.commandId,
|
|
9378
|
+
runId: commandRunId(command)
|
|
9379
|
+
});
|
|
9380
|
+
}
|
|
9381
|
+
throw error2;
|
|
8956
9382
|
}
|
|
8957
|
-
|
|
9383
|
+
await ingestLog(config, command, "system", "info", "Prepared isolated Pi child identity", {
|
|
9384
|
+
presentationKind: "pi_child_isolation_attestation",
|
|
9385
|
+
...piChildIsolation.attestation,
|
|
9386
|
+
...piCompanyMemory ? { companyMemory: piCompanyMemory.attestation } : {}
|
|
9387
|
+
});
|
|
8958
9388
|
}
|
|
8959
|
-
await ingestLog(config, command, "system", "info",
|
|
8960
|
-
presentationKind: "
|
|
8961
|
-
|
|
9389
|
+
await ingestLog(config, command, "system", "info", `Compiled ${contextManifest.mode} prompt using ${contextManifest.budget.usedChars}/${contextManifest.budget.totalChars} characters`, {
|
|
9390
|
+
presentationKind: "context_manifest",
|
|
9391
|
+
contextManifest
|
|
8962
9392
|
});
|
|
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 {
|
|
9393
|
+
await ackCommand(config, command, "spawned");
|
|
9394
|
+
await ingestLog(config, command, "system", "info", `Starting ${executor.kind} executor`, {
|
|
9395
|
+
executorKind: executor.kind,
|
|
9396
|
+
cwd,
|
|
9397
|
+
args: invocation.args
|
|
9398
|
+
});
|
|
9399
|
+
forgetActiveRunCommand = rememberActiveRunCommand(command, {
|
|
9400
|
+
executorKind: executor.kind,
|
|
9401
|
+
workspacePath: cwd,
|
|
9402
|
+
sourceWorkspacePath: workspace.sourceWorkspacePath,
|
|
9403
|
+
managedWorkdir: workspace.managed,
|
|
9404
|
+
manifestPath: workspaceManifestPath(workspace),
|
|
9405
|
+
outputFloodLimitBytesPerStream: config.executorMaxOutputBytes,
|
|
9406
|
+
...managedMcpProfile ? { managedMcpAttestation: managedMcpProfile.attestation } : {}
|
|
9407
|
+
});
|
|
9408
|
+
const abortController = new AbortController();
|
|
9409
|
+
stopActiveRunHeartbeats = startActiveRunHeartbeats(config, command, abortController);
|
|
9410
|
+
const protectedExecutorValues = managedMcpProfile?.protectedValues ?? providerProtectedValues;
|
|
9411
|
+
const runtimeArtifacts = [];
|
|
9412
|
+
const runtimeArtifactIngest = createRuntimeArtifactIngestQueue({
|
|
9413
|
+
ingest: (results) => ingestRuntimeArtifacts(config, command, cwd, results)
|
|
9414
|
+
});
|
|
9415
|
+
const liveOutputLogger = createLiveOutputLogger(
|
|
9416
|
+
config,
|
|
9417
|
+
command,
|
|
9418
|
+
executor.kind,
|
|
9419
|
+
protectedExecutorValues,
|
|
9420
|
+
(results) => runtimeArtifactIngest.enqueue(results)
|
|
9421
|
+
);
|
|
9422
|
+
let execution;
|
|
9000
9423
|
try {
|
|
9001
9424
|
execution = await runExecutor(invocation.command, invocation.args, {
|
|
9002
9425
|
cwd,
|
|
@@ -9065,6 +9488,19 @@ async function executeRunCommand(config, command) {
|
|
|
9065
9488
|
errorMessage: null
|
|
9066
9489
|
} : 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
9490
|
parsed.sessionId ??= liveOutputLogger.sessionId();
|
|
9491
|
+
const liveTerminalOutput = executor.kind === "pi" && !hasOutputFlood ? liveOutputLogger.terminalOutput() : null;
|
|
9492
|
+
if (liveTerminalOutput) {
|
|
9493
|
+
const parsedUsage = asRecord(parsed.usage);
|
|
9494
|
+
const liveUsage = asRecord(liveTerminalOutput.usage);
|
|
9495
|
+
parsed.summary = liveTerminalOutput.summary;
|
|
9496
|
+
parsed.hasAssistantOutput = true;
|
|
9497
|
+
parsed.usage = {
|
|
9498
|
+
inputTokens: readNumber(liveUsage.inputTokens, 0) || readNumber(parsedUsage.inputTokens, 0),
|
|
9499
|
+
cachedInputTokens: readNumber(liveUsage.cachedInputTokens, 0) || readNumber(parsedUsage.cachedInputTokens, 0),
|
|
9500
|
+
outputTokens: readNumber(liveUsage.outputTokens, 0) || readNumber(parsedUsage.outputTokens, 0),
|
|
9501
|
+
...readNumber(liveUsage.costUsd, 0) > 0 || readNumber(parsedUsage.costUsd, 0) > 0 ? { costUsd: readNumber(liveUsage.costUsd, 0) || readNumber(parsedUsage.costUsd, 0) } : {}
|
|
9502
|
+
};
|
|
9503
|
+
}
|
|
9068
9504
|
const outputTelemetry = liveOutputLogger.snapshot({
|
|
9069
9505
|
outputBytes: execution.outputBytes,
|
|
9070
9506
|
floodLimitBytes: config.executorMaxOutputBytes,
|
|
@@ -9119,7 +9555,7 @@ async function executeRunCommand(config, command) {
|
|
|
9119
9555
|
workspace,
|
|
9120
9556
|
workspaceStatus.artifacts.map((artifact) => ({
|
|
9121
9557
|
rawPath: artifact.relativePath,
|
|
9122
|
-
filePath:
|
|
9558
|
+
filePath: resolve11(cwd, artifact.relativePath)
|
|
9123
9559
|
}))
|
|
9124
9560
|
);
|
|
9125
9561
|
nativeSessionRollout = {
|
|
@@ -9171,6 +9607,7 @@ async function executeRunCommand(config, command) {
|
|
|
9171
9607
|
allowMissingTurnEnd: completionOutputStopped,
|
|
9172
9608
|
allowMissingAssistantOutput: execution.completionOutputType === "approval_required"
|
|
9173
9609
|
}) : null;
|
|
9610
|
+
const piProviderFailure = executor.kind === "pi" && !cancelled && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError ? classifyPiProviderError(parsed) : null;
|
|
9174
9611
|
const parsedErrorMessage = outputFloodError ?? memoryLimitError ?? piInvalidOutputError ?? nativeSessionRolloutError ?? nativeSessionRolloutCleanupError ?? parsed.errorMessage;
|
|
9175
9612
|
const codexTransientFailure = executor.kind === "codex" && (execution.exitCode ?? 0) !== 0 ? classifyCodexTransientUpstreamError({
|
|
9176
9613
|
stdout: execution.stdout,
|
|
@@ -9246,10 +9683,11 @@ async function executeRunCommand(config, command) {
|
|
|
9246
9683
|
...Array.isArray(execution.killedWorkspaceResidents) && execution.killedWorkspaceResidents.length > 0 ? {
|
|
9247
9684
|
killedWorkspaceResidents: execution.killedWorkspaceResidents
|
|
9248
9685
|
} : {},
|
|
9249
|
-
...piInvalidOutputError && !hasOutputFlood ? {
|
|
9686
|
+
...piInvalidOutputError && !cancelled && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError && !piProviderFailure ? {
|
|
9250
9687
|
errorCode: "pi_executor_invalid_output",
|
|
9251
9688
|
errorFamily: "validation"
|
|
9252
9689
|
} : {},
|
|
9690
|
+
...piProviderFailure ? piProviderFailure : {},
|
|
9253
9691
|
...codexTransientFailure ? codexTransientFailure : {},
|
|
9254
9692
|
...piUsageDiagnostic && !piInvalidOutputError ? {
|
|
9255
9693
|
piDiagnostics: {
|
|
@@ -9267,6 +9705,9 @@ async function executeRunCommand(config, command) {
|
|
|
9267
9705
|
...piChildIsolation ? {
|
|
9268
9706
|
piChildIsolation: piChildIsolation.attestation
|
|
9269
9707
|
} : {},
|
|
9708
|
+
...piCompanyMemory ? {
|
|
9709
|
+
companyMemory: piCompanyMemory.attestation
|
|
9710
|
+
} : {},
|
|
9270
9711
|
...trustedPiRuntimeProfile ? {
|
|
9271
9712
|
trustedPiRuntime: {
|
|
9272
9713
|
attestationId: trustedPiRuntime.attestationId,
|
|
@@ -9297,6 +9738,9 @@ async function executeRunCommand(config, command) {
|
|
|
9297
9738
|
});
|
|
9298
9739
|
}
|
|
9299
9740
|
piChildIsolation?.release();
|
|
9741
|
+
if (!piChildIsolation && piChildAssignmentAcquired) {
|
|
9742
|
+
piChildAllocator?.release(commandRunId(command));
|
|
9743
|
+
}
|
|
9300
9744
|
stopActiveRunHeartbeats();
|
|
9301
9745
|
forgetActiveRunCommand();
|
|
9302
9746
|
}
|
|
@@ -9325,10 +9769,14 @@ async function processCommand(config, command) {
|
|
|
9325
9769
|
});
|
|
9326
9770
|
} catch (err) {
|
|
9327
9771
|
const message = err instanceof Error ? err.message : String(err);
|
|
9772
|
+
const errorCode = readString(asRecord(err).code);
|
|
9773
|
+
const runtimeArtifacts = Array.isArray(asRecord(err).receipts) ? asRecord(err).receipts.map(asRecord) : [];
|
|
9328
9774
|
await ingestLog(config, command, "system", "error", message);
|
|
9329
9775
|
await completeCommand(config, command, "failed", {
|
|
9330
9776
|
summary: message,
|
|
9331
|
-
commandType: command.commandType
|
|
9777
|
+
commandType: command.commandType,
|
|
9778
|
+
...errorCode && /^[a-z][a-z0-9_]{0,127}$/.test(errorCode) ? { errorCode } : {},
|
|
9779
|
+
...runtimeArtifacts.length > 0 ? { runtimeArtifacts } : {}
|
|
9332
9780
|
}, message);
|
|
9333
9781
|
}
|
|
9334
9782
|
}
|
|
@@ -9499,7 +9947,7 @@ async function runLoop(config) {
|
|
|
9499
9947
|
${message}
|
|
9500
9948
|
`);
|
|
9501
9949
|
}
|
|
9502
|
-
await new Promise((
|
|
9950
|
+
await new Promise((resolve12) => setTimeout(resolve12, config.pollIntervalSeconds * 1e3));
|
|
9503
9951
|
}
|
|
9504
9952
|
}
|
|
9505
9953
|
function help() {
|