@amaster.ai/employee-runtime-connector 0.1.0-beta.31 → 0.1.0-beta.33
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 +1049 -201
- 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.33";
|
|
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,25 @@ 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
|
+
var lastPartialTrustedPiRuntimeSourceWarningKey = null;
|
|
5427
|
+
function configuredPiChildIdentityAllocator(config) {
|
|
5428
|
+
if (!(config.piChildUidBase > 0)) return null;
|
|
5429
|
+
const key = `${config.piChildUidBase}:${config.piChildUidSpan}`;
|
|
5430
|
+
if (!piChildIdentityAllocator || piChildIdentityAllocatorKey !== key) {
|
|
5431
|
+
if (piChildIdentityAllocator?.activeAssignments().length > 0) {
|
|
5432
|
+
throw new Error("pi_child_isolation_config_changed_with_active_runs");
|
|
5433
|
+
}
|
|
5434
|
+
piChildIdentityAllocator = createPiChildIdentityAllocator({
|
|
5435
|
+
uidBase: config.piChildUidBase,
|
|
5436
|
+
uidSpan: config.piChildUidSpan
|
|
5437
|
+
});
|
|
5438
|
+
piChildIdentityAllocatorKey = key;
|
|
5439
|
+
}
|
|
5440
|
+
return piChildIdentityAllocator;
|
|
5441
|
+
}
|
|
4774
5442
|
function mergeActiveRunManifestPatch(commandId, patch = {}) {
|
|
4775
5443
|
return activeRunManifestOutputFlusher.mergePendingPatch(commandId, patch);
|
|
4776
5444
|
}
|
|
@@ -4779,11 +5447,11 @@ function updateActiveRunWorkspaceManifest(commandId, manifestPath, patch = {}) {
|
|
|
4779
5447
|
}
|
|
4780
5448
|
function resultOutboxPendingCount(config) {
|
|
4781
5449
|
const dir = resultOutboxDir(config);
|
|
4782
|
-
if (!
|
|
5450
|
+
if (!existsSync10(dir)) return 0;
|
|
4783
5451
|
try {
|
|
4784
5452
|
let pending = 0;
|
|
4785
|
-
for (const file of
|
|
4786
|
-
if (readValidResultOutboxEntryOrQuarantine(config, file,
|
|
5453
|
+
for (const file of readdirSync8(dir).filter((name) => name.endsWith(".json"))) {
|
|
5454
|
+
if (readValidResultOutboxEntryOrQuarantine(config, file, join11(dir, file))) {
|
|
4787
5455
|
pending += 1;
|
|
4788
5456
|
}
|
|
4789
5457
|
}
|
|
@@ -4799,11 +5467,11 @@ function piCompletionOutputType(event) {
|
|
|
4799
5467
|
}
|
|
4800
5468
|
function resultOutboxActiveRunCommands(config) {
|
|
4801
5469
|
const dir = resultOutboxDir(config);
|
|
4802
|
-
if (!
|
|
5470
|
+
if (!existsSync10(dir)) return [];
|
|
4803
5471
|
const outboxPending = resultOutboxPendingCount(config);
|
|
4804
5472
|
const entries = [];
|
|
4805
|
-
for (const file of
|
|
4806
|
-
const entry = readValidResultOutboxEntryOrQuarantine(config, file,
|
|
5473
|
+
for (const file of readdirSync8(dir).filter((name) => name.endsWith(".json")).sort()) {
|
|
5474
|
+
const entry = readValidResultOutboxEntryOrQuarantine(config, file, join11(dir, file));
|
|
4807
5475
|
if (!entry) continue;
|
|
4808
5476
|
const activeRun = asRecord(entry.activeRun);
|
|
4809
5477
|
const commandId = readString(activeRun.commandId) ?? readString(entry.commandId);
|
|
@@ -4833,12 +5501,12 @@ function resultOutboxActiveRunCommands(config) {
|
|
|
4833
5501
|
}
|
|
4834
5502
|
function resultOutboxFailedRunCommands(config) {
|
|
4835
5503
|
const dir = resultOutboxInvalidDir(config);
|
|
4836
|
-
if (!
|
|
5504
|
+
if (!existsSync10(dir)) return [];
|
|
4837
5505
|
const entries = [];
|
|
4838
|
-
for (const file of
|
|
5506
|
+
for (const file of readdirSync8(dir).filter((name) => name.endsWith(".json")).sort().slice(-100)) {
|
|
4839
5507
|
let entry;
|
|
4840
5508
|
try {
|
|
4841
|
-
entry = asRecord(JSON.parse(
|
|
5509
|
+
entry = asRecord(JSON.parse(readFileSync8(join11(dir, file), "utf8")));
|
|
4842
5510
|
} catch {
|
|
4843
5511
|
continue;
|
|
4844
5512
|
}
|
|
@@ -4898,11 +5566,11 @@ function piExtraArgsDiagnostics(value) {
|
|
|
4898
5566
|
}
|
|
4899
5567
|
function safeExpandPath(value) {
|
|
4900
5568
|
const text = readString(value);
|
|
4901
|
-
return text ?
|
|
5569
|
+
return text ? resolve10(expandHomePath(text)) : null;
|
|
4902
5570
|
}
|
|
4903
5571
|
function safeJsonObjectFromFile(filePath) {
|
|
4904
5572
|
try {
|
|
4905
|
-
const parsed = JSON.parse(
|
|
5573
|
+
const parsed = JSON.parse(readFileSync8(filePath, "utf8"));
|
|
4906
5574
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
4907
5575
|
} catch {
|
|
4908
5576
|
return null;
|
|
@@ -4919,7 +5587,7 @@ function safeDirectorySummary(pathValue) {
|
|
|
4919
5587
|
}
|
|
4920
5588
|
let entryCount = 0;
|
|
4921
5589
|
let truncated = false;
|
|
4922
|
-
for (const name of
|
|
5590
|
+
for (const name of readdirSync8(pathValue)) {
|
|
4923
5591
|
if (name.startsWith(".")) continue;
|
|
4924
5592
|
entryCount += 1;
|
|
4925
5593
|
if (entryCount >= MAX_PI_CAPABILITY_SOURCE_ENTRIES) {
|
|
@@ -4943,12 +5611,12 @@ function safeSkillRootSummary(kind, source, pathValue) {
|
|
|
4943
5611
|
let truncated = false;
|
|
4944
5612
|
if (directory.available && pathValue) {
|
|
4945
5613
|
try {
|
|
4946
|
-
for (const name of
|
|
5614
|
+
for (const name of readdirSync8(pathValue)) {
|
|
4947
5615
|
if (name.startsWith(".")) continue;
|
|
4948
|
-
const skillDir =
|
|
5616
|
+
const skillDir = join11(pathValue, name);
|
|
4949
5617
|
try {
|
|
4950
5618
|
if (!statSync7(skillDir).isDirectory()) continue;
|
|
4951
|
-
if (!
|
|
5619
|
+
if (!existsSync10(join11(skillDir, "SKILL.md"))) continue;
|
|
4952
5620
|
skillCount += 1;
|
|
4953
5621
|
if (skillCount >= MAX_PI_CAPABILITY_SOURCE_ENTRIES) {
|
|
4954
5622
|
truncated = true;
|
|
@@ -4999,7 +5667,7 @@ function objectKeyCount(value) {
|
|
|
4999
5667
|
return value && typeof value === "object" && !Array.isArray(value) ? Object.keys(value).length : 0;
|
|
5000
5668
|
}
|
|
5001
5669
|
function defaultPiCodingAgentDir() {
|
|
5002
|
-
return
|
|
5670
|
+
return join11(homedir3(), ".pi", "agent");
|
|
5003
5671
|
}
|
|
5004
5672
|
function piCapabilitySourcesDiagnostics() {
|
|
5005
5673
|
const configuredPiCodingAgentDir = safeExpandPath(process.env.PI_CODING_AGENT_DIR);
|
|
@@ -5008,11 +5676,11 @@ function piCapabilitySourcesDiagnostics() {
|
|
|
5008
5676
|
const configuredPiAgentHome = safeExpandPath(process.env.PI_AGENT_HOME);
|
|
5009
5677
|
const piAgentHome = configuredPiAgentHome ?? piCodingAgentDir;
|
|
5010
5678
|
const piAgentHomeSource = configuredPiAgentHome ? "PI_AGENT_HOME" : piCodingAgentDirSource;
|
|
5011
|
-
const userSkillsPath = piAgentHome ?
|
|
5012
|
-
const marketplaceSkillsPath = safeExpandPath(process.env.PI_AGENT_MARKETPLACE_SKILLS_DIR) ?? (piAgentHome ?
|
|
5679
|
+
const userSkillsPath = piAgentHome ? join11(piAgentHome, "skills") : null;
|
|
5680
|
+
const marketplaceSkillsPath = safeExpandPath(process.env.PI_AGENT_MARKETPLACE_SKILLS_DIR) ?? (piAgentHome ? join11(piAgentHome, "marketplace", "skills") : null);
|
|
5013
5681
|
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 ?
|
|
5682
|
+
const mcpConfigPath = safeExpandPath(process.env.PI_AGENT_MCP_SERVERS_FILE) ?? (piAgentHome ? join11(piAgentHome, "mcp.json") : null);
|
|
5683
|
+
const settingsConfigPath = piCodingAgentDir ? join11(piCodingAgentDir, "settings.json") : null;
|
|
5016
5684
|
const skillRoots = [
|
|
5017
5685
|
safeSkillRootSummary("user", `${piAgentHomeSource}/skills`, userSkillsPath),
|
|
5018
5686
|
safeSkillRootSummary(
|
|
@@ -5127,6 +5795,31 @@ function executorReadinessFor(config, executor) {
|
|
|
5127
5795
|
function buildExecutorReadiness(config) {
|
|
5128
5796
|
return config.executors.filter((executor) => executor.kind === "codex" || executor.kind === "pi").map((executor) => executorReadinessFor(config, executor));
|
|
5129
5797
|
}
|
|
5798
|
+
function trustedPiRuntimeProvenancePayload(config) {
|
|
5799
|
+
const configuredSources = [
|
|
5800
|
+
Boolean(config.piRuntimeSeedRoot),
|
|
5801
|
+
Boolean(config.piRuntimeOverlayRoot),
|
|
5802
|
+
Boolean(config.piRuntimeEffectivePolicyFile)
|
|
5803
|
+
];
|
|
5804
|
+
const configured = configuredSources.filter(Boolean).length;
|
|
5805
|
+
if (configured === 0) {
|
|
5806
|
+
lastPartialTrustedPiRuntimeSourceWarningKey = null;
|
|
5807
|
+
return {};
|
|
5808
|
+
}
|
|
5809
|
+
if (configured !== 3) {
|
|
5810
|
+
const warningKey = configuredSources.map((value) => value ? "1" : "0").join("");
|
|
5811
|
+
if (warningKey !== lastPartialTrustedPiRuntimeSourceWarningKey) {
|
|
5812
|
+
process.stderr.write(
|
|
5813
|
+
`AMaster daemon warning pi_trusted_runtime_source_config_partial: configured=${configured} required=3; ordinary heartbeat continues without trusted runtime provenance.
|
|
5814
|
+
`
|
|
5815
|
+
);
|
|
5816
|
+
lastPartialTrustedPiRuntimeSourceWarningKey = warningKey;
|
|
5817
|
+
}
|
|
5818
|
+
return {};
|
|
5819
|
+
}
|
|
5820
|
+
lastPartialTrustedPiRuntimeSourceWarningKey = null;
|
|
5821
|
+
return trustedPiRuntimeProvenanceCache.read(trustedPiRuntimeSources(config));
|
|
5822
|
+
}
|
|
5130
5823
|
function buildRegisterPayload(config) {
|
|
5131
5824
|
const buildCommit = readString(process.env.AMASTER_RUNTIME_BUILD_COMMIT ?? process.env.AMASTER_SOURCE_COMMIT);
|
|
5132
5825
|
return {
|
|
@@ -5190,6 +5883,7 @@ function buildHeartbeatPayload(config, options = {}) {
|
|
|
5190
5883
|
contractVersion: CONNECTOR_CONTRACT_VERSION,
|
|
5191
5884
|
platform: process.platform,
|
|
5192
5885
|
arch: process.arch,
|
|
5886
|
+
...trustedPiRuntimeProvenancePayload(config),
|
|
5193
5887
|
runtimeStatus: {
|
|
5194
5888
|
daemon: "running",
|
|
5195
5889
|
pid: process.pid,
|
|
@@ -5217,13 +5911,13 @@ function piAgentLocalPlatformRunnerEnabled(config) {
|
|
|
5217
5911
|
}
|
|
5218
5912
|
function piAgentSystemDataDir(config) {
|
|
5219
5913
|
const configured = readString(config.AMASTER_PI_AGENT_SYSTEM_DATA_DIR ?? process.env.AMASTER_PI_AGENT_SYSTEM_DATA_DIR);
|
|
5220
|
-
return configured ?
|
|
5914
|
+
return configured ? resolve10(expandHomePath(configured)) : null;
|
|
5221
5915
|
}
|
|
5222
5916
|
function readPiAgentLocalPlatformCredential(credentialsDir) {
|
|
5223
|
-
const pointer =
|
|
5917
|
+
const pointer = readJsonFile2(join11(credentialsDir, "latest.json"));
|
|
5224
5918
|
const credentialRef = readString(pointer.credentialRef);
|
|
5225
5919
|
if (!credentialRef || !/^[a-f0-9]{64}$/i.test(credentialRef)) return null;
|
|
5226
|
-
const credential =
|
|
5920
|
+
const credential = readJsonFile2(join11(credentialsDir, `${credentialRef}.json`));
|
|
5227
5921
|
const organizationId = readString(credential.organizationId);
|
|
5228
5922
|
const apiKey = readString(credential.apiKey);
|
|
5229
5923
|
if (credential.version !== 1 || !organizationId || !apiKey) return null;
|
|
@@ -5239,17 +5933,17 @@ function piAgentLocalPlatformCredentials(config) {
|
|
|
5239
5933
|
if (!piAgentLocalPlatformRunnerEnabled(config)) return [];
|
|
5240
5934
|
const systemDataDir = piAgentSystemDataDir(config);
|
|
5241
5935
|
if (!systemDataDir) return [];
|
|
5242
|
-
const companiesDir =
|
|
5936
|
+
const companiesDir = join11(systemDataDir, "companies");
|
|
5243
5937
|
let entries = [];
|
|
5244
5938
|
try {
|
|
5245
|
-
entries =
|
|
5939
|
+
entries = readdirSync8(companiesDir, { withFileTypes: true });
|
|
5246
5940
|
} catch {
|
|
5247
5941
|
return [];
|
|
5248
5942
|
}
|
|
5249
5943
|
const credentialsByOrganizationId = /* @__PURE__ */ new Map();
|
|
5250
5944
|
for (const entry of entries) {
|
|
5251
5945
|
if (!entry.isDirectory()) continue;
|
|
5252
|
-
const credential = readPiAgentLocalPlatformCredential(
|
|
5946
|
+
const credential = readPiAgentLocalPlatformCredential(join11(companiesDir, entry.name, "model-credentials"));
|
|
5253
5947
|
if (credential) credentialsByOrganizationId.set(credential.organizationId, credential);
|
|
5254
5948
|
}
|
|
5255
5949
|
return [...credentialsByOrganizationId.values()];
|
|
@@ -5423,7 +6117,7 @@ AMASTER_WORKSPACE_ALLOWLIST=${quoteShell(config.workspaceBindings.join(","))}
|
|
|
5423
6117
|
AMASTER_EXECUTORS=${quoteShell(executorEnv)}
|
|
5424
6118
|
AMASTER_CAPABILITIES=${quoteShell(config.capabilities.join(","))}
|
|
5425
6119
|
AMASTER_NETWORK_DOMAINS=${quoteShell(config.networkDomains.join(","))}
|
|
5426
|
-
AMASTER_DAEMON_STATE_FILE=${quoteShell(
|
|
6120
|
+
AMASTER_DAEMON_STATE_FILE=${quoteShell(join11(homedir3(), ".amaster-employee", "runtime-connector-state.json"))}
|
|
5427
6121
|
EOF
|
|
5428
6122
|
|
|
5429
6123
|
set -a
|
|
@@ -5611,10 +6305,10 @@ function buildActiveRunCommandStatus(config, entry) {
|
|
|
5611
6305
|
const base = {
|
|
5612
6306
|
...entry,
|
|
5613
6307
|
phase: readString(entry.phase) ?? "executing",
|
|
5614
|
-
managedWorkdirPresent: entry.workspacePath ?
|
|
6308
|
+
managedWorkdirPresent: entry.workspacePath ? existsSync10(entry.workspacePath) : false,
|
|
5615
6309
|
outboxPending: resultOutboxPendingCount(config)
|
|
5616
6310
|
};
|
|
5617
|
-
if (!entry.workspacePath || !
|
|
6311
|
+
if (!entry.workspacePath || !existsSync10(entry.workspacePath)) return base;
|
|
5618
6312
|
const manifestPath = entry.manifestPath ?? workspaceManifestPath(entry.workspacePath);
|
|
5619
6313
|
const status = readWorkspaceStatus(entry.workspacePath, { hashCache: workspaceStatusHashCache });
|
|
5620
6314
|
const artifactCandidates = status.artifacts.slice(0, 20);
|
|
@@ -5778,18 +6472,33 @@ function commandExecutorEnv(command) {
|
|
|
5778
6472
|
...normalizeExecutorEnvValue(command.executorEnv)
|
|
5779
6473
|
};
|
|
5780
6474
|
}
|
|
5781
|
-
function
|
|
6475
|
+
function commandTrustedPiRuntimeAssertion(command) {
|
|
6476
|
+
const topLevel = asRecord(command.trustedPiRuntime);
|
|
6477
|
+
if (Object.keys(topLevel).length > 0) return topLevel;
|
|
6478
|
+
return asRecord(asRecord(command.payload).trustedPiRuntime);
|
|
6479
|
+
}
|
|
6480
|
+
function trustedPiRuntimeSources(config) {
|
|
6481
|
+
if (!config.piRuntimeSeedRoot || !config.piRuntimeOverlayRoot || !config.piRuntimeEffectivePolicyFile) {
|
|
6482
|
+
throw new Error("pi_trusted_runtime_source_config_missing");
|
|
6483
|
+
}
|
|
6484
|
+
return {
|
|
6485
|
+
seedRoot: config.piRuntimeSeedRoot,
|
|
6486
|
+
overlayRoot: config.piRuntimeOverlayRoot,
|
|
6487
|
+
policyFile: config.piRuntimeEffectivePolicyFile
|
|
6488
|
+
};
|
|
6489
|
+
}
|
|
6490
|
+
function readJsonFile2(filePath) {
|
|
5782
6491
|
try {
|
|
5783
|
-
const parsed = JSON.parse(
|
|
6492
|
+
const parsed = JSON.parse(readFileSync8(filePath, "utf8"));
|
|
5784
6493
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
5785
6494
|
} catch {
|
|
5786
6495
|
return {};
|
|
5787
6496
|
}
|
|
5788
6497
|
}
|
|
5789
6498
|
function writeJsonFileAtomic(filePath, value) {
|
|
5790
|
-
|
|
6499
|
+
mkdirSync6(dirname7(filePath), { recursive: true });
|
|
5791
6500
|
const tmpPath = `${filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
5792
|
-
|
|
6501
|
+
writeFileSync6(tmpPath, `${JSON.stringify(value, null, 2)}
|
|
5793
6502
|
`, { mode: 384 });
|
|
5794
6503
|
renameSync3(tmpPath, filePath);
|
|
5795
6504
|
}
|
|
@@ -5835,8 +6544,8 @@ function ensureAmasterProviderModel(models, modelId, flash) {
|
|
|
5835
6544
|
function syncAmasterProviderModels(agentDir, executorEnv) {
|
|
5836
6545
|
const apiKey = readString(executorEnv.AMASTER_API_KEY);
|
|
5837
6546
|
if (!apiKey) return false;
|
|
5838
|
-
const modelsPath =
|
|
5839
|
-
const config =
|
|
6547
|
+
const modelsPath = join11(agentDir, "models.json");
|
|
6548
|
+
const config = readJsonFile2(modelsPath);
|
|
5840
6549
|
const providers = asRecord(config.providers);
|
|
5841
6550
|
const amaster = { ...asRecord(providers.amaster) };
|
|
5842
6551
|
amaster.apiKey = apiKey;
|
|
@@ -5859,9 +6568,9 @@ function syncAmasterProviderModels(agentDir, executorEnv) {
|
|
|
5859
6568
|
function syncAmasterProviderSettings(agentDir, executorEnv) {
|
|
5860
6569
|
const apiKey = readString(executorEnv.AMASTER_API_KEY);
|
|
5861
6570
|
if (!apiKey) return false;
|
|
5862
|
-
const settingsPath =
|
|
5863
|
-
if (!
|
|
5864
|
-
const settings =
|
|
6571
|
+
const settingsPath = join11(agentDir, "settings.json");
|
|
6572
|
+
if (!existsSync10(settingsPath)) return false;
|
|
6573
|
+
const settings = readJsonFile2(settingsPath);
|
|
5865
6574
|
const baseUrl = readString(executorEnv.AMASTER_PROVIDER_BASE_URL);
|
|
5866
6575
|
const defaultModel = readString(executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL);
|
|
5867
6576
|
const imageGenBaseUrl = imageGenBaseUrlFromProviderBaseUrl(baseUrl);
|
|
@@ -5987,11 +6696,11 @@ function safeAgentInstructionMaterializationTarget(workspace, filePath) {
|
|
|
5987
6696
|
const raw = readString(filePath);
|
|
5988
6697
|
if (!raw || raw.includes("\0")) return null;
|
|
5989
6698
|
const normalized = raw.replace(/\\/g, "/");
|
|
5990
|
-
if (
|
|
6699
|
+
if (isAbsolute7(normalized)) return null;
|
|
5991
6700
|
const segments = normalized.split("/").filter(Boolean);
|
|
5992
6701
|
if (segments.length === 0 || segments.some((segment) => segment === "." || segment === "..")) return null;
|
|
5993
6702
|
const relativePath = segments.join("/");
|
|
5994
|
-
const targetPath =
|
|
6703
|
+
const targetPath = resolve10(workspace.cwd, relativePath);
|
|
5995
6704
|
if (!pathWithin2(targetPath, workspace.cwd)) return null;
|
|
5996
6705
|
return { relativePath, targetPath };
|
|
5997
6706
|
}
|
|
@@ -6005,8 +6714,8 @@ async function materializeAgentInstructionsBundle(config, command, workspace) {
|
|
|
6005
6714
|
if (!content) continue;
|
|
6006
6715
|
const target = safeAgentInstructionMaterializationTarget(workspace, filePath);
|
|
6007
6716
|
if (!target) continue;
|
|
6008
|
-
|
|
6009
|
-
|
|
6717
|
+
mkdirSync6(dirname7(target.targetPath), { recursive: true });
|
|
6718
|
+
writeFileSync6(target.targetPath, content, "utf8");
|
|
6010
6719
|
materialized.push({
|
|
6011
6720
|
path: target.relativePath,
|
|
6012
6721
|
byteSize: Buffer.byteLength(content, "utf8")
|
|
@@ -6075,20 +6784,20 @@ function safeCompanyPiHomeSegment(companyId) {
|
|
|
6075
6784
|
if (!raw) return null;
|
|
6076
6785
|
if (/^[A-Za-z0-9][A-Za-z0-9._-]{0,119}$/.test(raw)) return raw;
|
|
6077
6786
|
const normalized = raw.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[._-]+|[._-]+$/g, "").slice(0, 80);
|
|
6078
|
-
const hash =
|
|
6787
|
+
const hash = createHash8("sha256").update(raw).digest("hex").slice(0, 12);
|
|
6079
6788
|
return normalized ? `${normalized}-${hash}` : `company-${hash}`;
|
|
6080
6789
|
}
|
|
6081
6790
|
function companyPiHomeRoot(baseEnv) {
|
|
6082
6791
|
const explicitRoot = readString(baseEnv.AMASTER_COMPANY_PI_HOME_ROOT);
|
|
6083
|
-
if (explicitRoot) return
|
|
6792
|
+
if (explicitRoot) return resolve10(expandHomePath(explicitRoot));
|
|
6084
6793
|
const configuredPiHome = readString(baseEnv.PI_AGENT_HOME) ?? readString(baseEnv.PI_CODING_AGENT_DIR);
|
|
6085
|
-
if (configuredPiHome) return
|
|
6086
|
-
return
|
|
6794
|
+
if (configuredPiHome) return join11(dirname7(resolve10(expandHomePath(configuredPiHome))), "companies");
|
|
6795
|
+
return join11(homedir3(), ".amaster-employee", "companies");
|
|
6087
6796
|
}
|
|
6088
6797
|
function companyPiAgentHome(baseEnv, companyId) {
|
|
6089
6798
|
const segment = safeCompanyPiHomeSegment(companyId);
|
|
6090
6799
|
if (!segment) return null;
|
|
6091
|
-
return
|
|
6800
|
+
return join11(companyPiHomeRoot(baseEnv), segment, ".pi");
|
|
6092
6801
|
}
|
|
6093
6802
|
function commandUsesPiExecutor(command) {
|
|
6094
6803
|
return readString(asRecord(command.payload).executorKind) === "pi";
|
|
@@ -6157,7 +6866,7 @@ function resolveNativeSessionRequest(command, workspace) {
|
|
|
6157
6866
|
try {
|
|
6158
6867
|
cwdMatched = realpathSync3(requestedCwd) === realpathSync3(sourceWorkspacePath);
|
|
6159
6868
|
} catch {
|
|
6160
|
-
cwdMatched =
|
|
6869
|
+
cwdMatched = resolve10(requestedCwd) === resolve10(sourceWorkspacePath);
|
|
6161
6870
|
}
|
|
6162
6871
|
}
|
|
6163
6872
|
const used = Boolean(enabled && requested && sessionId && requestedCwd && cwdMatched);
|
|
@@ -6584,10 +7293,10 @@ function realOrResolvedPath(value) {
|
|
|
6584
7293
|
try {
|
|
6585
7294
|
return realpathSync3(value);
|
|
6586
7295
|
} catch {
|
|
6587
|
-
return
|
|
7296
|
+
return resolve10(value);
|
|
6588
7297
|
}
|
|
6589
7298
|
}
|
|
6590
|
-
var LSOF_COMMAND = process.platform === "darwin" &&
|
|
7299
|
+
var LSOF_COMMAND = process.platform === "darwin" && existsSync10("/usr/sbin/lsof") ? "/usr/sbin/lsof" : "lsof";
|
|
6591
7300
|
function processCwdForPid(pid) {
|
|
6592
7301
|
if (process.platform === "linux") {
|
|
6593
7302
|
try {
|
|
@@ -6613,7 +7322,7 @@ function allProcessCwdsByPid() {
|
|
|
6613
7322
|
if (process.platform === "linux") {
|
|
6614
7323
|
const procEntries = (() => {
|
|
6615
7324
|
try {
|
|
6616
|
-
return
|
|
7325
|
+
return readdirSync8("/proc", { withFileTypes: true });
|
|
6617
7326
|
} catch {
|
|
6618
7327
|
return [];
|
|
6619
7328
|
}
|
|
@@ -6709,21 +7418,21 @@ function killWorkspaceResidentProcesses(cwd, processGroupId, options = {}) {
|
|
|
6709
7418
|
}
|
|
6710
7419
|
function walkManagedWorkdirs(root) {
|
|
6711
7420
|
const workdirs = [];
|
|
6712
|
-
if (!root || !
|
|
7421
|
+
if (!root || !existsSync10(root)) return workdirs;
|
|
6713
7422
|
const stack = [root];
|
|
6714
7423
|
while (stack.length > 0) {
|
|
6715
7424
|
const current = stack.pop();
|
|
6716
7425
|
if (!current) continue;
|
|
6717
7426
|
let entries = [];
|
|
6718
7427
|
try {
|
|
6719
|
-
entries =
|
|
7428
|
+
entries = readdirSync8(current, { withFileTypes: true });
|
|
6720
7429
|
} catch {
|
|
6721
7430
|
continue;
|
|
6722
7431
|
}
|
|
6723
7432
|
for (const entry of entries) {
|
|
6724
7433
|
if (!entry.isDirectory()) continue;
|
|
6725
|
-
const fullPath =
|
|
6726
|
-
if (entry.name === "workdir" &&
|
|
7434
|
+
const fullPath = join11(current, entry.name);
|
|
7435
|
+
if (entry.name === "workdir" && existsSync10(workspaceManifestPath(fullPath))) {
|
|
6727
7436
|
workdirs.push(fullPath);
|
|
6728
7437
|
continue;
|
|
6729
7438
|
}
|
|
@@ -6761,8 +7470,8 @@ function manifestMatchesActiveRuntimeRef(manifest, refs, workdir = null) {
|
|
|
6761
7470
|
}
|
|
6762
7471
|
function buildOrphanReaperSample(root, workdir, manifest, residents) {
|
|
6763
7472
|
const relativeWorkdir = (() => {
|
|
6764
|
-
const value =
|
|
6765
|
-
return value && !value.startsWith("..") && !
|
|
7473
|
+
const value = relative7(root, workdir);
|
|
7474
|
+
return value && !value.startsWith("..") && !isAbsolute7(value) ? value : basename6(workdir);
|
|
6766
7475
|
})();
|
|
6767
7476
|
return {
|
|
6768
7477
|
workdir: relativeWorkdir,
|
|
@@ -6869,7 +7578,8 @@ function runExecutor(command, args, options) {
|
|
|
6869
7578
|
cwd: options.cwd,
|
|
6870
7579
|
env: options.env,
|
|
6871
7580
|
detached: process.platform !== "win32",
|
|
6872
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
7581
|
+
stdio: options.managedInput ? ["pipe", "pipe", "pipe", "pipe"] : ["pipe", "pipe", "pipe"],
|
|
7582
|
+
...options.spawnIdentity ?? {}
|
|
6873
7583
|
});
|
|
6874
7584
|
const processGroupId = processGroupIdForChild(child);
|
|
6875
7585
|
const finish = (result2) => {
|
|
@@ -6904,6 +7614,13 @@ function runExecutor(command, args, options) {
|
|
|
6904
7614
|
signalExecutorProcess(child, "SIGTERM", processGroupId);
|
|
6905
7615
|
scheduleStopKill();
|
|
6906
7616
|
};
|
|
7617
|
+
if (options.managedInput) {
|
|
7618
|
+
child.stdio[3].once("error", (error) => {
|
|
7619
|
+
spawnError = `managed_runtime_assertion_delivery_failed: ${error.message}`;
|
|
7620
|
+
requestStop("managed_runtime_assertion_delivery_failed");
|
|
7621
|
+
});
|
|
7622
|
+
child.stdio[3].end(options.managedInput);
|
|
7623
|
+
}
|
|
6907
7624
|
const reapStoppedWorkspaceResidents = () => {
|
|
6908
7625
|
if (settled || !stopReason || stopReason === "completion_cleanup") return;
|
|
6909
7626
|
const residents = listWorkspaceResidentProcesses(options.cwd, processGroupId, {
|
|
@@ -7146,12 +7863,16 @@ async function ingestRuntimeArtifacts(config, command, cwd, mcpToolResults) {
|
|
|
7146
7863
|
const receipts = [];
|
|
7147
7864
|
for (const upload of uploads) {
|
|
7148
7865
|
const path = `/api/amaster/runtime-connectors/${connectorId}/artifact-intents/${encodeURIComponent(upload.intentId)}/ingest`;
|
|
7866
|
+
const sourcePathHeaders = /^[\x20-\x7e]+$/.test(upload.sourceRelativePath) ? { "x-amaster-artifact-source-path": upload.sourceRelativePath } : {
|
|
7867
|
+
"x-amaster-artifact-source-path": encodeURIComponent(upload.sourceRelativePath),
|
|
7868
|
+
"x-amaster-artifact-source-path-encoding": "uri-component"
|
|
7869
|
+
};
|
|
7149
7870
|
try {
|
|
7150
7871
|
const receipt = asRecord(await postRuntimeConnectorBytes(config, path, upload.body, {
|
|
7151
7872
|
"x-amaster-command-id": command.commandId,
|
|
7152
7873
|
"x-amaster-run-id": runId,
|
|
7153
7874
|
"x-amaster-artifact-manifest-id": upload.manifestId,
|
|
7154
|
-
|
|
7875
|
+
...sourcePathHeaders
|
|
7155
7876
|
}));
|
|
7156
7877
|
if (readString(receipt.intentId) !== upload.intentId || readString(receipt.status) !== "finalized") {
|
|
7157
7878
|
throw new Error(`Runtime Artifact ${upload.intentId} was not finalized: ${JSON.stringify(receipt)}`);
|
|
@@ -7234,15 +7955,15 @@ async function completeCommand(config, command, status, result2, error) {
|
|
|
7234
7955
|
}
|
|
7235
7956
|
function resultOutboxDir(config) {
|
|
7236
7957
|
const explicit = readString(process.env.AMASTER_RESULT_OUTBOX_DIR);
|
|
7237
|
-
if (explicit) return
|
|
7238
|
-
return
|
|
7958
|
+
if (explicit) return resolve10(expandHomePath(explicit));
|
|
7959
|
+
return join11(dirname7(stateFilePath(process.env)), "result-outbox");
|
|
7239
7960
|
}
|
|
7240
7961
|
function resultOutboxInvalidDir(config) {
|
|
7241
|
-
return
|
|
7962
|
+
return join11(resultOutboxDir(config), "invalid");
|
|
7242
7963
|
}
|
|
7243
7964
|
function writeResultOutboxEntry(config, entry) {
|
|
7244
7965
|
const dir = resultOutboxDir(config);
|
|
7245
|
-
|
|
7966
|
+
mkdirSync6(dir, { recursive: true });
|
|
7246
7967
|
const body = {
|
|
7247
7968
|
version: 1,
|
|
7248
7969
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -7250,18 +7971,18 @@ function writeResultOutboxEntry(config, entry) {
|
|
|
7250
7971
|
lastAttemptAt: null,
|
|
7251
7972
|
...entry
|
|
7252
7973
|
};
|
|
7253
|
-
|
|
7974
|
+
writeFileSync6(join11(dir, resultOutboxFileName(entry.commandId)), `${JSON.stringify(body, null, 2)}
|
|
7254
7975
|
`, { mode: 384 });
|
|
7255
7976
|
}
|
|
7256
7977
|
function moveResultOutboxEntryToInvalid(config, file, fullPath, reason, detail, original) {
|
|
7257
7978
|
const invalidDir = resultOutboxInvalidDir(config);
|
|
7258
|
-
|
|
7259
|
-
const invalidPath =
|
|
7979
|
+
mkdirSync6(invalidDir, { recursive: true });
|
|
7980
|
+
const invalidPath = join11(invalidDir, file);
|
|
7260
7981
|
if (original === void 0) {
|
|
7261
7982
|
try {
|
|
7262
7983
|
renameSync3(fullPath, invalidPath);
|
|
7263
7984
|
} catch {
|
|
7264
|
-
|
|
7985
|
+
copyFileSync3(fullPath, invalidPath);
|
|
7265
7986
|
unlinkSync(fullPath);
|
|
7266
7987
|
}
|
|
7267
7988
|
return;
|
|
@@ -7272,14 +7993,14 @@ function moveResultOutboxEntryToInvalid(config, file, fullPath, reason, detail,
|
|
|
7272
7993
|
...detail ? { detail: truncateText(detail, 1e3) } : {},
|
|
7273
7994
|
original
|
|
7274
7995
|
};
|
|
7275
|
-
|
|
7996
|
+
writeFileSync6(invalidPath, `${JSON.stringify(evidence, null, 2)}
|
|
7276
7997
|
`, { mode: 384 });
|
|
7277
7998
|
unlinkSync(fullPath);
|
|
7278
7999
|
}
|
|
7279
8000
|
function readValidResultOutboxEntryOrQuarantine(config, file, fullPath) {
|
|
7280
8001
|
let entry;
|
|
7281
8002
|
try {
|
|
7282
|
-
entry = JSON.parse(
|
|
8003
|
+
entry = JSON.parse(readFileSync8(fullPath, "utf8"));
|
|
7283
8004
|
} catch (err) {
|
|
7284
8005
|
const message = err instanceof Error ? err.message : String(err);
|
|
7285
8006
|
moveResultOutboxEntryToInvalid(config, file, fullPath, "malformed_result_outbox_json", message);
|
|
@@ -7309,13 +8030,13 @@ function updateResultOutboxAttempt(fullPath, entry, err) {
|
|
|
7309
8030
|
...typeof err?.httpStatus === "number" ? { httpStatus: err.httpStatus } : {},
|
|
7310
8031
|
lastError: truncateText(err instanceof Error ? err.message : String(err), 1e3)
|
|
7311
8032
|
};
|
|
7312
|
-
|
|
8033
|
+
writeFileSync6(fullPath, `${JSON.stringify(next, null, 2)}
|
|
7313
8034
|
`, { mode: 384 });
|
|
7314
8035
|
return next;
|
|
7315
8036
|
}
|
|
7316
8037
|
function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err) {
|
|
7317
8038
|
const invalidDir = resultOutboxInvalidDir(config);
|
|
7318
|
-
|
|
8039
|
+
mkdirSync6(invalidDir, { recursive: true });
|
|
7319
8040
|
const body = {
|
|
7320
8041
|
...entry,
|
|
7321
8042
|
invalidReason: reason,
|
|
@@ -7323,8 +8044,8 @@ function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err)
|
|
|
7323
8044
|
...typeof err?.httpStatus === "number" ? { httpStatus: err.httpStatus } : {},
|
|
7324
8045
|
lastError: truncateText(err instanceof Error ? err.message : String(err), 1e3)
|
|
7325
8046
|
};
|
|
7326
|
-
const invalidPath =
|
|
7327
|
-
|
|
8047
|
+
const invalidPath = join11(invalidDir, file);
|
|
8048
|
+
writeFileSync6(invalidPath, `${JSON.stringify(body, null, 2)}
|
|
7328
8049
|
`, { mode: 384 });
|
|
7329
8050
|
try {
|
|
7330
8051
|
unlinkSync(fullPath);
|
|
@@ -7337,11 +8058,11 @@ function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err)
|
|
|
7337
8058
|
}
|
|
7338
8059
|
async function flushResultOutbox(config) {
|
|
7339
8060
|
const dir = resultOutboxDir(config);
|
|
7340
|
-
if (!
|
|
7341
|
-
const files =
|
|
8061
|
+
if (!existsSync10(dir)) return { attempted: 0, completed: 0 };
|
|
8062
|
+
const files = readdirSync8(dir).filter((name) => name.endsWith(".json")).sort();
|
|
7342
8063
|
let completed = 0;
|
|
7343
8064
|
for (const file of files) {
|
|
7344
|
-
const fullPath =
|
|
8065
|
+
const fullPath = join11(dir, file);
|
|
7345
8066
|
const entry = readValidResultOutboxEntryOrQuarantine(config, file, fullPath);
|
|
7346
8067
|
if (!entry) continue;
|
|
7347
8068
|
try {
|
|
@@ -7538,8 +8259,8 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
7538
8259
|
runtimeAuth,
|
|
7539
8260
|
issueId
|
|
7540
8261
|
);
|
|
7541
|
-
const targetDir =
|
|
7542
|
-
|
|
8262
|
+
const targetDir = join11(workspace.cwd, "input-attachments");
|
|
8263
|
+
mkdirSync6(targetDir, { recursive: true });
|
|
7543
8264
|
const usedFilenames = /* @__PURE__ */ new Set();
|
|
7544
8265
|
const materialized = [];
|
|
7545
8266
|
for (const [index, rawAttachment] of attachments.entries()) {
|
|
@@ -7553,11 +8274,11 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
7553
8274
|
filename = `${stem}-${index + 1}${ext}`;
|
|
7554
8275
|
}
|
|
7555
8276
|
usedFilenames.add(filename);
|
|
7556
|
-
const targetPath =
|
|
8277
|
+
const targetPath = join11(targetDir, filename);
|
|
7557
8278
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
7558
|
-
|
|
8279
|
+
writeFileSync6(targetPath, body);
|
|
7559
8280
|
const attachmentId = readString(attachment.id);
|
|
7560
|
-
const actualSha256 =
|
|
8281
|
+
const actualSha256 = createHash8("sha256").update(body).digest("hex");
|
|
7561
8282
|
const lineageCandidates = lineageCandidatesByAttachmentId.get(attachmentId) ?? [];
|
|
7562
8283
|
const lineage = selectAttachmentLineage(lineageCandidates, actualSha256);
|
|
7563
8284
|
if (lineageCandidates.length > 0 && !lineage) {
|
|
@@ -7580,7 +8301,7 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
7580
8301
|
id: attachmentId,
|
|
7581
8302
|
name: readString(attachment.originalFilename) ?? filename,
|
|
7582
8303
|
path: targetPath,
|
|
7583
|
-
relativePath:
|
|
8304
|
+
relativePath: relative7(workspace.cwd, targetPath),
|
|
7584
8305
|
contentType: readString(attachment.contentType),
|
|
7585
8306
|
byteSize: body.byteLength,
|
|
7586
8307
|
contentPath,
|
|
@@ -7629,9 +8350,9 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
7629
8350
|
if (manifest.version !== 1 || !Array.isArray(manifest.entries)) {
|
|
7630
8351
|
throw new Error("artifact_input_manifest_invalid: expected version 1 entries array");
|
|
7631
8352
|
}
|
|
7632
|
-
const targetRoot =
|
|
7633
|
-
|
|
7634
|
-
|
|
8353
|
+
const targetRoot = join11(workspace.cwd, "input-artifacts");
|
|
8354
|
+
rmSync6(targetRoot, { recursive: true, force: true });
|
|
8355
|
+
mkdirSync6(targetRoot, { recursive: true });
|
|
7635
8356
|
const usedPaths = /* @__PURE__ */ new Set();
|
|
7636
8357
|
const materialized = [];
|
|
7637
8358
|
for (const [index, rawEntry] of manifest.entries.entries()) {
|
|
@@ -7649,7 +8370,7 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
7649
8370
|
throw new Error(`artifact_input_manifest_invalid: entry ${index} contentPath does not match attachmentId`);
|
|
7650
8371
|
}
|
|
7651
8372
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
7652
|
-
const actualSha256 =
|
|
8373
|
+
const actualSha256 = createHash8("sha256").update(body).digest("hex");
|
|
7653
8374
|
if (body.byteLength !== byteSize || actualSha256 !== sha256) {
|
|
7654
8375
|
throw new Error(
|
|
7655
8376
|
`artifact_input_integrity_mismatch: workProductId=${workProductId} expectedBytes=${byteSize} actualBytes=${body.byteLength} expectedSha256=${sha256} actualSha256=${actualSha256}`
|
|
@@ -7660,18 +8381,18 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
7660
8381
|
id: attachmentId,
|
|
7661
8382
|
originalFilename: readString(entry.originalFilename)
|
|
7662
8383
|
}, index);
|
|
7663
|
-
let relativePath =
|
|
8384
|
+
let relativePath = join11("input-artifacts", sourceDir, filename).split(/[\\/]+/).join("/");
|
|
7664
8385
|
if (usedPaths.has(relativePath)) {
|
|
7665
8386
|
const ext = extname2(filename);
|
|
7666
8387
|
const stem = ext ? filename.slice(0, -ext.length) : filename;
|
|
7667
8388
|
filename = `${stem}-${index + 1}${ext}`;
|
|
7668
|
-
relativePath =
|
|
8389
|
+
relativePath = join11("input-artifacts", sourceDir, filename).split(/[\\/]+/).join("/");
|
|
7669
8390
|
}
|
|
7670
8391
|
usedPaths.add(relativePath);
|
|
7671
|
-
const targetPath =
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
8392
|
+
const targetPath = join11(workspace.cwd, relativePath);
|
|
8393
|
+
mkdirSync6(dirname7(targetPath), { recursive: true });
|
|
8394
|
+
writeFileSync6(targetPath, body);
|
|
8395
|
+
chmodSync5(targetPath, 292);
|
|
7675
8396
|
materialized.push({
|
|
7676
8397
|
id: attachmentId,
|
|
7677
8398
|
workProductId,
|
|
@@ -7690,9 +8411,9 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
7690
8411
|
version: 1,
|
|
7691
8412
|
entries: materialized.map(({ path: _path, relativePath, ...entry }) => ({ ...entry, path: relativePath }))
|
|
7692
8413
|
};
|
|
7693
|
-
const manifestPath =
|
|
7694
|
-
|
|
7695
|
-
|
|
8414
|
+
const manifestPath = join11(targetRoot, "artifact-input-manifest.json");
|
|
8415
|
+
writeFileSync6(manifestPath, JSON.stringify(localManifest, null, 2) + "\n");
|
|
8416
|
+
chmodSync5(manifestPath, 292);
|
|
7696
8417
|
updateWorkspaceManifest(workspaceManifestPath(workspace), { artifactInputManifest: localManifest });
|
|
7697
8418
|
await ingestLog(config, command, "system", "info", `Materialized ${materialized.length} required artifact input(s) into the execution workspace`, {
|
|
7698
8419
|
artifactInputCount: materialized.length,
|
|
@@ -7701,46 +8422,46 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
7701
8422
|
return materialized;
|
|
7702
8423
|
}
|
|
7703
8424
|
function issueCheckpointDir(workspace) {
|
|
7704
|
-
return
|
|
8425
|
+
return join11(dirname7(workspace.runDir), "checkpoint");
|
|
7705
8426
|
}
|
|
7706
8427
|
async function clearIssueCheckpoint(config, command, workspace, reason) {
|
|
7707
8428
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
7708
|
-
if (!
|
|
7709
|
-
|
|
8429
|
+
if (!existsSync10(checkpointDir)) return false;
|
|
8430
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
7710
8431
|
await ingestLog(config, command, "system", "info", "Cleared issue continuation checkpoint", { reason });
|
|
7711
8432
|
return true;
|
|
7712
8433
|
}
|
|
7713
8434
|
function safeCheckpointRelativePath(rawPath) {
|
|
7714
8435
|
const raw = String(rawPath ?? "").trim();
|
|
7715
|
-
if (
|
|
8436
|
+
if (isAbsolute7(raw) || /^[A-Za-z]:[\\/]/.test(raw)) return null;
|
|
7716
8437
|
const normalized = raw.split(/[\\/]+/).filter(Boolean).join("/");
|
|
7717
8438
|
if (!normalized || normalized.startsWith("../") || normalized.split("/").some((segment) => segment.startsWith("."))) return null;
|
|
7718
8439
|
if (normalized.startsWith("input-attachments/") || isRuntimeMetadataArtifactPath(normalized)) return null;
|
|
7719
8440
|
return normalized;
|
|
7720
8441
|
}
|
|
7721
8442
|
function hashFileSha256(filePath) {
|
|
7722
|
-
return
|
|
8443
|
+
return createHash8("sha256").update(readFileSync8(filePath)).digest("hex");
|
|
7723
8444
|
}
|
|
7724
8445
|
async function materializeIssueCheckpoint(config, command, workspace) {
|
|
7725
8446
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
7726
|
-
const manifestPath =
|
|
7727
|
-
if (!
|
|
8447
|
+
const manifestPath = join11(checkpointDir, "manifest.json");
|
|
8448
|
+
if (!existsSync10(manifestPath)) return [];
|
|
7728
8449
|
let manifest;
|
|
7729
8450
|
try {
|
|
7730
|
-
manifest = asRecord(JSON.parse(
|
|
8451
|
+
manifest = asRecord(JSON.parse(readFileSync8(manifestPath, "utf8")));
|
|
7731
8452
|
} catch (err) {
|
|
7732
|
-
|
|
8453
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
7733
8454
|
throw new Error(`invalid issue checkpoint manifest: ${err instanceof Error ? err.message : String(err)}`);
|
|
7734
8455
|
}
|
|
7735
8456
|
const expiresAt = Date.parse(readString(manifest.expiresAt) ?? "");
|
|
7736
8457
|
if (!Number.isFinite(expiresAt) || expiresAt <= Date.now() || readString(manifest.issueId) !== commandIssueId(command)) {
|
|
7737
|
-
|
|
8458
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
7738
8459
|
return [];
|
|
7739
8460
|
}
|
|
7740
8461
|
try {
|
|
7741
8462
|
const files = Array.isArray(manifest.files) ? manifest.files : [];
|
|
7742
8463
|
if (files.length > 20) throw new Error("issue checkpoint manifest exceeds the limit of 20 files");
|
|
7743
|
-
const filesRoot = realpathSync3(
|
|
8464
|
+
const filesRoot = realpathSync3(join11(checkpointDir, "files"));
|
|
7744
8465
|
const workspaceRoot = realpathSync3(workspace.cwd);
|
|
7745
8466
|
const validated = [];
|
|
7746
8467
|
let totalBytes = 0;
|
|
@@ -7748,12 +8469,12 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
7748
8469
|
const file = asRecord(rawFile);
|
|
7749
8470
|
const relativePath = safeCheckpointRelativePath(readString(file.path));
|
|
7750
8471
|
if (!relativePath) throw new Error("issue checkpoint manifest contains an invalid file path");
|
|
7751
|
-
const sourceCandidate =
|
|
7752
|
-
const target =
|
|
8472
|
+
const sourceCandidate = resolve10(filesRoot, relativePath);
|
|
8473
|
+
const target = resolve10(workspaceRoot, relativePath);
|
|
7753
8474
|
if (!pathWithin2(sourceCandidate, filesRoot) || !pathWithin2(target, workspaceRoot)) {
|
|
7754
8475
|
throw new Error(`issue checkpoint path escapes its workspace: ${relativePath}`);
|
|
7755
8476
|
}
|
|
7756
|
-
if (!
|
|
8477
|
+
if (!existsSync10(sourceCandidate)) throw new Error(`issue checkpoint file is missing: ${relativePath}`);
|
|
7757
8478
|
const source = realpathSync3(sourceCandidate);
|
|
7758
8479
|
if (!pathWithin2(source, filesRoot) || !statSync7(source).isFile()) {
|
|
7759
8480
|
throw new Error(`issue checkpoint source escapes its storage root: ${relativePath}`);
|
|
@@ -7773,17 +8494,17 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
7773
8494
|
const materialized = [];
|
|
7774
8495
|
for (const { relativePath, source, target } of validated) {
|
|
7775
8496
|
try {
|
|
7776
|
-
|
|
8497
|
+
lstatSync6(target);
|
|
7777
8498
|
continue;
|
|
7778
8499
|
} catch (err) {
|
|
7779
8500
|
if (err?.code !== "ENOENT") throw err;
|
|
7780
8501
|
}
|
|
7781
|
-
|
|
7782
|
-
const targetParent = realpathSync3(
|
|
8502
|
+
mkdirSync6(dirname7(target), { recursive: true });
|
|
8503
|
+
const targetParent = realpathSync3(dirname7(target));
|
|
7783
8504
|
if (!pathWithin2(targetParent, workspaceRoot)) {
|
|
7784
8505
|
throw new Error(`issue checkpoint target escapes its workspace: ${relativePath}`);
|
|
7785
8506
|
}
|
|
7786
|
-
|
|
8507
|
+
copyFileSync3(source, target);
|
|
7787
8508
|
materialized.push(relativePath);
|
|
7788
8509
|
}
|
|
7789
8510
|
if (materialized.length > 0) {
|
|
@@ -7807,31 +8528,31 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
7807
8528
|
}
|
|
7808
8529
|
async function saveIssueCheckpoint(config, command, workspace, candidates) {
|
|
7809
8530
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
7810
|
-
const filesDir =
|
|
7811
|
-
|
|
7812
|
-
|
|
8531
|
+
const filesDir = join11(checkpointDir, "files");
|
|
8532
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
8533
|
+
mkdirSync6(filesDir, { recursive: true });
|
|
7813
8534
|
const files = [];
|
|
7814
8535
|
let totalBytes = 0;
|
|
7815
8536
|
const workspaceRoot = realpathSync3(workspace.cwd);
|
|
7816
8537
|
for (const candidate of candidates.slice(0, 20)) {
|
|
7817
8538
|
const relativePath = safeCheckpointRelativePath(candidate.rawPath);
|
|
7818
8539
|
const source = readString(candidate.filePath);
|
|
7819
|
-
if (!relativePath || !source || !
|
|
8540
|
+
if (!relativePath || !source || !existsSync10(source) || !statSync7(source).isFile()) continue;
|
|
7820
8541
|
const ownedSource = realpathSync3(source);
|
|
7821
8542
|
if (!pathWithin2(ownedSource, workspaceRoot)) {
|
|
7822
8543
|
throw new Error(`issue checkpoint source escapes its execution workspace: ${relativePath}`);
|
|
7823
8544
|
}
|
|
7824
8545
|
const byteSize = statSync7(ownedSource).size;
|
|
7825
8546
|
if (byteSize <= 0 || totalBytes + byteSize > MAX_CHECKPOINT_BYTES) continue;
|
|
7826
|
-
const target =
|
|
8547
|
+
const target = resolve10(filesDir, relativePath);
|
|
7827
8548
|
if (!pathWithin2(target, filesDir)) continue;
|
|
7828
|
-
|
|
7829
|
-
|
|
8549
|
+
mkdirSync6(dirname7(target), { recursive: true });
|
|
8550
|
+
copyFileSync3(ownedSource, target);
|
|
7830
8551
|
totalBytes += byteSize;
|
|
7831
8552
|
files.push({ path: relativePath, byteSize, sha256: hashFileSha256(ownedSource) });
|
|
7832
8553
|
}
|
|
7833
8554
|
if (files.length === 0) {
|
|
7834
|
-
|
|
8555
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
7835
8556
|
return null;
|
|
7836
8557
|
}
|
|
7837
8558
|
const manifest = {
|
|
@@ -7843,7 +8564,7 @@ async function saveIssueCheckpoint(config, command, workspace, candidates) {
|
|
|
7843
8564
|
totalBytes,
|
|
7844
8565
|
files
|
|
7845
8566
|
};
|
|
7846
|
-
|
|
8567
|
+
writeFileSync6(join11(checkpointDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
7847
8568
|
`);
|
|
7848
8569
|
await ingestLog(config, command, "system", "warn", `Saved ${files.length} required deliverable(s) for continuation recovery`, manifest);
|
|
7849
8570
|
return manifest;
|
|
@@ -7915,6 +8636,11 @@ async function executeRunCommand(config, command) {
|
|
|
7915
8636
|
let managedMcpProfile = null;
|
|
7916
8637
|
let managedMcpCleanup = null;
|
|
7917
8638
|
let cleanupManagedMcpProfile = null;
|
|
8639
|
+
let piChildIsolation = null;
|
|
8640
|
+
let trustedPiRuntime = null;
|
|
8641
|
+
let trustedPiRuntimeSourcePaths = null;
|
|
8642
|
+
let trustedPiRuntimeProfile = null;
|
|
8643
|
+
let trustedPiRuntimeAudit = null;
|
|
7918
8644
|
if (executor.kind === "codex" && Object.keys(governedMcp).length > 0) {
|
|
7919
8645
|
managedMcpProfile = prepareManagedCodexMcpProfile({
|
|
7920
8646
|
commandId: command.commandId,
|
|
@@ -7987,6 +8713,92 @@ async function executeRunCommand(config, command) {
|
|
|
7987
8713
|
...managedMcpProfile.attestation
|
|
7988
8714
|
});
|
|
7989
8715
|
}
|
|
8716
|
+
const piChildAllocator = executor.kind === "pi" ? configuredPiChildIdentityAllocator(config) : null;
|
|
8717
|
+
const trustedPiRuntimeAssertion = commandTrustedPiRuntimeAssertion(command);
|
|
8718
|
+
if (Object.keys(trustedPiRuntimeAssertion).length > 0) {
|
|
8719
|
+
try {
|
|
8720
|
+
if (executor.kind !== "pi") {
|
|
8721
|
+
throw new Error("pi_trusted_runtime_assertion_binding_mismatch:executorKind");
|
|
8722
|
+
}
|
|
8723
|
+
trustedPiRuntimeSourcePaths = trustedPiRuntimeSources(config);
|
|
8724
|
+
trustedPiRuntime = verifyTrustedPiRuntimeAssertion({
|
|
8725
|
+
assertion: trustedPiRuntimeAssertion,
|
|
8726
|
+
connectorId: requireConnectorId(config),
|
|
8727
|
+
commandId: command.commandId,
|
|
8728
|
+
runId: commandRunId(command),
|
|
8729
|
+
leaseId: command.leaseId,
|
|
8730
|
+
executorKind: executor.kind,
|
|
8731
|
+
localDigests: readTrustedPiRuntimeLocalDigests(trustedPiRuntimeSourcePaths)
|
|
8732
|
+
});
|
|
8733
|
+
if (!managedMcpProfile) {
|
|
8734
|
+
throw new Error("pi_trusted_runtime_governed_profile_required");
|
|
8735
|
+
}
|
|
8736
|
+
requireTrustedPiChildAllocator(piChildAllocator, true);
|
|
8737
|
+
trustedPiRuntimeProfile = materializeTrustedPiRuntimeProfile({
|
|
8738
|
+
seedRoot: trustedPiRuntimeSourcePaths.seedRoot,
|
|
8739
|
+
overlayRoot: trustedPiRuntimeSourcePaths.overlayRoot,
|
|
8740
|
+
profileRoot: managedMcpProfile.profileRoot,
|
|
8741
|
+
agentDir: managedMcpProfile.env.PI_CODING_AGENT_DIR,
|
|
8742
|
+
governedMcpConfigPath: managedMcpProfile.configPath,
|
|
8743
|
+
verifiedAssertion: trustedPiRuntime
|
|
8744
|
+
});
|
|
8745
|
+
executorEnv = {
|
|
8746
|
+
...executorEnv,
|
|
8747
|
+
AMASTER_MANAGED_RUNTIME_ASSERTION_FD: "3",
|
|
8748
|
+
AMASTER_MANAGED_RUNTIME_AUDIT_FILE: join11(
|
|
8749
|
+
managedMcpProfile.env.HOME,
|
|
8750
|
+
".amaster-managed-runtime-audit.jsonl"
|
|
8751
|
+
),
|
|
8752
|
+
AMASTER_RUNTIME_LEASE_ID: command.leaseId
|
|
8753
|
+
};
|
|
8754
|
+
} catch (error) {
|
|
8755
|
+
if (managedMcpProfile) {
|
|
8756
|
+
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
8757
|
+
commandId: command.commandId,
|
|
8758
|
+
runId: commandRunId(command)
|
|
8759
|
+
});
|
|
8760
|
+
}
|
|
8761
|
+
throw error;
|
|
8762
|
+
}
|
|
8763
|
+
await ingestLog(config, command, "system", "info", "Verified trusted Pi runtime provenance", {
|
|
8764
|
+
presentationKind: "trusted_pi_runtime_attestation",
|
|
8765
|
+
attestationId: trustedPiRuntime.attestationId,
|
|
8766
|
+
unknownToolMode: trustedPiRuntime.unknownToolMode,
|
|
8767
|
+
directToolBudget: trustedPiRuntime.directToolBudget,
|
|
8768
|
+
digests: trustedPiRuntime.digests,
|
|
8769
|
+
profileAttestationId: trustedPiRuntimeProfile.attestationId,
|
|
8770
|
+
inheritedEntries: trustedPiRuntimeProfile.facts.inheritedEntries
|
|
8771
|
+
});
|
|
8772
|
+
}
|
|
8773
|
+
if (piChildAllocator) {
|
|
8774
|
+
try {
|
|
8775
|
+
const profileRoot = piChildIsolationProfileRoot({
|
|
8776
|
+
managedMcpProfile,
|
|
8777
|
+
executorHome: workspace.executorHome
|
|
8778
|
+
});
|
|
8779
|
+
piChildIsolation = preparePiChildIsolation({
|
|
8780
|
+
allocator: piChildAllocator,
|
|
8781
|
+
effectiveUid: typeof process.geteuid === "function" ? process.geteuid() : null,
|
|
8782
|
+
commandId: command.commandId,
|
|
8783
|
+
runId: commandRunId(command),
|
|
8784
|
+
profileRoot,
|
|
8785
|
+
workspaceRoot: cwd,
|
|
8786
|
+
allowedRoot: config.runtimeWorkspacesRoot
|
|
8787
|
+
});
|
|
8788
|
+
} catch (error) {
|
|
8789
|
+
if (managedMcpProfile) {
|
|
8790
|
+
cleanupManagedMcpProfile(managedMcpProfile, {
|
|
8791
|
+
commandId: command.commandId,
|
|
8792
|
+
runId: commandRunId(command)
|
|
8793
|
+
});
|
|
8794
|
+
}
|
|
8795
|
+
throw error;
|
|
8796
|
+
}
|
|
8797
|
+
await ingestLog(config, command, "system", "info", "Prepared isolated Pi child identity", {
|
|
8798
|
+
presentationKind: "pi_child_isolation_attestation",
|
|
8799
|
+
...piChildIsolation.attestation
|
|
8800
|
+
});
|
|
8801
|
+
}
|
|
7990
8802
|
await ingestLog(config, command, "system", "info", `Compiled ${contextManifest.mode} prompt using ${contextManifest.budget.usedChars}/${contextManifest.budget.totalChars} characters`, {
|
|
7991
8803
|
presentationKind: "context_manifest",
|
|
7992
8804
|
contextManifest
|
|
@@ -8033,11 +8845,35 @@ async function executeRunCommand(config, command) {
|
|
|
8033
8845
|
maxRssMb: config.executorMaxRssMb,
|
|
8034
8846
|
signal: abortController.signal,
|
|
8035
8847
|
executorKind: executor.kind,
|
|
8848
|
+
...piChildIsolation ? { spawnIdentity: piChildIsolation.spawn } : {},
|
|
8849
|
+
...trustedPiRuntime ? {
|
|
8850
|
+
managedInput: `${JSON.stringify(trustedPiRuntimeAssertion)}
|
|
8851
|
+
`
|
|
8852
|
+
} : {},
|
|
8036
8853
|
onOutput: (stream, chunk, rawBytes) => {
|
|
8037
8854
|
noteActiveRunOutput(command, stream, chunk, rawBytes);
|
|
8038
8855
|
liveOutputLogger.write(stream, chunk);
|
|
8039
8856
|
}
|
|
8040
8857
|
});
|
|
8858
|
+
if (trustedPiRuntime) {
|
|
8859
|
+
verifyTrustedPiRuntimeAssertion({
|
|
8860
|
+
assertion: trustedPiRuntimeAssertion,
|
|
8861
|
+
connectorId: requireConnectorId(config),
|
|
8862
|
+
commandId: command.commandId,
|
|
8863
|
+
runId: commandRunId(command),
|
|
8864
|
+
leaseId: command.leaseId,
|
|
8865
|
+
executorKind: executor.kind,
|
|
8866
|
+
localDigests: readTrustedPiRuntimeLocalDigests(trustedPiRuntimeSourcePaths),
|
|
8867
|
+
verifyExpiry: false
|
|
8868
|
+
});
|
|
8869
|
+
trustedPiRuntimeAudit = readTrustedPiRuntimeAudit({
|
|
8870
|
+
profileRoot: managedMcpProfile.profileRoot,
|
|
8871
|
+
auditFile: executorEnv.AMASTER_MANAGED_RUNTIME_AUDIT_FILE,
|
|
8872
|
+
commandId: command.commandId,
|
|
8873
|
+
runId: commandRunId(command),
|
|
8874
|
+
runtimeEnforcementDigest: trustedPiRuntime.digests.runtimeEnforcementDigest
|
|
8875
|
+
});
|
|
8876
|
+
}
|
|
8041
8877
|
} finally {
|
|
8042
8878
|
await liveOutputLogger.flush();
|
|
8043
8879
|
}
|
|
@@ -8121,7 +8957,7 @@ async function executeRunCommand(config, command) {
|
|
|
8121
8957
|
workspace,
|
|
8122
8958
|
workspaceStatus.artifacts.map((artifact) => ({
|
|
8123
8959
|
rawPath: artifact.relativePath,
|
|
8124
|
-
filePath:
|
|
8960
|
+
filePath: resolve10(cwd, artifact.relativePath)
|
|
8125
8961
|
}))
|
|
8126
8962
|
);
|
|
8127
8963
|
nativeSessionRollout = {
|
|
@@ -8265,6 +9101,17 @@ async function executeRunCommand(config, command) {
|
|
|
8265
9101
|
attestation: managedMcpProfile.attestation,
|
|
8266
9102
|
cleanup: managedMcpCleanup
|
|
8267
9103
|
}
|
|
9104
|
+
} : {},
|
|
9105
|
+
...piChildIsolation ? {
|
|
9106
|
+
piChildIsolation: piChildIsolation.attestation
|
|
9107
|
+
} : {},
|
|
9108
|
+
...trustedPiRuntimeProfile ? {
|
|
9109
|
+
trustedPiRuntime: {
|
|
9110
|
+
attestationId: trustedPiRuntime.attestationId,
|
|
9111
|
+
profileAttestationId: trustedPiRuntimeProfile.attestationId,
|
|
9112
|
+
...trustedPiRuntimeProfile.facts,
|
|
9113
|
+
audit: trustedPiRuntimeAudit
|
|
9114
|
+
}
|
|
8268
9115
|
} : {}
|
|
8269
9116
|
};
|
|
8270
9117
|
const completion = await completeCommand(config, command, cancelled ? "cancelled" : succeeded ? "succeeded" : "failed", result2, error ?? void 0);
|
|
@@ -8287,6 +9134,7 @@ async function executeRunCommand(config, command) {
|
|
|
8287
9134
|
runId: commandRunId(command)
|
|
8288
9135
|
});
|
|
8289
9136
|
}
|
|
9137
|
+
piChildIsolation?.release();
|
|
8290
9138
|
stopActiveRunHeartbeats();
|
|
8291
9139
|
forgetActiveRunCommand();
|
|
8292
9140
|
}
|
|
@@ -8489,7 +9337,7 @@ async function runLoop(config) {
|
|
|
8489
9337
|
${message}
|
|
8490
9338
|
`);
|
|
8491
9339
|
}
|
|
8492
|
-
await new Promise((
|
|
9340
|
+
await new Promise((resolve11) => setTimeout(resolve11, config.pollIntervalSeconds * 1e3));
|
|
8493
9341
|
}
|
|
8494
9342
|
}
|
|
8495
9343
|
function help() {
|