@amaster.ai/employee-runtime-connector 0.1.1-beta.2 → 0.1.1-beta.4
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 +591 -111
- package/dist/amaster-runtime.mjs +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// MirrorX runtime connector daemon bundle.
|
|
3
3
|
|
|
4
4
|
// src/amaster-runtime-daemon.mjs
|
|
5
|
-
import { createHash as
|
|
5
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
6
6
|
import { chmodSync as chmodSync6, copyFileSync as copyFileSync3, existsSync as existsSync14, lstatSync as lstatSync7, mkdirSync as mkdirSync9, mkdtempSync, readFileSync as readFileSync11, readdirSync as readdirSync9, realpathSync as realpathSync5, renameSync as renameSync6, rmSync as rmSync7, statSync as statSync7, symlinkSync as symlinkSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "node:fs";
|
|
7
7
|
import { arch as arch3, homedir as homedir3, hostname as hostname2, platform as platform3, tmpdir } from "node:os";
|
|
8
8
|
import { basename as basename6, delimiter as delimiter2, dirname as dirname9, extname as extname2, isAbsolute as isAbsolute8, join as join15, relative as relative9, resolve as resolve12 } from "node:path";
|
|
@@ -1560,7 +1560,7 @@ function reconcileManagedCodexMcpProfiles(rootPath, options = {}) {
|
|
|
1560
1560
|
}
|
|
1561
1561
|
|
|
1562
1562
|
// src/amaster-runtime-daemon/pi-managed-mcp-profile.mjs
|
|
1563
|
-
import { createHash as
|
|
1563
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
1564
1564
|
import {
|
|
1565
1565
|
chmodSync as chmodSync2,
|
|
1566
1566
|
copyFileSync,
|
|
@@ -1593,8 +1593,6 @@ var MANAGED_PI_PROVIDER_ENV_NAMES = Object.freeze([
|
|
|
1593
1593
|
"AMASTER_MODEL_CREDENTIAL_REF",
|
|
1594
1594
|
"AMASTER_API_KEY",
|
|
1595
1595
|
"AMASTER_PROVIDER_BASE_URL",
|
|
1596
|
-
"AMASTER_PROVIDER_DEFAULT_MODEL",
|
|
1597
|
-
"AMASTER_PROVIDER_FLASH_MODEL",
|
|
1598
1596
|
"AMASTER_PLATFORM_OAUTH_TOKEN",
|
|
1599
1597
|
"AMASTER_PLATFORM_ORGANIZATION_ID",
|
|
1600
1598
|
"AMASTER_BILLING_TURN_ID"
|
|
@@ -1636,28 +1634,6 @@ function imageGenBaseUrlFromProviderBaseUrl(value) {
|
|
|
1636
1634
|
return input.replace(/\/v1\/?$/, "");
|
|
1637
1635
|
}
|
|
1638
1636
|
}
|
|
1639
|
-
function ensureAmasterProviderModel(models, modelId, flash) {
|
|
1640
|
-
const id = readString(modelId);
|
|
1641
|
-
if (!id) return;
|
|
1642
|
-
const existing = Array.isArray(models) ? models : [];
|
|
1643
|
-
const index = existing.findIndex((entry) => asRecord(entry).id === id);
|
|
1644
|
-
if (index >= 0) {
|
|
1645
|
-
existing[index] = {
|
|
1646
|
-
...asRecord(existing[index]),
|
|
1647
|
-
id,
|
|
1648
|
-
input: readStringArray(asRecord(existing[index]).input).length > 0 ? asRecord(existing[index]).input : ["text", "image"],
|
|
1649
|
-
reasoning: asRecord(existing[index]).reasoning ?? true,
|
|
1650
|
-
...flash ? { flash: true } : {}
|
|
1651
|
-
};
|
|
1652
|
-
return;
|
|
1653
|
-
}
|
|
1654
|
-
existing.push({
|
|
1655
|
-
id,
|
|
1656
|
-
input: ["text", "image"],
|
|
1657
|
-
reasoning: true,
|
|
1658
|
-
...flash ? { flash: true } : {}
|
|
1659
|
-
});
|
|
1660
|
-
}
|
|
1661
1637
|
function withoutManagedBillingHeaders(value) {
|
|
1662
1638
|
const headers = { ...asRecord(value) };
|
|
1663
1639
|
for (const name of Object.keys(AMASTER_BILLING_HEADER_ENV_REFERENCES)) {
|
|
@@ -1689,10 +1665,6 @@ function syncAmasterProviderModels(agentDir, executorEnv) {
|
|
|
1689
1665
|
const headers = syncManagedBillingHeaders(amaster.headers, executorEnv);
|
|
1690
1666
|
if (headers) amaster.headers = headers;
|
|
1691
1667
|
else delete amaster.headers;
|
|
1692
|
-
const models = Array.isArray(amaster.models) ? [...amaster.models] : [];
|
|
1693
|
-
ensureAmasterProviderModel(models, executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL, false);
|
|
1694
|
-
ensureAmasterProviderModel(models, executorEnv.AMASTER_PROVIDER_FLASH_MODEL, true);
|
|
1695
|
-
if (models.length > 0) amaster.models = models;
|
|
1696
1668
|
writeJsonFileAtomic(modelsPath, {
|
|
1697
1669
|
...config,
|
|
1698
1670
|
providers: {
|
|
@@ -1709,19 +1681,8 @@ function syncAmasterProviderSettings(agentDir, executorEnv) {
|
|
|
1709
1681
|
if (!existsSync2(settingsPath)) return false;
|
|
1710
1682
|
const settings = readJsonFile(settingsPath);
|
|
1711
1683
|
const baseUrl = readString(executorEnv.AMASTER_PROVIDER_BASE_URL);
|
|
1712
|
-
const defaultModel = readString(executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL);
|
|
1713
1684
|
const imageGenBaseUrl = imageGenBaseUrlFromProviderBaseUrl(baseUrl);
|
|
1714
1685
|
let changed = false;
|
|
1715
|
-
if (defaultModel) {
|
|
1716
|
-
if (settings.defaultProvider !== "amaster") {
|
|
1717
|
-
settings.defaultProvider = "amaster";
|
|
1718
|
-
changed = true;
|
|
1719
|
-
}
|
|
1720
|
-
if (settings.defaultModel !== defaultModel) {
|
|
1721
|
-
settings.defaultModel = defaultModel;
|
|
1722
|
-
changed = true;
|
|
1723
|
-
}
|
|
1724
|
-
}
|
|
1725
1686
|
const imageGen = settings["pi-image-gen"];
|
|
1726
1687
|
if (isRecord(imageGen) && isRecord(imageGen.customProviders) && isRecord(imageGen.customProviders.amaster)) {
|
|
1727
1688
|
const customProviders = imageGen.customProviders;
|
|
@@ -2004,8 +1965,207 @@ function managedPiMcpArgsNormalizerExtensionSource() {
|
|
|
2004
1965
|
].join("\n\n");
|
|
2005
1966
|
}
|
|
2006
1967
|
|
|
1968
|
+
// src/amaster-runtime-daemon/pi-effective-tools-attestor.mjs
|
|
1969
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
1970
|
+
var MANAGED_PI_EFFECTIVE_TOOLS_ATTESTOR_FILENAME = "amaster-effective-tools-attestor.js";
|
|
1971
|
+
var MANAGED_PI_EFFECTIVE_TOOLS_SCHEMA_VERSION = "amaster.pi-effective-tools.v1";
|
|
1972
|
+
function normalizedSchema(value, adapterNormalized) {
|
|
1973
|
+
const schema = value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1974
|
+
if (!adapterNormalized) return schema;
|
|
1975
|
+
const { $schema: _schema, additionalProperties: _additionalProperties, ...normalized } = schema;
|
|
1976
|
+
return normalized;
|
|
1977
|
+
}
|
|
1978
|
+
function stablePiJson(value) {
|
|
1979
|
+
if (value === null || value === void 0 || typeof value !== "object") {
|
|
1980
|
+
const serialized = JSON.stringify(value);
|
|
1981
|
+
return serialized === void 0 ? "undefined" : serialized;
|
|
1982
|
+
}
|
|
1983
|
+
if (Array.isArray(value)) return `[${value.map(stablePiJson).join(",")}]`;
|
|
1984
|
+
const keys = Object.keys(value).sort();
|
|
1985
|
+
return `{${keys.map((key) => `${JSON.stringify(key)}:${stablePiJson(value[key])}`).join(",")}}`;
|
|
1986
|
+
}
|
|
1987
|
+
function stablePiToolSchemaHash(schema, options = {}) {
|
|
1988
|
+
return createHash2("sha256").update(stablePiJson(normalizedSchema(schema, options.adapterNormalized === true))).digest("hex");
|
|
1989
|
+
}
|
|
1990
|
+
function stablePiEffectiveToolSetHash(entries) {
|
|
1991
|
+
const normalized = entries.map((entry) => ({ name: entry.name, schemaHash: entry.schemaHash ?? entry.effectiveSchemaHash })).sort((left, right) => left.name.localeCompare(right.name));
|
|
1992
|
+
return createHash2("sha256").update(stablePiJson(normalized)).digest("hex");
|
|
1993
|
+
}
|
|
1994
|
+
function stablePiDirectCatalogSetHash(entries) {
|
|
1995
|
+
const normalized = entries.map((entry) => ({ name: entry.name, exposedName: entry.exposedName, schemaHash: entry.schemaHash, riskLevel: entry.riskLevel })).sort((left, right) => left.name.localeCompare(right.name));
|
|
1996
|
+
return createHash2("sha256").update(stablePiJson(normalized)).digest("hex");
|
|
1997
|
+
}
|
|
1998
|
+
function managedPiEffectiveToolsAttestorExtensionSource() {
|
|
1999
|
+
return String.raw`import { createHash } from "node:crypto";
|
|
2000
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
2001
|
+
import { fileURLToPath } from "node:url";
|
|
2002
|
+
import { Value } from "typebox/value";
|
|
2003
|
+
|
|
2004
|
+
const SCHEMA_VERSION = ${JSON.stringify(MANAGED_PI_EFFECTIVE_TOOLS_SCHEMA_VERSION)};
|
|
2005
|
+
|
|
2006
|
+
function record(value) {
|
|
2007
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2008
|
+
}
|
|
2009
|
+
|
|
2010
|
+
function stableJson(value) {
|
|
2011
|
+
if (value === null || value === undefined || typeof value !== "object") {
|
|
2012
|
+
const serialized = JSON.stringify(value);
|
|
2013
|
+
return serialized === undefined ? "undefined" : serialized;
|
|
2014
|
+
}
|
|
2015
|
+
if (Array.isArray(value)) return "[" + value.map(stableJson).join(",") + "]";
|
|
2016
|
+
const keys = Object.keys(value).sort();
|
|
2017
|
+
return "{" + keys.map((key) => JSON.stringify(key) + ":" + stableJson(value[key])).join(",") + "}";
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
function sha256(value) {
|
|
2021
|
+
return createHash("sha256").update(value).digest("hex");
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
function schemaHash(value) {
|
|
2025
|
+
return sha256(stableJson(record(value)));
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
function toolSetHash(entries) {
|
|
2029
|
+
return sha256(stableJson(entries
|
|
2030
|
+
.map((entry) => ({ name: entry.name, schemaHash: entry.schemaHash }))
|
|
2031
|
+
.sort((left, right) => left.name.localeCompare(right.name))));
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
function requiredPath(name) {
|
|
2035
|
+
const value = process.env[name];
|
|
2036
|
+
if (typeof value !== "string" || value.trim() === "") throw new Error(name + " is required");
|
|
2037
|
+
return value;
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
function sourceIsMcpAdapter(sourceInfo) {
|
|
2041
|
+
return stableJson(sourceInfo).includes("pi-mcp-adapter");
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
function safeWriteReceipt(receiptPath, receipt) {
|
|
2045
|
+
writeFileSync(receiptPath, JSON.stringify(receipt) + "\n", { encoding: "utf8", mode: 0o600 });
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
function validationErrorPath(error) {
|
|
2049
|
+
if (typeof error.path === "string" && error.path) return error.path;
|
|
2050
|
+
const base = typeof error.instancePath === "string" ? error.instancePath : "";
|
|
2051
|
+
const params = record(error.params);
|
|
2052
|
+
const additional = Array.isArray(params.additionalProperties) ? params.additionalProperties[0] : null;
|
|
2053
|
+
if (typeof additional === "string" && additional) return base + "/" + additional;
|
|
2054
|
+
const required = Array.isArray(params.requiredProperties) ? params.requiredProperties[0] : null;
|
|
2055
|
+
if (typeof required === "string" && required) return base + "/" + required;
|
|
2056
|
+
return base || "/";
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
function inputErrorReason(schema, input) {
|
|
2060
|
+
const errors = [...Value.Errors(schema, input)];
|
|
2061
|
+
if (errors.length === 0) return null;
|
|
2062
|
+
return errors.slice(0, 8).map((error) => validationErrorPath(error) + ": " + error.message).join("; ");
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
export default function amasterEffectiveToolsAttestor(pi) {
|
|
2066
|
+
const mode = process.env.AMASTER_PI_EFFECTIVE_TOOLS_MODE;
|
|
2067
|
+
if (mode !== "probe" && mode !== "enforce") return;
|
|
2068
|
+
const manifestPath = requiredPath("AMASTER_PI_EFFECTIVE_TOOLS_MANIFEST");
|
|
2069
|
+
const receiptPath = requiredPath("AMASTER_PI_EFFECTIVE_TOOLS_RECEIPT");
|
|
2070
|
+
const cachePath = requiredPath("AMASTER_PI_EFFECTIVE_TOOLS_CACHE");
|
|
2071
|
+
const configPath = requiredPath("AMASTER_PI_EFFECTIVE_TOOLS_CONFIG");
|
|
2072
|
+
|
|
2073
|
+
pi.on("session_start", async () => {
|
|
2074
|
+
let receipt;
|
|
2075
|
+
try {
|
|
2076
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
2077
|
+
if (manifest.schemaVersion !== SCHEMA_VERSION || manifest.serverName !== "amaster") {
|
|
2078
|
+
throw new Error("effective tool manifest identity mismatch");
|
|
2079
|
+
}
|
|
2080
|
+
const sourceDigest = sha256(readFileSync(fileURLToPath(import.meta.url)));
|
|
2081
|
+
if (sourceDigest !== manifest.attestorSourceSha256) throw new Error("attestor source digest mismatch");
|
|
2082
|
+
const configDigest = sha256(readFileSync(configPath));
|
|
2083
|
+
if (configDigest !== manifest.configSha256) throw new Error("managed MCP config digest mismatch");
|
|
2084
|
+
const cacheDigest = sha256(readFileSync(cachePath));
|
|
2085
|
+
if (cacheDigest !== manifest.cacheSha256) throw new Error("managed MCP cache digest mismatch");
|
|
2086
|
+
|
|
2087
|
+
const expectedEntries = Array.isArray(manifest.entries) ? manifest.entries : [];
|
|
2088
|
+
if (expectedEntries.length === 0) throw new Error("effective tool manifest is empty");
|
|
2089
|
+
const expectedByName = new Map(expectedEntries.map((entry) => [entry.name, entry]));
|
|
2090
|
+
if (expectedByName.size !== expectedEntries.length) throw new Error("effective tool manifest has duplicate names");
|
|
2091
|
+
for (const entry of expectedEntries) {
|
|
2092
|
+
const validatorSelfTest = inputErrorReason(entry.schema, { __amasterUnexpected: true });
|
|
2093
|
+
if (!validatorSelfTest || !validatorSelfTest.includes("/__amasterUnexpected")) {
|
|
2094
|
+
throw new Error("strict input validator self-test failed for " + entry.name);
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
const allTools = pi.getAllTools();
|
|
2099
|
+
const proxyPresent = allTools.some((tool) => tool.name === "mcp");
|
|
2100
|
+
const adapterTools = allTools.filter((tool) => sourceIsMcpAdapter(tool.sourceInfo));
|
|
2101
|
+
const directTools = adapterTools.filter((tool) => tool.name !== "mcp").map((tool) => ({
|
|
2102
|
+
name: tool.name,
|
|
2103
|
+
schemaHash: schemaHash(tool.parameters),
|
|
2104
|
+
}));
|
|
2105
|
+
const actualByName = new Map(directTools.map((entry) => [entry.name, entry]));
|
|
2106
|
+
const missing = [...expectedByName.keys()].filter((name) => !actualByName.has(name)).sort();
|
|
2107
|
+
const unexpected = [...actualByName.keys()].filter((name) => !expectedByName.has(name)).sort();
|
|
2108
|
+
const schemaMismatches = [...expectedByName.entries()].flatMap(([name, expected]) => {
|
|
2109
|
+
const actual = actualByName.get(name);
|
|
2110
|
+
return actual && actual.schemaHash !== expected.effectiveSchemaHash
|
|
2111
|
+
? [{ name, expected: expected.effectiveSchemaHash, actual: actual.schemaHash }]
|
|
2112
|
+
: [];
|
|
2113
|
+
});
|
|
2114
|
+
const effectiveSetHash = toolSetHash(directTools);
|
|
2115
|
+
if (proxyPresent || missing.length > 0 || unexpected.length > 0 || schemaMismatches.length > 0) {
|
|
2116
|
+
throw new Error("effective tool surface mismatch: proxy=" + proxyPresent + " missing=" + missing.join(",") + " unexpected=" + unexpected.join(",") + " schemas=" + schemaMismatches.map((entry) => entry.name).join(","));
|
|
2117
|
+
}
|
|
2118
|
+
if (effectiveSetHash !== manifest.effectiveSetHash) throw new Error("effective tool set hash mismatch");
|
|
2119
|
+
receipt = {
|
|
2120
|
+
schemaVersion: SCHEMA_VERSION,
|
|
2121
|
+
status: "attested",
|
|
2122
|
+
mode,
|
|
2123
|
+
proxyPresent,
|
|
2124
|
+
effectiveSetHash,
|
|
2125
|
+
effectiveTools: directTools.sort((left, right) => left.name.localeCompare(right.name)),
|
|
2126
|
+
effectiveToolBindings: expectedEntries
|
|
2127
|
+
.map((entry) => ({ canonicalName: entry.canonicalName, exposedName: entry.name, effectiveSchemaHash: entry.effectiveSchemaHash }))
|
|
2128
|
+
.sort((left, right) => left.canonicalName.localeCompare(right.canonicalName)),
|
|
2129
|
+
attestorSourceSha256: sourceDigest,
|
|
2130
|
+
configSha256: configDigest,
|
|
2131
|
+
cacheSha256: cacheDigest,
|
|
2132
|
+
strictInputValidatorSelfTest: true,
|
|
2133
|
+
modelInvocationStarted: false,
|
|
2134
|
+
attestedAt: new Date().toISOString(),
|
|
2135
|
+
};
|
|
2136
|
+
safeWriteReceipt(receiptPath, receipt);
|
|
2137
|
+
if (mode === "probe") process.exit(0);
|
|
2138
|
+
} catch (error) {
|
|
2139
|
+
receipt = {
|
|
2140
|
+
schemaVersion: SCHEMA_VERSION,
|
|
2141
|
+
status: "rejected",
|
|
2142
|
+
mode,
|
|
2143
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2144
|
+
modelInvocationStarted: false,
|
|
2145
|
+
attestedAt: new Date().toISOString(),
|
|
2146
|
+
};
|
|
2147
|
+
safeWriteReceipt(receiptPath, receipt);
|
|
2148
|
+
process.exit(78);
|
|
2149
|
+
}
|
|
2150
|
+
});
|
|
2151
|
+
|
|
2152
|
+
pi.on("tool_call", (event) => {
|
|
2153
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
2154
|
+
const entry = Array.isArray(manifest.entries)
|
|
2155
|
+
? manifest.entries.find((candidate) => candidate.name === event.toolName)
|
|
2156
|
+
: null;
|
|
2157
|
+
if (!entry) return;
|
|
2158
|
+
const reason = inputErrorReason(entry.schema, event.input);
|
|
2159
|
+
if (!reason) return;
|
|
2160
|
+
return { block: true, reason: "Governed tool input rejected: " + reason };
|
|
2161
|
+
});
|
|
2162
|
+
}
|
|
2163
|
+
`;
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2007
2166
|
// src/amaster-runtime-daemon/pi-managed-mcp-profile.mjs
|
|
2008
2167
|
var MANAGED_PI_MCP_TOOL_MODE = "proxy_only";
|
|
2168
|
+
var MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE = "direct_typed";
|
|
2009
2169
|
var MANAGED_PI_MCP_ARGS_NORMALIZATION = "json_string_control_characters_v1";
|
|
2010
2170
|
var MANAGED_PI_MCP_ARGS_NORMALIZER_FILENAME = "amaster-mcp-args-normalizer.js";
|
|
2011
2171
|
function createManagedPiMcpProfileApi(options = {}) {
|
|
@@ -2013,6 +2173,14 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2013
2173
|
const nowImpl = typeof options.now === "function" ? options.now : Date.now;
|
|
2014
2174
|
const SUPPORTED_SCHEMA_VERSION2 = "amaster.governed-mcp.v1";
|
|
2015
2175
|
const SUPPORTED_SERVER_NAME2 = "amaster";
|
|
2176
|
+
const DIRECT_CATALOG_SCHEMA_VERSION = "amaster.governed-mcp-direct-catalog.v1";
|
|
2177
|
+
const DIRECT_TYPED_V1_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
2178
|
+
"runtime_action.submit",
|
|
2179
|
+
"amaster.read_company_diagnosis",
|
|
2180
|
+
"amaster.publish_company_diagnosis_brief"
|
|
2181
|
+
]);
|
|
2182
|
+
const PROVIDER_SAFE_TOOL_NAME = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
2183
|
+
const PI_BUILTIN_TOOL_NAMES = /* @__PURE__ */ new Set(["read", "bash", "edit", "write", "grep", "find", "ls", "mcp"]);
|
|
2016
2184
|
const MINIMUM_PI_VERSION = [0, 73, 1];
|
|
2017
2185
|
const MINIMUM_MCP_ADAPTER_VERSION = [2, 6, 1];
|
|
2018
2186
|
const MANAGED_BROWSER_USE_PACKAGE = "@amaster.ai/pi-browser-use";
|
|
@@ -2179,7 +2347,7 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2179
2347
|
nonEmpty2(session.invocationId, "nativeSession.invocationId");
|
|
2180
2348
|
const sourceWorkspacePath = nonEmpty2(session.cwd, "nativeSession.cwd");
|
|
2181
2349
|
const issueRoot = dirname3(runDir);
|
|
2182
|
-
const managedSourceRunDirName = `${sourceRunId}-${
|
|
2350
|
+
const managedSourceRunDirName = `${sourceRunId}-${createHash3("sha256").update(sourceRunId).digest("hex").slice(0, 8)}`;
|
|
2183
2351
|
const sourceRunDirs = readdirSync2(issueRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.isSymbolicLink() && (entry.name === sourceRunId || entry.name === managedSourceRunDirName)).map((entry) => join4(issueRoot, entry.name));
|
|
2184
2352
|
if (sourceRunDirs.length !== 1) {
|
|
2185
2353
|
throw new Error(`pi_managed_mcp_session_rollout_missing: expected one source run directory for ${sourceRunId}, received ${sourceRunDirs.length}`);
|
|
@@ -2224,6 +2392,82 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2224
2392
|
if (!Number.isFinite(value)) throw new Error("pi_managed_mcp_attestation_failed: invalid attestation clock");
|
|
2225
2393
|
return value;
|
|
2226
2394
|
}
|
|
2395
|
+
function sha256(value) {
|
|
2396
|
+
return createHash3("sha256").update(value).digest("hex");
|
|
2397
|
+
}
|
|
2398
|
+
function adapterServerConfigHash(definition) {
|
|
2399
|
+
return sha256(stablePiJson({
|
|
2400
|
+
command: definition.command,
|
|
2401
|
+
args: definition.args,
|
|
2402
|
+
env: definition.env,
|
|
2403
|
+
cwd: definition.cwd,
|
|
2404
|
+
url: definition.url,
|
|
2405
|
+
headers: definition.headers,
|
|
2406
|
+
auth: definition.auth,
|
|
2407
|
+
bearerToken: definition.bearerToken,
|
|
2408
|
+
bearerTokenEnv: definition.bearerTokenEnv,
|
|
2409
|
+
exposeResources: definition.exposeResources,
|
|
2410
|
+
excludeTools: definition.excludeTools
|
|
2411
|
+
}));
|
|
2412
|
+
}
|
|
2413
|
+
function validateDirectCatalog(gateway) {
|
|
2414
|
+
const catalog = record6(gateway.toolCatalog);
|
|
2415
|
+
if (catalog.schemaVersion !== DIRECT_CATALOG_SCHEMA_VERSION) {
|
|
2416
|
+
throw new Error("pi_managed_mcp_invalid: direct tool catalog schema mismatch");
|
|
2417
|
+
}
|
|
2418
|
+
const tools = Array.isArray(catalog.tools) ? catalog.tools.map(record6) : [];
|
|
2419
|
+
if (tools.length !== DIRECT_TYPED_V1_TOOL_NAMES.size) {
|
|
2420
|
+
throw new Error("pi_managed_mcp_invalid: direct tool catalog size mismatch");
|
|
2421
|
+
}
|
|
2422
|
+
const names = /* @__PURE__ */ new Set();
|
|
2423
|
+
const exposedNames = /* @__PURE__ */ new Set();
|
|
2424
|
+
const normalized = tools.map((tool) => {
|
|
2425
|
+
const name = nonEmpty2(tool.name, "toolCatalog.tools.name");
|
|
2426
|
+
if (!DIRECT_TYPED_V1_TOOL_NAMES.has(name) || names.has(name)) {
|
|
2427
|
+
throw new Error("pi_managed_mcp_invalid: direct tool catalog name mismatch");
|
|
2428
|
+
}
|
|
2429
|
+
names.add(name);
|
|
2430
|
+
const exposedName = nonEmpty2(tool.exposedName, `toolCatalog.tools.exposedName:${name}`);
|
|
2431
|
+
if (!PROVIDER_SAFE_TOOL_NAME.test(exposedName) || PI_BUILTIN_TOOL_NAMES.has(exposedName)) {
|
|
2432
|
+
throw new Error(`pi_managed_mcp_invalid: direct tool exposed name is unsafe for ${name}`);
|
|
2433
|
+
}
|
|
2434
|
+
if (exposedNames.has(exposedName)) {
|
|
2435
|
+
throw new Error(`pi_managed_mcp_invalid: direct tool exposed name collision for ${exposedName}`);
|
|
2436
|
+
}
|
|
2437
|
+
exposedNames.add(exposedName);
|
|
2438
|
+
const inputSchema = record6(tool.inputSchema);
|
|
2439
|
+
if (inputSchema.type !== "object" || inputSchema.additionalProperties !== false) {
|
|
2440
|
+
throw new Error(`pi_managed_mcp_invalid: direct tool schema is not strict for ${name}`);
|
|
2441
|
+
}
|
|
2442
|
+
const schemaHash = stablePiToolSchemaHash(inputSchema);
|
|
2443
|
+
if (tool.schemaHash !== schemaHash) {
|
|
2444
|
+
throw new Error(`pi_managed_mcp_invalid: direct tool schema hash mismatch for ${name}`);
|
|
2445
|
+
}
|
|
2446
|
+
const riskLevel = nonEmpty2(tool.riskLevel, `toolCatalog.tools.riskLevel:${name}`);
|
|
2447
|
+
if (!(/* @__PURE__ */ new Set(["read", "write", "destructive"])).has(riskLevel)) {
|
|
2448
|
+
throw new Error(`pi_managed_mcp_invalid: direct tool risk level mismatch for ${name}`);
|
|
2449
|
+
}
|
|
2450
|
+
return {
|
|
2451
|
+
name,
|
|
2452
|
+
exposedName,
|
|
2453
|
+
description: typeof tool.description === "string" ? tool.description : "",
|
|
2454
|
+
inputSchema,
|
|
2455
|
+
schemaHash,
|
|
2456
|
+
riskLevel,
|
|
2457
|
+
effectiveSchemaHash: stablePiToolSchemaHash(inputSchema, { adapterNormalized: true })
|
|
2458
|
+
};
|
|
2459
|
+
});
|
|
2460
|
+
const setHash = stablePiDirectCatalogSetHash(normalized.map((tool) => ({
|
|
2461
|
+
name: tool.name,
|
|
2462
|
+
exposedName: tool.exposedName,
|
|
2463
|
+
schemaHash: tool.schemaHash,
|
|
2464
|
+
riskLevel: tool.riskLevel
|
|
2465
|
+
})));
|
|
2466
|
+
if (catalog.setHash !== setHash) {
|
|
2467
|
+
throw new Error("pi_managed_mcp_invalid: direct tool catalog set hash mismatch");
|
|
2468
|
+
}
|
|
2469
|
+
return { setHash, tools: normalized.sort((left, right) => left.name.localeCompare(right.name)) };
|
|
2470
|
+
}
|
|
2227
2471
|
function piExecutableIdentity(executorCommand) {
|
|
2228
2472
|
try {
|
|
2229
2473
|
const realPath = realpathSync2(executorCommand);
|
|
@@ -2231,8 +2475,8 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2231
2475
|
if (!executableStat.isFile() || executableStat.isSymbolicLink()) {
|
|
2232
2476
|
throw Object.assign(new Error("Pi executable is not a regular file"), { code: "EUNSAFE" });
|
|
2233
2477
|
}
|
|
2234
|
-
const contentSha256 =
|
|
2235
|
-
return `sha256:${
|
|
2478
|
+
const contentSha256 = createHash3("sha256").update(readFileSync3(realPath)).digest("hex");
|
|
2479
|
+
return `sha256:${createHash3("sha256").update(JSON.stringify({ realPath, contentSha256 })).digest("hex")}`;
|
|
2236
2480
|
} catch (error) {
|
|
2237
2481
|
const errorCode = typeof error?.code === "string" ? error.code : "UNKNOWN";
|
|
2238
2482
|
throw new Error(`pi_managed_mcp_attestation_failed: --version error=${errorCode}`);
|
|
@@ -2278,7 +2522,15 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2278
2522
|
throw new Error("pi_managed_mcp_invalid: Gateway authority mismatch");
|
|
2279
2523
|
}
|
|
2280
2524
|
if ((runtimeAuth.issueId ?? null) !== (headers["x-amaster-issue-id"] ?? null)) throw new Error("pi_managed_mcp_invalid: issue authority mismatch");
|
|
2281
|
-
|
|
2525
|
+
const mcpToolMode = gateway.mcpToolMode ?? MANAGED_PI_MCP_TOOL_MODE;
|
|
2526
|
+
if (mcpToolMode !== MANAGED_PI_MCP_TOOL_MODE && mcpToolMode !== MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE) {
|
|
2527
|
+
throw new Error("pi_managed_mcp_invalid: unsupported managed Pi MCP tool mode");
|
|
2528
|
+
}
|
|
2529
|
+
const directCatalog = mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE ? validateDirectCatalog(gateway) : null;
|
|
2530
|
+
if (mcpToolMode === MANAGED_PI_MCP_TOOL_MODE && gateway.toolCatalog !== void 0) {
|
|
2531
|
+
throw new Error("pi_managed_mcp_invalid: proxy-only authority cannot carry a direct tool catalog");
|
|
2532
|
+
}
|
|
2533
|
+
return { gateway, gatewayUrl, sessionToken, headers, runId, mcpToolMode, directCatalog };
|
|
2282
2534
|
}
|
|
2283
2535
|
function isSensitiveAuthKey2(key) {
|
|
2284
2536
|
const normalized = String(key).trim().replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().replaceAll("-", "_");
|
|
@@ -2443,8 +2695,13 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2443
2695
|
config: record6(sourceSettings["pi-telemetry"])
|
|
2444
2696
|
};
|
|
2445
2697
|
}
|
|
2446
|
-
function seedPiRuntime(sourceHome, agentDir, sourceAcquisition = null) {
|
|
2698
|
+
function seedPiRuntime(sourceHome, agentDir, sourceAcquisition = null, mcpToolMode = MANAGED_PI_MCP_TOOL_MODE) {
|
|
2447
2699
|
const source = resolve2(nonEmpty2(sourceHome, "sourcePiHome"));
|
|
2700
|
+
const sourceStat = lstatSync2(source);
|
|
2701
|
+
if (!sourceStat.isDirectory() || sourceStat.isSymbolicLink()) {
|
|
2702
|
+
throw new Error("pi_managed_mcp_source_config_unsafe: Pi home");
|
|
2703
|
+
}
|
|
2704
|
+
chmodSync2(source, sourceStat.mode & 511 | 1);
|
|
2448
2705
|
const npmSource = join4(source, "npm");
|
|
2449
2706
|
const adapterPackagePath = join4(npmSource, "node_modules", "pi-mcp-adapter", "package.json");
|
|
2450
2707
|
if (!existsSync3(adapterPackagePath) || lstatSync2(adapterPackagePath).isSymbolicLink()) {
|
|
@@ -2494,10 +2751,17 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2494
2751
|
`);
|
|
2495
2752
|
const extensionsDir = join4(agentDir, "extensions");
|
|
2496
2753
|
mkdirSync3(extensionsDir, { recursive: true, mode: 448 });
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2754
|
+
if (mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE) {
|
|
2755
|
+
writePrivateFile2(
|
|
2756
|
+
join4(extensionsDir, MANAGED_PI_EFFECTIVE_TOOLS_ATTESTOR_FILENAME),
|
|
2757
|
+
managedPiEffectiveToolsAttestorExtensionSource()
|
|
2758
|
+
);
|
|
2759
|
+
} else {
|
|
2760
|
+
writePrivateFile2(
|
|
2761
|
+
join4(extensionsDir, MANAGED_PI_MCP_ARGS_NORMALIZER_FILENAME),
|
|
2762
|
+
managedPiMcpArgsNormalizerExtensionSource()
|
|
2763
|
+
);
|
|
2764
|
+
}
|
|
2501
2765
|
if (sourceAcquisition && !copyPrivateFile(
|
|
2502
2766
|
join4(source, "extensions", "amaster-source-acquisition.js"),
|
|
2503
2767
|
join4(extensionsDir, "amaster-source-acquisition.js")
|
|
@@ -2590,9 +2854,62 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
2590
2854
|
liveProbeAgeMs
|
|
2591
2855
|
};
|
|
2592
2856
|
}
|
|
2857
|
+
function attestDirectPiTools(executorCommand, env, input) {
|
|
2858
|
+
const result3 = spawnSyncImpl(executorCommand, [
|
|
2859
|
+
"--no-session",
|
|
2860
|
+
"--no-skills",
|
|
2861
|
+
"--no-context-files",
|
|
2862
|
+
"--no-builtin-tools",
|
|
2863
|
+
"--print",
|
|
2864
|
+
"probe effective tools"
|
|
2865
|
+
], {
|
|
2866
|
+
cwd: env.AMASTER_RUNTIME_EXECUTION_WORKDIR,
|
|
2867
|
+
env: { ...env, AMASTER_PI_EFFECTIVE_TOOLS_MODE: "probe" },
|
|
2868
|
+
encoding: "utf8",
|
|
2869
|
+
timeout: PI_ATTESTATION_TIMEOUT_MS,
|
|
2870
|
+
killSignal: "SIGKILL",
|
|
2871
|
+
maxBuffer: 1024 * 1024
|
|
2872
|
+
});
|
|
2873
|
+
if (result3.error) {
|
|
2874
|
+
const code = typeof result3.error.code === "string" ? result3.error.code : "UNKNOWN";
|
|
2875
|
+
throw new Error(`pi_managed_mcp_effective_tools_failed: probe error=${code}`);
|
|
2876
|
+
}
|
|
2877
|
+
if (result3.status !== 0) {
|
|
2878
|
+
let receiptError = "receipt unavailable";
|
|
2879
|
+
try {
|
|
2880
|
+
const rejectedReceipt = JSON.parse(readFileSync3(input.receiptPath, "utf8"));
|
|
2881
|
+
if (typeof rejectedReceipt.error === "string" && rejectedReceipt.error.length > 0) {
|
|
2882
|
+
receiptError = rejectedReceipt.error.slice(0, 512);
|
|
2883
|
+
}
|
|
2884
|
+
} catch {
|
|
2885
|
+
}
|
|
2886
|
+
throw new Error(`pi_managed_mcp_effective_tools_failed: probe exit=${result3.status ?? "unknown"} reason=${receiptError}`);
|
|
2887
|
+
}
|
|
2888
|
+
let receipt;
|
|
2889
|
+
try {
|
|
2890
|
+
receipt = JSON.parse(readFileSync3(input.receiptPath, "utf8"));
|
|
2891
|
+
} catch {
|
|
2892
|
+
throw new Error("pi_managed_mcp_effective_tools_failed: probe receipt missing");
|
|
2893
|
+
}
|
|
2894
|
+
if (receipt.status !== "attested" || receipt.mode !== "probe" || receipt.proxyPresent !== false || receipt.effectiveSetHash !== input.effectiveSetHash || receipt.attestorSourceSha256 !== input.attestorSourceSha256 || receipt.configSha256 !== input.configSha256 || receipt.cacheSha256 !== input.cacheSha256) {
|
|
2895
|
+
throw new Error("pi_managed_mcp_effective_tools_failed: probe receipt mismatch");
|
|
2896
|
+
}
|
|
2897
|
+
if (sha256(readFileSync3(input.configPath)) !== input.configSha256) {
|
|
2898
|
+
throw new Error("pi_managed_mcp_effective_tools_failed: config drifted during probe");
|
|
2899
|
+
}
|
|
2900
|
+
if (sha256(readFileSync3(input.cachePath)) !== input.cacheSha256) {
|
|
2901
|
+
throw new Error("pi_managed_mcp_effective_tools_failed: cache drifted during probe");
|
|
2902
|
+
}
|
|
2903
|
+
return {
|
|
2904
|
+
effectiveToolSetHash: receipt.effectiveSetHash,
|
|
2905
|
+
effectiveToolProbeDigest: sha256(stablePiJson(receipt)),
|
|
2906
|
+
effectiveToolProbeAt: receipt.attestedAt,
|
|
2907
|
+
effectiveToolBindings: receipt.effectiveToolBindings
|
|
2908
|
+
};
|
|
2909
|
+
}
|
|
2593
2910
|
function prepareManagedPiMcpProfile2(input) {
|
|
2594
2911
|
assertInvocationIsolation2(input);
|
|
2595
|
-
const { gateway, gatewayUrl, sessionToken, headers, runId } = validateAuthority2(input);
|
|
2912
|
+
const { gateway, gatewayUrl, sessionToken, headers, runId, mcpToolMode, directCatalog } = validateAuthority2(input);
|
|
2596
2913
|
const runDir = resolve2(nonEmpty2(input.runDir, "runDir"));
|
|
2597
2914
|
const executorHome = resolve2(nonEmpty2(input.executorHome, "executorHome"));
|
|
2598
2915
|
if (!within4(executorHome, join4(runDir, "executors"))) throw new Error("pi_managed_mcp_owner_mismatch: executorHome is outside the managed run");
|
|
@@ -2619,24 +2936,82 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
2619
2936
|
commandId: input.commandId
|
|
2620
2937
|
});
|
|
2621
2938
|
const sourcePiHome = nonEmpty2(input.baseEnv?.PI_CODING_AGENT_DIR ?? input.baseEnv?.PI_AGENT_HOME, "sourcePiHome");
|
|
2622
|
-
const seededRuntime = seedPiRuntime(sourcePiHome, piCodingAgentDir, input.sourceAcquisition);
|
|
2939
|
+
const seededRuntime = seedPiRuntime(sourcePiHome, piCodingAgentDir, input.sourceAcquisition, mcpToolMode);
|
|
2623
2940
|
const restoredNativeSession = restoreManagedPiSessionRollout(input, sessionsRoot, runDir, executorHome, authority);
|
|
2624
2941
|
const configPath = join4(piCodingAgentDir, "mcp.json");
|
|
2942
|
+
const directToolNames = directCatalog?.tools.map((tool) => tool.exposedName) ?? [];
|
|
2943
|
+
const serverConfig = {
|
|
2944
|
+
type: "http",
|
|
2945
|
+
url: gatewayUrl,
|
|
2946
|
+
headers: { Authorization: `Bearer ${sessionToken}`, ...headers },
|
|
2947
|
+
lifecycle: directCatalog ? "lazy" : "eager",
|
|
2948
|
+
...directCatalog ? { exposeResources: false, directTools: directToolNames } : {}
|
|
2949
|
+
};
|
|
2625
2950
|
const config = {
|
|
2626
2951
|
settings: {
|
|
2627
|
-
toolPrefix: "none"
|
|
2952
|
+
toolPrefix: "none",
|
|
2953
|
+
...directCatalog ? { disableProxyTool: true } : {}
|
|
2628
2954
|
},
|
|
2629
2955
|
mcpServers: {
|
|
2630
|
-
[SUPPORTED_SERVER_NAME2]:
|
|
2631
|
-
type: "http",
|
|
2632
|
-
url: gatewayUrl,
|
|
2633
|
-
headers: { Authorization: `Bearer ${sessionToken}`, ...headers },
|
|
2634
|
-
lifecycle: "eager"
|
|
2635
|
-
}
|
|
2956
|
+
[SUPPORTED_SERVER_NAME2]: serverConfig
|
|
2636
2957
|
}
|
|
2637
2958
|
};
|
|
2638
2959
|
writePrivateFile2(configPath, `${JSON.stringify(config, null, 2)}
|
|
2639
2960
|
`);
|
|
2961
|
+
let directAttestationInput = null;
|
|
2962
|
+
if (directCatalog) {
|
|
2963
|
+
const cachePath = join4(piCodingAgentDir, "mcp-cache.json");
|
|
2964
|
+
const cache = {
|
|
2965
|
+
version: 1,
|
|
2966
|
+
servers: {
|
|
2967
|
+
[SUPPORTED_SERVER_NAME2]: {
|
|
2968
|
+
configHash: adapterServerConfigHash(serverConfig),
|
|
2969
|
+
tools: directCatalog.tools.map((tool) => ({
|
|
2970
|
+
name: tool.exposedName,
|
|
2971
|
+
description: tool.description,
|
|
2972
|
+
inputSchema: tool.inputSchema
|
|
2973
|
+
})),
|
|
2974
|
+
resources: [],
|
|
2975
|
+
cachedAt: currentTimeMs()
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
};
|
|
2979
|
+
writePrivateFile2(cachePath, `${JSON.stringify(cache, null, 2)}
|
|
2980
|
+
`);
|
|
2981
|
+
const cacheSha256 = sha256(readFileSync3(cachePath));
|
|
2982
|
+
const attestorSourceSha256 = sha256(managedPiEffectiveToolsAttestorExtensionSource());
|
|
2983
|
+
const manifestPath = join4(piCodingAgentDir, "effective-tools-manifest.json");
|
|
2984
|
+
const receiptPath = join4(tmp, "effective-tools-receipt.json");
|
|
2985
|
+
const manifest = {
|
|
2986
|
+
schemaVersion: MANAGED_PI_EFFECTIVE_TOOLS_SCHEMA_VERSION,
|
|
2987
|
+
serverName: SUPPORTED_SERVER_NAME2,
|
|
2988
|
+
entries: directCatalog.tools.map((tool) => ({
|
|
2989
|
+
name: tool.exposedName,
|
|
2990
|
+
canonicalName: tool.name,
|
|
2991
|
+
schema: tool.inputSchema,
|
|
2992
|
+
effectiveSchemaHash: tool.effectiveSchemaHash
|
|
2993
|
+
})),
|
|
2994
|
+
effectiveSetHash: stablePiEffectiveToolSetHash(directCatalog.tools.map((tool) => ({
|
|
2995
|
+
name: tool.exposedName,
|
|
2996
|
+
schemaHash: tool.effectiveSchemaHash
|
|
2997
|
+
}))),
|
|
2998
|
+
attestorSourceSha256,
|
|
2999
|
+
configSha256: sha256(readFileSync3(configPath)),
|
|
3000
|
+
cacheSha256
|
|
3001
|
+
};
|
|
3002
|
+
writePrivateFile2(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
3003
|
+
`);
|
|
3004
|
+
directAttestationInput = {
|
|
3005
|
+
cachePath,
|
|
3006
|
+
manifestPath,
|
|
3007
|
+
receiptPath,
|
|
3008
|
+
cacheSha256,
|
|
3009
|
+
configPath,
|
|
3010
|
+
configSha256: sha256(readFileSync3(configPath)),
|
|
3011
|
+
attestorSourceSha256,
|
|
3012
|
+
effectiveSetHash: manifest.effectiveSetHash
|
|
3013
|
+
};
|
|
3014
|
+
}
|
|
2640
3015
|
const env = {
|
|
2641
3016
|
...buildIsolatedEnvironment2(input.baseEnv, input.commandEnv),
|
|
2642
3017
|
HOME: home,
|
|
@@ -2647,18 +3022,30 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
2647
3022
|
"AMASTER-CLI_CODING_AGENT_SESSION_DIR": sessionsRoot,
|
|
2648
3023
|
PI_AGENT_MCP_SERVERS_FILE: configPath,
|
|
2649
3024
|
TMPDIR: tmp,
|
|
3025
|
+
...directAttestationInput ? {
|
|
3026
|
+
AMASTER_PI_EFFECTIVE_TOOLS_MODE: "enforce",
|
|
3027
|
+
AMASTER_PI_EFFECTIVE_TOOLS_MANIFEST: directAttestationInput.manifestPath,
|
|
3028
|
+
AMASTER_PI_EFFECTIVE_TOOLS_RECEIPT: directAttestationInput.receiptPath,
|
|
3029
|
+
AMASTER_PI_EFFECTIVE_TOOLS_CACHE: directAttestationInput.cachePath,
|
|
3030
|
+
AMASTER_PI_EFFECTIVE_TOOLS_CONFIG: directAttestationInput.configPath
|
|
3031
|
+
} : {},
|
|
2650
3032
|
...input.sourceAcquisition ? {
|
|
2651
3033
|
PI_BROWSER_USE_RUNTIME_READ_POLICY: "required"
|
|
2652
3034
|
} : {}
|
|
2653
3035
|
};
|
|
2654
3036
|
const executorAttestation = attestPi(nonEmpty2(input.executorCommand, "executorCommand"), env, configPath, config);
|
|
3037
|
+
const effectiveToolsAttestation = directAttestationInput ? attestDirectPiTools(nonEmpty2(input.executorCommand, "executorCommand"), env, directAttestationInput) : {};
|
|
2655
3038
|
const attestationFacts = {
|
|
2656
3039
|
connectorVersion: nonEmpty2(input.connectorVersion, "connectorVersion"),
|
|
2657
3040
|
executorKind: "pi",
|
|
2658
3041
|
...executorAttestation,
|
|
2659
3042
|
mcpAdapterVersion: seededRuntime.adapterVersion,
|
|
2660
|
-
mcpToolMode
|
|
2661
|
-
mcpArgsNormalization: MANAGED_PI_MCP_ARGS_NORMALIZATION,
|
|
3043
|
+
mcpToolMode,
|
|
3044
|
+
mcpArgsNormalization: directCatalog ? "none" : MANAGED_PI_MCP_ARGS_NORMALIZATION,
|
|
3045
|
+
...directCatalog ? {
|
|
3046
|
+
catalogSetHash: directCatalog.setHash,
|
|
3047
|
+
...effectiveToolsAttestation
|
|
3048
|
+
} : {},
|
|
2662
3049
|
configMode: "isolated_home_run_scoped_mcp_file",
|
|
2663
3050
|
namespace: SUPPORTED_SERVER_NAME2,
|
|
2664
3051
|
schemaVersion: SUPPORTED_SCHEMA_VERSION2,
|
|
@@ -2684,7 +3071,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
2684
3071
|
])],
|
|
2685
3072
|
attestation: {
|
|
2686
3073
|
...attestationFacts,
|
|
2687
|
-
attestationId:
|
|
3074
|
+
attestationId: createHash3("sha256").update(JSON.stringify(attestationFacts)).digest("hex"),
|
|
2688
3075
|
attestedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2689
3076
|
}
|
|
2690
3077
|
};
|
|
@@ -3505,10 +3892,10 @@ function wikiAccessRuleLine(input) {
|
|
|
3505
3892
|
const tools = input.hasGovernedMcp === true && access.tools === true;
|
|
3506
3893
|
const treePath = readString(access.treePath);
|
|
3507
3894
|
if (tools && treePath) {
|
|
3508
|
-
return `- Company wiki access in this run: the governed tools wiki_search / wiki_read_page / wiki_list_pages via the amaster MCP, and the wiki tree at ${treePath} (read wiki/index.md there first).`;
|
|
3895
|
+
return `- Company wiki access in this run: the governed tools wiki_search / wiki_read_page / wiki_list_pages / wiki_read_source / wiki_write_page via the amaster MCP, and the wiki tree at ${treePath} (read wiki/index.md there first).`;
|
|
3509
3896
|
}
|
|
3510
3897
|
if (tools) {
|
|
3511
|
-
return "- Company wiki access in this run: the governed tools wiki_search / wiki_read_page / wiki_list_pages via the amaster MCP. Use them for
|
|
3898
|
+
return "- Company wiki access in this run: the governed tools wiki_search / wiki_read_page / wiki_list_pages / wiki_read_source / wiki_write_page via the amaster MCP. Use them for governed lookup and durable Wiki updates; Company Knowledge operations must use the exact operationId and sourceRefs named by the issue.";
|
|
3512
3899
|
}
|
|
3513
3900
|
if (treePath) {
|
|
3514
3901
|
return `- Company wiki access in this run: the wiki tree at ${treePath}. Read wiki/index.md first (every page listed with a one-line summary), then open the specific pages you need; wiki_* tools are not available in this run.`;
|
|
@@ -3606,6 +3993,13 @@ function continuationRuntimeActionEnvelope(context) {
|
|
|
3606
3993
|
if (!readString(envelope.schemaVersion) || !readString(envelope.idempotencyKey) || action.type !== "update_parent" || action.status !== "todo" || !readString(action.comment)) return null;
|
|
3607
3994
|
return envelope;
|
|
3608
3995
|
}
|
|
3996
|
+
function managedDirectToolName(input, canonicalName) {
|
|
3997
|
+
if (input.managedMcpToolMode !== "direct_typed") return null;
|
|
3998
|
+
const catalog = asRecord(input.managedMcpToolCatalog);
|
|
3999
|
+
const tools = Array.isArray(catalog.tools) ? catalog.tools.map(asRecord) : [];
|
|
4000
|
+
const match = tools.find((tool) => readString(tool.name) === canonicalName);
|
|
4001
|
+
return readString(match?.exposedName) ?? null;
|
|
4002
|
+
}
|
|
3609
4003
|
function runtimeActionContinuationOptionText(input) {
|
|
3610
4004
|
if (!isRecoveryWakeReason(input.wakeReason)) return "";
|
|
3611
4005
|
const heading = "### Runtime Action Continuation Option";
|
|
@@ -3619,6 +4013,20 @@ Runtime Action continuation is unavailable: managed governed MCP capability is m
|
|
|
3619
4013
|
Runtime Action continuation is unavailable: continuationRuntimeActionEnvelope is missing or invalid. Do not guess a tool call.`;
|
|
3620
4014
|
}
|
|
3621
4015
|
if (input.executorKind === "pi") {
|
|
4016
|
+
if (input.managedMcpToolMode === "direct_typed") {
|
|
4017
|
+
const toolName = managedDirectToolName(input, "runtime_action.submit");
|
|
4018
|
+
if (!toolName) {
|
|
4019
|
+
return `${heading}
|
|
4020
|
+
Runtime Action continuation is unavailable: the run catalog does not advertise the required typed submit tool. Do not guess a tool call.`;
|
|
4021
|
+
}
|
|
4022
|
+
return [
|
|
4023
|
+
heading,
|
|
4024
|
+
`Only after selecting continuation/todo from the disposition menu, emit an actual \`${toolName}\` typed tool call with the exact object arguments below. Do not print this JSON as prose.`,
|
|
4025
|
+
"```json",
|
|
4026
|
+
jsonText(envelope),
|
|
4027
|
+
"```"
|
|
4028
|
+
].join("\n");
|
|
4029
|
+
}
|
|
3622
4030
|
if (input.managedMcpToolMode !== "proxy_only") {
|
|
3623
4031
|
return `${heading}
|
|
3624
4032
|
Runtime Action continuation is unavailable: managed Pi MCP tool mode is not proxy_only. Do not guess a proxy or direct-tool call.`;
|
|
@@ -3839,6 +4247,19 @@ function piMcpProxyExamplesText(input) {
|
|
|
3839
4247
|
`- read document: ${proxy("amaster.read_issue_document", { issueId: "AM-123", key: "plan" })}`
|
|
3840
4248
|
].join("\n");
|
|
3841
4249
|
}
|
|
4250
|
+
function piDirectTypedToolsText(input) {
|
|
4251
|
+
if (!input.hasGovernedMcp || input.executorKind !== "pi" || input.managedMcpToolMode !== "direct_typed") return "";
|
|
4252
|
+
const catalog = asRecord(input.managedMcpToolCatalog);
|
|
4253
|
+
const tools = (Array.isArray(catalog.tools) ? catalog.tools : []).map(asRecord).map((tool) => ({ name: readString(tool.exposedName), description: readString(tool.description) })).filter((tool) => tool.name);
|
|
4254
|
+
if (tools.length === 0) {
|
|
4255
|
+
return "Direct typed governed tools are unavailable because the run catalog snapshot is empty. Do not guess a proxy or tool name.";
|
|
4256
|
+
}
|
|
4257
|
+
return [
|
|
4258
|
+
"This run uses the attested direct typed Governed MCP surface below. Call these exact names with object arguments; do not call the `mcp` proxy and do not stringify an inner argument envelope.",
|
|
4259
|
+
...tools.map((tool) => `- ${tool.name}${tool.description ? `: ${tool.description}` : ""}`),
|
|
4260
|
+
"A tool not listed above is unavailable in this run. Do not infer a namespace or fall back to REST/bare MCP."
|
|
4261
|
+
].join("\n");
|
|
4262
|
+
}
|
|
3842
4263
|
function sectionText(section) {
|
|
3843
4264
|
if (!section.content) return "";
|
|
3844
4265
|
return section.title ? `## ${section.title}
|
|
@@ -3945,10 +4366,14 @@ function compileCommandPromptWithManifest(input, options = {}) {
|
|
|
3945
4366
|
resolvedDependencies.details.content ? `Auxiliary predecessor context (may be truncated):
|
|
3946
4367
|
${resolvedDependencies.details.content}` : ""
|
|
3947
4368
|
].filter(Boolean).join("\n\n") : "";
|
|
3948
|
-
const piMcpProxyExamples = resolvedDependencies.required.content ? "" : piMcpProxyExamplesText(input);
|
|
4369
|
+
const piMcpProxyExamples = resolvedDependencies.required.content ? "" : [piMcpProxyExamplesText(input), piDirectTypedToolsText(input)].filter(Boolean).join("\n");
|
|
3949
4370
|
const deliveryReadinessContent = runtimeDeliveryReadinessText(context, input);
|
|
3950
4371
|
const rawSections = [
|
|
3951
|
-
{ name: "
|
|
4372
|
+
{ name: "recovery_instruction", title: "Recovery Instruction", priority: 100, sourceRef: `run:${input.runId ?? "unknown"}`, content: completeRecoveryInstruction, truncationReason: completeRecoveryInstruction ? null : "mode_selection" },
|
|
4373
|
+
{ name: "approval_continuation", title: "Approved Runtime Action Continuation", priority: 99, sourceRef: `run:${input.runId ?? "unknown"}`, content: approvalContinuationText(input), truncationReason: mode === "continuation" ? null : "mode_selection" },
|
|
4374
|
+
{ name: "wake_comments", title: wakeDeltaTitle, priority: interactionResolution ? 99 : 95, sourceRef: wakeDeltaSourceRefs, originalContent: wakeDeltaOriginal, content: wakeDeltaContent, truncationReason: commentsSelected ? null : "duplicate_task_context" },
|
|
4375
|
+
{ name: "task", title: "Task Context", priority: 90, sourceRef: `issue:${input.issueId ?? "unknown"}`, originalContent: [taskText, taskCommentRefGuidance(input)].filter(Boolean).join("\n"), content: includeTask ? [taskText, taskCommentRefGuidance(input)].filter(Boolean).join("\n") : "", truncationReason: includeTask ? null : "mode_selection" },
|
|
4376
|
+
{ name: "continuation_summary", title: "Continuation Summary", priority: 97, sourceRef: readString(asRecord(context.paperclipContinuationSummary).key) ?? `issue:${input.issueId ?? "unknown"}`, observedAt: readString(asRecord(context.paperclipContinuationSummary).updatedAt), originalContent: continuationSummary, content: mode === "cold" ? "" : continuationSummary, truncationReason: mode === "cold" ? "mode_selection" : null },
|
|
3952
4377
|
...resolvedDependencyContent ? [{
|
|
3953
4378
|
name: "resolved_dependencies",
|
|
3954
4379
|
title: "Resolved Dependency Outputs",
|
|
@@ -3957,16 +4382,12 @@ ${resolvedDependencies.details.content}` : ""
|
|
|
3957
4382
|
content: resolvedDependencyContent,
|
|
3958
4383
|
mandatoryContent: resolvedDependencies.required.content
|
|
3959
4384
|
}] : [],
|
|
3960
|
-
{ name: "
|
|
3961
|
-
{ name: "
|
|
4385
|
+
...deliveryReadinessContent ? [{ name: "runtime_delivery_readiness", title: "Current Delivery Readiness", priority: 99, sourceRef: `issue:${input.issueId ?? "unknown"}:delivery`, content: deliveryReadinessContent }] : [],
|
|
4386
|
+
{ name: "runtime_rules", title: "", priority: 100, sourceRef: `command:${input.commandId}`, content: fixedRules(input, !hasTask) },
|
|
3962
4387
|
{ name: "runtime_authorization", title: "Runtime Action Contract", priority: 98, sourceRef: `run:${input.runId ?? "unknown"}`, content: runtimeAuthorizationText(context, mode, { suppressOrdinaryCompletionContract }) },
|
|
3963
4388
|
{ name: "runtime_decomposition_requirement", title: "Required Task Decomposition", priority: 98, sourceRef: `issue:${input.issueId ?? "unknown"}`, content: runtimeDecompositionRequirementText(context) },
|
|
3964
|
-
...deliveryReadinessContent ? [{ name: "runtime_delivery_readiness", title: "Current Delivery Readiness", priority: 99, sourceRef: `issue:${input.issueId ?? "unknown"}:delivery`, content: deliveryReadinessContent }] : [],
|
|
3965
|
-
...piMcpProxyExamples ? [{ name: "pi_mcp_proxy_examples", title: "Pi MCP Proxy Examples", priority: 96, sourceRef: "amaster_governed_mcp_proxy_contract", content: piMcpProxyExamples }] : [],
|
|
3966
|
-
{ name: "continuation_summary", title: "Continuation Summary", priority: 97, sourceRef: readString(asRecord(context.paperclipContinuationSummary).key) ?? `issue:${input.issueId ?? "unknown"}`, observedAt: readString(asRecord(context.paperclipContinuationSummary).updatedAt), originalContent: continuationSummary, content: mode === "cold" ? "" : continuationSummary, truncationReason: mode === "cold" ? "mode_selection" : null },
|
|
3967
4389
|
...verifiedCompanyContext.content ? [{ name: "verified_company_context", title: "Verified Company Context", priority: 96, sourceRef: verifiedCompanyContext.sourceRef, observedAt: verifiedCompanyContext.observedAt, freshness: { kind: "run_snapshot" }, content: verifiedCompanyContext.content }] : [],
|
|
3968
|
-
{ name: "
|
|
3969
|
-
{ name: "task", title: "Task Context", priority: 90, sourceRef: `issue:${input.issueId ?? "unknown"}`, originalContent: [taskText, taskCommentRefGuidance(input)].filter(Boolean).join("\n"), content: includeTask ? [taskText, taskCommentRefGuidance(input)].filter(Boolean).join("\n") : "", truncationReason: includeTask ? null : "mode_selection" },
|
|
4390
|
+
...piMcpProxyExamples ? [{ name: "pi_mcp_proxy_examples", title: "Pi MCP Proxy Examples", priority: 96, sourceRef: "amaster_governed_mcp_proxy_contract", content: piMcpProxyExamples }] : [],
|
|
3970
4391
|
{ name: "governed_reads", title: "Governed External Reads", priority: 88, sourceRef: governedReads.provenance.map((entry) => entry.sourceRef), observedAt: governedReads.provenance.map((entry) => entry.observedAt), freshness: governedReads.provenance.map((entry) => entry.freshness), scope: governedReads.provenance.map((entry) => entry.scope), content: governedReads.content },
|
|
3971
4392
|
{ name: "agent_instructions", title: "Agent Instructions", priority: 100, sourceRef: "agent_instructions_bundle", content: readString(input.agentInstructions) ?? "" },
|
|
3972
4393
|
{ name: "attachments", title: "Materialized Inputs", priority: 80, sourceRef: "materialized_attachments", content: readString(input.attachmentsText) ?? "" },
|
|
@@ -5830,7 +6251,7 @@ var postJsonWithRetry = postRuntimeConnectorJsonWithRetry;
|
|
|
5830
6251
|
var bestEffortPostJson = bestEffortPostRuntimeConnectorJson;
|
|
5831
6252
|
|
|
5832
6253
|
// src/amaster-runtime-daemon/runtime-artifact-upload.mjs
|
|
5833
|
-
import { createHash as
|
|
6254
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
5834
6255
|
import { lstatSync as lstatSync3, readFileSync as readFileSync6, realpathSync as realpathSync3 } from "node:fs";
|
|
5835
6256
|
import { isAbsolute as isAbsolute3, relative as relative3, resolve as resolve3 } from "node:path";
|
|
5836
6257
|
var SHA256_PATTERN = /^[a-f0-9]{64}$/;
|
|
@@ -5873,7 +6294,7 @@ function prepareRuntimeArtifactUploads(cwd, mcpToolResults) {
|
|
|
5873
6294
|
throw new Error(`Runtime Artifact ${intentId} source is not an owned regular file`);
|
|
5874
6295
|
}
|
|
5875
6296
|
const body = readFileSync6(sourcePath);
|
|
5876
|
-
const actualSha256 =
|
|
6297
|
+
const actualSha256 = createHash4("sha256").update(body).digest("hex");
|
|
5877
6298
|
if (body.length !== expectedByteSize || actualSha256 !== expectedSha256) {
|
|
5878
6299
|
throw new Error(`Runtime Artifact ${intentId} bytes do not match the governed ownership manifest`);
|
|
5879
6300
|
}
|
|
@@ -5963,7 +6384,7 @@ function createRuntimeArtifactIngestQueue({ ingest, onError }) {
|
|
|
5963
6384
|
}
|
|
5964
6385
|
|
|
5965
6386
|
// src/amaster-runtime-daemon/workspace-guard.mjs
|
|
5966
|
-
import { createHash as
|
|
6387
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
5967
6388
|
import { existsSync as existsSync7, mkdirSync as mkdirSync6, realpathSync as realpathSync4, statSync as statSync3 } from "node:fs";
|
|
5968
6389
|
import { basename as basename4, join as join8, isAbsolute as isAbsolute4, relative as relative4, resolve as resolve4 } from "node:path";
|
|
5969
6390
|
|
|
@@ -6074,7 +6495,7 @@ function resolveWorkspaceCwd(config, command) {
|
|
|
6074
6495
|
return cwd;
|
|
6075
6496
|
}
|
|
6076
6497
|
function shortHash(value, length = 12) {
|
|
6077
|
-
return
|
|
6498
|
+
return createHash5("sha256").update(String(value)).digest("hex").slice(0, length);
|
|
6078
6499
|
}
|
|
6079
6500
|
function safeSegment(value, fallback) {
|
|
6080
6501
|
const raw = String(value ?? "").trim();
|
|
@@ -6506,7 +6927,7 @@ function summarizeAmasterRuntimeVersionDrift(input = {}) {
|
|
|
6506
6927
|
}
|
|
6507
6928
|
|
|
6508
6929
|
// src/amaster-runtime-daemon/pi-child-isolation.mjs
|
|
6509
|
-
import { createHash as
|
|
6930
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
6510
6931
|
import {
|
|
6511
6932
|
chmodSync as chmodSync3,
|
|
6512
6933
|
chownSync,
|
|
@@ -6517,7 +6938,7 @@ import {
|
|
|
6517
6938
|
import { resolve as resolve7, sep } from "node:path";
|
|
6518
6939
|
var defaultFs = { chmodSync: chmodSync3, chownSync, lchownSync, lstatSync: lstatSync4, readdirSync: readdirSync6 };
|
|
6519
6940
|
function defaultHashRunId(runId) {
|
|
6520
|
-
return Number.parseInt(
|
|
6941
|
+
return Number.parseInt(createHash6("sha256").update(runId).digest("hex").slice(0, 8), 16);
|
|
6521
6942
|
}
|
|
6522
6943
|
function positiveInteger(value, label) {
|
|
6523
6944
|
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
@@ -6641,7 +7062,7 @@ function preparePiChildIsolation(input) {
|
|
|
6641
7062
|
}
|
|
6642
7063
|
|
|
6643
7064
|
// src/amaster-runtime-daemon/pi-company-memory.mjs
|
|
6644
|
-
import { createHash as
|
|
7065
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
6645
7066
|
import {
|
|
6646
7067
|
chmodSync as chmodSync4,
|
|
6647
7068
|
chownSync as chownSync2,
|
|
@@ -6727,7 +7148,7 @@ function safeCompanyPiHomeSegment(companyId) {
|
|
|
6727
7148
|
const raw = requiredString2(companyId, "companyId");
|
|
6728
7149
|
if (/^[A-Za-z0-9][A-Za-z0-9._-]{0,119}$/.test(raw)) return raw;
|
|
6729
7150
|
const normalized = raw.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[._-]+|[._-]+$/g, "").slice(0, 80);
|
|
6730
|
-
const hash =
|
|
7151
|
+
const hash = createHash7("sha256").update(raw).digest("hex").slice(0, 12);
|
|
6731
7152
|
return normalized ? `${normalized}-${hash}` : `company-${hash}`;
|
|
6732
7153
|
}
|
|
6733
7154
|
function ensureMemoryRoot(root, fs) {
|
|
@@ -6766,7 +7187,7 @@ function allocateCompanyGid(root, companyId, input, fs) {
|
|
|
6766
7187
|
if (groups[companyId]) return groups[companyId];
|
|
6767
7188
|
const used = new Set(Object.values(groups));
|
|
6768
7189
|
const initialOffset = Number.parseInt(
|
|
6769
|
-
|
|
7190
|
+
createHash7("sha256").update(companyId).digest("hex").slice(0, 12),
|
|
6770
7191
|
16
|
|
6771
7192
|
) % gidSpan;
|
|
6772
7193
|
let gid = null;
|
|
@@ -6868,7 +7289,7 @@ function prepareCompanyPiMemory(input, fs = defaultFs2) {
|
|
|
6868
7289
|
}
|
|
6869
7290
|
|
|
6870
7291
|
// src/amaster-runtime-daemon/pi-trusted-runtime-profile.mjs
|
|
6871
|
-
import { createHash as
|
|
7292
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
6872
7293
|
import {
|
|
6873
7294
|
chmodSync as chmodSync5,
|
|
6874
7295
|
copyFileSync as copyFileSync2,
|
|
@@ -6886,6 +7307,8 @@ var ASSERTION_VERSION = "2026-07-25.v1";
|
|
|
6886
7307
|
var SHA256 = /^[a-f0-9]{64}$/;
|
|
6887
7308
|
var COPY_ENTRIES = ["SYSTEM.md", "policy", "skills", "agents", "bundles", "extensions"];
|
|
6888
7309
|
var JSON_ENTRIES = ["settings.json", "models.json"];
|
|
7310
|
+
var ROLE_SKILLS_DIR = "role-skills";
|
|
7311
|
+
var DISABLE_MODEL_INVOCATION_LINE = /^[ \t]*disable-model-invocation:[ \t]*true[ \t]*\r?$/m;
|
|
6889
7312
|
var SECRET_KEY = /(authorization|cookie|api[_-]?key|password|secret|token)$/i;
|
|
6890
7313
|
var SECRET_VALUE = /(?:authorization|cookie|api[_-]?key|password|secret|token)\s*[:=]\s*(?:bearer\s+)?[^\s"',;]+|bearer\s+[^\s"',;]+/i;
|
|
6891
7314
|
var MAX_AUDIT_BYTES = 1024 * 1024;
|
|
@@ -6906,7 +7329,7 @@ function sha256File(path, label) {
|
|
|
6906
7329
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
6907
7330
|
throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
|
|
6908
7331
|
}
|
|
6909
|
-
return
|
|
7332
|
+
return createHash8("sha256").update(readFileSync9(path)).digest("hex");
|
|
6910
7333
|
}
|
|
6911
7334
|
function verifyDeclaredFiles(manifest, root, label, ignoredPaths = [], enforceComplete = true) {
|
|
6912
7335
|
if (!Array.isArray(manifest.files) || manifest.files.length === 0) {
|
|
@@ -7004,6 +7427,53 @@ function copyTreeNoLinks(source, target) {
|
|
|
7004
7427
|
copyFileSync2(source, target);
|
|
7005
7428
|
chmodSync5(target, 384 | stat.mode & 73);
|
|
7006
7429
|
}
|
|
7430
|
+
var SKILL_PROFILE_NAME = /^[a-z0-9-]+$/;
|
|
7431
|
+
function readSkillProfile(seedRoot, skillProfile) {
|
|
7432
|
+
const agentsRoot = resolve9(seedRoot, "agents");
|
|
7433
|
+
const agentFile = resolve9(agentsRoot, `${skillProfile}.md`);
|
|
7434
|
+
if (!SKILL_PROFILE_NAME.test(skillProfile) || !within3(agentFile, agentsRoot) || !existsSync11(agentFile)) {
|
|
7435
|
+
throw new Error(`pi_trusted_runtime_skill_profile_unknown:${skillProfile}`);
|
|
7436
|
+
}
|
|
7437
|
+
const declared = readFileSync9(agentFile, "utf8").match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1].match(/^skills:\s*(.+)$/m)?.[1].split(",").map((entry) => entry.trim()).filter(Boolean) ?? [];
|
|
7438
|
+
const bundlesRoot = resolve9(seedRoot, "bundles");
|
|
7439
|
+
const profile = [];
|
|
7440
|
+
for (const name of declared) {
|
|
7441
|
+
let source = join12(bundlesRoot, skillProfile, "skills", name);
|
|
7442
|
+
if (!existsSync11(join12(source, "SKILL.md"))) {
|
|
7443
|
+
const candidates = [];
|
|
7444
|
+
for (const category of readdirSync7(bundlesRoot).sort()) {
|
|
7445
|
+
if (category === skillProfile) continue;
|
|
7446
|
+
const candidate = join12(bundlesRoot, category, "skills", name);
|
|
7447
|
+
if (existsSync11(join12(candidate, "SKILL.md"))) candidates.push(candidate);
|
|
7448
|
+
}
|
|
7449
|
+
if (candidates.length > 1) {
|
|
7450
|
+
throw new Error(`pi_trusted_runtime_skill_profile_ambiguous:${skillProfile}:${name}`);
|
|
7451
|
+
}
|
|
7452
|
+
source = candidates[0];
|
|
7453
|
+
}
|
|
7454
|
+
if (source) profile.push({ name, source });
|
|
7455
|
+
}
|
|
7456
|
+
if (profile.length === 0) {
|
|
7457
|
+
throw new Error(`pi_trusted_runtime_skill_profile_unknown:${skillProfile}`);
|
|
7458
|
+
}
|
|
7459
|
+
return profile;
|
|
7460
|
+
}
|
|
7461
|
+
function materializeRoleSkills(seedRoot, agentDir, skillProfile) {
|
|
7462
|
+
const profile = readSkillProfile(seedRoot, skillProfile);
|
|
7463
|
+
const bundlesRoot = resolve9(seedRoot, "bundles");
|
|
7464
|
+
const enabled = [];
|
|
7465
|
+
for (const entry of profile) {
|
|
7466
|
+
const target = join12(agentDir, ROLE_SKILLS_DIR, entry.name);
|
|
7467
|
+
rmSync6(target, { recursive: true, force: true });
|
|
7468
|
+
copyTreeNoLinks(entry.source, target);
|
|
7469
|
+
const skillFile = join12(target, "SKILL.md");
|
|
7470
|
+
writeFileSync8(skillFile, readFileSync9(skillFile, "utf8").replace(DISABLE_MODEL_INVOCATION_LINE, ""), {
|
|
7471
|
+
mode: 384
|
|
7472
|
+
});
|
|
7473
|
+
enabled.push({ name: entry.name, path: relative6(bundlesRoot, entry.source).split("\\").join("/") });
|
|
7474
|
+
}
|
|
7475
|
+
return enabled;
|
|
7476
|
+
}
|
|
7007
7477
|
function mergeMcp(seedRoot, overlayRoot, governedConfig) {
|
|
7008
7478
|
const seed = record5(readJsonFile2(join12(seedRoot, "mcp.json"), "seed_mcp", { mcpServers: {} }));
|
|
7009
7479
|
const overlay = record5(readJsonFile2(join12(overlayRoot, "mcp.json"), "overlay_mcp", { mcpServers: {} }));
|
|
@@ -7068,6 +7538,8 @@ function materializeTrustedPiRuntimeProfile(input) {
|
|
|
7068
7538
|
if (existsSync11(source)) copyTreeNoLinks(source, target);
|
|
7069
7539
|
}
|
|
7070
7540
|
}
|
|
7541
|
+
const skillProfile = typeof input.skillProfile === "string" && input.skillProfile.trim() ? input.skillProfile.trim() : null;
|
|
7542
|
+
const enabledSkills = skillProfile ? materializeRoleSkills(seedRoot, agentDir, skillProfile) : [];
|
|
7071
7543
|
const mergedJson = {};
|
|
7072
7544
|
for (const entry of JSON_ENTRIES) {
|
|
7073
7545
|
const seed = readJsonFile2(join12(seedRoot, entry), `seed_${entry}`, {});
|
|
@@ -7082,6 +7554,13 @@ function materializeTrustedPiRuntimeProfile(input) {
|
|
|
7082
7554
|
allowSessionGrants: false
|
|
7083
7555
|
}
|
|
7084
7556
|
};
|
|
7557
|
+
if (skillProfile) {
|
|
7558
|
+
const current = Array.isArray(merged.skills) ? merged.skills : [];
|
|
7559
|
+
merged.skills = [
|
|
7560
|
+
ROLE_SKILLS_DIR,
|
|
7561
|
+
...current.filter((value) => value !== ROLE_SKILLS_DIR)
|
|
7562
|
+
];
|
|
7563
|
+
}
|
|
7085
7564
|
}
|
|
7086
7565
|
assertNoPersistentSecrets(merged, [entry]);
|
|
7087
7566
|
writeFileSync8(join12(agentDir, entry), `${JSON.stringify(merged, null, 2)}
|
|
@@ -7113,11 +7592,17 @@ function materializeTrustedPiRuntimeProfile(input) {
|
|
|
7113
7592
|
runtimeEnforcementDigest: input.verifiedAssertion.digests.runtimeEnforcementDigest,
|
|
7114
7593
|
unknownToolMode: input.verifiedAssertion.unknownToolMode,
|
|
7115
7594
|
directToolBudget: input.verifiedAssertion.directToolBudget,
|
|
7116
|
-
inheritedEntries: [...COPY_ENTRIES, ...JSON_ENTRIES, "mcp.json", "npm"]
|
|
7595
|
+
inheritedEntries: [...COPY_ENTRIES, ...JSON_ENTRIES, "mcp.json", "npm"],
|
|
7596
|
+
// What the model can actually see this run: which profile and which exact
|
|
7597
|
+
// bundle skills were enabled. Absent profile => main skills only.
|
|
7598
|
+
...skillProfile ? {
|
|
7599
|
+
skillProfile,
|
|
7600
|
+
enabledSkillsDigest: createHash8("sha256").update(JSON.stringify(enabledSkills)).digest("hex")
|
|
7601
|
+
} : {}
|
|
7117
7602
|
};
|
|
7118
7603
|
return {
|
|
7119
7604
|
facts,
|
|
7120
|
-
attestationId:
|
|
7605
|
+
attestationId: createHash8("sha256").update(JSON.stringify(facts)).digest("hex")
|
|
7121
7606
|
};
|
|
7122
7607
|
}
|
|
7123
7608
|
function assertAuditArgsRedacted(value) {
|
|
@@ -7313,7 +7798,7 @@ function verifyTrustedPiRuntimeAssertion(input) {
|
|
|
7313
7798
|
if (hasSourceAssertion) {
|
|
7314
7799
|
const exactTools = Array.isArray(record5(sourceProfile.tools).exactAllowlist) ? record5(sourceProfile.tools).exactAllowlist : [];
|
|
7315
7800
|
const exactActions = Array.isArray(record5(sourceProfile.actions).exactAllowlist) ? record5(sourceProfile.actions).exactAllowlist : [];
|
|
7316
|
-
const profileHash =
|
|
7801
|
+
const profileHash = createHash8("sha256").update(JSON.stringify(sourceProfile)).digest("hex");
|
|
7317
7802
|
if (assertion.unknownToolMode !== "deny" || maxCalls !== 0 || sourceAssertion.profileVersion !== sourceProfile.purpose || sourceAssertion.profileHash !== profileHash || sourceAssertion.retentionVersion !== sourceProfile.retention || JSON.stringify(sourceAssertion.exactTools) !== JSON.stringify(exactTools) || JSON.stringify(sourceAssertion.exactActions) !== JSON.stringify(exactActions) || sourceAssertion.sourceId !== sourceProfile.sourceId || sourceAssertion.sourceRevisionId !== sourceProfile.sourceRevisionId || sourceAssertion.sourceRevision !== sourceProfile.sourceRevision || sourceAssertion.attemptId !== sourceProfile.attemptId || sourceAssertion.epoch !== sourceProfile.epoch) {
|
|
7318
7803
|
throw new Error("pi_trusted_runtime_assertion_binding_mismatch:sourceAcquisition");
|
|
7319
7804
|
}
|
|
@@ -7342,7 +7827,7 @@ function verifyTrustedPiRuntimeAssertion(input) {
|
|
|
7342
7827
|
|
|
7343
7828
|
// src/amaster-runtime-daemon/workspace-status.mjs
|
|
7344
7829
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
7345
|
-
import { createHash as
|
|
7830
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
7346
7831
|
import { existsSync as existsSync12, readdirSync as readdirSync8, readFileSync as readFileSync10, statSync as statSync6 } from "node:fs";
|
|
7347
7832
|
import { basename as basename5, extname, isAbsolute as isAbsolute7, join as join13, relative as relative7, resolve as resolve10 } from "node:path";
|
|
7348
7833
|
var WORKSPACE_RUNTIME_SERVICES_FILENAME = ".amaster-runtime-services.json";
|
|
@@ -7414,7 +7899,7 @@ function sanitizeTrackedChange(line) {
|
|
|
7414
7899
|
return isSafeRelativePath(path) ? line : null;
|
|
7415
7900
|
}
|
|
7416
7901
|
function sha256File2(filePath) {
|
|
7417
|
-
return
|
|
7902
|
+
return createHash9("sha256").update(readFileSync10(filePath)).digest("hex");
|
|
7418
7903
|
}
|
|
7419
7904
|
function artifactHashCacheKey(relativePath, stat) {
|
|
7420
7905
|
return `${relativePath}\0${stat.size}\0${stat.mtimeMs}`;
|
|
@@ -7615,7 +8100,7 @@ function readWorkspaceStatus(cwd, opts = {}) {
|
|
|
7615
8100
|
}
|
|
7616
8101
|
|
|
7617
8102
|
// src/amaster-runtime-daemon/pi-browser-session-adapter.mjs
|
|
7618
|
-
import { createHash as
|
|
8103
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
7619
8104
|
import { spawn, spawnSync as spawnSync5 } from "node:child_process";
|
|
7620
8105
|
import { existsSync as existsSync13 } from "node:fs";
|
|
7621
8106
|
import {
|
|
@@ -7738,7 +8223,7 @@ function fail(code) {
|
|
|
7738
8223
|
throw Object.assign(new Error(code), { code });
|
|
7739
8224
|
}
|
|
7740
8225
|
function profileName(identity2) {
|
|
7741
|
-
return
|
|
8226
|
+
return createHash10("sha256").update(`${identity2.companyId}\0${identity2.bindingId}\0${identity2.localOpaqueRef}`).digest("hex");
|
|
7742
8227
|
}
|
|
7743
8228
|
function expectedMarker(identity2) {
|
|
7744
8229
|
return {
|
|
@@ -8137,7 +8622,7 @@ async function executeBrowserSessionCommand(command, dependencies = {}) {
|
|
|
8137
8622
|
}
|
|
8138
8623
|
|
|
8139
8624
|
// src/amaster-runtime-daemon/source-acquisition-invocation.mjs
|
|
8140
|
-
import { createHash as
|
|
8625
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
8141
8626
|
var SOURCE_ACQUISITION_PUBLIC_TOOLS = Object.freeze([
|
|
8142
8627
|
"source_open",
|
|
8143
8628
|
"source_snapshot",
|
|
@@ -8174,7 +8659,7 @@ function serializeSourceAcquisitionProfile(profile) {
|
|
|
8174
8659
|
const input = Buffer.from(JSON.stringify(profile), "utf8");
|
|
8175
8660
|
return {
|
|
8176
8661
|
input,
|
|
8177
|
-
sha256:
|
|
8662
|
+
sha256: createHash11("sha256").update(input).digest("hex")
|
|
8178
8663
|
};
|
|
8179
8664
|
}
|
|
8180
8665
|
function sourceAcquisitionManagedInputs(options) {
|
|
@@ -8210,7 +8695,7 @@ function assertSourceAcquisitionRuntimeAuthority({
|
|
|
8210
8695
|
}
|
|
8211
8696
|
|
|
8212
8697
|
// src/amaster-runtime-daemon.mjs
|
|
8213
|
-
var CONNECTOR_VERSION = "0.1.1-beta.
|
|
8698
|
+
var CONNECTOR_VERSION = "0.1.1-beta.4";
|
|
8214
8699
|
var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
|
|
8215
8700
|
var SOURCE_ACQUISITION_CAPABILITY = "source_acquisition_v1";
|
|
8216
8701
|
var SOURCE_ACQUISITION_PROFILE_VERSION = "source_acquisition_v1";
|
|
@@ -8934,9 +9419,7 @@ function readPiAgentLocalPlatformCredential(credentialsDir) {
|
|
|
8934
9419
|
return {
|
|
8935
9420
|
organizationId,
|
|
8936
9421
|
apiKey,
|
|
8937
|
-
...readString(credential.baseUrl) ? { baseUrl: readString(credential.baseUrl) } : {}
|
|
8938
|
-
...readString(credential.defaultModel) ? { defaultModel: readString(credential.defaultModel) } : {},
|
|
8939
|
-
...readString(credential.flashModel) ? { flashModel: readString(credential.flashModel) } : {}
|
|
9422
|
+
...readString(credential.baseUrl) ? { baseUrl: readString(credential.baseUrl) } : {}
|
|
8940
9423
|
};
|
|
8941
9424
|
}
|
|
8942
9425
|
function piAgentLocalPlatformCredentials(config) {
|
|
@@ -9509,7 +9992,7 @@ function sourceAcquisitionRuntimeProfile(config, command) {
|
|
|
9509
9992
|
if (!companyId || !bindingId || !/^profile_[a-z0-9]{16,64}$/i.test(localOpaqueRef ?? "")) {
|
|
9510
9993
|
throw new Error("source_acquisition_profile_invalid");
|
|
9511
9994
|
}
|
|
9512
|
-
const profileName2 =
|
|
9995
|
+
const profileName2 = createHash12("sha256").update(`${companyId}\0${bindingId}\0${localOpaqueRef}`).digest("hex");
|
|
9513
9996
|
const stateRoot = resolve12(config.browserSessionStateRoot);
|
|
9514
9997
|
const userDataDir = resolve12(stateRoot, profileName2);
|
|
9515
9998
|
if (!pathWithin2(userDataDir, stateRoot)) throw new Error("source_acquisition_browser_profile_invalid");
|
|
@@ -9557,9 +10040,7 @@ async function syncPiExecutorProviderConfig(config, command, agentDir, resolvedP
|
|
|
9557
10040
|
modelsSynced,
|
|
9558
10041
|
settingsSynced,
|
|
9559
10042
|
credentialSource,
|
|
9560
|
-
providerBaseUrlConfigured: Boolean(readString(providerConfig.AMASTER_PROVIDER_BASE_URL))
|
|
9561
|
-
defaultModelConfigured: Boolean(readString(providerConfig.AMASTER_PROVIDER_DEFAULT_MODEL)),
|
|
9562
|
-
flashModelConfigured: Boolean(readString(providerConfig.AMASTER_PROVIDER_FLASH_MODEL))
|
|
10043
|
+
providerBaseUrlConfigured: Boolean(readString(providerConfig.AMASTER_PROVIDER_BASE_URL))
|
|
9563
10044
|
});
|
|
9564
10045
|
}
|
|
9565
10046
|
}
|
|
@@ -9573,9 +10054,7 @@ function piAgentLocalPlatformCredentialForCommand(config, command) {
|
|
|
9573
10054
|
if (!credential) return null;
|
|
9574
10055
|
return {
|
|
9575
10056
|
AMASTER_API_KEY: credential.apiKey,
|
|
9576
|
-
...credential.baseUrl ? { AMASTER_PROVIDER_BASE_URL: credential.baseUrl } : {}
|
|
9577
|
-
...credential.defaultModel ? { AMASTER_PROVIDER_DEFAULT_MODEL: credential.defaultModel } : {},
|
|
9578
|
-
...credential.flashModel ? { AMASTER_PROVIDER_FLASH_MODEL: credential.flashModel } : {}
|
|
10057
|
+
...credential.baseUrl ? { AMASTER_PROVIDER_BASE_URL: credential.baseUrl } : {}
|
|
9579
10058
|
};
|
|
9580
10059
|
}
|
|
9581
10060
|
function normalizeWorkspaceContext(workspace) {
|
|
@@ -9710,6 +10189,7 @@ function buildCommandPrompt(command, workspace, materializedAttachments = [], op
|
|
|
9710
10189
|
hasGovernedMcp,
|
|
9711
10190
|
executorKind: options.executorKind,
|
|
9712
10191
|
managedMcpToolMode: options.managedMcpToolMode,
|
|
10192
|
+
managedMcpToolCatalog: options.managedMcpToolCatalog,
|
|
9713
10193
|
agentInstructions,
|
|
9714
10194
|
taskMarkdown,
|
|
9715
10195
|
attachmentsText,
|
|
@@ -12242,7 +12722,7 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
12242
12722
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
12243
12723
|
writeFileSync9(targetPath, body);
|
|
12244
12724
|
const attachmentId = readString(attachment.id);
|
|
12245
|
-
const actualSha256 =
|
|
12725
|
+
const actualSha256 = createHash12("sha256").update(body).digest("hex");
|
|
12246
12726
|
const lineageCandidates = lineageCandidatesByAttachmentId.get(attachmentId) ?? [];
|
|
12247
12727
|
const lineage = selectAttachmentLineage(lineageCandidates, actualSha256);
|
|
12248
12728
|
if (lineageCandidates.length > 0 && !lineage) {
|
|
@@ -12334,7 +12814,7 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
12334
12814
|
throw new Error(`artifact_input_manifest_invalid: entry ${index} contentPath does not match attachmentId`);
|
|
12335
12815
|
}
|
|
12336
12816
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
12337
|
-
const actualSha256 =
|
|
12817
|
+
const actualSha256 = createHash12("sha256").update(body).digest("hex");
|
|
12338
12818
|
if (body.byteLength !== byteSize || actualSha256 !== sha256) {
|
|
12339
12819
|
throw new Error(
|
|
12340
12820
|
`artifact_input_integrity_mismatch: workProductId=${workProductId} expectedBytes=${byteSize} actualBytes=${body.byteLength} expectedSha256=${sha256} actualSha256=${actualSha256}`
|
|
@@ -12404,7 +12884,7 @@ function safeCheckpointRelativePath(rawPath) {
|
|
|
12404
12884
|
return normalized;
|
|
12405
12885
|
}
|
|
12406
12886
|
function hashFileSha256(filePath) {
|
|
12407
|
-
return
|
|
12887
|
+
return createHash12("sha256").update(readFileSync11(filePath)).digest("hex");
|
|
12408
12888
|
}
|
|
12409
12889
|
async function materializeIssueCheckpoint(config, command, workspace) {
|
|
12410
12890
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
@@ -12590,7 +13070,8 @@ async function executeRunCommand(config, command) {
|
|
|
12590
13070
|
await ingestWorkspaceStatus(config, command, cwd);
|
|
12591
13071
|
const promptCompilation = buildCommandPrompt(command, workspace, materializedAttachments, {
|
|
12592
13072
|
executorKind: executor.kind,
|
|
12593
|
-
managedMcpToolMode: executor.kind === "pi" && Object.keys(governedMcp).length > 0 ? MANAGED_PI_MCP_TOOL_MODE : null,
|
|
13073
|
+
managedMcpToolMode: executor.kind === "pi" && Object.keys(governedMcp).length > 0 ? readString(governedMcp.mcpToolMode) ?? MANAGED_PI_MCP_TOOL_MODE : null,
|
|
13074
|
+
managedMcpToolCatalog: asRecord(governedMcp.toolCatalog),
|
|
12594
13075
|
artifactVerifierCommands: config.artifactVerifierCommands,
|
|
12595
13076
|
workspaceBindings: config.workspaceBindings
|
|
12596
13077
|
});
|
|
@@ -12647,8 +13128,6 @@ async function executeRunCommand(config, command) {
|
|
|
12647
13128
|
if (piAgentLocalPlatformRunnerEnabled(config)) {
|
|
12648
13129
|
delete executorEnv.AMASTER_API_KEY;
|
|
12649
13130
|
delete executorEnv.AMASTER_PROVIDER_BASE_URL;
|
|
12650
|
-
delete executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL;
|
|
12651
|
-
delete executorEnv.AMASTER_PROVIDER_FLASH_MODEL;
|
|
12652
13131
|
}
|
|
12653
13132
|
piResolvedProviderConfig = resolvePiExecutorProviderConfig(config, command, executorEnv);
|
|
12654
13133
|
for (const envName of ["AMASTER_API_KEY", "AMASTER_PLATFORM_OAUTH_TOKEN"]) {
|
|
@@ -12715,7 +13194,8 @@ async function executeRunCommand(config, command) {
|
|
|
12715
13194
|
profileRoot: managedMcpProfile.profileRoot,
|
|
12716
13195
|
agentDir: managedMcpProfile.env.PI_CODING_AGENT_DIR,
|
|
12717
13196
|
governedMcpConfigPath: managedMcpProfile.configPath,
|
|
12718
|
-
verifiedAssertion: trustedPiRuntime
|
|
13197
|
+
verifiedAssertion: trustedPiRuntime,
|
|
13198
|
+
skillProfile: readString(asRecord(command.payload).skillProfile)
|
|
12719
13199
|
});
|
|
12720
13200
|
executorEnv = {
|
|
12721
13201
|
...executorEnv,
|
package/dist/amaster-runtime.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { dirname, join, resolve } from "node:path";
|
|
|
5
5
|
import { homedir, hostname } from "node:os";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
|
|
8
|
-
const CONNECTOR_VERSION = "0.1.1-beta.
|
|
8
|
+
const CONNECTOR_VERSION = "0.1.1-beta.4";
|
|
9
9
|
|
|
10
10
|
const CAPABILITIES = [
|
|
11
11
|
"remote_registration",
|