@amaster.ai/employee-runtime-connector 0.1.0-beta.30 → 0.1.0-beta.32
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 +1066 -208
- 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 createHash8 } from "node:crypto";
|
|
6
|
+
import { chmodSync as chmodSync5, copyFileSync as copyFileSync3, existsSync as existsSync10, lstatSync as lstatSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync8, readdirSync as readdirSync8, realpathSync as realpathSync3, renameSync as renameSync3, rmSync as rmSync6, statSync as statSync7, symlinkSync as symlinkSync3, unlinkSync, writeFileSync as writeFileSync6 } 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 dirname7, extname as extname2, isAbsolute as isAbsolute7, join as join11, relative as relative7, resolve as resolve10 } from "node:path";
|
|
9
9
|
import { spawn, spawnSync as spawnSync5 } from "node:child_process";
|
|
10
10
|
|
|
11
11
|
// src/amaster-runtime-daemon/common.mjs
|
|
@@ -388,7 +388,7 @@ function skipVoid(str, ptr, banNewLines, banComments) {
|
|
|
388
388
|
}
|
|
389
389
|
return ptr;
|
|
390
390
|
}
|
|
391
|
-
function skipUntil(str, ptr,
|
|
391
|
+
function skipUntil(str, ptr, sep2, end, banNewLines = false) {
|
|
392
392
|
if (!end) {
|
|
393
393
|
ptr = indexOfNewline(str, ptr);
|
|
394
394
|
return ptr < 0 ? str.length : ptr;
|
|
@@ -397,7 +397,7 @@ function skipUntil(str, ptr, sep, end, banNewLines = false) {
|
|
|
397
397
|
let c = str[i];
|
|
398
398
|
if (c === "#") {
|
|
399
399
|
i = indexOfNewline(str, i);
|
|
400
|
-
} else if (c ===
|
|
400
|
+
} else if (c === sep2) {
|
|
401
401
|
return i + 1;
|
|
402
402
|
} else if (c === end || banNewLines && (c === "\n" || c === "\r" && str[i + 1] === "\n")) {
|
|
403
403
|
return i;
|
|
@@ -1572,6 +1572,17 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1572
1572
|
const SUPPORTED_SERVER_NAME2 = "amaster";
|
|
1573
1573
|
const MINIMUM_PI_VERSION = [0, 73, 1];
|
|
1574
1574
|
const MINIMUM_MCP_ADAPTER_VERSION = [2, 6, 1];
|
|
1575
|
+
const MANAGED_BROWSER_USE_PACKAGE = "@amaster.ai/pi-browser-use";
|
|
1576
|
+
const MANAGED_BROWSER_USE_PLUGIN = "browser-use";
|
|
1577
|
+
const MANAGED_BROWSER_USE_BOOLEAN_SETTINGS = [
|
|
1578
|
+
"headless",
|
|
1579
|
+
"categoryNetwork",
|
|
1580
|
+
"categoryEmulation",
|
|
1581
|
+
"categoryPerformance",
|
|
1582
|
+
"experimentalVision",
|
|
1583
|
+
"experimentalScreencast",
|
|
1584
|
+
"experimentalMemory"
|
|
1585
|
+
];
|
|
1575
1586
|
const REQUIRED_AUTHORITY_HEADERS2 = [
|
|
1576
1587
|
"x-amaster-company-id",
|
|
1577
1588
|
"x-amaster-agent-id",
|
|
@@ -1637,14 +1648,20 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1637
1648
|
const PROFILE_MARKER2 = ".amaster-managed-pi-profile.json";
|
|
1638
1649
|
const SESSION_ROLLOUT_MARKER2 = ".amaster-pi-session-rollout.json";
|
|
1639
1650
|
const DEFAULT_SESSION_ROLLOUT_TTL_MS2 = 24 * 60 * 60 * 1e3;
|
|
1640
|
-
function
|
|
1651
|
+
function record3(value) {
|
|
1641
1652
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1642
1653
|
}
|
|
1654
|
+
function npmPackageName(source) {
|
|
1655
|
+
if (typeof source !== "string" || !source.startsWith("npm:")) return null;
|
|
1656
|
+
const spec = source.slice("npm:".length);
|
|
1657
|
+
const versionSeparator = spec.startsWith("@") ? spec.indexOf("@", 1) : spec.indexOf("@");
|
|
1658
|
+
return (versionSeparator === -1 ? spec : spec.slice(0, versionSeparator)) || null;
|
|
1659
|
+
}
|
|
1643
1660
|
function nonEmpty2(value, label) {
|
|
1644
1661
|
if (typeof value !== "string" || value.trim() === "") throw new Error(`pi_managed_mcp_invalid: ${label} is required`);
|
|
1645
1662
|
return value.trim();
|
|
1646
1663
|
}
|
|
1647
|
-
function
|
|
1664
|
+
function within3(candidate, root) {
|
|
1648
1665
|
const rel = relative2(root, candidate);
|
|
1649
1666
|
return rel === "" || !rel.startsWith("..") && !isAbsolute2(rel);
|
|
1650
1667
|
}
|
|
@@ -1687,7 +1704,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1687
1704
|
return matches[0];
|
|
1688
1705
|
}
|
|
1689
1706
|
function restoreManagedPiSessionRollout(input, sessionsRoot, runDir, executorHome, authority) {
|
|
1690
|
-
const session =
|
|
1707
|
+
const session = record3(input.nativeSession);
|
|
1691
1708
|
if (session.mode !== "governed_action_approval" || session.required !== true) return null;
|
|
1692
1709
|
const sessionId = nonEmpty2(session.sessionId, "nativeSession.sessionId");
|
|
1693
1710
|
const sourceRunId = nonEmpty2(session.sourceRunId, "nativeSession.sourceRunId");
|
|
@@ -1711,11 +1728,11 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1711
1728
|
throw new Error("pi_managed_mcp_session_rollout_authority_mismatch: source rollout does not match the approved continuation");
|
|
1712
1729
|
}
|
|
1713
1730
|
const sourceRollout = resolve2(cacheRoot, nonEmpty2(marker.rolloutRelativePath, "rolloutRelativePath"));
|
|
1714
|
-
if (!
|
|
1731
|
+
if (!within3(sourceRollout, cacheRoot) || lstatSync2(sourceRollout).isSymbolicLink() || !lstatSync2(sourceRollout).isFile()) {
|
|
1715
1732
|
throw new Error("pi_managed_mcp_session_rollout_unsafe: source rollout path is invalid");
|
|
1716
1733
|
}
|
|
1717
1734
|
const targetRollout = resolve2(sessionsRoot, marker.rolloutRelativePath);
|
|
1718
|
-
if (!
|
|
1735
|
+
if (!within3(targetRollout, sessionsRoot)) {
|
|
1719
1736
|
throw new Error("pi_managed_mcp_session_rollout_unsafe: target rollout path is invalid");
|
|
1720
1737
|
}
|
|
1721
1738
|
mkdirSync2(dirname2(targetRollout), { recursive: true, mode: 448 });
|
|
@@ -1737,8 +1754,8 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1737
1754
|
return tuple.join(".");
|
|
1738
1755
|
}
|
|
1739
1756
|
function validateAuthority2(input) {
|
|
1740
|
-
const runtimeAuth =
|
|
1741
|
-
const gateway =
|
|
1757
|
+
const runtimeAuth = record3(input.runtimeAuth);
|
|
1758
|
+
const gateway = record3(runtimeAuth.governedMcp);
|
|
1742
1759
|
const runId = nonEmpty2(input.runId, "runId");
|
|
1743
1760
|
if (runtimeAuth.runId !== runId) throw new Error("pi_managed_mcp_owner_mismatch: command runId does not match runtime authority");
|
|
1744
1761
|
if (gateway.schemaVersion !== SUPPORTED_SCHEMA_VERSION2) throw new Error("pi_managed_mcp_invalid: unsupported schema version");
|
|
@@ -1754,7 +1771,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1754
1771
|
if (!Number.isFinite(expiresAt) || expiresAt <= Date.now() + 3e4) {
|
|
1755
1772
|
throw new Error("pi_managed_mcp_session_expired: Gateway session must remain valid through spawn preflight");
|
|
1756
1773
|
}
|
|
1757
|
-
const headers =
|
|
1774
|
+
const headers = record3(gateway.headers);
|
|
1758
1775
|
for (const name of REQUIRED_AUTHORITY_HEADERS2) nonEmpty2(headers[name], `headers.${name}`);
|
|
1759
1776
|
const allowedHeaderNames = /* @__PURE__ */ new Set([...REQUIRED_AUTHORITY_HEADERS2, ...runtimeAuth.issueId ? ["x-amaster-issue-id"] : []]);
|
|
1760
1777
|
if (Object.keys(headers).some((name) => !allowedHeaderNames.has(name)) || Object.keys(headers).length !== allowedHeaderNames.size) {
|
|
@@ -1783,7 +1800,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1783
1800
|
return output;
|
|
1784
1801
|
}
|
|
1785
1802
|
function assertInvocationIsolation2(input) {
|
|
1786
|
-
for (const name of Object.keys(
|
|
1803
|
+
for (const name of Object.keys(record3(input.commandEnv))) {
|
|
1787
1804
|
if (FORBIDDEN_COMMAND_ENV2.has(name)) throw new Error(`pi_managed_mcp_env_override_blocked: ${name}`);
|
|
1788
1805
|
if (!ALLOWED_COMMAND_ENV2.has(name)) throw new Error(`pi_managed_mcp_env_injection_blocked: ${name}`);
|
|
1789
1806
|
}
|
|
@@ -1815,7 +1832,7 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1815
1832
|
const value = safeProxyValue2(baseEnv?.[name], name);
|
|
1816
1833
|
if (value) env[name] = value;
|
|
1817
1834
|
}
|
|
1818
|
-
return { ...env, ...
|
|
1835
|
+
return { ...env, ...record3(commandEnv) };
|
|
1819
1836
|
}
|
|
1820
1837
|
function projectMcpConfigHasContent(filePath) {
|
|
1821
1838
|
if (!existsSync2(filePath)) return false;
|
|
@@ -1825,14 +1842,14 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1825
1842
|
} catch {
|
|
1826
1843
|
return true;
|
|
1827
1844
|
}
|
|
1828
|
-
const config =
|
|
1829
|
-
return Object.keys(
|
|
1845
|
+
const config = record3(parsed);
|
|
1846
|
+
return Object.keys(record3(config.mcpServers)).length > 0 || Object.keys(record3(config.servers)).length > 0 || Array.isArray(config.imports) && config.imports.length > 0;
|
|
1830
1847
|
}
|
|
1831
1848
|
function assertNoProjectMcpOverride(cwd, runDir) {
|
|
1832
1849
|
let cursor = resolve2(cwd);
|
|
1833
1850
|
const boundary = resolve2(runDir);
|
|
1834
|
-
if (!
|
|
1835
|
-
while (
|
|
1851
|
+
if (!within3(cursor, boundary)) throw new Error("pi_managed_mcp_owner_mismatch: cwd is outside the managed run");
|
|
1852
|
+
while (within3(cursor, boundary)) {
|
|
1836
1853
|
for (const relativePath of [".mcp.json", join3(".pi", "mcp.json")]) {
|
|
1837
1854
|
const configPath = join3(cursor, relativePath);
|
|
1838
1855
|
if (projectMcpConfigHasContent(configPath)) throw new Error(`pi_managed_mcp_project_override_blocked: ${configPath}`);
|
|
@@ -1841,6 +1858,50 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1841
1858
|
cursor = dirname2(cursor);
|
|
1842
1859
|
}
|
|
1843
1860
|
}
|
|
1861
|
+
function selectManagedBrowserUse(sourceSettings, npmSource) {
|
|
1862
|
+
const plugin = record3(record3(sourceSettings.plugins)[MANAGED_BROWSER_USE_PLUGIN]);
|
|
1863
|
+
if (plugin.enabled !== true || plugin.package !== MANAGED_BROWSER_USE_PACKAGE) return null;
|
|
1864
|
+
const packageSpec = Array.isArray(sourceSettings.packages) ? sourceSettings.packages.find((entry) => npmPackageName(entry) === MANAGED_BROWSER_USE_PACKAGE) : null;
|
|
1865
|
+
if (typeof packageSpec !== "string") return null;
|
|
1866
|
+
const packagePath = join3(npmSource, "node_modules", ...MANAGED_BROWSER_USE_PACKAGE.split("/"), "package.json");
|
|
1867
|
+
if (!existsSync2(packagePath) || lstatSync2(packagePath).isSymbolicLink() || !lstatSync2(packagePath).isFile()) {
|
|
1868
|
+
throw new Error(`pi_managed_mcp_attestation_failed: enabled ${MANAGED_BROWSER_USE_PACKAGE} package is unavailable`);
|
|
1869
|
+
}
|
|
1870
|
+
let packageMetadata;
|
|
1871
|
+
try {
|
|
1872
|
+
packageMetadata = JSON.parse(readFileSync2(packagePath, "utf8"));
|
|
1873
|
+
} catch {
|
|
1874
|
+
throw new Error(`pi_managed_mcp_attestation_failed: enabled ${MANAGED_BROWSER_USE_PACKAGE} package metadata is invalid`);
|
|
1875
|
+
}
|
|
1876
|
+
if (packageMetadata.name !== MANAGED_BROWSER_USE_PACKAGE) {
|
|
1877
|
+
throw new Error(`pi_managed_mcp_attestation_failed: enabled ${MANAGED_BROWSER_USE_PACKAGE} package identity mismatch`);
|
|
1878
|
+
}
|
|
1879
|
+
const sourceConfig = record3(sourceSettings["pi-browser-use"]);
|
|
1880
|
+
const config = {};
|
|
1881
|
+
for (const key of MANAGED_BROWSER_USE_BOOLEAN_SETTINGS) {
|
|
1882
|
+
if (typeof sourceConfig[key] === "boolean") config[key] = sourceConfig[key];
|
|
1883
|
+
}
|
|
1884
|
+
if (typeof sourceConfig.viewport === "string" && /^\d{2,5}x\d{2,5}$/.test(sourceConfig.viewport)) {
|
|
1885
|
+
config.viewport = sourceConfig.viewport;
|
|
1886
|
+
}
|
|
1887
|
+
if (typeof sourceConfig.channel === "string" && ["stable", "beta", "dev", "canary"].includes(sourceConfig.channel)) {
|
|
1888
|
+
config.channel = sourceConfig.channel;
|
|
1889
|
+
}
|
|
1890
|
+
return {
|
|
1891
|
+
packageSpec,
|
|
1892
|
+
plugin: {
|
|
1893
|
+
enabled: true,
|
|
1894
|
+
package: MANAGED_BROWSER_USE_PACKAGE
|
|
1895
|
+
},
|
|
1896
|
+
config: {
|
|
1897
|
+
...config,
|
|
1898
|
+
categoryExtensions: false,
|
|
1899
|
+
usageStatistics: false,
|
|
1900
|
+
performanceCrux: false,
|
|
1901
|
+
redactNetworkHeaders: true
|
|
1902
|
+
}
|
|
1903
|
+
};
|
|
1904
|
+
}
|
|
1844
1905
|
function seedPiRuntime(sourceHome, agentDir) {
|
|
1845
1906
|
const source = resolve2(nonEmpty2(sourceHome, "sourcePiHome"));
|
|
1846
1907
|
const npmSource = join3(source, "npm");
|
|
@@ -1859,15 +1920,22 @@ var piManagedMcpProfileApi = (() => {
|
|
|
1859
1920
|
let sourceSettings = {};
|
|
1860
1921
|
if (existsSync2(settingsSource)) {
|
|
1861
1922
|
try {
|
|
1862
|
-
sourceSettings =
|
|
1923
|
+
sourceSettings = record3(JSON.parse(readFileSync2(settingsSource, "utf8")));
|
|
1863
1924
|
} catch {
|
|
1864
1925
|
throw new Error("pi_managed_mcp_attestation_failed: source Pi settings are invalid");
|
|
1865
1926
|
}
|
|
1866
1927
|
}
|
|
1928
|
+
const browserUse = selectManagedBrowserUse(sourceSettings, npmSource);
|
|
1867
1929
|
const settings = {
|
|
1868
1930
|
...typeof sourceSettings.defaultProvider === "string" ? { defaultProvider: sourceSettings.defaultProvider } : {},
|
|
1869
1931
|
...typeof sourceSettings.defaultModel === "string" ? { defaultModel: sourceSettings.defaultModel } : {},
|
|
1870
|
-
packages: ["npm:pi-mcp-adapter"]
|
|
1932
|
+
packages: ["npm:pi-mcp-adapter", ...browserUse ? [browserUse.packageSpec] : []],
|
|
1933
|
+
...browserUse ? {
|
|
1934
|
+
plugins: {
|
|
1935
|
+
[MANAGED_BROWSER_USE_PLUGIN]: browserUse.plugin
|
|
1936
|
+
},
|
|
1937
|
+
"pi-browser-use": browserUse.config
|
|
1938
|
+
} : {}
|
|
1871
1939
|
};
|
|
1872
1940
|
writePrivateFile2(join3(agentDir, "settings.json"), `${JSON.stringify(settings, null, 2)}
|
|
1873
1941
|
`);
|
|
@@ -1915,7 +1983,7 @@ ${result2.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
1915
1983
|
const { gateway, gatewayUrl, sessionToken, headers, runId } = validateAuthority2(input);
|
|
1916
1984
|
const runDir = resolve2(nonEmpty2(input.runDir, "runDir"));
|
|
1917
1985
|
const executorHome = resolve2(nonEmpty2(input.executorHome, "executorHome"));
|
|
1918
|
-
if (!
|
|
1986
|
+
if (!within3(executorHome, join3(runDir, "executors"))) throw new Error("pi_managed_mcp_owner_mismatch: executorHome is outside the managed run");
|
|
1919
1987
|
assertNoProjectMcpOverride(nonEmpty2(input.cwd, "cwd"), runDir);
|
|
1920
1988
|
const profileRoot = join3(executorHome, "managed-mcp");
|
|
1921
1989
|
if (existsSync2(profileRoot)) throw new Error(`pi_managed_mcp_profile_exists: ${profileRoot}`);
|
|
@@ -1930,7 +1998,7 @@ ${result2.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
1930
1998
|
const owner = Object.freeze({ commandId: input.commandId, runId });
|
|
1931
1999
|
writePrivateFile2(markerPath, `${JSON.stringify({ version: 1, ...owner, profileRoot })}
|
|
1932
2000
|
`);
|
|
1933
|
-
const runtimeAuth =
|
|
2001
|
+
const runtimeAuth = record3(input.runtimeAuth);
|
|
1934
2002
|
const authority = Object.freeze({
|
|
1935
2003
|
companyId: nonEmpty2(runtimeAuth.companyId, "runtimeAuth.companyId"),
|
|
1936
2004
|
agentId: nonEmpty2(runtimeAuth.agentId, "runtimeAuth.agentId"),
|
|
@@ -2084,7 +2152,7 @@ ${result2.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
2084
2152
|
const profileRoot = dirname2(markerPath);
|
|
2085
2153
|
try {
|
|
2086
2154
|
const marker = JSON.parse(readFileSync2(markerPath, "utf8"));
|
|
2087
|
-
if (!
|
|
2155
|
+
if (!within3(profileRoot, root) || marker?.profileRoot !== profileRoot) throw new Error("ownership marker root mismatch");
|
|
2088
2156
|
cleanupManagedPiMcpProfile2({ profileRoot }, { commandId: marker.commandId, runId: marker.runId });
|
|
2089
2157
|
removedProfiles += 1;
|
|
2090
2158
|
} catch (error) {
|
|
@@ -2099,7 +2167,7 @@ ${result2.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
2099
2167
|
const markerStat = lstatSync2(markerPath);
|
|
2100
2168
|
const cacheStat = lstatSync2(cacheRoot);
|
|
2101
2169
|
const marker = JSON.parse(readFileSync2(markerPath, "utf8"));
|
|
2102
|
-
if (!
|
|
2170
|
+
if (!within3(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");
|
|
2103
2171
|
const preservedAtMs = typeof marker.preservedAt === "string" ? Date.parse(marker.preservedAt) : Number.NaN;
|
|
2104
2172
|
const markerAgeMs = nowMs - (Number.isFinite(preservedAtMs) ? preservedAtMs : markerStat.mtimeMs);
|
|
2105
2173
|
if (markerAgeMs < rolloutTtlMs) continue;
|
|
@@ -2193,8 +2261,8 @@ function resultOutboxFileName(commandId, now = Date.now()) {
|
|
|
2193
2261
|
return `${now}-${safeCommandId}.json`;
|
|
2194
2262
|
}
|
|
2195
2263
|
function isValidResultOutboxEntry(entry) {
|
|
2196
|
-
const
|
|
2197
|
-
return
|
|
2264
|
+
const record3 = asRecord(entry);
|
|
2265
|
+
return record3.version === 1 && Boolean(readString(record3.path)) && Object.keys(asRecord(record3.payload)).length > 0;
|
|
2198
2266
|
}
|
|
2199
2267
|
function resultOutboxEntryAgeMs(entry, nowMs) {
|
|
2200
2268
|
const createdAt = Date.parse(readString(entry.createdAt) ?? "");
|
|
@@ -2272,8 +2340,8 @@ function governedReadSection(context) {
|
|
|
2272
2340
|
const reads = Array.isArray(context.governedReadResults) ? context.governedReadResults : [];
|
|
2273
2341
|
if (reads.length === 0) return { content: "", provenance: [] };
|
|
2274
2342
|
const normalized = reads.map((entry, index) => {
|
|
2275
|
-
const
|
|
2276
|
-
const receipt = asRecord(
|
|
2343
|
+
const record3 = asRecord(entry);
|
|
2344
|
+
const receipt = asRecord(record3.receipt);
|
|
2277
2345
|
const provider = readString(receipt.provider) ?? readString(receipt.transport);
|
|
2278
2346
|
const operation = readString(receipt.operation);
|
|
2279
2347
|
const observedAt = readString(receipt.retrievedAt) ?? readString(receipt.observedAt);
|
|
@@ -2283,7 +2351,7 @@ function governedReadSection(context) {
|
|
|
2283
2351
|
throw new Error(`governed_read_context_provenance_invalid: entry ${index} requires provider, operation, observedAt, and source`);
|
|
2284
2352
|
}
|
|
2285
2353
|
return {
|
|
2286
|
-
content:
|
|
2354
|
+
content: record3.content,
|
|
2287
2355
|
receipt: {
|
|
2288
2356
|
provider,
|
|
2289
2357
|
operation,
|
|
@@ -2311,6 +2379,7 @@ function fixedRules(input, includeIssueLine) {
|
|
|
2311
2379
|
"## AMaster Runtime Connector Task",
|
|
2312
2380
|
"You are executing a task dispatched by MirrorX from the central control plane.",
|
|
2313
2381
|
"Work only inside the declared workspace. Make concrete progress and finish with a concise result summary.",
|
|
2382
|
+
"Before changing the task status to done, audit every explicit requirement in the task against the final evidence. A successful tool or document write proves delivery, not acceptance: inspect the delivered content for required sections, diagrams, tables, and factual constraints. Do not leave stale in-progress wording such as \u201Ccurrent run\u201D in a terminal deliverable; rewrite it to the final observed state. Do not list finalization itself as remaining or next work in a terminal deliverable. If any requirement is missing or cannot be verified, do not mark done. To request review, use create_interaction with kind request_confirmation and payload.resolutionMode review; never call update_parent with status in_review. Otherwise keep the issue todo or blocked with the exact gap and next owner.",
|
|
2314
2383
|
"Do not install operating-system or user-global packages, and do not use host package managers such as brew, apt, yum, or global pip/npm installs. Use tools already available or workspace-local dependencies or virtual environments. If a required renderer or evaluator is unavailable, keep the source artifact, record the exact verification gap, and do not mutate the host.",
|
|
2315
2384
|
`- command id: ${input.commandId}`,
|
|
2316
2385
|
`- run id: ${input.runId ?? "unknown"}`,
|
|
@@ -2731,6 +2800,23 @@ function buildConfig(env = process.env, flags = {}) {
|
|
|
2731
2800
|
flags.executorMaxRssMb ?? env.AMASTER_EXECUTOR_MAX_RSS_MB,
|
|
2732
2801
|
0
|
|
2733
2802
|
),
|
|
2803
|
+
piChildUidBase: parseNonNegativeInteger(
|
|
2804
|
+
flags.piChildUidBase ?? env.AMASTER_PI_CHILD_UID_BASE,
|
|
2805
|
+
0
|
|
2806
|
+
),
|
|
2807
|
+
piChildUidSpan: parsePositiveInteger(
|
|
2808
|
+
flags.piChildUidSpan ?? env.AMASTER_PI_CHILD_UID_SPAN,
|
|
2809
|
+
3e4
|
|
2810
|
+
),
|
|
2811
|
+
piRuntimeSeedRoot: String(
|
|
2812
|
+
flags.piRuntimeSeedRoot ?? env.PI_RUNTIME_SEED_DIR ?? ""
|
|
2813
|
+
).trim(),
|
|
2814
|
+
piRuntimeOverlayRoot: String(
|
|
2815
|
+
flags.piRuntimeOverlayRoot ?? env.AMASTER_PI_RUNTIME_OVERLAY_DIR ?? ""
|
|
2816
|
+
).trim(),
|
|
2817
|
+
piRuntimeEffectivePolicyFile: String(
|
|
2818
|
+
flags.piRuntimeEffectivePolicyFile ?? env.AMASTER_PI_RUNTIME_EFFECTIVE_POLICY_FILE ?? ""
|
|
2819
|
+
).trim(),
|
|
2734
2820
|
artifactVerifierCommands: splitList(
|
|
2735
2821
|
flags.artifactVerifierCommands ?? env.AMASTER_ARTIFACT_VERIFIER_COMMANDS ?? ""
|
|
2736
2822
|
),
|
|
@@ -2805,10 +2891,10 @@ function compactExecutorJsonlForTranscript(event) {
|
|
|
2805
2891
|
const text = JSON.stringify(compactExecutorJsonValue(event, stringMaxChars));
|
|
2806
2892
|
if (text.length <= 15e3) return text;
|
|
2807
2893
|
}
|
|
2808
|
-
const
|
|
2809
|
-
const item = tcAsRecord(
|
|
2894
|
+
const record3 = tcAsRecord(event);
|
|
2895
|
+
const item = tcAsRecord(record3.item);
|
|
2810
2896
|
return JSON.stringify({
|
|
2811
|
-
type: tcReadString(
|
|
2897
|
+
type: tcReadString(record3.type) ?? "executor.event",
|
|
2812
2898
|
item: item.type ? {
|
|
2813
2899
|
id: tcReadString(item.id),
|
|
2814
2900
|
type: tcReadString(item.type),
|
|
@@ -2821,10 +2907,10 @@ function compactExecutorJsonlForTranscript(event) {
|
|
|
2821
2907
|
});
|
|
2822
2908
|
}
|
|
2823
2909
|
function summarizeTokenUsage(usage) {
|
|
2824
|
-
const
|
|
2825
|
-
const inputTokens = tcReadNumber(
|
|
2826
|
-
const cachedInputTokens = tcReadNumber(
|
|
2827
|
-
const outputTokens = tcReadNumber(
|
|
2910
|
+
const record3 = tcAsRecord(usage);
|
|
2911
|
+
const inputTokens = tcReadNumber(record3.input_tokens ?? record3.inputTokens, 0);
|
|
2912
|
+
const cachedInputTokens = tcReadNumber(record3.cached_input_tokens ?? record3.cachedInputTokens, 0);
|
|
2913
|
+
const outputTokens = tcReadNumber(record3.output_tokens ?? record3.outputTokens, 0);
|
|
2828
2914
|
const parts = [];
|
|
2829
2915
|
if (inputTokens > 0) parts.push(`\u8F93\u5165 ${inputTokens}`);
|
|
2830
2916
|
if (cachedInputTokens > 0) parts.push(`\u7F13\u5B58 ${cachedInputTokens}`);
|
|
@@ -3079,8 +3165,8 @@ function summarizeClaudeEvent(event) {
|
|
|
3079
3165
|
return null;
|
|
3080
3166
|
}
|
|
3081
3167
|
function tcPiMessageText(message) {
|
|
3082
|
-
const
|
|
3083
|
-
const content =
|
|
3168
|
+
const record3 = tcAsRecord(message);
|
|
3169
|
+
const content = record3.content;
|
|
3084
3170
|
if (typeof content === "string" && content.trim().length > 0) return content.trim();
|
|
3085
3171
|
if (!Array.isArray(content)) return "";
|
|
3086
3172
|
return content.map((entry) => {
|
|
@@ -3094,14 +3180,14 @@ function tcPiAssistantMessageEventText(assistantMessageEvent) {
|
|
|
3094
3180
|
return tcReadString(event.content) ?? "";
|
|
3095
3181
|
}
|
|
3096
3182
|
function tcPiMessageStopReason(message) {
|
|
3097
|
-
const
|
|
3098
|
-
return tcReadString(
|
|
3183
|
+
const record3 = tcAsRecord(message);
|
|
3184
|
+
return tcReadString(record3.stopReason ?? record3.stop_reason);
|
|
3099
3185
|
}
|
|
3100
3186
|
function tcPiMessageErrorText(message) {
|
|
3101
|
-
const
|
|
3102
|
-
const explicitError = tcReadString(
|
|
3187
|
+
const record3 = tcAsRecord(message);
|
|
3188
|
+
const explicitError = tcReadString(record3.errorMessage ?? record3.error_message)?.trim();
|
|
3103
3189
|
if (explicitError) return explicitError;
|
|
3104
|
-
const stopReason = tcPiMessageStopReason(
|
|
3190
|
+
const stopReason = tcPiMessageStopReason(record3);
|
|
3105
3191
|
if (stopReason === "error" || stopReason === "failed" || stopReason === "exception") {
|
|
3106
3192
|
return `Pi Agent message ended with stopReason=${stopReason}`;
|
|
3107
3193
|
}
|
|
@@ -3521,13 +3607,13 @@ function parseClaudeStreamJson(stdout) {
|
|
|
3521
3607
|
}
|
|
3522
3608
|
function openCodeErrorText(value) {
|
|
3523
3609
|
if (typeof value === "string") return value;
|
|
3524
|
-
const
|
|
3525
|
-
const message = readString(
|
|
3610
|
+
const record3 = asRecord(value);
|
|
3611
|
+
const message = readString(record3.message);
|
|
3526
3612
|
if (message) return message;
|
|
3527
|
-
const data = asRecord(
|
|
3613
|
+
const data = asRecord(record3.data);
|
|
3528
3614
|
const nestedMessage = readString(data.message);
|
|
3529
3615
|
if (nestedMessage) return nestedMessage;
|
|
3530
|
-
return readString(
|
|
3616
|
+
return readString(record3.name) ?? readString(record3.code) ?? "";
|
|
3531
3617
|
}
|
|
3532
3618
|
function parseOpenCodeJsonl(stdout) {
|
|
3533
3619
|
let sessionId = null;
|
|
@@ -3565,8 +3651,8 @@ function parseOpenCodeJsonl(stdout) {
|
|
|
3565
3651
|
return { sessionId, summary, usage, errorMessage };
|
|
3566
3652
|
}
|
|
3567
3653
|
function piMessageText(message) {
|
|
3568
|
-
const
|
|
3569
|
-
const content =
|
|
3654
|
+
const record3 = asRecord(message);
|
|
3655
|
+
const content = record3.content;
|
|
3570
3656
|
if (typeof content === "string") return content.trim();
|
|
3571
3657
|
if (!Array.isArray(content)) return "";
|
|
3572
3658
|
return content.map((entry) => {
|
|
@@ -3591,10 +3677,10 @@ function piTextValue(value) {
|
|
|
3591
3677
|
return typeof value === "string" && value.length > 0 ? value : "";
|
|
3592
3678
|
}
|
|
3593
3679
|
function piAssistantEventText(assistantEvent) {
|
|
3594
|
-
const
|
|
3595
|
-
const type = readString(
|
|
3596
|
-
if (type === "text_delta") return piTextValue(
|
|
3597
|
-
if (type === "text_end") return piTextValue(
|
|
3680
|
+
const record3 = asRecord(assistantEvent);
|
|
3681
|
+
const type = readString(record3.type);
|
|
3682
|
+
if (type === "text_delta") return piTextValue(record3.delta);
|
|
3683
|
+
if (type === "text_end") return piTextValue(record3.content);
|
|
3598
3684
|
return "";
|
|
3599
3685
|
}
|
|
3600
3686
|
function piMessageUsage(message) {
|
|
@@ -3615,14 +3701,14 @@ function assignPiUsage(target, source) {
|
|
|
3615
3701
|
if (source.costUsd > 0) target.costUsd = source.costUsd;
|
|
3616
3702
|
}
|
|
3617
3703
|
function piMessageStopReason(message) {
|
|
3618
|
-
const
|
|
3619
|
-
return readString(
|
|
3704
|
+
const record3 = asRecord(message);
|
|
3705
|
+
return readString(record3.stopReason ?? record3.stop_reason);
|
|
3620
3706
|
}
|
|
3621
3707
|
function piMessageErrorText(message) {
|
|
3622
|
-
const
|
|
3623
|
-
const explicitError = readString(
|
|
3708
|
+
const record3 = asRecord(message);
|
|
3709
|
+
const explicitError = readString(record3.errorMessage ?? record3.error_message)?.trim();
|
|
3624
3710
|
if (explicitError) return explicitError;
|
|
3625
|
-
const stopReason = piMessageStopReason(
|
|
3711
|
+
const stopReason = piMessageStopReason(record3);
|
|
3626
3712
|
if (stopReason === "error" || stopReason === "failed" || stopReason === "exception") {
|
|
3627
3713
|
return `Pi Agent message ended with stopReason=${stopReason}`;
|
|
3628
3714
|
}
|
|
@@ -3889,7 +3975,7 @@ async function postRuntimeConnectorJsonWithRetry(config, path, payload, options
|
|
|
3889
3975
|
} catch (error) {
|
|
3890
3976
|
lastError = error;
|
|
3891
3977
|
if (attempt >= maxAttempts || !retryableRuntimeConnectorPost(error)) throw error;
|
|
3892
|
-
if (delayMs > 0) await new Promise((
|
|
3978
|
+
if (delayMs > 0) await new Promise((resolve11) => setTimeout(resolve11, delayMs));
|
|
3893
3979
|
}
|
|
3894
3980
|
}
|
|
3895
3981
|
throw lastError;
|
|
@@ -4475,11 +4561,574 @@ function summarizeAmasterRuntimeVersionDrift(input = {}) {
|
|
|
4475
4561
|
};
|
|
4476
4562
|
}
|
|
4477
4563
|
|
|
4564
|
+
// src/amaster-runtime-daemon/pi-child-isolation.mjs
|
|
4565
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
4566
|
+
import {
|
|
4567
|
+
chmodSync as chmodSync3,
|
|
4568
|
+
chownSync,
|
|
4569
|
+
lchownSync,
|
|
4570
|
+
lstatSync as lstatSync4,
|
|
4571
|
+
readdirSync as readdirSync5
|
|
4572
|
+
} from "node:fs";
|
|
4573
|
+
import { resolve as resolve7, sep } from "node:path";
|
|
4574
|
+
function defaultHashRunId(runId) {
|
|
4575
|
+
return Number.parseInt(createHash5("sha256").update(runId).digest("hex").slice(0, 8), 16);
|
|
4576
|
+
}
|
|
4577
|
+
function positiveInteger(value, label) {
|
|
4578
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
4579
|
+
throw new Error(`pi_child_isolation_invalid_${label}`);
|
|
4580
|
+
}
|
|
4581
|
+
return value;
|
|
4582
|
+
}
|
|
4583
|
+
function isWithin(path, root) {
|
|
4584
|
+
const normalizedPath = resolve7(path);
|
|
4585
|
+
const normalizedRoot = resolve7(root);
|
|
4586
|
+
return normalizedPath === normalizedRoot || normalizedPath.startsWith(`${normalizedRoot}${sep}`);
|
|
4587
|
+
}
|
|
4588
|
+
function isolatePiChildPath(path, uid, gid) {
|
|
4589
|
+
const resolvedPath = resolve7(path);
|
|
4590
|
+
const visit = (entryPath) => {
|
|
4591
|
+
const stat = lstatSync4(entryPath);
|
|
4592
|
+
if (stat.isSymbolicLink()) {
|
|
4593
|
+
lchownSync(entryPath, uid, gid);
|
|
4594
|
+
return;
|
|
4595
|
+
}
|
|
4596
|
+
chownSync(entryPath, uid, gid);
|
|
4597
|
+
if (stat.isDirectory()) {
|
|
4598
|
+
chmodSync3(entryPath, 448);
|
|
4599
|
+
for (const entry of readdirSync5(entryPath)) {
|
|
4600
|
+
visit(resolve7(entryPath, entry));
|
|
4601
|
+
}
|
|
4602
|
+
return;
|
|
4603
|
+
}
|
|
4604
|
+
chmodSync3(entryPath, 384 | stat.mode & 73);
|
|
4605
|
+
};
|
|
4606
|
+
visit(resolvedPath);
|
|
4607
|
+
}
|
|
4608
|
+
function createPiChildIdentityAllocator(input = {}) {
|
|
4609
|
+
const uidBase = positiveInteger(input.uidBase ?? 2e4, "uid_base");
|
|
4610
|
+
const uidSpan = positiveInteger(input.uidSpan ?? 3e4, "uid_span");
|
|
4611
|
+
const hashRunId = input.hashRunId ?? defaultHashRunId;
|
|
4612
|
+
const runAssignments = /* @__PURE__ */ new Map();
|
|
4613
|
+
const uidAssignments = /* @__PURE__ */ new Map();
|
|
4614
|
+
return {
|
|
4615
|
+
acquire(runId) {
|
|
4616
|
+
if (typeof runId !== "string" || runId.trim().length === 0) {
|
|
4617
|
+
throw new Error("pi_child_isolation_run_id_required");
|
|
4618
|
+
}
|
|
4619
|
+
const normalizedRunId = runId.trim();
|
|
4620
|
+
const existing = runAssignments.get(normalizedRunId);
|
|
4621
|
+
if (existing) return { ...existing };
|
|
4622
|
+
const initialOffset = Math.abs(hashRunId(normalizedRunId)) % uidSpan;
|
|
4623
|
+
for (let attempt = 0; attempt < uidSpan; attempt += 1) {
|
|
4624
|
+
const uid = uidBase + (initialOffset + attempt) % uidSpan;
|
|
4625
|
+
if (uidAssignments.has(uid)) continue;
|
|
4626
|
+
const assignment = { uid, gid: uid };
|
|
4627
|
+
runAssignments.set(normalizedRunId, assignment);
|
|
4628
|
+
uidAssignments.set(uid, normalizedRunId);
|
|
4629
|
+
return { ...assignment };
|
|
4630
|
+
}
|
|
4631
|
+
throw new Error("pi_child_isolation_uid_pool_exhausted");
|
|
4632
|
+
},
|
|
4633
|
+
release(runId) {
|
|
4634
|
+
const assignment = runAssignments.get(runId);
|
|
4635
|
+
if (!assignment) return false;
|
|
4636
|
+
runAssignments.delete(runId);
|
|
4637
|
+
uidAssignments.delete(assignment.uid);
|
|
4638
|
+
return true;
|
|
4639
|
+
},
|
|
4640
|
+
activeAssignments() {
|
|
4641
|
+
return Array.from(runAssignments, ([runId, assignment]) => ({ runId, ...assignment }));
|
|
4642
|
+
}
|
|
4643
|
+
};
|
|
4644
|
+
}
|
|
4645
|
+
function piChildIsolationProfileRoot(input) {
|
|
4646
|
+
const managedProfileRoot = input.managedMcpProfile?.profileRoot;
|
|
4647
|
+
if (typeof managedProfileRoot === "string" && managedProfileRoot.trim() !== "") {
|
|
4648
|
+
return managedProfileRoot;
|
|
4649
|
+
}
|
|
4650
|
+
return input.executorHome;
|
|
4651
|
+
}
|
|
4652
|
+
function requireTrustedPiChildAllocator(allocator, trustedRuntimeEnabled) {
|
|
4653
|
+
if (trustedRuntimeEnabled && !allocator) {
|
|
4654
|
+
throw new Error("pi_trusted_runtime_child_isolation_required");
|
|
4655
|
+
}
|
|
4656
|
+
return allocator;
|
|
4657
|
+
}
|
|
4658
|
+
function preparePiChildIsolation(input) {
|
|
4659
|
+
if (input.effectiveUid !== 0) {
|
|
4660
|
+
throw new Error("pi_child_isolation_root_parent_required");
|
|
4661
|
+
}
|
|
4662
|
+
if (!isWithin(input.profileRoot, input.allowedRoot) || !isWithin(input.workspaceRoot, input.allowedRoot)) {
|
|
4663
|
+
throw new Error("pi_child_isolation_path_outside_run_root");
|
|
4664
|
+
}
|
|
4665
|
+
const assignment = input.allocator.acquire(input.runId);
|
|
4666
|
+
const isolatePath = input.isolatePath ?? isolatePiChildPath;
|
|
4667
|
+
try {
|
|
4668
|
+
for (const path of [resolve7(input.profileRoot), resolve7(input.workspaceRoot)]) {
|
|
4669
|
+
isolatePath(path, assignment.uid, assignment.gid);
|
|
4670
|
+
}
|
|
4671
|
+
} catch (error) {
|
|
4672
|
+
input.allocator.release(input.runId);
|
|
4673
|
+
throw error;
|
|
4674
|
+
}
|
|
4675
|
+
return {
|
|
4676
|
+
spawn: { uid: assignment.uid, gid: assignment.gid },
|
|
4677
|
+
attestation: {
|
|
4678
|
+
schemaVersion: "amaster.pi-child-isolation.v1",
|
|
4679
|
+
commandId: input.commandId,
|
|
4680
|
+
runId: input.runId,
|
|
4681
|
+
identity: `dynamic-uid:${assignment.uid}`,
|
|
4682
|
+
profileRoot: resolve7(input.profileRoot),
|
|
4683
|
+
workspaceRoot: resolve7(input.workspaceRoot)
|
|
4684
|
+
},
|
|
4685
|
+
release: () => input.allocator.release(input.runId)
|
|
4686
|
+
};
|
|
4687
|
+
}
|
|
4688
|
+
|
|
4689
|
+
// src/amaster-runtime-daemon/pi-trusted-runtime-profile.mjs
|
|
4690
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
4691
|
+
import {
|
|
4692
|
+
chmodSync as chmodSync4,
|
|
4693
|
+
copyFileSync as copyFileSync2,
|
|
4694
|
+
existsSync as existsSync8,
|
|
4695
|
+
lstatSync as lstatSync5,
|
|
4696
|
+
mkdirSync as mkdirSync5,
|
|
4697
|
+
readFileSync as readFileSync6,
|
|
4698
|
+
readdirSync as readdirSync6,
|
|
4699
|
+
rmSync as rmSync5,
|
|
4700
|
+
symlinkSync as symlinkSync2,
|
|
4701
|
+
writeFileSync as writeFileSync5
|
|
4702
|
+
} from "node:fs";
|
|
4703
|
+
import { dirname as dirname6, isAbsolute as isAbsolute5, join as join9, relative as relative5, resolve as resolve8 } from "node:path";
|
|
4704
|
+
var ASSERTION_VERSION = "2026-07-25.v1";
|
|
4705
|
+
var SHA256 = /^[a-f0-9]{64}$/;
|
|
4706
|
+
var COPY_ENTRIES = ["SYSTEM.md", "policy", "skills", "agents", "bundles", "extensions"];
|
|
4707
|
+
var JSON_ENTRIES = ["settings.json", "models.json"];
|
|
4708
|
+
var SECRET_KEY = /(authorization|cookie|api[_-]?key|password|secret|token)$/i;
|
|
4709
|
+
var SECRET_VALUE = /(?:authorization|cookie|api[_-]?key|password|secret|token)\s*[:=]\s*(?:bearer\s+)?[^\s"',;]+|bearer\s+[^\s"',;]+/i;
|
|
4710
|
+
var MAX_AUDIT_BYTES = 1024 * 1024;
|
|
4711
|
+
var MAX_AUDIT_EVENTS = 2e3;
|
|
4712
|
+
function requiredString2(value, field) {
|
|
4713
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
4714
|
+
throw new Error(`pi_trusted_runtime_assertion_invalid:${field}`);
|
|
4715
|
+
}
|
|
4716
|
+
return value.trim();
|
|
4717
|
+
}
|
|
4718
|
+
function requiredDigest(value, field) {
|
|
4719
|
+
const digest = requiredString2(value, field);
|
|
4720
|
+
if (!SHA256.test(digest)) throw new Error(`pi_trusted_runtime_assertion_invalid:${field}`);
|
|
4721
|
+
return digest;
|
|
4722
|
+
}
|
|
4723
|
+
function sha256File(path, label) {
|
|
4724
|
+
const stat = lstatSync5(path);
|
|
4725
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
4726
|
+
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
4727
|
+
}
|
|
4728
|
+
return createHash6("sha256").update(readFileSync6(path)).digest("hex");
|
|
4729
|
+
}
|
|
4730
|
+
function verifyDeclaredFiles(manifest, root, label, ignoredPaths = [], enforceComplete = true) {
|
|
4731
|
+
if (!Array.isArray(manifest.files) || manifest.files.length === 0) {
|
|
4732
|
+
throw new Error(`pi_trusted_runtime_source_invalid:${label}_files`);
|
|
4733
|
+
}
|
|
4734
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4735
|
+
for (const entry of manifest.files) {
|
|
4736
|
+
const relativePath = requiredString2(entry?.path, `${label}.files.path`);
|
|
4737
|
+
const expectedDigest = requiredDigest(entry?.sha256, `${label}.files.sha256`);
|
|
4738
|
+
const filePath = resolve8(root, relativePath);
|
|
4739
|
+
if (!within2(filePath, root) || seen.has(relativePath)) {
|
|
4740
|
+
throw new Error(`pi_trusted_runtime_source_invalid:${label}_files`);
|
|
4741
|
+
}
|
|
4742
|
+
seen.add(relativePath);
|
|
4743
|
+
if (sha256File(filePath, `${label}_file`) !== expectedDigest) {
|
|
4744
|
+
throw new Error(`pi_trusted_runtime_source_digest_mismatch:${label}:${relativePath}`);
|
|
4745
|
+
}
|
|
4746
|
+
}
|
|
4747
|
+
if (!enforceComplete) return;
|
|
4748
|
+
const ignored = new Set(ignoredPaths);
|
|
4749
|
+
const visit = (directory) => {
|
|
4750
|
+
for (const entry of readdirSync6(directory)) {
|
|
4751
|
+
const filePath = join9(directory, entry);
|
|
4752
|
+
const relativePath = relative5(root, filePath);
|
|
4753
|
+
if (ignored.has(relativePath)) continue;
|
|
4754
|
+
const stat = lstatSync5(filePath);
|
|
4755
|
+
if (stat.isSymbolicLink()) {
|
|
4756
|
+
throw new Error(`pi_trusted_runtime_source_unsafe:${label}_file`);
|
|
4757
|
+
}
|
|
4758
|
+
if (stat.isDirectory()) {
|
|
4759
|
+
visit(filePath);
|
|
4760
|
+
} else if (!stat.isFile() || !seen.has(relativePath)) {
|
|
4761
|
+
throw new Error(`pi_trusted_runtime_source_invalid:${label}_files`);
|
|
4762
|
+
}
|
|
4763
|
+
}
|
|
4764
|
+
};
|
|
4765
|
+
visit(root);
|
|
4766
|
+
}
|
|
4767
|
+
function record2(value) {
|
|
4768
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
4769
|
+
}
|
|
4770
|
+
function within2(candidate, root) {
|
|
4771
|
+
const rel = relative5(root, candidate);
|
|
4772
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute5(rel);
|
|
4773
|
+
}
|
|
4774
|
+
function readJsonFile(path, label, fallback = {}) {
|
|
4775
|
+
if (!existsSync8(path)) return fallback;
|
|
4776
|
+
const stat = lstatSync5(path);
|
|
4777
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
4778
|
+
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
4779
|
+
}
|
|
4780
|
+
try {
|
|
4781
|
+
return JSON.parse(readFileSync6(path, "utf8"));
|
|
4782
|
+
} catch {
|
|
4783
|
+
throw new Error(`pi_trusted_runtime_source_invalid:${label}`);
|
|
4784
|
+
}
|
|
4785
|
+
}
|
|
4786
|
+
function deepMerge(base, overlay) {
|
|
4787
|
+
if (!base || typeof base !== "object" || Array.isArray(base)) return structuredClone(overlay);
|
|
4788
|
+
if (!overlay || typeof overlay !== "object" || Array.isArray(overlay)) return structuredClone(overlay);
|
|
4789
|
+
const merged = { ...structuredClone(base) };
|
|
4790
|
+
for (const [key, value] of Object.entries(overlay)) {
|
|
4791
|
+
merged[key] = key in merged ? deepMerge(merged[key], value) : structuredClone(value);
|
|
4792
|
+
}
|
|
4793
|
+
return merged;
|
|
4794
|
+
}
|
|
4795
|
+
function assertNoPersistentSecrets(value, path = []) {
|
|
4796
|
+
if (Array.isArray(value)) {
|
|
4797
|
+
value.forEach((entry, index) => assertNoPersistentSecrets(entry, [...path, String(index)]));
|
|
4798
|
+
return;
|
|
4799
|
+
}
|
|
4800
|
+
if (!value || typeof value !== "object") return;
|
|
4801
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
4802
|
+
if (SECRET_KEY.test(key) && typeof entry === "string" && entry.length > 0 && !/^\$\{[A-Z_][A-Z0-9_]*\}$/.test(entry)) {
|
|
4803
|
+
throw new Error(`pi_trusted_runtime_persistent_secret_blocked:${[...path, key].join(".")}`);
|
|
4804
|
+
}
|
|
4805
|
+
assertNoPersistentSecrets(entry, [...path, key]);
|
|
4806
|
+
}
|
|
4807
|
+
}
|
|
4808
|
+
function copyTreeNoLinks(source, target) {
|
|
4809
|
+
const stat = lstatSync5(source);
|
|
4810
|
+
if (stat.isSymbolicLink()) throw new Error("pi_trusted_runtime_source_symlink_blocked");
|
|
4811
|
+
if (stat.isDirectory()) {
|
|
4812
|
+
mkdirSync5(target, { recursive: true, mode: 448 });
|
|
4813
|
+
chmodSync4(target, 448);
|
|
4814
|
+
for (const entry of readdirSync6(source)) {
|
|
4815
|
+
copyTreeNoLinks(join9(source, entry), join9(target, entry));
|
|
4816
|
+
}
|
|
4817
|
+
return;
|
|
4818
|
+
}
|
|
4819
|
+
if (!stat.isFile()) throw new Error("pi_trusted_runtime_source_type_blocked");
|
|
4820
|
+
mkdirSync5(dirname6(target), { recursive: true, mode: 448 });
|
|
4821
|
+
copyFileSync2(source, target);
|
|
4822
|
+
chmodSync4(target, 384 | stat.mode & 73);
|
|
4823
|
+
}
|
|
4824
|
+
function mergeMcp(seedRoot, overlayRoot, governedConfig) {
|
|
4825
|
+
const seed = record2(readJsonFile(join9(seedRoot, "mcp.json"), "seed_mcp", { mcpServers: {} }));
|
|
4826
|
+
const overlay = record2(readJsonFile(join9(overlayRoot, "mcp.json"), "overlay_mcp", { mcpServers: {} }));
|
|
4827
|
+
assertNoPersistentSecrets(seed, ["seed", "mcp.json"]);
|
|
4828
|
+
assertNoPersistentSecrets(overlay, ["overlay", "mcp.json"]);
|
|
4829
|
+
const seedServers = record2(seed.mcpServers);
|
|
4830
|
+
const overlayServers = record2(overlay.mcpServers);
|
|
4831
|
+
if ("amaster" in seedServers || "amaster" in overlayServers) {
|
|
4832
|
+
throw new Error("pi_trusted_runtime_reserved_mcp_override:amaster");
|
|
4833
|
+
}
|
|
4834
|
+
const governed = record2(record2(governedConfig).mcpServers).amaster;
|
|
4835
|
+
if (!governed) throw new Error("pi_trusted_runtime_governed_mcp_missing");
|
|
4836
|
+
return {
|
|
4837
|
+
...deepMerge(seed, overlay),
|
|
4838
|
+
mcpServers: {
|
|
4839
|
+
...deepMerge(seedServers, overlayServers),
|
|
4840
|
+
amaster: governed
|
|
4841
|
+
}
|
|
4842
|
+
};
|
|
4843
|
+
}
|
|
4844
|
+
function packageName(spec) {
|
|
4845
|
+
if (typeof spec !== "string" || !spec.startsWith("npm:")) return null;
|
|
4846
|
+
const value = spec.slice(4);
|
|
4847
|
+
const separator = value.startsWith("@") ? value.indexOf("@", 1) : value.indexOf("@");
|
|
4848
|
+
return separator < 0 ? value : value.slice(0, separator);
|
|
4849
|
+
}
|
|
4850
|
+
function assertEnabledPackagesAvailable(settings, npmRoot) {
|
|
4851
|
+
const requiredNames = new Set(
|
|
4852
|
+
(Array.isArray(settings.packages) ? settings.packages : []).map(packageName).filter(Boolean)
|
|
4853
|
+
);
|
|
4854
|
+
for (const plugin of Object.values(record2(settings.plugins))) {
|
|
4855
|
+
const config = record2(plugin);
|
|
4856
|
+
if (config.enabled === true && typeof config.package === "string") {
|
|
4857
|
+
requiredNames.add(config.package);
|
|
4858
|
+
}
|
|
4859
|
+
}
|
|
4860
|
+
for (const name of requiredNames) {
|
|
4861
|
+
const metadataPath = join9(npmRoot, "node_modules", ...name.split("/"), "package.json");
|
|
4862
|
+
const metadata = readJsonFile(metadataPath, `package:${name}`, null);
|
|
4863
|
+
if (!metadata || metadata.name !== name) {
|
|
4864
|
+
throw new Error(`pi_trusted_runtime_package_unavailable:${name}`);
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
}
|
|
4868
|
+
function materializeTrustedPiRuntimeProfile(input) {
|
|
4869
|
+
const seedRoot = resolve8(requiredString2(input.seedRoot, "seedRoot"));
|
|
4870
|
+
const overlayRoot = resolve8(requiredString2(input.overlayRoot, "overlayRoot"));
|
|
4871
|
+
const profileRoot = resolve8(requiredString2(input.profileRoot, "profileRoot"));
|
|
4872
|
+
const agentDir = resolve8(requiredString2(input.agentDir, "agentDir"));
|
|
4873
|
+
if (!within2(agentDir, profileRoot)) throw new Error("pi_trusted_runtime_profile_path_escape");
|
|
4874
|
+
for (const [root, label] of [[seedRoot, "seed_root"], [overlayRoot, "overlay_root"]]) {
|
|
4875
|
+
const stat = lstatSync5(root);
|
|
4876
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
4877
|
+
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
4878
|
+
}
|
|
4879
|
+
}
|
|
4880
|
+
for (const entry of COPY_ENTRIES) {
|
|
4881
|
+
const target = join9(agentDir, entry);
|
|
4882
|
+
rmSync5(target, { recursive: true, force: true });
|
|
4883
|
+
for (const sourceRoot of [seedRoot, overlayRoot]) {
|
|
4884
|
+
const source = join9(sourceRoot, entry);
|
|
4885
|
+
if (existsSync8(source)) copyTreeNoLinks(source, target);
|
|
4886
|
+
}
|
|
4887
|
+
}
|
|
4888
|
+
const mergedJson = {};
|
|
4889
|
+
for (const entry of JSON_ENTRIES) {
|
|
4890
|
+
const seed = readJsonFile(join9(seedRoot, entry), `seed_${entry}`, {});
|
|
4891
|
+
const overlay = readJsonFile(join9(overlayRoot, entry), `overlay_${entry}`, {});
|
|
4892
|
+
const merged = deepMerge(seed, overlay);
|
|
4893
|
+
if (entry === "settings.json") {
|
|
4894
|
+
merged["pi-security"] = {
|
|
4895
|
+
...record2(merged["pi-security"]),
|
|
4896
|
+
enabled: true,
|
|
4897
|
+
approvals: {
|
|
4898
|
+
...record2(record2(merged["pi-security"]).approvals),
|
|
4899
|
+
allowSessionGrants: false
|
|
4900
|
+
}
|
|
4901
|
+
};
|
|
4902
|
+
}
|
|
4903
|
+
assertNoPersistentSecrets(merged, [entry]);
|
|
4904
|
+
writeFileSync5(join9(agentDir, entry), `${JSON.stringify(merged, null, 2)}
|
|
4905
|
+
`, {
|
|
4906
|
+
mode: 384
|
|
4907
|
+
});
|
|
4908
|
+
chmodSync4(join9(agentDir, entry), 384);
|
|
4909
|
+
mergedJson[entry] = merged;
|
|
4910
|
+
}
|
|
4911
|
+
const governedConfig = readJsonFile(input.governedMcpConfigPath, "governed_mcp");
|
|
4912
|
+
const mcp = mergeMcp(seedRoot, overlayRoot, governedConfig);
|
|
4913
|
+
writeFileSync5(input.governedMcpConfigPath, `${JSON.stringify(mcp, null, 2)}
|
|
4914
|
+
`, { mode: 384 });
|
|
4915
|
+
chmodSync4(input.governedMcpConfigPath, 384);
|
|
4916
|
+
const npmRoot = join9(seedRoot, "npm");
|
|
4917
|
+
assertEnabledPackagesAvailable(mergedJson["settings.json"], npmRoot);
|
|
4918
|
+
const npmTarget = join9(agentDir, "npm");
|
|
4919
|
+
rmSync5(npmTarget, { recursive: true, force: true });
|
|
4920
|
+
const npmStat = lstatSync5(npmRoot);
|
|
4921
|
+
if (!npmStat.isDirectory() || npmStat.isSymbolicLink()) {
|
|
4922
|
+
throw new Error("pi_trusted_runtime_source_unsafe:seed_npm");
|
|
4923
|
+
}
|
|
4924
|
+
symlinkSync2(npmRoot, npmTarget, "dir");
|
|
4925
|
+
const facts = {
|
|
4926
|
+
schemaVersion: "amaster.trusted-pi-profile.v1",
|
|
4927
|
+
seedManifestDigest: input.verifiedAssertion.digests.seedManifestDigest,
|
|
4928
|
+
runtimeOverlayDigest: input.verifiedAssertion.digests.runtimeOverlayDigest,
|
|
4929
|
+
effectivePolicyDigest: input.verifiedAssertion.digests.effectivePolicyDigest,
|
|
4930
|
+
runtimeEnforcementDigest: input.verifiedAssertion.digests.runtimeEnforcementDigest,
|
|
4931
|
+
unknownToolMode: input.verifiedAssertion.unknownToolMode,
|
|
4932
|
+
directToolBudget: input.verifiedAssertion.directToolBudget,
|
|
4933
|
+
inheritedEntries: [...COPY_ENTRIES, ...JSON_ENTRIES, "mcp.json", "npm"]
|
|
4934
|
+
};
|
|
4935
|
+
return {
|
|
4936
|
+
facts,
|
|
4937
|
+
attestationId: createHash6("sha256").update(JSON.stringify(facts)).digest("hex")
|
|
4938
|
+
};
|
|
4939
|
+
}
|
|
4940
|
+
function assertAuditArgsRedacted(value) {
|
|
4941
|
+
if (Array.isArray(value)) {
|
|
4942
|
+
value.forEach(assertAuditArgsRedacted);
|
|
4943
|
+
return;
|
|
4944
|
+
}
|
|
4945
|
+
if (typeof value === "string") {
|
|
4946
|
+
if (SECRET_VALUE.test(value)) {
|
|
4947
|
+
throw new Error("pi_trusted_runtime_audit_secret_not_redacted");
|
|
4948
|
+
}
|
|
4949
|
+
return;
|
|
4950
|
+
}
|
|
4951
|
+
if (!value || typeof value !== "object") return;
|
|
4952
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
4953
|
+
if (SECRET_KEY.test(key) && entry !== "[redacted]") {
|
|
4954
|
+
throw new Error("pi_trusted_runtime_audit_secret_not_redacted");
|
|
4955
|
+
}
|
|
4956
|
+
assertAuditArgsRedacted(entry);
|
|
4957
|
+
}
|
|
4958
|
+
}
|
|
4959
|
+
function readTrustedPiRuntimeAudit(input) {
|
|
4960
|
+
const profileRoot = resolve8(requiredString2(input.profileRoot, "profileRoot"));
|
|
4961
|
+
const auditFile = resolve8(requiredString2(input.auditFile, "auditFile"));
|
|
4962
|
+
if (!within2(auditFile, profileRoot)) throw new Error("pi_trusted_runtime_audit_path_escape");
|
|
4963
|
+
if (!existsSync8(auditFile)) throw new Error("pi_trusted_runtime_audit_startup_missing");
|
|
4964
|
+
const stat = lstatSync5(auditFile);
|
|
4965
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
4966
|
+
throw new Error("pi_trusted_runtime_audit_unsafe");
|
|
4967
|
+
}
|
|
4968
|
+
if (stat.size > MAX_AUDIT_BYTES) throw new Error("pi_trusted_runtime_audit_too_large");
|
|
4969
|
+
const lines = readFileSync6(auditFile, "utf8").split("\n").filter(Boolean);
|
|
4970
|
+
if (lines.length === 0 || lines.length > MAX_AUDIT_EVENTS) {
|
|
4971
|
+
throw new Error("pi_trusted_runtime_audit_event_count_invalid");
|
|
4972
|
+
}
|
|
4973
|
+
let decisions = 0;
|
|
4974
|
+
let outcomes = 0;
|
|
4975
|
+
let startupSeen = false;
|
|
4976
|
+
const decisionBySequence = /* @__PURE__ */ new Map();
|
|
4977
|
+
const outcomeSequences = /* @__PURE__ */ new Set();
|
|
4978
|
+
const events = lines.map((line) => {
|
|
4979
|
+
let event;
|
|
4980
|
+
try {
|
|
4981
|
+
event = JSON.parse(line);
|
|
4982
|
+
} catch {
|
|
4983
|
+
throw new Error("pi_trusted_runtime_audit_invalid_json");
|
|
4984
|
+
}
|
|
4985
|
+
if (event?.schemaVersion !== "amaster.managed-runtime-audit.v1" || event.commandId !== input.commandId || event.runId !== input.runId || !Number.isInteger(event.sequence) || event.sequence < 0) throw new Error("pi_trusted_runtime_audit_binding_mismatch");
|
|
4986
|
+
if (event.event === "decision") {
|
|
4987
|
+
decisions += 1;
|
|
4988
|
+
if (event.sequence !== decisions || decisionBySequence.has(event.sequence) || typeof event.toolCallId !== "string" || event.toolCallId === "" || typeof event.toolName !== "string" || event.toolName === "" || !["allow", "deny"].includes(event.decision)) {
|
|
4989
|
+
throw new Error("pi_trusted_runtime_audit_sequence_invalid");
|
|
4990
|
+
}
|
|
4991
|
+
decisionBySequence.set(event.sequence, event);
|
|
4992
|
+
assertAuditArgsRedacted(event.args);
|
|
4993
|
+
} else if (event.event === "outcome") {
|
|
4994
|
+
outcomes += 1;
|
|
4995
|
+
const decision = decisionBySequence.get(event.sequence);
|
|
4996
|
+
if (!decision || decision.decision !== "allow" || outcomeSequences.has(event.sequence) || event.toolCallId !== decision.toolCallId || event.toolName !== decision.toolName || !["success", "error"].includes(event.outcome)) {
|
|
4997
|
+
throw new Error("pi_trusted_runtime_audit_outcome_without_decision");
|
|
4998
|
+
}
|
|
4999
|
+
outcomeSequences.add(event.sequence);
|
|
5000
|
+
} else if (event.event !== "startup" || startupSeen || event.sequence !== 0 || event.assertionValid !== true || event.runtimeEnforcementDigest !== input.runtimeEnforcementDigest) {
|
|
5001
|
+
throw new Error("pi_trusted_runtime_audit_startup_invalid");
|
|
5002
|
+
}
|
|
5003
|
+
if (event.event === "startup") startupSeen = true;
|
|
5004
|
+
return event;
|
|
5005
|
+
});
|
|
5006
|
+
if (events[0]?.event !== "startup") throw new Error("pi_trusted_runtime_audit_startup_missing");
|
|
5007
|
+
return {
|
|
5008
|
+
schemaVersion: "amaster.managed-runtime-audit-summary.v1",
|
|
5009
|
+
decisionCount: decisions,
|
|
5010
|
+
outcomeCount: outcomes,
|
|
5011
|
+
deniedCount: events.filter((event) => event.event === "decision" && event.decision === "deny").length,
|
|
5012
|
+
maxSequence: decisions,
|
|
5013
|
+
events
|
|
5014
|
+
};
|
|
5015
|
+
}
|
|
5016
|
+
function readTrustedPiRuntimeLocalDigests(input) {
|
|
5017
|
+
const seedRoot = resolve8(requiredString2(input.seedRoot, "seedRoot"));
|
|
5018
|
+
const overlayRoot = resolve8(requiredString2(input.overlayRoot, "overlayRoot"));
|
|
5019
|
+
const policyFile = resolve8(requiredString2(input.policyFile, "policyFile"));
|
|
5020
|
+
for (const [path, label] of [[seedRoot, "seed_root"], [overlayRoot, "overlay_root"]]) {
|
|
5021
|
+
const stat = lstatSync5(path);
|
|
5022
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
5023
|
+
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
5024
|
+
}
|
|
5025
|
+
}
|
|
5026
|
+
const seedManifestFile = join9(seedRoot, "seed-manifest.json");
|
|
5027
|
+
const overlayManifestFile = join9(overlayRoot, "runtime-overlay-manifest.json");
|
|
5028
|
+
const seedManifest = JSON.parse(readFileSync6(seedManifestFile, "utf8"));
|
|
5029
|
+
const overlayManifest = JSON.parse(readFileSync6(overlayManifestFile, "utf8"));
|
|
5030
|
+
const policyManifest = JSON.parse(readFileSync6(policyFile, "utf8"));
|
|
5031
|
+
verifyDeclaredFiles(seedManifest, seedRoot, "seed", ["seed-manifest.json"]);
|
|
5032
|
+
verifyDeclaredFiles(overlayManifest, overlayRoot, "overlay", ["runtime-overlay-manifest.json"]);
|
|
5033
|
+
verifyDeclaredFiles(
|
|
5034
|
+
policyManifest,
|
|
5035
|
+
dirname6(policyFile),
|
|
5036
|
+
"policy",
|
|
5037
|
+
[relative5(dirname6(policyFile), policyFile)],
|
|
5038
|
+
false
|
|
5039
|
+
);
|
|
5040
|
+
return {
|
|
5041
|
+
seedManifestDigest: sha256File(seedManifestFile, "seed_manifest"),
|
|
5042
|
+
runtimeOverlayDigest: sha256File(overlayManifestFile, "runtime_overlay_manifest"),
|
|
5043
|
+
effectivePolicyDigest: sha256File(policyFile, "effective_policy"),
|
|
5044
|
+
runtimeEnforcementDigest: requiredDigest(
|
|
5045
|
+
seedManifest.runtimeEnforcementDigest,
|
|
5046
|
+
"runtimeEnforcementDigest"
|
|
5047
|
+
)
|
|
5048
|
+
};
|
|
5049
|
+
}
|
|
5050
|
+
function createTrustedPiRuntimeProvenanceCache(input = {}) {
|
|
5051
|
+
const readDigests = input.readDigests ?? readTrustedPiRuntimeLocalDigests;
|
|
5052
|
+
let cachedKey = null;
|
|
5053
|
+
let cachedDigests = null;
|
|
5054
|
+
return {
|
|
5055
|
+
read(paths) {
|
|
5056
|
+
const key = JSON.stringify([
|
|
5057
|
+
paths.seedRoot,
|
|
5058
|
+
paths.overlayRoot,
|
|
5059
|
+
paths.policyFile
|
|
5060
|
+
]);
|
|
5061
|
+
if (cachedDigests && cachedKey === key) return cachedDigests;
|
|
5062
|
+
cachedDigests = readDigests(paths);
|
|
5063
|
+
cachedKey = key;
|
|
5064
|
+
return cachedDigests;
|
|
5065
|
+
}
|
|
5066
|
+
};
|
|
5067
|
+
}
|
|
5068
|
+
function verifyTrustedPiRuntimeAssertion(input) {
|
|
5069
|
+
const assertion = input.assertion;
|
|
5070
|
+
if (!assertion || typeof assertion !== "object" || Array.isArray(assertion)) {
|
|
5071
|
+
throw new Error("pi_trusted_runtime_assertion_missing");
|
|
5072
|
+
}
|
|
5073
|
+
if (assertion.version !== ASSERTION_VERSION) {
|
|
5074
|
+
throw new Error("pi_trusted_runtime_assertion_invalid:version");
|
|
5075
|
+
}
|
|
5076
|
+
const bindings = {
|
|
5077
|
+
connectorId: input.connectorId,
|
|
5078
|
+
commandId: input.commandId,
|
|
5079
|
+
runId: input.runId,
|
|
5080
|
+
leaseId: input.leaseId,
|
|
5081
|
+
executorKind: input.executorKind
|
|
5082
|
+
};
|
|
5083
|
+
requiredString2(assertion.attestationId, "attestationId");
|
|
5084
|
+
for (const [field, expected] of Object.entries(bindings)) {
|
|
5085
|
+
if (requiredString2(assertion[field], field) !== expected) {
|
|
5086
|
+
throw new Error(`pi_trusted_runtime_assertion_binding_mismatch:${field}`);
|
|
5087
|
+
}
|
|
5088
|
+
}
|
|
5089
|
+
if (assertion.executorKind !== "pi") {
|
|
5090
|
+
throw new Error("pi_trusted_runtime_assertion_binding_mismatch:executorKind");
|
|
5091
|
+
}
|
|
5092
|
+
const expiresAt = Date.parse(requiredString2(assertion.expiresAt, "expiresAt"));
|
|
5093
|
+
const now = input.now instanceof Date ? input.now : new Date(input.now ?? Date.now());
|
|
5094
|
+
if (!Number.isFinite(expiresAt) || input.verifyExpiry !== false && expiresAt <= now.getTime()) {
|
|
5095
|
+
throw new Error("pi_trusted_runtime_assertion_expired");
|
|
5096
|
+
}
|
|
5097
|
+
for (const field of [
|
|
5098
|
+
"seedManifestDigest",
|
|
5099
|
+
"runtimeOverlayDigest",
|
|
5100
|
+
"effectivePolicyDigest",
|
|
5101
|
+
"runtimeEnforcementDigest"
|
|
5102
|
+
]) {
|
|
5103
|
+
const asserted = requiredDigest(assertion[field], field);
|
|
5104
|
+
if (asserted !== requiredDigest(input.localDigests?.[field], field)) {
|
|
5105
|
+
throw new Error(`pi_trusted_runtime_digest_mismatch:${field}`);
|
|
5106
|
+
}
|
|
5107
|
+
}
|
|
5108
|
+
if (!["deny", "allow_audited_bounded"].includes(assertion.unknownToolMode)) {
|
|
5109
|
+
throw new Error("pi_trusted_runtime_assertion_invalid:unknownToolMode");
|
|
5110
|
+
}
|
|
5111
|
+
const maxCalls = assertion.directToolBudget?.maxCalls;
|
|
5112
|
+
if (!Number.isInteger(maxCalls) || maxCalls < 0) {
|
|
5113
|
+
throw new Error("pi_trusted_runtime_assertion_invalid:directToolBudget.maxCalls");
|
|
5114
|
+
}
|
|
5115
|
+
if (assertion.unknownToolMode === "allow_audited_bounded" && maxCalls < 1) {
|
|
5116
|
+
throw new Error("pi_trusted_runtime_assertion_invalid:directToolBudget.maxCalls");
|
|
5117
|
+
}
|
|
5118
|
+
return {
|
|
5119
|
+
attestationId: assertion.attestationId,
|
|
5120
|
+
unknownToolMode: assertion.unknownToolMode,
|
|
5121
|
+
directToolBudget: { maxCalls },
|
|
5122
|
+
expiresAt: assertion.expiresAt,
|
|
5123
|
+
digests: { ...input.localDigests }
|
|
5124
|
+
};
|
|
5125
|
+
}
|
|
5126
|
+
|
|
4478
5127
|
// src/amaster-runtime-daemon/workspace-status.mjs
|
|
4479
5128
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
4480
|
-
import { createHash as
|
|
4481
|
-
import { existsSync as
|
|
4482
|
-
import { basename as basename5, extname, isAbsolute as
|
|
5129
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
5130
|
+
import { existsSync as existsSync9, readdirSync as readdirSync7, readFileSync as readFileSync7, statSync as statSync6 } from "node:fs";
|
|
5131
|
+
import { basename as basename5, extname, isAbsolute as isAbsolute6, join as join10, relative as relative6, resolve as resolve9 } from "node:path";
|
|
4483
5132
|
var WORKSPACE_RUNTIME_SERVICES_FILENAME = ".amaster-runtime-services.json";
|
|
4484
5133
|
var ARTIFACT_EXTENSIONS = /* @__PURE__ */ new Map([
|
|
4485
5134
|
[".md", "markdown"],
|
|
@@ -4524,11 +5173,11 @@ var SAFE_RUNTIME_SERVICE_STATUSES = /* @__PURE__ */ new Set(["starting", "runnin
|
|
|
4524
5173
|
var SAFE_RUNTIME_SERVICE_HEALTH_STATUSES = /* @__PURE__ */ new Set(["unknown", "healthy", "unhealthy"]);
|
|
4525
5174
|
var SAFE_RUNTIME_SERVICE_LIFECYCLES = /* @__PURE__ */ new Set(["shared", "ephemeral"]);
|
|
4526
5175
|
function statusPathWithin(candidate, root) {
|
|
4527
|
-
const rel =
|
|
4528
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
5176
|
+
const rel = relative6(root, candidate);
|
|
5177
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute6(rel);
|
|
4529
5178
|
}
|
|
4530
5179
|
function normalizeRelativePath(root, filePath) {
|
|
4531
|
-
return
|
|
5180
|
+
return relative6(root, filePath).split(/[\\/]+/).join("/");
|
|
4532
5181
|
}
|
|
4533
5182
|
function isSafeRelativePath(value) {
|
|
4534
5183
|
const text = String(value ?? "").trim().split(/[\\/]+/).join("/");
|
|
@@ -4547,8 +5196,8 @@ function sanitizeTrackedChange(line) {
|
|
|
4547
5196
|
if (path === WORKSPACE_RUNTIME_SERVICES_FILENAME) return null;
|
|
4548
5197
|
return isSafeRelativePath(path) ? line : null;
|
|
4549
5198
|
}
|
|
4550
|
-
function
|
|
4551
|
-
return
|
|
5199
|
+
function sha256File2(filePath) {
|
|
5200
|
+
return createHash7("sha256").update(readFileSync7(filePath)).digest("hex");
|
|
4552
5201
|
}
|
|
4553
5202
|
function artifactHashCacheKey(relativePath, stat) {
|
|
4554
5203
|
return `${relativePath}\0${stat.size}\0${stat.mtimeMs}`;
|
|
@@ -4562,7 +5211,7 @@ function artifactSha256(filePath, relativePath, stat, opts = {}) {
|
|
|
4562
5211
|
cache.set(key, cached);
|
|
4563
5212
|
return cached;
|
|
4564
5213
|
}
|
|
4565
|
-
const hashFile = typeof opts.hashFile === "function" ? opts.hashFile :
|
|
5214
|
+
const hashFile = typeof opts.hashFile === "function" ? opts.hashFile : sha256File2;
|
|
4566
5215
|
const hash = hashFile(filePath);
|
|
4567
5216
|
if (cache) {
|
|
4568
5217
|
cache.set(key, hash);
|
|
@@ -4576,7 +5225,7 @@ function artifactSha256(filePath, relativePath, stat, opts = {}) {
|
|
|
4576
5225
|
return hash;
|
|
4577
5226
|
}
|
|
4578
5227
|
function scanArtifactCandidates(cwd, opts = {}) {
|
|
4579
|
-
const root =
|
|
5228
|
+
const root = resolve9(cwd);
|
|
4580
5229
|
const maxCandidates = opts.maxCandidates ?? MAX_CANDIDATES;
|
|
4581
5230
|
const maxEntries = opts.maxEntries ?? MAX_SCAN_ENTRIES;
|
|
4582
5231
|
const candidates = [];
|
|
@@ -4586,7 +5235,7 @@ function scanArtifactCandidates(cwd, opts = {}) {
|
|
|
4586
5235
|
const current = stack.pop();
|
|
4587
5236
|
let entries;
|
|
4588
5237
|
try {
|
|
4589
|
-
entries =
|
|
5238
|
+
entries = readdirSync7(current, { withFileTypes: true });
|
|
4590
5239
|
} catch {
|
|
4591
5240
|
continue;
|
|
4592
5241
|
}
|
|
@@ -4597,7 +5246,7 @@ function scanArtifactCandidates(cwd, opts = {}) {
|
|
|
4597
5246
|
if (entry.name.startsWith(".") && entry.name !== ".amaster-runtime.json") {
|
|
4598
5247
|
if (entry.name === ".git") continue;
|
|
4599
5248
|
}
|
|
4600
|
-
const fullPath =
|
|
5249
|
+
const fullPath = join10(current, entry.name);
|
|
4601
5250
|
const relativePath = normalizeRelativePath(root, fullPath);
|
|
4602
5251
|
if (!isSafeRelativePath(relativePath)) continue;
|
|
4603
5252
|
if (basename5(relativePath) === ".amaster-runtime.json") continue;
|
|
@@ -4616,7 +5265,7 @@ function scanArtifactCandidates(cwd, opts = {}) {
|
|
|
4616
5265
|
} catch {
|
|
4617
5266
|
continue;
|
|
4618
5267
|
}
|
|
4619
|
-
if (!statusPathWithin(
|
|
5268
|
+
if (!statusPathWithin(resolve9(fullPath), root) || stat.size > MAX_HASH_BYTES) continue;
|
|
4620
5269
|
candidates.push({
|
|
4621
5270
|
relativePath,
|
|
4622
5271
|
name: basename5(fullPath),
|
|
@@ -4676,10 +5325,10 @@ function sanitizeRuntimeService(entry) {
|
|
|
4676
5325
|
};
|
|
4677
5326
|
}
|
|
4678
5327
|
function readRuntimeServicesSnapshot(cwd) {
|
|
4679
|
-
const snapshotPath =
|
|
4680
|
-
if (!
|
|
5328
|
+
const snapshotPath = join10(resolve9(cwd), WORKSPACE_RUNTIME_SERVICES_FILENAME);
|
|
5329
|
+
if (!existsSync9(snapshotPath)) return [];
|
|
4681
5330
|
try {
|
|
4682
|
-
const parsed = JSON.parse(
|
|
5331
|
+
const parsed = JSON.parse(readFileSync7(snapshotPath, "utf8"));
|
|
4683
5332
|
const rawServices = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.services) ? parsed.services : [];
|
|
4684
5333
|
return rawServices.map((entry) => sanitizeRuntimeService(entry)).filter((entry) => entry !== null).slice(0, 50);
|
|
4685
5334
|
} catch {
|
|
@@ -4750,7 +5399,7 @@ function readWorkspaceStatus(cwd, opts = {}) {
|
|
|
4750
5399
|
}
|
|
4751
5400
|
|
|
4752
5401
|
// src/amaster-runtime-daemon.mjs
|
|
4753
|
-
var CONNECTOR_VERSION = "0.1.0-beta.
|
|
5402
|
+
var CONNECTOR_VERSION = "0.1.0-beta.32";
|
|
4754
5403
|
var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
|
|
4755
5404
|
var MAX_CHECKPOINT_BYTES = 20 * 1024 * 1024;
|
|
4756
5405
|
var CHECKPOINT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -4771,6 +5420,24 @@ var processGroupRssSampleCache = null;
|
|
|
4771
5420
|
var lastOrphanReaperRunAtMs = 0;
|
|
4772
5421
|
var lastOrphanReaperSummary = null;
|
|
4773
5422
|
var activeRunManifestOutputFlusher = createManifestOutputFlusher({ updateWorkspaceManifest });
|
|
5423
|
+
var piChildIdentityAllocator = null;
|
|
5424
|
+
var piChildIdentityAllocatorKey = null;
|
|
5425
|
+
var trustedPiRuntimeProvenanceCache = createTrustedPiRuntimeProvenanceCache();
|
|
5426
|
+
function configuredPiChildIdentityAllocator(config) {
|
|
5427
|
+
if (!(config.piChildUidBase > 0)) return null;
|
|
5428
|
+
const key = `${config.piChildUidBase}:${config.piChildUidSpan}`;
|
|
5429
|
+
if (!piChildIdentityAllocator || piChildIdentityAllocatorKey !== key) {
|
|
5430
|
+
if (piChildIdentityAllocator?.activeAssignments().length > 0) {
|
|
5431
|
+
throw new Error("pi_child_isolation_config_changed_with_active_runs");
|
|
5432
|
+
}
|
|
5433
|
+
piChildIdentityAllocator = createPiChildIdentityAllocator({
|
|
5434
|
+
uidBase: config.piChildUidBase,
|
|
5435
|
+
uidSpan: config.piChildUidSpan
|
|
5436
|
+
});
|
|
5437
|
+
piChildIdentityAllocatorKey = key;
|
|
5438
|
+
}
|
|
5439
|
+
return piChildIdentityAllocator;
|
|
5440
|
+
}
|
|
4774
5441
|
function mergeActiveRunManifestPatch(commandId, patch = {}) {
|
|
4775
5442
|
return activeRunManifestOutputFlusher.mergePendingPatch(commandId, patch);
|
|
4776
5443
|
}
|
|
@@ -4779,11 +5446,11 @@ function updateActiveRunWorkspaceManifest(commandId, manifestPath, patch = {}) {
|
|
|
4779
5446
|
}
|
|
4780
5447
|
function resultOutboxPendingCount(config) {
|
|
4781
5448
|
const dir = resultOutboxDir(config);
|
|
4782
|
-
if (!
|
|
5449
|
+
if (!existsSync10(dir)) return 0;
|
|
4783
5450
|
try {
|
|
4784
5451
|
let pending = 0;
|
|
4785
|
-
for (const file of
|
|
4786
|
-
if (readValidResultOutboxEntryOrQuarantine(config, file,
|
|
5452
|
+
for (const file of readdirSync8(dir).filter((name) => name.endsWith(".json"))) {
|
|
5453
|
+
if (readValidResultOutboxEntryOrQuarantine(config, file, join11(dir, file))) {
|
|
4787
5454
|
pending += 1;
|
|
4788
5455
|
}
|
|
4789
5456
|
}
|
|
@@ -4799,11 +5466,11 @@ function piCompletionOutputType(event) {
|
|
|
4799
5466
|
}
|
|
4800
5467
|
function resultOutboxActiveRunCommands(config) {
|
|
4801
5468
|
const dir = resultOutboxDir(config);
|
|
4802
|
-
if (!
|
|
5469
|
+
if (!existsSync10(dir)) return [];
|
|
4803
5470
|
const outboxPending = resultOutboxPendingCount(config);
|
|
4804
5471
|
const entries = [];
|
|
4805
|
-
for (const file of
|
|
4806
|
-
const entry = readValidResultOutboxEntryOrQuarantine(config, file,
|
|
5472
|
+
for (const file of readdirSync8(dir).filter((name) => name.endsWith(".json")).sort()) {
|
|
5473
|
+
const entry = readValidResultOutboxEntryOrQuarantine(config, file, join11(dir, file));
|
|
4807
5474
|
if (!entry) continue;
|
|
4808
5475
|
const activeRun = asRecord(entry.activeRun);
|
|
4809
5476
|
const commandId = readString(activeRun.commandId) ?? readString(entry.commandId);
|
|
@@ -4833,12 +5500,12 @@ function resultOutboxActiveRunCommands(config) {
|
|
|
4833
5500
|
}
|
|
4834
5501
|
function resultOutboxFailedRunCommands(config) {
|
|
4835
5502
|
const dir = resultOutboxInvalidDir(config);
|
|
4836
|
-
if (!
|
|
5503
|
+
if (!existsSync10(dir)) return [];
|
|
4837
5504
|
const entries = [];
|
|
4838
|
-
for (const file of
|
|
5505
|
+
for (const file of readdirSync8(dir).filter((name) => name.endsWith(".json")).sort().slice(-100)) {
|
|
4839
5506
|
let entry;
|
|
4840
5507
|
try {
|
|
4841
|
-
entry = asRecord(JSON.parse(
|
|
5508
|
+
entry = asRecord(JSON.parse(readFileSync8(join11(dir, file), "utf8")));
|
|
4842
5509
|
} catch {
|
|
4843
5510
|
continue;
|
|
4844
5511
|
}
|
|
@@ -4898,11 +5565,11 @@ function piExtraArgsDiagnostics(value) {
|
|
|
4898
5565
|
}
|
|
4899
5566
|
function safeExpandPath(value) {
|
|
4900
5567
|
const text = readString(value);
|
|
4901
|
-
return text ?
|
|
5568
|
+
return text ? resolve10(expandHomePath(text)) : null;
|
|
4902
5569
|
}
|
|
4903
5570
|
function safeJsonObjectFromFile(filePath) {
|
|
4904
5571
|
try {
|
|
4905
|
-
const parsed = JSON.parse(
|
|
5572
|
+
const parsed = JSON.parse(readFileSync8(filePath, "utf8"));
|
|
4906
5573
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
4907
5574
|
} catch {
|
|
4908
5575
|
return null;
|
|
@@ -4919,7 +5586,7 @@ function safeDirectorySummary(pathValue) {
|
|
|
4919
5586
|
}
|
|
4920
5587
|
let entryCount = 0;
|
|
4921
5588
|
let truncated = false;
|
|
4922
|
-
for (const name of
|
|
5589
|
+
for (const name of readdirSync8(pathValue)) {
|
|
4923
5590
|
if (name.startsWith(".")) continue;
|
|
4924
5591
|
entryCount += 1;
|
|
4925
5592
|
if (entryCount >= MAX_PI_CAPABILITY_SOURCE_ENTRIES) {
|
|
@@ -4943,12 +5610,12 @@ function safeSkillRootSummary(kind, source, pathValue) {
|
|
|
4943
5610
|
let truncated = false;
|
|
4944
5611
|
if (directory.available && pathValue) {
|
|
4945
5612
|
try {
|
|
4946
|
-
for (const name of
|
|
5613
|
+
for (const name of readdirSync8(pathValue)) {
|
|
4947
5614
|
if (name.startsWith(".")) continue;
|
|
4948
|
-
const skillDir =
|
|
5615
|
+
const skillDir = join11(pathValue, name);
|
|
4949
5616
|
try {
|
|
4950
5617
|
if (!statSync7(skillDir).isDirectory()) continue;
|
|
4951
|
-
if (!
|
|
5618
|
+
if (!existsSync10(join11(skillDir, "SKILL.md"))) continue;
|
|
4952
5619
|
skillCount += 1;
|
|
4953
5620
|
if (skillCount >= MAX_PI_CAPABILITY_SOURCE_ENTRIES) {
|
|
4954
5621
|
truncated = true;
|
|
@@ -4999,7 +5666,7 @@ function objectKeyCount(value) {
|
|
|
4999
5666
|
return value && typeof value === "object" && !Array.isArray(value) ? Object.keys(value).length : 0;
|
|
5000
5667
|
}
|
|
5001
5668
|
function defaultPiCodingAgentDir() {
|
|
5002
|
-
return
|
|
5669
|
+
return join11(homedir3(), ".pi", "agent");
|
|
5003
5670
|
}
|
|
5004
5671
|
function piCapabilitySourcesDiagnostics() {
|
|
5005
5672
|
const configuredPiCodingAgentDir = safeExpandPath(process.env.PI_CODING_AGENT_DIR);
|
|
@@ -5008,11 +5675,11 @@ function piCapabilitySourcesDiagnostics() {
|
|
|
5008
5675
|
const configuredPiAgentHome = safeExpandPath(process.env.PI_AGENT_HOME);
|
|
5009
5676
|
const piAgentHome = configuredPiAgentHome ?? piCodingAgentDir;
|
|
5010
5677
|
const piAgentHomeSource = configuredPiAgentHome ? "PI_AGENT_HOME" : piCodingAgentDirSource;
|
|
5011
|
-
const userSkillsPath = piAgentHome ?
|
|
5012
|
-
const marketplaceSkillsPath = safeExpandPath(process.env.PI_AGENT_MARKETPLACE_SKILLS_DIR) ?? (piAgentHome ?
|
|
5678
|
+
const userSkillsPath = piAgentHome ? join11(piAgentHome, "skills") : null;
|
|
5679
|
+
const marketplaceSkillsPath = safeExpandPath(process.env.PI_AGENT_MARKETPLACE_SKILLS_DIR) ?? (piAgentHome ? join11(piAgentHome, "marketplace", "skills") : null);
|
|
5013
5680
|
const builtinSkillsPath = safeExpandPath(process.env.PI_AGENT_BUILTIN_SKILLS_DIR) ?? safeExpandPath(process.env.AMASTER_BUILTIN_SKILLS);
|
|
5014
|
-
const mcpConfigPath = safeExpandPath(process.env.PI_AGENT_MCP_SERVERS_FILE) ?? (piAgentHome ?
|
|
5015
|
-
const settingsConfigPath = piCodingAgentDir ?
|
|
5681
|
+
const mcpConfigPath = safeExpandPath(process.env.PI_AGENT_MCP_SERVERS_FILE) ?? (piAgentHome ? join11(piAgentHome, "mcp.json") : null);
|
|
5682
|
+
const settingsConfigPath = piCodingAgentDir ? join11(piCodingAgentDir, "settings.json") : null;
|
|
5016
5683
|
const skillRoots = [
|
|
5017
5684
|
safeSkillRootSummary("user", `${piAgentHomeSource}/skills`, userSkillsPath),
|
|
5018
5685
|
safeSkillRootSummary(
|
|
@@ -5127,6 +5794,16 @@ function executorReadinessFor(config, executor) {
|
|
|
5127
5794
|
function buildExecutorReadiness(config) {
|
|
5128
5795
|
return config.executors.filter((executor) => executor.kind === "codex" || executor.kind === "pi").map((executor) => executorReadinessFor(config, executor));
|
|
5129
5796
|
}
|
|
5797
|
+
function trustedPiRuntimeProvenancePayload(config) {
|
|
5798
|
+
const configured = [
|
|
5799
|
+
config.piRuntimeSeedRoot,
|
|
5800
|
+
config.piRuntimeOverlayRoot,
|
|
5801
|
+
config.piRuntimeEffectivePolicyFile
|
|
5802
|
+
].filter(Boolean).length;
|
|
5803
|
+
if (configured === 0) return {};
|
|
5804
|
+
if (configured !== 3) throw new Error("pi_trusted_runtime_source_config_missing");
|
|
5805
|
+
return trustedPiRuntimeProvenanceCache.read(trustedPiRuntimeSources(config));
|
|
5806
|
+
}
|
|
5130
5807
|
function buildRegisterPayload(config) {
|
|
5131
5808
|
const buildCommit = readString(process.env.AMASTER_RUNTIME_BUILD_COMMIT ?? process.env.AMASTER_SOURCE_COMMIT);
|
|
5132
5809
|
return {
|
|
@@ -5190,6 +5867,7 @@ function buildHeartbeatPayload(config, options = {}) {
|
|
|
5190
5867
|
contractVersion: CONNECTOR_CONTRACT_VERSION,
|
|
5191
5868
|
platform: process.platform,
|
|
5192
5869
|
arch: process.arch,
|
|
5870
|
+
...trustedPiRuntimeProvenancePayload(config),
|
|
5193
5871
|
runtimeStatus: {
|
|
5194
5872
|
daemon: "running",
|
|
5195
5873
|
pid: process.pid,
|
|
@@ -5217,13 +5895,13 @@ function piAgentLocalPlatformRunnerEnabled(config) {
|
|
|
5217
5895
|
}
|
|
5218
5896
|
function piAgentSystemDataDir(config) {
|
|
5219
5897
|
const configured = readString(config.AMASTER_PI_AGENT_SYSTEM_DATA_DIR ?? process.env.AMASTER_PI_AGENT_SYSTEM_DATA_DIR);
|
|
5220
|
-
return configured ?
|
|
5898
|
+
return configured ? resolve10(expandHomePath(configured)) : null;
|
|
5221
5899
|
}
|
|
5222
5900
|
function readPiAgentLocalPlatformCredential(credentialsDir) {
|
|
5223
|
-
const pointer =
|
|
5901
|
+
const pointer = readJsonFile2(join11(credentialsDir, "latest.json"));
|
|
5224
5902
|
const credentialRef = readString(pointer.credentialRef);
|
|
5225
5903
|
if (!credentialRef || !/^[a-f0-9]{64}$/i.test(credentialRef)) return null;
|
|
5226
|
-
const credential =
|
|
5904
|
+
const credential = readJsonFile2(join11(credentialsDir, `${credentialRef}.json`));
|
|
5227
5905
|
const organizationId = readString(credential.organizationId);
|
|
5228
5906
|
const apiKey = readString(credential.apiKey);
|
|
5229
5907
|
if (credential.version !== 1 || !organizationId || !apiKey) return null;
|
|
@@ -5239,17 +5917,17 @@ function piAgentLocalPlatformCredentials(config) {
|
|
|
5239
5917
|
if (!piAgentLocalPlatformRunnerEnabled(config)) return [];
|
|
5240
5918
|
const systemDataDir = piAgentSystemDataDir(config);
|
|
5241
5919
|
if (!systemDataDir) return [];
|
|
5242
|
-
const companiesDir =
|
|
5920
|
+
const companiesDir = join11(systemDataDir, "companies");
|
|
5243
5921
|
let entries = [];
|
|
5244
5922
|
try {
|
|
5245
|
-
entries =
|
|
5923
|
+
entries = readdirSync8(companiesDir, { withFileTypes: true });
|
|
5246
5924
|
} catch {
|
|
5247
5925
|
return [];
|
|
5248
5926
|
}
|
|
5249
5927
|
const credentialsByOrganizationId = /* @__PURE__ */ new Map();
|
|
5250
5928
|
for (const entry of entries) {
|
|
5251
5929
|
if (!entry.isDirectory()) continue;
|
|
5252
|
-
const credential = readPiAgentLocalPlatformCredential(
|
|
5930
|
+
const credential = readPiAgentLocalPlatformCredential(join11(companiesDir, entry.name, "model-credentials"));
|
|
5253
5931
|
if (credential) credentialsByOrganizationId.set(credential.organizationId, credential);
|
|
5254
5932
|
}
|
|
5255
5933
|
return [...credentialsByOrganizationId.values()];
|
|
@@ -5423,7 +6101,7 @@ AMASTER_WORKSPACE_ALLOWLIST=${quoteShell(config.workspaceBindings.join(","))}
|
|
|
5423
6101
|
AMASTER_EXECUTORS=${quoteShell(executorEnv)}
|
|
5424
6102
|
AMASTER_CAPABILITIES=${quoteShell(config.capabilities.join(","))}
|
|
5425
6103
|
AMASTER_NETWORK_DOMAINS=${quoteShell(config.networkDomains.join(","))}
|
|
5426
|
-
AMASTER_DAEMON_STATE_FILE=${quoteShell(
|
|
6104
|
+
AMASTER_DAEMON_STATE_FILE=${quoteShell(join11(homedir3(), ".amaster-employee", "runtime-connector-state.json"))}
|
|
5427
6105
|
EOF
|
|
5428
6106
|
|
|
5429
6107
|
set -a
|
|
@@ -5611,10 +6289,10 @@ function buildActiveRunCommandStatus(config, entry) {
|
|
|
5611
6289
|
const base = {
|
|
5612
6290
|
...entry,
|
|
5613
6291
|
phase: readString(entry.phase) ?? "executing",
|
|
5614
|
-
managedWorkdirPresent: entry.workspacePath ?
|
|
6292
|
+
managedWorkdirPresent: entry.workspacePath ? existsSync10(entry.workspacePath) : false,
|
|
5615
6293
|
outboxPending: resultOutboxPendingCount(config)
|
|
5616
6294
|
};
|
|
5617
|
-
if (!entry.workspacePath || !
|
|
6295
|
+
if (!entry.workspacePath || !existsSync10(entry.workspacePath)) return base;
|
|
5618
6296
|
const manifestPath = entry.manifestPath ?? workspaceManifestPath(entry.workspacePath);
|
|
5619
6297
|
const status = readWorkspaceStatus(entry.workspacePath, { hashCache: workspaceStatusHashCache });
|
|
5620
6298
|
const artifactCandidates = status.artifacts.slice(0, 20);
|
|
@@ -5778,18 +6456,33 @@ function commandExecutorEnv(command) {
|
|
|
5778
6456
|
...normalizeExecutorEnvValue(command.executorEnv)
|
|
5779
6457
|
};
|
|
5780
6458
|
}
|
|
5781
|
-
function
|
|
6459
|
+
function commandTrustedPiRuntimeAssertion(command) {
|
|
6460
|
+
const topLevel = asRecord(command.trustedPiRuntime);
|
|
6461
|
+
if (Object.keys(topLevel).length > 0) return topLevel;
|
|
6462
|
+
return asRecord(asRecord(command.payload).trustedPiRuntime);
|
|
6463
|
+
}
|
|
6464
|
+
function trustedPiRuntimeSources(config) {
|
|
6465
|
+
if (!config.piRuntimeSeedRoot || !config.piRuntimeOverlayRoot || !config.piRuntimeEffectivePolicyFile) {
|
|
6466
|
+
throw new Error("pi_trusted_runtime_source_config_missing");
|
|
6467
|
+
}
|
|
6468
|
+
return {
|
|
6469
|
+
seedRoot: config.piRuntimeSeedRoot,
|
|
6470
|
+
overlayRoot: config.piRuntimeOverlayRoot,
|
|
6471
|
+
policyFile: config.piRuntimeEffectivePolicyFile
|
|
6472
|
+
};
|
|
6473
|
+
}
|
|
6474
|
+
function readJsonFile2(filePath) {
|
|
5782
6475
|
try {
|
|
5783
|
-
const parsed = JSON.parse(
|
|
6476
|
+
const parsed = JSON.parse(readFileSync8(filePath, "utf8"));
|
|
5784
6477
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
5785
6478
|
} catch {
|
|
5786
6479
|
return {};
|
|
5787
6480
|
}
|
|
5788
6481
|
}
|
|
5789
6482
|
function writeJsonFileAtomic(filePath, value) {
|
|
5790
|
-
|
|
6483
|
+
mkdirSync6(dirname7(filePath), { recursive: true });
|
|
5791
6484
|
const tmpPath = `${filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
5792
|
-
|
|
6485
|
+
writeFileSync6(tmpPath, `${JSON.stringify(value, null, 2)}
|
|
5793
6486
|
`, { mode: 384 });
|
|
5794
6487
|
renameSync3(tmpPath, filePath);
|
|
5795
6488
|
}
|
|
@@ -5835,8 +6528,8 @@ function ensureAmasterProviderModel(models, modelId, flash) {
|
|
|
5835
6528
|
function syncAmasterProviderModels(agentDir, executorEnv) {
|
|
5836
6529
|
const apiKey = readString(executorEnv.AMASTER_API_KEY);
|
|
5837
6530
|
if (!apiKey) return false;
|
|
5838
|
-
const modelsPath =
|
|
5839
|
-
const config =
|
|
6531
|
+
const modelsPath = join11(agentDir, "models.json");
|
|
6532
|
+
const config = readJsonFile2(modelsPath);
|
|
5840
6533
|
const providers = asRecord(config.providers);
|
|
5841
6534
|
const amaster = { ...asRecord(providers.amaster) };
|
|
5842
6535
|
amaster.apiKey = apiKey;
|
|
@@ -5859,9 +6552,9 @@ function syncAmasterProviderModels(agentDir, executorEnv) {
|
|
|
5859
6552
|
function syncAmasterProviderSettings(agentDir, executorEnv) {
|
|
5860
6553
|
const apiKey = readString(executorEnv.AMASTER_API_KEY);
|
|
5861
6554
|
if (!apiKey) return false;
|
|
5862
|
-
const settingsPath =
|
|
5863
|
-
if (!
|
|
5864
|
-
const settings =
|
|
6555
|
+
const settingsPath = join11(agentDir, "settings.json");
|
|
6556
|
+
if (!existsSync10(settingsPath)) return false;
|
|
6557
|
+
const settings = readJsonFile2(settingsPath);
|
|
5865
6558
|
const baseUrl = readString(executorEnv.AMASTER_PROVIDER_BASE_URL);
|
|
5866
6559
|
const defaultModel = readString(executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL);
|
|
5867
6560
|
const imageGenBaseUrl = imageGenBaseUrlFromProviderBaseUrl(baseUrl);
|
|
@@ -5923,22 +6616,26 @@ function syncAmasterProviderSettings(agentDir, executorEnv) {
|
|
|
5923
6616
|
writeJsonFileAtomic(settingsPath, settings);
|
|
5924
6617
|
return true;
|
|
5925
6618
|
}
|
|
5926
|
-
|
|
5927
|
-
const hasGovernedMcp = Object.keys(asRecord(commandRuntimeAuth(command).governedMcp)).length > 0;
|
|
5928
|
-
const agentDir = piAgentLocalPlatformRunnerEnabled(config) || hasGovernedMcp ? readString(executorEnv.PI_AGENT_HOME) ?? readString(executorEnv.PI_CODING_AGENT_DIR) : readString(executorEnv.PI_CODING_AGENT_DIR) ?? readString(executorEnv.PI_AGENT_HOME) ?? null;
|
|
5929
|
-
if (!agentDir) return;
|
|
6619
|
+
function resolvePiExecutorProviderConfig(config, command, executorEnv) {
|
|
5930
6620
|
const localPlatformCredential = piAgentLocalPlatformCredentialForCommand(config, command);
|
|
5931
6621
|
if (piAgentLocalPlatformRunnerEnabled(config) && !localPlatformCredential) {
|
|
5932
6622
|
throw new Error("Pi Agent local Platform credential is unavailable for this command organization");
|
|
5933
6623
|
}
|
|
5934
|
-
|
|
6624
|
+
return {
|
|
6625
|
+
providerConfig: localPlatformCredential ?? executorEnv,
|
|
6626
|
+
credentialSource: localPlatformCredential ? "pi_agent_local_platform" : "command_executor_env"
|
|
6627
|
+
};
|
|
6628
|
+
}
|
|
6629
|
+
async function syncPiExecutorProviderConfig(config, command, agentDir, resolvedProviderConfig) {
|
|
6630
|
+
if (!agentDir) return;
|
|
6631
|
+
const { providerConfig, credentialSource } = resolvedProviderConfig;
|
|
5935
6632
|
const modelsSynced = syncAmasterProviderModels(agentDir, providerConfig);
|
|
5936
6633
|
const settingsSynced = syncAmasterProviderSettings(agentDir, providerConfig);
|
|
5937
6634
|
if (modelsSynced || settingsSynced) {
|
|
5938
6635
|
await ingestLog(config, command, "system", "info", "Synced AMaster provider config for pi executor", {
|
|
5939
6636
|
modelsSynced,
|
|
5940
6637
|
settingsSynced,
|
|
5941
|
-
credentialSource
|
|
6638
|
+
credentialSource,
|
|
5942
6639
|
providerBaseUrlConfigured: Boolean(readString(providerConfig.AMASTER_PROVIDER_BASE_URL)),
|
|
5943
6640
|
defaultModelConfigured: Boolean(readString(providerConfig.AMASTER_PROVIDER_DEFAULT_MODEL)),
|
|
5944
6641
|
flashModelConfigured: Boolean(readString(providerConfig.AMASTER_PROVIDER_FLASH_MODEL))
|
|
@@ -5983,11 +6680,11 @@ function safeAgentInstructionMaterializationTarget(workspace, filePath) {
|
|
|
5983
6680
|
const raw = readString(filePath);
|
|
5984
6681
|
if (!raw || raw.includes("\0")) return null;
|
|
5985
6682
|
const normalized = raw.replace(/\\/g, "/");
|
|
5986
|
-
if (
|
|
6683
|
+
if (isAbsolute7(normalized)) return null;
|
|
5987
6684
|
const segments = normalized.split("/").filter(Boolean);
|
|
5988
6685
|
if (segments.length === 0 || segments.some((segment) => segment === "." || segment === "..")) return null;
|
|
5989
6686
|
const relativePath = segments.join("/");
|
|
5990
|
-
const targetPath =
|
|
6687
|
+
const targetPath = resolve10(workspace.cwd, relativePath);
|
|
5991
6688
|
if (!pathWithin2(targetPath, workspace.cwd)) return null;
|
|
5992
6689
|
return { relativePath, targetPath };
|
|
5993
6690
|
}
|
|
@@ -6001,8 +6698,8 @@ async function materializeAgentInstructionsBundle(config, command, workspace) {
|
|
|
6001
6698
|
if (!content) continue;
|
|
6002
6699
|
const target = safeAgentInstructionMaterializationTarget(workspace, filePath);
|
|
6003
6700
|
if (!target) continue;
|
|
6004
|
-
|
|
6005
|
-
|
|
6701
|
+
mkdirSync6(dirname7(target.targetPath), { recursive: true });
|
|
6702
|
+
writeFileSync6(target.targetPath, content, "utf8");
|
|
6006
6703
|
materialized.push({
|
|
6007
6704
|
path: target.relativePath,
|
|
6008
6705
|
byteSize: Buffer.byteLength(content, "utf8")
|
|
@@ -6071,20 +6768,20 @@ function safeCompanyPiHomeSegment(companyId) {
|
|
|
6071
6768
|
if (!raw) return null;
|
|
6072
6769
|
if (/^[A-Za-z0-9][A-Za-z0-9._-]{0,119}$/.test(raw)) return raw;
|
|
6073
6770
|
const normalized = raw.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[._-]+|[._-]+$/g, "").slice(0, 80);
|
|
6074
|
-
const hash =
|
|
6771
|
+
const hash = createHash8("sha256").update(raw).digest("hex").slice(0, 12);
|
|
6075
6772
|
return normalized ? `${normalized}-${hash}` : `company-${hash}`;
|
|
6076
6773
|
}
|
|
6077
6774
|
function companyPiHomeRoot(baseEnv) {
|
|
6078
6775
|
const explicitRoot = readString(baseEnv.AMASTER_COMPANY_PI_HOME_ROOT);
|
|
6079
|
-
if (explicitRoot) return
|
|
6776
|
+
if (explicitRoot) return resolve10(expandHomePath(explicitRoot));
|
|
6080
6777
|
const configuredPiHome = readString(baseEnv.PI_AGENT_HOME) ?? readString(baseEnv.PI_CODING_AGENT_DIR);
|
|
6081
|
-
if (configuredPiHome) return
|
|
6082
|
-
return
|
|
6778
|
+
if (configuredPiHome) return join11(dirname7(resolve10(expandHomePath(configuredPiHome))), "companies");
|
|
6779
|
+
return join11(homedir3(), ".amaster-employee", "companies");
|
|
6083
6780
|
}
|
|
6084
6781
|
function companyPiAgentHome(baseEnv, companyId) {
|
|
6085
6782
|
const segment = safeCompanyPiHomeSegment(companyId);
|
|
6086
6783
|
if (!segment) return null;
|
|
6087
|
-
return
|
|
6784
|
+
return join11(companyPiHomeRoot(baseEnv), segment, ".pi");
|
|
6088
6785
|
}
|
|
6089
6786
|
function commandUsesPiExecutor(command) {
|
|
6090
6787
|
return readString(asRecord(command.payload).executorKind) === "pi";
|
|
@@ -6153,7 +6850,7 @@ function resolveNativeSessionRequest(command, workspace) {
|
|
|
6153
6850
|
try {
|
|
6154
6851
|
cwdMatched = realpathSync3(requestedCwd) === realpathSync3(sourceWorkspacePath);
|
|
6155
6852
|
} catch {
|
|
6156
|
-
cwdMatched =
|
|
6853
|
+
cwdMatched = resolve10(requestedCwd) === resolve10(sourceWorkspacePath);
|
|
6157
6854
|
}
|
|
6158
6855
|
}
|
|
6159
6856
|
const used = Boolean(enabled && requested && sessionId && requestedCwd && cwdMatched);
|
|
@@ -6580,10 +7277,10 @@ function realOrResolvedPath(value) {
|
|
|
6580
7277
|
try {
|
|
6581
7278
|
return realpathSync3(value);
|
|
6582
7279
|
} catch {
|
|
6583
|
-
return
|
|
7280
|
+
return resolve10(value);
|
|
6584
7281
|
}
|
|
6585
7282
|
}
|
|
6586
|
-
var LSOF_COMMAND = process.platform === "darwin" &&
|
|
7283
|
+
var LSOF_COMMAND = process.platform === "darwin" && existsSync10("/usr/sbin/lsof") ? "/usr/sbin/lsof" : "lsof";
|
|
6587
7284
|
function processCwdForPid(pid) {
|
|
6588
7285
|
if (process.platform === "linux") {
|
|
6589
7286
|
try {
|
|
@@ -6609,7 +7306,7 @@ function allProcessCwdsByPid() {
|
|
|
6609
7306
|
if (process.platform === "linux") {
|
|
6610
7307
|
const procEntries = (() => {
|
|
6611
7308
|
try {
|
|
6612
|
-
return
|
|
7309
|
+
return readdirSync8("/proc", { withFileTypes: true });
|
|
6613
7310
|
} catch {
|
|
6614
7311
|
return [];
|
|
6615
7312
|
}
|
|
@@ -6705,21 +7402,21 @@ function killWorkspaceResidentProcesses(cwd, processGroupId, options = {}) {
|
|
|
6705
7402
|
}
|
|
6706
7403
|
function walkManagedWorkdirs(root) {
|
|
6707
7404
|
const workdirs = [];
|
|
6708
|
-
if (!root || !
|
|
7405
|
+
if (!root || !existsSync10(root)) return workdirs;
|
|
6709
7406
|
const stack = [root];
|
|
6710
7407
|
while (stack.length > 0) {
|
|
6711
7408
|
const current = stack.pop();
|
|
6712
7409
|
if (!current) continue;
|
|
6713
7410
|
let entries = [];
|
|
6714
7411
|
try {
|
|
6715
|
-
entries =
|
|
7412
|
+
entries = readdirSync8(current, { withFileTypes: true });
|
|
6716
7413
|
} catch {
|
|
6717
7414
|
continue;
|
|
6718
7415
|
}
|
|
6719
7416
|
for (const entry of entries) {
|
|
6720
7417
|
if (!entry.isDirectory()) continue;
|
|
6721
|
-
const fullPath =
|
|
6722
|
-
if (entry.name === "workdir" &&
|
|
7418
|
+
const fullPath = join11(current, entry.name);
|
|
7419
|
+
if (entry.name === "workdir" && existsSync10(workspaceManifestPath(fullPath))) {
|
|
6723
7420
|
workdirs.push(fullPath);
|
|
6724
7421
|
continue;
|
|
6725
7422
|
}
|
|
@@ -6757,8 +7454,8 @@ function manifestMatchesActiveRuntimeRef(manifest, refs, workdir = null) {
|
|
|
6757
7454
|
}
|
|
6758
7455
|
function buildOrphanReaperSample(root, workdir, manifest, residents) {
|
|
6759
7456
|
const relativeWorkdir = (() => {
|
|
6760
|
-
const value =
|
|
6761
|
-
return value && !value.startsWith("..") && !
|
|
7457
|
+
const value = relative7(root, workdir);
|
|
7458
|
+
return value && !value.startsWith("..") && !isAbsolute7(value) ? value : basename6(workdir);
|
|
6762
7459
|
})();
|
|
6763
7460
|
return {
|
|
6764
7461
|
workdir: relativeWorkdir,
|
|
@@ -6865,7 +7562,8 @@ function runExecutor(command, args, options) {
|
|
|
6865
7562
|
cwd: options.cwd,
|
|
6866
7563
|
env: options.env,
|
|
6867
7564
|
detached: process.platform !== "win32",
|
|
6868
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
7565
|
+
stdio: options.managedInput ? ["pipe", "pipe", "pipe", "pipe"] : ["pipe", "pipe", "pipe"],
|
|
7566
|
+
...options.spawnIdentity ?? {}
|
|
6869
7567
|
});
|
|
6870
7568
|
const processGroupId = processGroupIdForChild(child);
|
|
6871
7569
|
const finish = (result2) => {
|
|
@@ -6900,6 +7598,13 @@ function runExecutor(command, args, options) {
|
|
|
6900
7598
|
signalExecutorProcess(child, "SIGTERM", processGroupId);
|
|
6901
7599
|
scheduleStopKill();
|
|
6902
7600
|
};
|
|
7601
|
+
if (options.managedInput) {
|
|
7602
|
+
child.stdio[3].once("error", (error) => {
|
|
7603
|
+
spawnError = `managed_runtime_assertion_delivery_failed: ${error.message}`;
|
|
7604
|
+
requestStop("managed_runtime_assertion_delivery_failed");
|
|
7605
|
+
});
|
|
7606
|
+
child.stdio[3].end(options.managedInput);
|
|
7607
|
+
}
|
|
6903
7608
|
const reapStoppedWorkspaceResidents = () => {
|
|
6904
7609
|
if (settled || !stopReason || stopReason === "completion_cleanup") return;
|
|
6905
7610
|
const residents = listWorkspaceResidentProcesses(options.cwd, processGroupId, {
|
|
@@ -7142,12 +7847,16 @@ async function ingestRuntimeArtifacts(config, command, cwd, mcpToolResults) {
|
|
|
7142
7847
|
const receipts = [];
|
|
7143
7848
|
for (const upload of uploads) {
|
|
7144
7849
|
const path = `/api/amaster/runtime-connectors/${connectorId}/artifact-intents/${encodeURIComponent(upload.intentId)}/ingest`;
|
|
7850
|
+
const sourcePathHeaders = /^[\x20-\x7e]+$/.test(upload.sourceRelativePath) ? { "x-amaster-artifact-source-path": upload.sourceRelativePath } : {
|
|
7851
|
+
"x-amaster-artifact-source-path": encodeURIComponent(upload.sourceRelativePath),
|
|
7852
|
+
"x-amaster-artifact-source-path-encoding": "uri-component"
|
|
7853
|
+
};
|
|
7145
7854
|
try {
|
|
7146
7855
|
const receipt = asRecord(await postRuntimeConnectorBytes(config, path, upload.body, {
|
|
7147
7856
|
"x-amaster-command-id": command.commandId,
|
|
7148
7857
|
"x-amaster-run-id": runId,
|
|
7149
7858
|
"x-amaster-artifact-manifest-id": upload.manifestId,
|
|
7150
|
-
|
|
7859
|
+
...sourcePathHeaders
|
|
7151
7860
|
}));
|
|
7152
7861
|
if (readString(receipt.intentId) !== upload.intentId || readString(receipt.status) !== "finalized") {
|
|
7153
7862
|
throw new Error(`Runtime Artifact ${upload.intentId} was not finalized: ${JSON.stringify(receipt)}`);
|
|
@@ -7230,15 +7939,15 @@ async function completeCommand(config, command, status, result2, error) {
|
|
|
7230
7939
|
}
|
|
7231
7940
|
function resultOutboxDir(config) {
|
|
7232
7941
|
const explicit = readString(process.env.AMASTER_RESULT_OUTBOX_DIR);
|
|
7233
|
-
if (explicit) return
|
|
7234
|
-
return
|
|
7942
|
+
if (explicit) return resolve10(expandHomePath(explicit));
|
|
7943
|
+
return join11(dirname7(stateFilePath(process.env)), "result-outbox");
|
|
7235
7944
|
}
|
|
7236
7945
|
function resultOutboxInvalidDir(config) {
|
|
7237
|
-
return
|
|
7946
|
+
return join11(resultOutboxDir(config), "invalid");
|
|
7238
7947
|
}
|
|
7239
7948
|
function writeResultOutboxEntry(config, entry) {
|
|
7240
7949
|
const dir = resultOutboxDir(config);
|
|
7241
|
-
|
|
7950
|
+
mkdirSync6(dir, { recursive: true });
|
|
7242
7951
|
const body = {
|
|
7243
7952
|
version: 1,
|
|
7244
7953
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -7246,18 +7955,18 @@ function writeResultOutboxEntry(config, entry) {
|
|
|
7246
7955
|
lastAttemptAt: null,
|
|
7247
7956
|
...entry
|
|
7248
7957
|
};
|
|
7249
|
-
|
|
7958
|
+
writeFileSync6(join11(dir, resultOutboxFileName(entry.commandId)), `${JSON.stringify(body, null, 2)}
|
|
7250
7959
|
`, { mode: 384 });
|
|
7251
7960
|
}
|
|
7252
7961
|
function moveResultOutboxEntryToInvalid(config, file, fullPath, reason, detail, original) {
|
|
7253
7962
|
const invalidDir = resultOutboxInvalidDir(config);
|
|
7254
|
-
|
|
7255
|
-
const invalidPath =
|
|
7963
|
+
mkdirSync6(invalidDir, { recursive: true });
|
|
7964
|
+
const invalidPath = join11(invalidDir, file);
|
|
7256
7965
|
if (original === void 0) {
|
|
7257
7966
|
try {
|
|
7258
7967
|
renameSync3(fullPath, invalidPath);
|
|
7259
7968
|
} catch {
|
|
7260
|
-
|
|
7969
|
+
copyFileSync3(fullPath, invalidPath);
|
|
7261
7970
|
unlinkSync(fullPath);
|
|
7262
7971
|
}
|
|
7263
7972
|
return;
|
|
@@ -7268,14 +7977,14 @@ function moveResultOutboxEntryToInvalid(config, file, fullPath, reason, detail,
|
|
|
7268
7977
|
...detail ? { detail: truncateText(detail, 1e3) } : {},
|
|
7269
7978
|
original
|
|
7270
7979
|
};
|
|
7271
|
-
|
|
7980
|
+
writeFileSync6(invalidPath, `${JSON.stringify(evidence, null, 2)}
|
|
7272
7981
|
`, { mode: 384 });
|
|
7273
7982
|
unlinkSync(fullPath);
|
|
7274
7983
|
}
|
|
7275
7984
|
function readValidResultOutboxEntryOrQuarantine(config, file, fullPath) {
|
|
7276
7985
|
let entry;
|
|
7277
7986
|
try {
|
|
7278
|
-
entry = JSON.parse(
|
|
7987
|
+
entry = JSON.parse(readFileSync8(fullPath, "utf8"));
|
|
7279
7988
|
} catch (err) {
|
|
7280
7989
|
const message = err instanceof Error ? err.message : String(err);
|
|
7281
7990
|
moveResultOutboxEntryToInvalid(config, file, fullPath, "malformed_result_outbox_json", message);
|
|
@@ -7305,13 +8014,13 @@ function updateResultOutboxAttempt(fullPath, entry, err) {
|
|
|
7305
8014
|
...typeof err?.httpStatus === "number" ? { httpStatus: err.httpStatus } : {},
|
|
7306
8015
|
lastError: truncateText(err instanceof Error ? err.message : String(err), 1e3)
|
|
7307
8016
|
};
|
|
7308
|
-
|
|
8017
|
+
writeFileSync6(fullPath, `${JSON.stringify(next, null, 2)}
|
|
7309
8018
|
`, { mode: 384 });
|
|
7310
8019
|
return next;
|
|
7311
8020
|
}
|
|
7312
8021
|
function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err) {
|
|
7313
8022
|
const invalidDir = resultOutboxInvalidDir(config);
|
|
7314
|
-
|
|
8023
|
+
mkdirSync6(invalidDir, { recursive: true });
|
|
7315
8024
|
const body = {
|
|
7316
8025
|
...entry,
|
|
7317
8026
|
invalidReason: reason,
|
|
@@ -7319,8 +8028,8 @@ function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err)
|
|
|
7319
8028
|
...typeof err?.httpStatus === "number" ? { httpStatus: err.httpStatus } : {},
|
|
7320
8029
|
lastError: truncateText(err instanceof Error ? err.message : String(err), 1e3)
|
|
7321
8030
|
};
|
|
7322
|
-
const invalidPath =
|
|
7323
|
-
|
|
8031
|
+
const invalidPath = join11(invalidDir, file);
|
|
8032
|
+
writeFileSync6(invalidPath, `${JSON.stringify(body, null, 2)}
|
|
7324
8033
|
`, { mode: 384 });
|
|
7325
8034
|
try {
|
|
7326
8035
|
unlinkSync(fullPath);
|
|
@@ -7333,11 +8042,11 @@ function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err)
|
|
|
7333
8042
|
}
|
|
7334
8043
|
async function flushResultOutbox(config) {
|
|
7335
8044
|
const dir = resultOutboxDir(config);
|
|
7336
|
-
if (!
|
|
7337
|
-
const files =
|
|
8045
|
+
if (!existsSync10(dir)) return { attempted: 0, completed: 0 };
|
|
8046
|
+
const files = readdirSync8(dir).filter((name) => name.endsWith(".json")).sort();
|
|
7338
8047
|
let completed = 0;
|
|
7339
8048
|
for (const file of files) {
|
|
7340
|
-
const fullPath =
|
|
8049
|
+
const fullPath = join11(dir, file);
|
|
7341
8050
|
const entry = readValidResultOutboxEntryOrQuarantine(config, file, fullPath);
|
|
7342
8051
|
if (!entry) continue;
|
|
7343
8052
|
try {
|
|
@@ -7534,8 +8243,8 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
7534
8243
|
runtimeAuth,
|
|
7535
8244
|
issueId
|
|
7536
8245
|
);
|
|
7537
|
-
const targetDir =
|
|
7538
|
-
|
|
8246
|
+
const targetDir = join11(workspace.cwd, "input-attachments");
|
|
8247
|
+
mkdirSync6(targetDir, { recursive: true });
|
|
7539
8248
|
const usedFilenames = /* @__PURE__ */ new Set();
|
|
7540
8249
|
const materialized = [];
|
|
7541
8250
|
for (const [index, rawAttachment] of attachments.entries()) {
|
|
@@ -7549,11 +8258,11 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
7549
8258
|
filename = `${stem}-${index + 1}${ext}`;
|
|
7550
8259
|
}
|
|
7551
8260
|
usedFilenames.add(filename);
|
|
7552
|
-
const targetPath =
|
|
8261
|
+
const targetPath = join11(targetDir, filename);
|
|
7553
8262
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
7554
|
-
|
|
8263
|
+
writeFileSync6(targetPath, body);
|
|
7555
8264
|
const attachmentId = readString(attachment.id);
|
|
7556
|
-
const actualSha256 =
|
|
8265
|
+
const actualSha256 = createHash8("sha256").update(body).digest("hex");
|
|
7557
8266
|
const lineageCandidates = lineageCandidatesByAttachmentId.get(attachmentId) ?? [];
|
|
7558
8267
|
const lineage = selectAttachmentLineage(lineageCandidates, actualSha256);
|
|
7559
8268
|
if (lineageCandidates.length > 0 && !lineage) {
|
|
@@ -7576,7 +8285,7 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
7576
8285
|
id: attachmentId,
|
|
7577
8286
|
name: readString(attachment.originalFilename) ?? filename,
|
|
7578
8287
|
path: targetPath,
|
|
7579
|
-
relativePath:
|
|
8288
|
+
relativePath: relative7(workspace.cwd, targetPath),
|
|
7580
8289
|
contentType: readString(attachment.contentType),
|
|
7581
8290
|
byteSize: body.byteLength,
|
|
7582
8291
|
contentPath,
|
|
@@ -7625,9 +8334,9 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
7625
8334
|
if (manifest.version !== 1 || !Array.isArray(manifest.entries)) {
|
|
7626
8335
|
throw new Error("artifact_input_manifest_invalid: expected version 1 entries array");
|
|
7627
8336
|
}
|
|
7628
|
-
const targetRoot =
|
|
7629
|
-
|
|
7630
|
-
|
|
8337
|
+
const targetRoot = join11(workspace.cwd, "input-artifacts");
|
|
8338
|
+
rmSync6(targetRoot, { recursive: true, force: true });
|
|
8339
|
+
mkdirSync6(targetRoot, { recursive: true });
|
|
7631
8340
|
const usedPaths = /* @__PURE__ */ new Set();
|
|
7632
8341
|
const materialized = [];
|
|
7633
8342
|
for (const [index, rawEntry] of manifest.entries.entries()) {
|
|
@@ -7645,7 +8354,7 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
7645
8354
|
throw new Error(`artifact_input_manifest_invalid: entry ${index} contentPath does not match attachmentId`);
|
|
7646
8355
|
}
|
|
7647
8356
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
7648
|
-
const actualSha256 =
|
|
8357
|
+
const actualSha256 = createHash8("sha256").update(body).digest("hex");
|
|
7649
8358
|
if (body.byteLength !== byteSize || actualSha256 !== sha256) {
|
|
7650
8359
|
throw new Error(
|
|
7651
8360
|
`artifact_input_integrity_mismatch: workProductId=${workProductId} expectedBytes=${byteSize} actualBytes=${body.byteLength} expectedSha256=${sha256} actualSha256=${actualSha256}`
|
|
@@ -7656,18 +8365,18 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
7656
8365
|
id: attachmentId,
|
|
7657
8366
|
originalFilename: readString(entry.originalFilename)
|
|
7658
8367
|
}, index);
|
|
7659
|
-
let relativePath =
|
|
8368
|
+
let relativePath = join11("input-artifacts", sourceDir, filename).split(/[\\/]+/).join("/");
|
|
7660
8369
|
if (usedPaths.has(relativePath)) {
|
|
7661
8370
|
const ext = extname2(filename);
|
|
7662
8371
|
const stem = ext ? filename.slice(0, -ext.length) : filename;
|
|
7663
8372
|
filename = `${stem}-${index + 1}${ext}`;
|
|
7664
|
-
relativePath =
|
|
8373
|
+
relativePath = join11("input-artifacts", sourceDir, filename).split(/[\\/]+/).join("/");
|
|
7665
8374
|
}
|
|
7666
8375
|
usedPaths.add(relativePath);
|
|
7667
|
-
const targetPath =
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
8376
|
+
const targetPath = join11(workspace.cwd, relativePath);
|
|
8377
|
+
mkdirSync6(dirname7(targetPath), { recursive: true });
|
|
8378
|
+
writeFileSync6(targetPath, body);
|
|
8379
|
+
chmodSync5(targetPath, 292);
|
|
7671
8380
|
materialized.push({
|
|
7672
8381
|
id: attachmentId,
|
|
7673
8382
|
workProductId,
|
|
@@ -7686,9 +8395,9 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
7686
8395
|
version: 1,
|
|
7687
8396
|
entries: materialized.map(({ path: _path, relativePath, ...entry }) => ({ ...entry, path: relativePath }))
|
|
7688
8397
|
};
|
|
7689
|
-
const manifestPath =
|
|
7690
|
-
|
|
7691
|
-
|
|
8398
|
+
const manifestPath = join11(targetRoot, "artifact-input-manifest.json");
|
|
8399
|
+
writeFileSync6(manifestPath, JSON.stringify(localManifest, null, 2) + "\n");
|
|
8400
|
+
chmodSync5(manifestPath, 292);
|
|
7692
8401
|
updateWorkspaceManifest(workspaceManifestPath(workspace), { artifactInputManifest: localManifest });
|
|
7693
8402
|
await ingestLog(config, command, "system", "info", `Materialized ${materialized.length} required artifact input(s) into the execution workspace`, {
|
|
7694
8403
|
artifactInputCount: materialized.length,
|
|
@@ -7697,46 +8406,46 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
7697
8406
|
return materialized;
|
|
7698
8407
|
}
|
|
7699
8408
|
function issueCheckpointDir(workspace) {
|
|
7700
|
-
return
|
|
8409
|
+
return join11(dirname7(workspace.runDir), "checkpoint");
|
|
7701
8410
|
}
|
|
7702
8411
|
async function clearIssueCheckpoint(config, command, workspace, reason) {
|
|
7703
8412
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
7704
|
-
if (!
|
|
7705
|
-
|
|
8413
|
+
if (!existsSync10(checkpointDir)) return false;
|
|
8414
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
7706
8415
|
await ingestLog(config, command, "system", "info", "Cleared issue continuation checkpoint", { reason });
|
|
7707
8416
|
return true;
|
|
7708
8417
|
}
|
|
7709
8418
|
function safeCheckpointRelativePath(rawPath) {
|
|
7710
8419
|
const raw = String(rawPath ?? "").trim();
|
|
7711
|
-
if (
|
|
8420
|
+
if (isAbsolute7(raw) || /^[A-Za-z]:[\\/]/.test(raw)) return null;
|
|
7712
8421
|
const normalized = raw.split(/[\\/]+/).filter(Boolean).join("/");
|
|
7713
8422
|
if (!normalized || normalized.startsWith("../") || normalized.split("/").some((segment) => segment.startsWith("."))) return null;
|
|
7714
8423
|
if (normalized.startsWith("input-attachments/") || isRuntimeMetadataArtifactPath(normalized)) return null;
|
|
7715
8424
|
return normalized;
|
|
7716
8425
|
}
|
|
7717
8426
|
function hashFileSha256(filePath) {
|
|
7718
|
-
return
|
|
8427
|
+
return createHash8("sha256").update(readFileSync8(filePath)).digest("hex");
|
|
7719
8428
|
}
|
|
7720
8429
|
async function materializeIssueCheckpoint(config, command, workspace) {
|
|
7721
8430
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
7722
|
-
const manifestPath =
|
|
7723
|
-
if (!
|
|
8431
|
+
const manifestPath = join11(checkpointDir, "manifest.json");
|
|
8432
|
+
if (!existsSync10(manifestPath)) return [];
|
|
7724
8433
|
let manifest;
|
|
7725
8434
|
try {
|
|
7726
|
-
manifest = asRecord(JSON.parse(
|
|
8435
|
+
manifest = asRecord(JSON.parse(readFileSync8(manifestPath, "utf8")));
|
|
7727
8436
|
} catch (err) {
|
|
7728
|
-
|
|
8437
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
7729
8438
|
throw new Error(`invalid issue checkpoint manifest: ${err instanceof Error ? err.message : String(err)}`);
|
|
7730
8439
|
}
|
|
7731
8440
|
const expiresAt = Date.parse(readString(manifest.expiresAt) ?? "");
|
|
7732
8441
|
if (!Number.isFinite(expiresAt) || expiresAt <= Date.now() || readString(manifest.issueId) !== commandIssueId(command)) {
|
|
7733
|
-
|
|
8442
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
7734
8443
|
return [];
|
|
7735
8444
|
}
|
|
7736
8445
|
try {
|
|
7737
8446
|
const files = Array.isArray(manifest.files) ? manifest.files : [];
|
|
7738
8447
|
if (files.length > 20) throw new Error("issue checkpoint manifest exceeds the limit of 20 files");
|
|
7739
|
-
const filesRoot = realpathSync3(
|
|
8448
|
+
const filesRoot = realpathSync3(join11(checkpointDir, "files"));
|
|
7740
8449
|
const workspaceRoot = realpathSync3(workspace.cwd);
|
|
7741
8450
|
const validated = [];
|
|
7742
8451
|
let totalBytes = 0;
|
|
@@ -7744,12 +8453,12 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
7744
8453
|
const file = asRecord(rawFile);
|
|
7745
8454
|
const relativePath = safeCheckpointRelativePath(readString(file.path));
|
|
7746
8455
|
if (!relativePath) throw new Error("issue checkpoint manifest contains an invalid file path");
|
|
7747
|
-
const sourceCandidate =
|
|
7748
|
-
const target =
|
|
8456
|
+
const sourceCandidate = resolve10(filesRoot, relativePath);
|
|
8457
|
+
const target = resolve10(workspaceRoot, relativePath);
|
|
7749
8458
|
if (!pathWithin2(sourceCandidate, filesRoot) || !pathWithin2(target, workspaceRoot)) {
|
|
7750
8459
|
throw new Error(`issue checkpoint path escapes its workspace: ${relativePath}`);
|
|
7751
8460
|
}
|
|
7752
|
-
if (!
|
|
8461
|
+
if (!existsSync10(sourceCandidate)) throw new Error(`issue checkpoint file is missing: ${relativePath}`);
|
|
7753
8462
|
const source = realpathSync3(sourceCandidate);
|
|
7754
8463
|
if (!pathWithin2(source, filesRoot) || !statSync7(source).isFile()) {
|
|
7755
8464
|
throw new Error(`issue checkpoint source escapes its storage root: ${relativePath}`);
|
|
@@ -7769,17 +8478,17 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
7769
8478
|
const materialized = [];
|
|
7770
8479
|
for (const { relativePath, source, target } of validated) {
|
|
7771
8480
|
try {
|
|
7772
|
-
|
|
8481
|
+
lstatSync6(target);
|
|
7773
8482
|
continue;
|
|
7774
8483
|
} catch (err) {
|
|
7775
8484
|
if (err?.code !== "ENOENT") throw err;
|
|
7776
8485
|
}
|
|
7777
|
-
|
|
7778
|
-
const targetParent = realpathSync3(
|
|
8486
|
+
mkdirSync6(dirname7(target), { recursive: true });
|
|
8487
|
+
const targetParent = realpathSync3(dirname7(target));
|
|
7779
8488
|
if (!pathWithin2(targetParent, workspaceRoot)) {
|
|
7780
8489
|
throw new Error(`issue checkpoint target escapes its workspace: ${relativePath}`);
|
|
7781
8490
|
}
|
|
7782
|
-
|
|
8491
|
+
copyFileSync3(source, target);
|
|
7783
8492
|
materialized.push(relativePath);
|
|
7784
8493
|
}
|
|
7785
8494
|
if (materialized.length > 0) {
|
|
@@ -7803,31 +8512,31 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
7803
8512
|
}
|
|
7804
8513
|
async function saveIssueCheckpoint(config, command, workspace, candidates) {
|
|
7805
8514
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
7806
|
-
const filesDir =
|
|
7807
|
-
|
|
7808
|
-
|
|
8515
|
+
const filesDir = join11(checkpointDir, "files");
|
|
8516
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
8517
|
+
mkdirSync6(filesDir, { recursive: true });
|
|
7809
8518
|
const files = [];
|
|
7810
8519
|
let totalBytes = 0;
|
|
7811
8520
|
const workspaceRoot = realpathSync3(workspace.cwd);
|
|
7812
8521
|
for (const candidate of candidates.slice(0, 20)) {
|
|
7813
8522
|
const relativePath = safeCheckpointRelativePath(candidate.rawPath);
|
|
7814
8523
|
const source = readString(candidate.filePath);
|
|
7815
|
-
if (!relativePath || !source || !
|
|
8524
|
+
if (!relativePath || !source || !existsSync10(source) || !statSync7(source).isFile()) continue;
|
|
7816
8525
|
const ownedSource = realpathSync3(source);
|
|
7817
8526
|
if (!pathWithin2(ownedSource, workspaceRoot)) {
|
|
7818
8527
|
throw new Error(`issue checkpoint source escapes its execution workspace: ${relativePath}`);
|
|
7819
8528
|
}
|
|
7820
8529
|
const byteSize = statSync7(ownedSource).size;
|
|
7821
8530
|
if (byteSize <= 0 || totalBytes + byteSize > MAX_CHECKPOINT_BYTES) continue;
|
|
7822
|
-
const target =
|
|
8531
|
+
const target = resolve10(filesDir, relativePath);
|
|
7823
8532
|
if (!pathWithin2(target, filesDir)) continue;
|
|
7824
|
-
|
|
7825
|
-
|
|
8533
|
+
mkdirSync6(dirname7(target), { recursive: true });
|
|
8534
|
+
copyFileSync3(ownedSource, target);
|
|
7826
8535
|
totalBytes += byteSize;
|
|
7827
8536
|
files.push({ path: relativePath, byteSize, sha256: hashFileSha256(ownedSource) });
|
|
7828
8537
|
}
|
|
7829
8538
|
if (files.length === 0) {
|
|
7830
|
-
|
|
8539
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
7831
8540
|
return null;
|
|
7832
8541
|
}
|
|
7833
8542
|
const manifest = {
|
|
@@ -7839,7 +8548,7 @@ async function saveIssueCheckpoint(config, command, workspace, candidates) {
|
|
|
7839
8548
|
totalBytes,
|
|
7840
8549
|
files
|
|
7841
8550
|
};
|
|
7842
|
-
|
|
8551
|
+
writeFileSync6(join11(checkpointDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
7843
8552
|
`);
|
|
7844
8553
|
await ingestLog(config, command, "system", "warn", `Saved ${files.length} required deliverable(s) for continuation recovery`, manifest);
|
|
7845
8554
|
return manifest;
|
|
@@ -7911,6 +8620,11 @@ async function executeRunCommand(config, command) {
|
|
|
7911
8620
|
let managedMcpProfile = null;
|
|
7912
8621
|
let managedMcpCleanup = null;
|
|
7913
8622
|
let cleanupManagedMcpProfile = null;
|
|
8623
|
+
let piChildIsolation = null;
|
|
8624
|
+
let trustedPiRuntime = null;
|
|
8625
|
+
let trustedPiRuntimeSourcePaths = null;
|
|
8626
|
+
let trustedPiRuntimeProfile = null;
|
|
8627
|
+
let trustedPiRuntimeAudit = null;
|
|
7914
8628
|
if (executor.kind === "codex" && Object.keys(governedMcp).length > 0) {
|
|
7915
8629
|
managedMcpProfile = prepareManagedCodexMcpProfile({
|
|
7916
8630
|
commandId: command.commandId,
|
|
@@ -7935,7 +8649,7 @@ async function executeRunCommand(config, command) {
|
|
|
7935
8649
|
delete executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL;
|
|
7936
8650
|
delete executorEnv.AMASTER_PROVIDER_FLASH_MODEL;
|
|
7937
8651
|
}
|
|
7938
|
-
|
|
8652
|
+
const resolvedProviderConfig = resolvePiExecutorProviderConfig(config, command, executorEnv);
|
|
7939
8653
|
if (Object.keys(governedMcp).length > 0) {
|
|
7940
8654
|
managedMcpProfile = prepareManagedPiMcpProfile({
|
|
7941
8655
|
commandId: command.commandId,
|
|
@@ -7952,6 +8666,28 @@ async function executeRunCommand(config, command) {
|
|
|
7952
8666
|
extraArgs: splitExtraArgs(process.env.AMASTER_PI_EXTRA_ARGS)
|
|
7953
8667
|
});
|
|
7954
8668
|
cleanupManagedMcpProfile = cleanupManagedPiMcpProfile;
|
|
8669
|
+
try {
|
|
8670
|
+
await syncPiExecutorProviderConfig(
|
|
8671
|
+
config,
|
|
8672
|
+
command,
|
|
8673
|
+
readString(managedMcpProfile.env.PI_CODING_AGENT_DIR) ?? readString(managedMcpProfile.env.PI_AGENT_HOME) ?? null,
|
|
8674
|
+
resolvedProviderConfig
|
|
8675
|
+
);
|
|
8676
|
+
const providerCredential = readString(resolvedProviderConfig.providerConfig.AMASTER_API_KEY);
|
|
8677
|
+
if (providerCredential && !managedMcpProfile.protectedValues.includes(providerCredential)) {
|
|
8678
|
+
managedMcpProfile.protectedValues.push(providerCredential);
|
|
8679
|
+
}
|
|
8680
|
+
} catch (error) {
|
|
8681
|
+
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
8682
|
+
commandId: command.commandId,
|
|
8683
|
+
runId: commandRunId(command)
|
|
8684
|
+
});
|
|
8685
|
+
managedMcpProfile = null;
|
|
8686
|
+
throw error;
|
|
8687
|
+
}
|
|
8688
|
+
} else {
|
|
8689
|
+
const agentDir = 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;
|
|
8690
|
+
await syncPiExecutorProviderConfig(config, command, agentDir, resolvedProviderConfig);
|
|
7955
8691
|
}
|
|
7956
8692
|
}
|
|
7957
8693
|
if (managedMcpProfile) {
|
|
@@ -7961,6 +8697,92 @@ async function executeRunCommand(config, command) {
|
|
|
7961
8697
|
...managedMcpProfile.attestation
|
|
7962
8698
|
});
|
|
7963
8699
|
}
|
|
8700
|
+
const piChildAllocator = executor.kind === "pi" ? configuredPiChildIdentityAllocator(config) : null;
|
|
8701
|
+
const trustedPiRuntimeAssertion = commandTrustedPiRuntimeAssertion(command);
|
|
8702
|
+
if (Object.keys(trustedPiRuntimeAssertion).length > 0) {
|
|
8703
|
+
try {
|
|
8704
|
+
if (executor.kind !== "pi") {
|
|
8705
|
+
throw new Error("pi_trusted_runtime_assertion_binding_mismatch:executorKind");
|
|
8706
|
+
}
|
|
8707
|
+
trustedPiRuntimeSourcePaths = trustedPiRuntimeSources(config);
|
|
8708
|
+
trustedPiRuntime = verifyTrustedPiRuntimeAssertion({
|
|
8709
|
+
assertion: trustedPiRuntimeAssertion,
|
|
8710
|
+
connectorId: requireConnectorId(config),
|
|
8711
|
+
commandId: command.commandId,
|
|
8712
|
+
runId: commandRunId(command),
|
|
8713
|
+
leaseId: command.leaseId,
|
|
8714
|
+
executorKind: executor.kind,
|
|
8715
|
+
localDigests: readTrustedPiRuntimeLocalDigests(trustedPiRuntimeSourcePaths)
|
|
8716
|
+
});
|
|
8717
|
+
if (!managedMcpProfile) {
|
|
8718
|
+
throw new Error("pi_trusted_runtime_governed_profile_required");
|
|
8719
|
+
}
|
|
8720
|
+
requireTrustedPiChildAllocator(piChildAllocator, true);
|
|
8721
|
+
trustedPiRuntimeProfile = materializeTrustedPiRuntimeProfile({
|
|
8722
|
+
seedRoot: trustedPiRuntimeSourcePaths.seedRoot,
|
|
8723
|
+
overlayRoot: trustedPiRuntimeSourcePaths.overlayRoot,
|
|
8724
|
+
profileRoot: managedMcpProfile.profileRoot,
|
|
8725
|
+
agentDir: managedMcpProfile.env.PI_CODING_AGENT_DIR,
|
|
8726
|
+
governedMcpConfigPath: managedMcpProfile.configPath,
|
|
8727
|
+
verifiedAssertion: trustedPiRuntime
|
|
8728
|
+
});
|
|
8729
|
+
executorEnv = {
|
|
8730
|
+
...executorEnv,
|
|
8731
|
+
AMASTER_MANAGED_RUNTIME_ASSERTION_FD: "3",
|
|
8732
|
+
AMASTER_MANAGED_RUNTIME_AUDIT_FILE: join11(
|
|
8733
|
+
managedMcpProfile.env.HOME,
|
|
8734
|
+
".amaster-managed-runtime-audit.jsonl"
|
|
8735
|
+
),
|
|
8736
|
+
AMASTER_RUNTIME_LEASE_ID: command.leaseId
|
|
8737
|
+
};
|
|
8738
|
+
} catch (error) {
|
|
8739
|
+
if (managedMcpProfile) {
|
|
8740
|
+
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
8741
|
+
commandId: command.commandId,
|
|
8742
|
+
runId: commandRunId(command)
|
|
8743
|
+
});
|
|
8744
|
+
}
|
|
8745
|
+
throw error;
|
|
8746
|
+
}
|
|
8747
|
+
await ingestLog(config, command, "system", "info", "Verified trusted Pi runtime provenance", {
|
|
8748
|
+
presentationKind: "trusted_pi_runtime_attestation",
|
|
8749
|
+
attestationId: trustedPiRuntime.attestationId,
|
|
8750
|
+
unknownToolMode: trustedPiRuntime.unknownToolMode,
|
|
8751
|
+
directToolBudget: trustedPiRuntime.directToolBudget,
|
|
8752
|
+
digests: trustedPiRuntime.digests,
|
|
8753
|
+
profileAttestationId: trustedPiRuntimeProfile.attestationId,
|
|
8754
|
+
inheritedEntries: trustedPiRuntimeProfile.facts.inheritedEntries
|
|
8755
|
+
});
|
|
8756
|
+
}
|
|
8757
|
+
if (piChildAllocator) {
|
|
8758
|
+
try {
|
|
8759
|
+
const profileRoot = piChildIsolationProfileRoot({
|
|
8760
|
+
managedMcpProfile,
|
|
8761
|
+
executorHome: workspace.executorHome
|
|
8762
|
+
});
|
|
8763
|
+
piChildIsolation = preparePiChildIsolation({
|
|
8764
|
+
allocator: piChildAllocator,
|
|
8765
|
+
effectiveUid: typeof process.geteuid === "function" ? process.geteuid() : null,
|
|
8766
|
+
commandId: command.commandId,
|
|
8767
|
+
runId: commandRunId(command),
|
|
8768
|
+
profileRoot,
|
|
8769
|
+
workspaceRoot: cwd,
|
|
8770
|
+
allowedRoot: config.runtimeWorkspacesRoot
|
|
8771
|
+
});
|
|
8772
|
+
} catch (error) {
|
|
8773
|
+
if (managedMcpProfile) {
|
|
8774
|
+
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
8775
|
+
commandId: command.commandId,
|
|
8776
|
+
runId: commandRunId(command)
|
|
8777
|
+
});
|
|
8778
|
+
}
|
|
8779
|
+
throw error;
|
|
8780
|
+
}
|
|
8781
|
+
await ingestLog(config, command, "system", "info", "Prepared isolated Pi child identity", {
|
|
8782
|
+
presentationKind: "pi_child_isolation_attestation",
|
|
8783
|
+
...piChildIsolation.attestation
|
|
8784
|
+
});
|
|
8785
|
+
}
|
|
7964
8786
|
await ingestLog(config, command, "system", "info", `Compiled ${contextManifest.mode} prompt using ${contextManifest.budget.usedChars}/${contextManifest.budget.totalChars} characters`, {
|
|
7965
8787
|
presentationKind: "context_manifest",
|
|
7966
8788
|
contextManifest
|
|
@@ -8007,11 +8829,35 @@ async function executeRunCommand(config, command) {
|
|
|
8007
8829
|
maxRssMb: config.executorMaxRssMb,
|
|
8008
8830
|
signal: abortController.signal,
|
|
8009
8831
|
executorKind: executor.kind,
|
|
8832
|
+
...piChildIsolation ? { spawnIdentity: piChildIsolation.spawn } : {},
|
|
8833
|
+
...trustedPiRuntime ? {
|
|
8834
|
+
managedInput: `${JSON.stringify(trustedPiRuntimeAssertion)}
|
|
8835
|
+
`
|
|
8836
|
+
} : {},
|
|
8010
8837
|
onOutput: (stream, chunk, rawBytes) => {
|
|
8011
8838
|
noteActiveRunOutput(command, stream, chunk, rawBytes);
|
|
8012
8839
|
liveOutputLogger.write(stream, chunk);
|
|
8013
8840
|
}
|
|
8014
8841
|
});
|
|
8842
|
+
if (trustedPiRuntime) {
|
|
8843
|
+
verifyTrustedPiRuntimeAssertion({
|
|
8844
|
+
assertion: trustedPiRuntimeAssertion,
|
|
8845
|
+
connectorId: requireConnectorId(config),
|
|
8846
|
+
commandId: command.commandId,
|
|
8847
|
+
runId: commandRunId(command),
|
|
8848
|
+
leaseId: command.leaseId,
|
|
8849
|
+
executorKind: executor.kind,
|
|
8850
|
+
localDigests: readTrustedPiRuntimeLocalDigests(trustedPiRuntimeSourcePaths),
|
|
8851
|
+
verifyExpiry: false
|
|
8852
|
+
});
|
|
8853
|
+
trustedPiRuntimeAudit = readTrustedPiRuntimeAudit({
|
|
8854
|
+
profileRoot: managedMcpProfile.profileRoot,
|
|
8855
|
+
auditFile: executorEnv.AMASTER_MANAGED_RUNTIME_AUDIT_FILE,
|
|
8856
|
+
commandId: command.commandId,
|
|
8857
|
+
runId: commandRunId(command),
|
|
8858
|
+
runtimeEnforcementDigest: trustedPiRuntime.digests.runtimeEnforcementDigest
|
|
8859
|
+
});
|
|
8860
|
+
}
|
|
8015
8861
|
} finally {
|
|
8016
8862
|
await liveOutputLogger.flush();
|
|
8017
8863
|
}
|
|
@@ -8095,7 +8941,7 @@ async function executeRunCommand(config, command) {
|
|
|
8095
8941
|
workspace,
|
|
8096
8942
|
workspaceStatus.artifacts.map((artifact) => ({
|
|
8097
8943
|
rawPath: artifact.relativePath,
|
|
8098
|
-
filePath:
|
|
8944
|
+
filePath: resolve10(cwd, artifact.relativePath)
|
|
8099
8945
|
}))
|
|
8100
8946
|
);
|
|
8101
8947
|
nativeSessionRollout = {
|
|
@@ -8239,6 +9085,17 @@ async function executeRunCommand(config, command) {
|
|
|
8239
9085
|
attestation: managedMcpProfile.attestation,
|
|
8240
9086
|
cleanup: managedMcpCleanup
|
|
8241
9087
|
}
|
|
9088
|
+
} : {},
|
|
9089
|
+
...piChildIsolation ? {
|
|
9090
|
+
piChildIsolation: piChildIsolation.attestation
|
|
9091
|
+
} : {},
|
|
9092
|
+
...trustedPiRuntimeProfile ? {
|
|
9093
|
+
trustedPiRuntime: {
|
|
9094
|
+
attestationId: trustedPiRuntime.attestationId,
|
|
9095
|
+
profileAttestationId: trustedPiRuntimeProfile.attestationId,
|
|
9096
|
+
...trustedPiRuntimeProfile.facts,
|
|
9097
|
+
audit: trustedPiRuntimeAudit
|
|
9098
|
+
}
|
|
8242
9099
|
} : {}
|
|
8243
9100
|
};
|
|
8244
9101
|
const completion = await completeCommand(config, command, cancelled ? "cancelled" : succeeded ? "succeeded" : "failed", result2, error ?? void 0);
|
|
@@ -8261,6 +9118,7 @@ async function executeRunCommand(config, command) {
|
|
|
8261
9118
|
runId: commandRunId(command)
|
|
8262
9119
|
});
|
|
8263
9120
|
}
|
|
9121
|
+
piChildIsolation?.release();
|
|
8264
9122
|
stopActiveRunHeartbeats();
|
|
8265
9123
|
forgetActiveRunCommand();
|
|
8266
9124
|
}
|
|
@@ -8463,7 +9321,7 @@ async function runLoop(config) {
|
|
|
8463
9321
|
${message}
|
|
8464
9322
|
`);
|
|
8465
9323
|
}
|
|
8466
|
-
await new Promise((
|
|
9324
|
+
await new Promise((resolve11) => setTimeout(resolve11, config.pollIntervalSeconds * 1e3));
|
|
8467
9325
|
}
|
|
8468
9326
|
}
|
|
8469
9327
|
function help() {
|