@amaster.ai/employee-runtime-connector 0.1.1-beta.15 → 0.1.1-beta.17
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 +250 -143
- package/dist/amaster-runtime.mjs +1 -1
- package/package.json +1 -1
|
@@ -1913,12 +1913,12 @@ function syncAmasterProviderSettings(agentDir, executorEnv) {
|
|
|
1913
1913
|
const settings = readJsonFile(settingsPath);
|
|
1914
1914
|
const baseUrl = readString(executorEnv.AMASTER_PROVIDER_BASE_URL);
|
|
1915
1915
|
const imageGenBaseUrl = imageGenBaseUrlFromProviderBaseUrl(baseUrl);
|
|
1916
|
+
const managedApiKey = managedApiKeyConfigValue(executorEnv, apiKey);
|
|
1916
1917
|
let changed = false;
|
|
1917
1918
|
const imageGen = settings["pi-image-gen"];
|
|
1918
1919
|
if (isRecord(imageGen) && isRecord(imageGen.customProviders) && isRecord(imageGen.customProviders.amaster)) {
|
|
1919
1920
|
const customProviders = imageGen.customProviders;
|
|
1920
1921
|
const imageGenAmaster = { ...asRecord(customProviders.amaster) };
|
|
1921
|
-
const managedApiKey = managedApiKeyConfigValue(executorEnv, apiKey);
|
|
1922
1922
|
if (imageGenAmaster.apiKey !== managedApiKey) {
|
|
1923
1923
|
imageGenAmaster.apiKey = managedApiKey;
|
|
1924
1924
|
changed = true;
|
|
@@ -1941,6 +1941,32 @@ function syncAmasterProviderSettings(agentDir, executorEnv) {
|
|
|
1941
1941
|
}
|
|
1942
1942
|
};
|
|
1943
1943
|
}
|
|
1944
|
+
const videoGen = settings["pi-video-gen"];
|
|
1945
|
+
if (isRecord(videoGen) && isRecord(videoGen.customProviders) && isRecord(videoGen.customProviders.newapi)) {
|
|
1946
|
+
const customProviders = videoGen.customProviders;
|
|
1947
|
+
const videoGenNewapi = { ...asRecord(customProviders.newapi) };
|
|
1948
|
+
if (videoGenNewapi.apiKey !== managedApiKey) {
|
|
1949
|
+
videoGenNewapi.apiKey = managedApiKey;
|
|
1950
|
+
changed = true;
|
|
1951
|
+
}
|
|
1952
|
+
if (baseUrl && videoGenNewapi.baseUrl !== baseUrl) {
|
|
1953
|
+
videoGenNewapi.baseUrl = baseUrl;
|
|
1954
|
+
changed = true;
|
|
1955
|
+
}
|
|
1956
|
+
const videoGenHeaders = syncManagedBillingHeaders(videoGenNewapi.headers, executorEnv);
|
|
1957
|
+
if (JSON.stringify(videoGenHeaders) !== JSON.stringify(videoGenNewapi.headers)) {
|
|
1958
|
+
if (videoGenHeaders) videoGenNewapi.headers = videoGenHeaders;
|
|
1959
|
+
else delete videoGenNewapi.headers;
|
|
1960
|
+
changed = true;
|
|
1961
|
+
}
|
|
1962
|
+
settings["pi-video-gen"] = {
|
|
1963
|
+
...asRecord(videoGen),
|
|
1964
|
+
customProviders: {
|
|
1965
|
+
...customProviders,
|
|
1966
|
+
newapi: videoGenNewapi
|
|
1967
|
+
}
|
|
1968
|
+
};
|
|
1969
|
+
}
|
|
1944
1970
|
const webAccess = settings["pi-web-access"];
|
|
1945
1971
|
if (isRecord(webAccess) && isRecord(webAccess.providers)) {
|
|
1946
1972
|
const webProviders = webAccess.providers;
|
|
@@ -2317,6 +2343,10 @@ export default function amasterEffectiveToolsAttestor(pi) {
|
|
|
2317
2343
|
|
|
2318
2344
|
const expectedEntries = Array.isArray(manifest.entries) ? manifest.entries : [];
|
|
2319
2345
|
if (expectedEntries.length === 0) throw new Error("effective tool manifest is empty");
|
|
2346
|
+
const proxyMode = manifest.proxyMode ?? "forbidden";
|
|
2347
|
+
if (proxyMode !== "required" && proxyMode !== "forbidden") {
|
|
2348
|
+
throw new Error("effective tool proxy mode is invalid");
|
|
2349
|
+
}
|
|
2320
2350
|
const expectedByName = new Map(expectedEntries.map((entry) => [entry.name, entry]));
|
|
2321
2351
|
if (expectedByName.size !== expectedEntries.length) throw new Error("effective tool manifest has duplicate names");
|
|
2322
2352
|
for (const entry of expectedEntries) {
|
|
@@ -2337,7 +2367,8 @@ export default function amasterEffectiveToolsAttestor(pi) {
|
|
|
2337
2367
|
activeToolNames.sort();
|
|
2338
2368
|
const activeToolNameSet = new Set(activeToolNames);
|
|
2339
2369
|
const proxyPresent = allTools.some((tool) => tool.name === "mcp");
|
|
2340
|
-
|
|
2370
|
+
// Hybrid keeps Pi builtins active, so catalog drift applies only to adapter tools;
|
|
2371
|
+
// direct_typed constrains the complete active surface separately via toolAllowlist.
|
|
2341
2372
|
const adapterTools = allTools.filter((tool) => sourceIsMcpAdapter(tool.sourceInfo));
|
|
2342
2373
|
const directTools = adapterTools.filter((tool) => tool.name !== "mcp" && activeToolNameSet.has(tool.name)).map((tool) => ({
|
|
2343
2374
|
name: tool.name,
|
|
@@ -2356,14 +2387,16 @@ export default function amasterEffectiveToolsAttestor(pi) {
|
|
|
2356
2387
|
: [];
|
|
2357
2388
|
});
|
|
2358
2389
|
const effectiveSetHash = toolSetHash(directTools);
|
|
2359
|
-
|
|
2360
|
-
|
|
2390
|
+
const proxyMismatch = proxyMode === "required" ? !proxyPresent : proxyPresent;
|
|
2391
|
+
if (proxyMismatch || missing.length > 0 || unexpected.length > 0 || schemaMismatches.length > 0) {
|
|
2392
|
+
throw new Error("effective tool surface mismatch: proxyMode=" + proxyMode + " proxy=" + proxyPresent + " missing=" + missing.join(",") + " unexpected=" + unexpected.join(",") + " schemas=" + schemaMismatches.map((entry) => entry.name).join(","));
|
|
2361
2393
|
}
|
|
2362
2394
|
if (effectiveSetHash !== manifest.effectiveSetHash) throw new Error("effective tool set hash mismatch");
|
|
2363
2395
|
receipt = {
|
|
2364
2396
|
schemaVersion: SCHEMA_VERSION,
|
|
2365
2397
|
status: "attested",
|
|
2366
2398
|
mode,
|
|
2399
|
+
proxyMode,
|
|
2367
2400
|
proxyPresent,
|
|
2368
2401
|
effectiveSetHash,
|
|
2369
2402
|
effectiveTools: directTools.sort((left, right) => left.name.localeCompare(right.name)),
|
|
@@ -2409,6 +2442,7 @@ export default function amasterEffectiveToolsAttestor(pi) {
|
|
|
2409
2442
|
|
|
2410
2443
|
// src/amaster-runtime-daemon/pi-managed-mcp-profile.mjs
|
|
2411
2444
|
var MANAGED_PI_MCP_TOOL_MODE = "proxy_only";
|
|
2445
|
+
var MANAGED_PI_HYBRID_MCP_TOOL_MODE = "hybrid";
|
|
2412
2446
|
var MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE = "direct_typed";
|
|
2413
2447
|
var MANAGED_PI_MCP_ARGS_NORMALIZATION = "json_string_control_characters_v1";
|
|
2414
2448
|
var MANAGED_PI_MCP_ARGS_NORMALIZER_FILENAME = "amaster-mcp-args-normalizer.js";
|
|
@@ -2435,35 +2469,18 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2435
2469
|
"amaster.read_company_diagnosis",
|
|
2436
2470
|
"amaster.publish_company_diagnosis_brief"
|
|
2437
2471
|
]);
|
|
2472
|
+
const HYBRID_DIRECT_TYPED_V1_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
2473
|
+
"amaster.read_company_snapshot",
|
|
2474
|
+
"runtime_action.describe",
|
|
2475
|
+
"amaster.read_issue_document",
|
|
2476
|
+
"amaster.read_issue_evidence"
|
|
2477
|
+
]);
|
|
2438
2478
|
const PROVIDER_SAFE_TOOL_NAME = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
2439
2479
|
const PI_BUILTIN_TOOL_NAMES = /* @__PURE__ */ new Set(["read", "bash", "edit", "write", "grep", "find", "ls", "mcp"]);
|
|
2440
2480
|
const MINIMUM_PI_VERSION = [0, 73, 1];
|
|
2441
2481
|
const MINIMUM_MCP_ADAPTER_VERSION = [2, 6, 1];
|
|
2442
2482
|
const MANAGED_BROWSER_USE_PACKAGE = "@amaster.ai/pi-browser-use";
|
|
2443
2483
|
const MANAGED_BROWSER_USE_PLUGIN = "browser-use";
|
|
2444
|
-
const MANAGED_WEB_ACCESS_PACKAGE = "@amaster.ai/pi-web-access";
|
|
2445
|
-
const MANAGED_TELEMETRY_PACKAGE = "@amaster.ai/pi-telemetry";
|
|
2446
|
-
const MANAGED_TELEMETRY_ENV_NAMES = [
|
|
2447
|
-
"PI_TELEMETRY_TASK_RUN_ID",
|
|
2448
|
-
"PI_TELEMETRY_SERVICE_NAME",
|
|
2449
|
-
"PI_TELEMETRY_SERVICE_VERSION",
|
|
2450
|
-
"PI_TELEMETRY_INCLUDE_PAYLOADS",
|
|
2451
|
-
"PI_TELEMETRY_LANGFUSE_ENABLED",
|
|
2452
|
-
"PI_TELEMETRY_LANGFUSE_PUBLIC_KEY",
|
|
2453
|
-
"PI_TELEMETRY_LANGFUSE_SECRET_KEY",
|
|
2454
|
-
"PI_TELEMETRY_LANGFUSE_BASE_URL",
|
|
2455
|
-
"PI_TELEMETRY_LANGFUSE_FLUSH_AT",
|
|
2456
|
-
"PI_TELEMETRY_LANGFUSE_FLUSH_INTERVAL_MS",
|
|
2457
|
-
"PI_TELEMETRY_OTEL_ENABLED",
|
|
2458
|
-
"PI_TELEMETRY_OTEL_ENDPOINT",
|
|
2459
|
-
"PI_TELEMETRY_OTEL_HEADERS",
|
|
2460
|
-
"PI_TELEMETRY_OTEL_FLUSH_AT",
|
|
2461
|
-
"PI_TELEMETRY_OTEL_FLUSH_INTERVAL_MS"
|
|
2462
|
-
];
|
|
2463
|
-
const MANAGED_TELEMETRY_PROTECTED_ENV_NAMES = [
|
|
2464
|
-
"PI_TELEMETRY_LANGFUSE_SECRET_KEY",
|
|
2465
|
-
"PI_TELEMETRY_OTEL_HEADERS"
|
|
2466
|
-
];
|
|
2467
2484
|
const MANAGED_BROWSER_USE_BOOLEAN_SETTINGS = [
|
|
2468
2485
|
"headless",
|
|
2469
2486
|
"categoryNetwork",
|
|
@@ -2490,6 +2507,12 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2490
2507
|
"AMASTER-CLI_CODING_AGENT_SESSION_DIR",
|
|
2491
2508
|
"PI_AGENT_MCP_SERVERS_FILE"
|
|
2492
2509
|
]);
|
|
2510
|
+
const RUN_OWNED_SETTINGS_ENV = /* @__PURE__ */ new Set([
|
|
2511
|
+
...FORBIDDEN_COMMAND_ENV2,
|
|
2512
|
+
"MCP_DIRECT_TOOLS",
|
|
2513
|
+
"PAPERCLIP_API_KEY",
|
|
2514
|
+
"AMASTER_BOARD_API_KEY"
|
|
2515
|
+
]);
|
|
2493
2516
|
const ALLOWED_COMMAND_ENV2 = new Set(MANAGED_PI_PROVIDER_ENV_NAMES);
|
|
2494
2517
|
const SAFE_INHERITED_ENV2 = /* @__PURE__ */ new Set([
|
|
2495
2518
|
"PATH",
|
|
@@ -2515,8 +2538,7 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2515
2538
|
"PAPERCLIP_TASK_ID",
|
|
2516
2539
|
"PAPERCLIP_AGENT_ID",
|
|
2517
2540
|
"PAPERCLIP_COMPANY_ID",
|
|
2518
|
-
"AMASTER_EMPLOYEE_COMPANY_ID"
|
|
2519
|
-
...MANAGED_TELEMETRY_ENV_NAMES
|
|
2541
|
+
"AMASTER_EMPLOYEE_COMPANY_ID"
|
|
2520
2542
|
]);
|
|
2521
2543
|
const FORBIDDEN_ARGV = /* @__PURE__ */ new Set([
|
|
2522
2544
|
"--no-tools",
|
|
@@ -2685,20 +2707,21 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2685
2707
|
excludeTools: definition.excludeTools
|
|
2686
2708
|
}));
|
|
2687
2709
|
}
|
|
2688
|
-
function validateDirectCatalog(gateway) {
|
|
2710
|
+
function validateDirectCatalog(gateway, mcpToolMode) {
|
|
2689
2711
|
const catalog = record8(gateway.toolCatalog);
|
|
2690
2712
|
if (catalog.schemaVersion !== DIRECT_CATALOG_SCHEMA_VERSION) {
|
|
2691
2713
|
throw new Error("pi_managed_mcp_invalid: direct tool catalog schema mismatch");
|
|
2692
2714
|
}
|
|
2693
2715
|
const tools = Array.isArray(catalog.tools) ? catalog.tools.map(record8) : [];
|
|
2694
|
-
|
|
2716
|
+
const admittedToolNames = mcpToolMode === MANAGED_PI_HYBRID_MCP_TOOL_MODE ? HYBRID_DIRECT_TYPED_V1_TOOL_NAMES : DIRECT_TYPED_V1_TOOL_NAMES;
|
|
2717
|
+
if (tools.length !== admittedToolNames.size) {
|
|
2695
2718
|
throw new Error("pi_managed_mcp_invalid: direct tool catalog size mismatch");
|
|
2696
2719
|
}
|
|
2697
2720
|
const names = /* @__PURE__ */ new Set();
|
|
2698
2721
|
const exposedNames = /* @__PURE__ */ new Set();
|
|
2699
2722
|
const normalized = tools.map((tool) => {
|
|
2700
2723
|
const name = nonEmpty2(tool.name, "toolCatalog.tools.name");
|
|
2701
|
-
if (!
|
|
2724
|
+
if (!admittedToolNames.has(name) || names.has(name)) {
|
|
2702
2725
|
throw new Error("pi_managed_mcp_invalid: direct tool catalog name mismatch");
|
|
2703
2726
|
}
|
|
2704
2727
|
names.add(name);
|
|
@@ -2722,6 +2745,9 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2722
2745
|
if (!(/* @__PURE__ */ new Set(["read", "write", "destructive"])).has(riskLevel)) {
|
|
2723
2746
|
throw new Error(`pi_managed_mcp_invalid: direct tool risk level mismatch for ${name}`);
|
|
2724
2747
|
}
|
|
2748
|
+
if (mcpToolMode === MANAGED_PI_HYBRID_MCP_TOOL_MODE && riskLevel !== "read") {
|
|
2749
|
+
throw new Error(`pi_managed_mcp_invalid: hybrid direct tool must be read-only for ${name}`);
|
|
2750
|
+
}
|
|
2725
2751
|
return {
|
|
2726
2752
|
name,
|
|
2727
2753
|
exposedName,
|
|
@@ -2729,6 +2755,7 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2729
2755
|
inputSchema,
|
|
2730
2756
|
schemaHash,
|
|
2731
2757
|
riskLevel,
|
|
2758
|
+
// Match the adapter-exposed schema, which omits top-level $schema and additionalProperties.
|
|
2732
2759
|
effectiveSchemaHash: stablePiToolSchemaHash(inputSchema, { adapterNormalized: true })
|
|
2733
2760
|
};
|
|
2734
2761
|
});
|
|
@@ -2818,10 +2845,10 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2818
2845
|
}
|
|
2819
2846
|
if ((runtimeAuth.issueId ?? null) !== (headers["x-amaster-issue-id"] ?? null)) throw new Error("pi_managed_mcp_invalid: issue authority mismatch");
|
|
2820
2847
|
const mcpToolMode = gateway.mcpToolMode ?? MANAGED_PI_MCP_TOOL_MODE;
|
|
2821
|
-
if (mcpToolMode !== MANAGED_PI_MCP_TOOL_MODE && mcpToolMode !== MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE) {
|
|
2848
|
+
if (mcpToolMode !== MANAGED_PI_MCP_TOOL_MODE && mcpToolMode !== MANAGED_PI_HYBRID_MCP_TOOL_MODE && mcpToolMode !== MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE) {
|
|
2822
2849
|
throw new Error("pi_managed_mcp_invalid: unsupported managed Pi MCP tool mode");
|
|
2823
2850
|
}
|
|
2824
|
-
const directCatalog = mcpToolMode
|
|
2851
|
+
const directCatalog = mcpToolMode !== MANAGED_PI_MCP_TOOL_MODE ? validateDirectCatalog(gateway, mcpToolMode) : null;
|
|
2825
2852
|
if (mcpToolMode === MANAGED_PI_MCP_TOOL_MODE && gateway.toolCatalog !== void 0) {
|
|
2826
2853
|
throw new Error("pi_managed_mcp_invalid: proxy-only authority cannot carry a direct tool catalog");
|
|
2827
2854
|
}
|
|
@@ -2832,13 +2859,38 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2832
2859
|
return /^(?:(?:access|refresh|id)_)?token$/.test(normalized) || normalized.includes("api_key") || normalized.includes("secret") || normalized.includes("password") || normalized.includes("credential") || normalized.includes("authorization") || normalized.includes("cookie");
|
|
2833
2860
|
}
|
|
2834
2861
|
function collectAuthSecretStrings2(value, output = []) {
|
|
2835
|
-
if (!value || typeof value !== "object"
|
|
2862
|
+
if (!value || typeof value !== "object") return output;
|
|
2863
|
+
if (Array.isArray(value)) {
|
|
2864
|
+
for (const entry of value) collectAuthSecretStrings2(entry, output);
|
|
2865
|
+
return output;
|
|
2866
|
+
}
|
|
2836
2867
|
for (const [key, entry] of Object.entries(value)) {
|
|
2837
2868
|
if (typeof entry === "string" && entry && isSensitiveAuthKey2(key)) output.push(entry);
|
|
2838
|
-
else if (entry && typeof entry === "object"
|
|
2869
|
+
else if (entry && typeof entry === "object") collectAuthSecretStrings2(entry, output);
|
|
2839
2870
|
}
|
|
2840
2871
|
return output;
|
|
2841
2872
|
}
|
|
2873
|
+
function referencedSettingsEnvironment(settings, baseEnv) {
|
|
2874
|
+
const names = /* @__PURE__ */ new Set();
|
|
2875
|
+
const visit = (value) => {
|
|
2876
|
+
if (typeof value === "string") {
|
|
2877
|
+
for (const match of value.matchAll(/\$(?:\{([A-Za-z_][A-Za-z0-9_]*)(?::-[^}]*)?\}|([A-Za-z_][A-Za-z0-9_]*))/g)) {
|
|
2878
|
+
names.add(match[1] ?? match[2]);
|
|
2879
|
+
}
|
|
2880
|
+
} else if (Array.isArray(value)) {
|
|
2881
|
+
for (const entry of value) visit(entry);
|
|
2882
|
+
} else if (value && typeof value === "object") {
|
|
2883
|
+
for (const entry of Object.values(value)) visit(entry);
|
|
2884
|
+
}
|
|
2885
|
+
};
|
|
2886
|
+
visit(settings);
|
|
2887
|
+
const env = {};
|
|
2888
|
+
for (const name of names) {
|
|
2889
|
+
if (RUN_OWNED_SETTINGS_ENV.has(name)) continue;
|
|
2890
|
+
if (typeof baseEnv?.[name] === "string" && baseEnv[name]) env[name] = baseEnv[name];
|
|
2891
|
+
}
|
|
2892
|
+
return env;
|
|
2893
|
+
}
|
|
2842
2894
|
function assertInvocationIsolation2(input) {
|
|
2843
2895
|
for (const name of Object.keys(record8(input.commandEnv))) {
|
|
2844
2896
|
if (FORBIDDEN_COMMAND_ENV2.has(name)) throw new Error(`pi_managed_mcp_env_override_blocked: ${name}`);
|
|
@@ -2948,49 +3000,7 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2948
3000
|
}
|
|
2949
3001
|
};
|
|
2950
3002
|
}
|
|
2951
|
-
function
|
|
2952
|
-
const packageSpec = Array.isArray(sourceSettings.packages) ? sourceSettings.packages.find((entry) => npmPackageName(entry) === MANAGED_WEB_ACCESS_PACKAGE) : null;
|
|
2953
|
-
if (typeof packageSpec !== "string") return null;
|
|
2954
|
-
const packagePath = join4(npmSource, "node_modules", ...MANAGED_WEB_ACCESS_PACKAGE.split("/"), "package.json");
|
|
2955
|
-
if (!existsSync3(packagePath) || lstatSync2(packagePath).isSymbolicLink() || !lstatSync2(packagePath).isFile()) {
|
|
2956
|
-
throw new Error(`pi_managed_mcp_attestation_failed: configured ${MANAGED_WEB_ACCESS_PACKAGE} package is unavailable`);
|
|
2957
|
-
}
|
|
2958
|
-
let packageMetadata;
|
|
2959
|
-
try {
|
|
2960
|
-
packageMetadata = JSON.parse(readFileSync3(packagePath, "utf8"));
|
|
2961
|
-
} catch {
|
|
2962
|
-
throw new Error(`pi_managed_mcp_attestation_failed: configured ${MANAGED_WEB_ACCESS_PACKAGE} package metadata is invalid`);
|
|
2963
|
-
}
|
|
2964
|
-
if (!packageMetadata || packageMetadata.name !== MANAGED_WEB_ACCESS_PACKAGE) {
|
|
2965
|
-
throw new Error(`pi_managed_mcp_attestation_failed: configured ${MANAGED_WEB_ACCESS_PACKAGE} package identity mismatch`);
|
|
2966
|
-
}
|
|
2967
|
-
return {
|
|
2968
|
-
packageSpec,
|
|
2969
|
-
config: record8(sourceSettings["pi-web-access"])
|
|
2970
|
-
};
|
|
2971
|
-
}
|
|
2972
|
-
function selectManagedTelemetry(sourceSettings, npmSource) {
|
|
2973
|
-
const packageSpec = Array.isArray(sourceSettings.packages) ? sourceSettings.packages.find((entry) => npmPackageName(entry) === MANAGED_TELEMETRY_PACKAGE) : null;
|
|
2974
|
-
if (typeof packageSpec !== "string") return null;
|
|
2975
|
-
const packagePath = join4(npmSource, "node_modules", ...MANAGED_TELEMETRY_PACKAGE.split("/"), "package.json");
|
|
2976
|
-
if (!existsSync3(packagePath) || lstatSync2(packagePath).isSymbolicLink() || !lstatSync2(packagePath).isFile()) {
|
|
2977
|
-
throw new Error(`pi_managed_mcp_attestation_failed: configured ${MANAGED_TELEMETRY_PACKAGE} package is unavailable`);
|
|
2978
|
-
}
|
|
2979
|
-
let packageMetadata;
|
|
2980
|
-
try {
|
|
2981
|
-
packageMetadata = JSON.parse(readFileSync3(packagePath, "utf8"));
|
|
2982
|
-
} catch {
|
|
2983
|
-
throw new Error(`pi_managed_mcp_attestation_failed: configured ${MANAGED_TELEMETRY_PACKAGE} package metadata is invalid`);
|
|
2984
|
-
}
|
|
2985
|
-
if (packageMetadata.name !== MANAGED_TELEMETRY_PACKAGE) {
|
|
2986
|
-
throw new Error(`pi_managed_mcp_attestation_failed: configured ${MANAGED_TELEMETRY_PACKAGE} package identity mismatch`);
|
|
2987
|
-
}
|
|
2988
|
-
return {
|
|
2989
|
-
packageSpec,
|
|
2990
|
-
config: record8(sourceSettings["pi-telemetry"])
|
|
2991
|
-
};
|
|
2992
|
-
}
|
|
2993
|
-
function seedPiRuntime(sourceHome, agentDir, sourceAcquisition = null, mcpToolMode = MANAGED_PI_MCP_TOOL_MODE) {
|
|
3003
|
+
function seedPiRuntime(sourceHome, agentDir, sourceAcquisition = null, mcpToolMode = MANAGED_PI_MCP_TOOL_MODE, baseEnv = {}) {
|
|
2994
3004
|
const source = resolve2(nonEmpty2(sourceHome, "sourcePiHome"));
|
|
2995
3005
|
const sourceStat = lstatSync2(source);
|
|
2996
3006
|
if (!sourceStat.isDirectory() || sourceStat.isSymbolicLink()) {
|
|
@@ -3018,40 +3028,31 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
3018
3028
|
throw new Error("pi_managed_mcp_attestation_failed: source Pi settings are invalid");
|
|
3019
3029
|
}
|
|
3020
3030
|
}
|
|
3021
|
-
const browserUse = selectManagedBrowserUse(sourceSettings, npmSource);
|
|
3022
|
-
const webAccess = sourceAcquisition ? null : selectManagedWebAccess(sourceSettings, npmSource);
|
|
3023
|
-
const telemetry = selectManagedTelemetry(sourceSettings, npmSource);
|
|
3031
|
+
const browserUse = sourceAcquisition ? selectManagedBrowserUse(sourceSettings, npmSource) : null;
|
|
3024
3032
|
if (sourceAcquisition && !browserUse) {
|
|
3025
3033
|
throw new Error("pi_managed_mcp_source_acquisition_packages_missing");
|
|
3026
3034
|
}
|
|
3027
|
-
const
|
|
3035
|
+
const sourcePackages = Array.isArray(sourceSettings.packages) ? [...sourceSettings.packages] : [];
|
|
3036
|
+
const settings = sourceAcquisition ? {
|
|
3028
3037
|
...typeof sourceSettings.defaultProvider === "string" ? { defaultProvider: sourceSettings.defaultProvider } : {},
|
|
3029
3038
|
...typeof sourceSettings.defaultModel === "string" ? { defaultModel: sourceSettings.defaultModel } : {},
|
|
3030
|
-
packages: [
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
...!sourceAcquisition && browserUse ? [browserUse.packageSpec] : []
|
|
3035
|
-
],
|
|
3036
|
-
...telemetry ? { "pi-telemetry": telemetry.config } : {},
|
|
3037
|
-
...webAccess ? { "pi-web-access": webAccess.config } : {},
|
|
3038
|
-
...!sourceAcquisition && browserUse ? {
|
|
3039
|
-
plugins: {
|
|
3040
|
-
[MANAGED_BROWSER_USE_PLUGIN]: browserUse.plugin
|
|
3041
|
-
},
|
|
3042
|
-
"pi-browser-use": browserUse.config
|
|
3043
|
-
} : {}
|
|
3039
|
+
packages: ["npm:pi-mcp-adapter"]
|
|
3040
|
+
} : {
|
|
3041
|
+
...sourceSettings,
|
|
3042
|
+
packages: sourcePackages.some((entry) => npmPackageName(entry) === "pi-mcp-adapter") ? sourcePackages : ["npm:pi-mcp-adapter", ...sourcePackages]
|
|
3044
3043
|
};
|
|
3044
|
+
const settingsEnv = sourceAcquisition ? {} : referencedSettingsEnvironment(settings, baseEnv);
|
|
3045
3045
|
writePrivateFile2(join4(agentDir, "settings.json"), `${JSON.stringify(settings, null, 2)}
|
|
3046
3046
|
`);
|
|
3047
3047
|
const extensionsDir = join4(agentDir, "extensions");
|
|
3048
3048
|
mkdirSync3(extensionsDir, { recursive: true, mode: 448 });
|
|
3049
|
-
if (mcpToolMode
|
|
3049
|
+
if (mcpToolMode !== MANAGED_PI_MCP_TOOL_MODE) {
|
|
3050
3050
|
writePrivateFile2(
|
|
3051
3051
|
join4(extensionsDir, MANAGED_PI_EFFECTIVE_TOOLS_ATTESTOR_FILENAME),
|
|
3052
3052
|
managedPiEffectiveToolsAttestorExtensionSource()
|
|
3053
3053
|
);
|
|
3054
|
-
}
|
|
3054
|
+
}
|
|
3055
|
+
if (mcpToolMode !== MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE) {
|
|
3055
3056
|
writePrivateFile2(
|
|
3056
3057
|
join4(extensionsDir, MANAGED_PI_MCP_ARGS_NORMALIZER_FILENAME),
|
|
3057
3058
|
managedPiMcpArgsNormalizerExtensionSource()
|
|
@@ -3066,7 +3067,10 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
3066
3067
|
copyPrivateFile(join4(source, "models.json"), join4(agentDir, "models.json"));
|
|
3067
3068
|
copyPrivateFile(join4(source, "SYSTEM.md"), join4(agentDir, "SYSTEM.md"));
|
|
3068
3069
|
const authSource = join4(source, "auth.json");
|
|
3069
|
-
const protectedValues =
|
|
3070
|
+
const protectedValues = collectAuthSecretStrings2(settings);
|
|
3071
|
+
for (const [name, value] of Object.entries(settingsEnv)) {
|
|
3072
|
+
if (isSensitiveAuthKey2(name)) protectedValues.push(value);
|
|
3073
|
+
}
|
|
3070
3074
|
if (copyPrivateFile(authSource, join4(agentDir, "auth.json"))) {
|
|
3071
3075
|
try {
|
|
3072
3076
|
collectAuthSecretStrings2(JSON.parse(readFileSync3(authSource, "utf8")), protectedValues);
|
|
@@ -3077,7 +3081,7 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
3077
3081
|
const npmStat = lstatSync2(npmSource);
|
|
3078
3082
|
if (!npmStat.isDirectory() || npmStat.isSymbolicLink()) throw new Error("pi_managed_mcp_source_config_unsafe: Pi npm root");
|
|
3079
3083
|
symlinkSync(npmSource, join4(agentDir, "npm"), "dir");
|
|
3080
|
-
return { adapterVersion, protectedValues };
|
|
3084
|
+
return { adapterVersion, protectedValues, settingsEnv };
|
|
3081
3085
|
}
|
|
3082
3086
|
function seedDelegatedPiRuntime(sourceHome, agentDir) {
|
|
3083
3087
|
const source = resolve2(nonEmpty2(sourceHome, "sourcePiHome"));
|
|
@@ -3215,7 +3219,8 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
3215
3219
|
} catch {
|
|
3216
3220
|
throw new Error("pi_managed_mcp_effective_tools_failed: probe receipt missing");
|
|
3217
3221
|
}
|
|
3218
|
-
|
|
3222
|
+
const expectedProxyPresent = input.proxyMode === "required";
|
|
3223
|
+
if (receipt.status !== "attested" || receipt.mode !== "probe" || receipt.proxyMode !== input.proxyMode || receipt.proxyPresent !== expectedProxyPresent || receipt.effectiveSetHash !== input.effectiveSetHash || receipt.attestorSourceSha256 !== input.attestorSourceSha256 || receipt.configSha256 !== input.configSha256 || receipt.cacheSha256 !== input.cacheSha256) {
|
|
3219
3224
|
throw new Error("pi_managed_mcp_effective_tools_failed: probe receipt mismatch");
|
|
3220
3225
|
}
|
|
3221
3226
|
if (sha256(readFileSync3(input.configPath)) !== input.configSha256) {
|
|
@@ -3225,6 +3230,8 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
3225
3230
|
throw new Error("pi_managed_mcp_effective_tools_failed: cache drifted during probe");
|
|
3226
3231
|
}
|
|
3227
3232
|
return {
|
|
3233
|
+
effectiveToolProxyMode: receipt.proxyMode,
|
|
3234
|
+
effectiveToolProxyPresent: receipt.proxyPresent,
|
|
3228
3235
|
effectiveToolSetHash: receipt.effectiveSetHash,
|
|
3229
3236
|
effectiveToolProbeDigest: sha256(stablePiJson(receipt)),
|
|
3230
3237
|
effectiveToolProbeAt: receipt.attestedAt,
|
|
@@ -3260,7 +3267,13 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
3260
3267
|
commandId: input.commandId
|
|
3261
3268
|
});
|
|
3262
3269
|
const sourcePiHome = nonEmpty2(input.baseEnv?.PI_CODING_AGENT_DIR ?? input.baseEnv?.PI_AGENT_HOME, "sourcePiHome");
|
|
3263
|
-
const seededRuntime = seedPiRuntime(
|
|
3270
|
+
const seededRuntime = seedPiRuntime(
|
|
3271
|
+
sourcePiHome,
|
|
3272
|
+
piCodingAgentDir,
|
|
3273
|
+
input.sourceAcquisition,
|
|
3274
|
+
mcpToolMode,
|
|
3275
|
+
input.baseEnv
|
|
3276
|
+
);
|
|
3264
3277
|
const restoredNativeSession = restoreManagedPiSessionRollout(input, sessionsRoot, runDir, executorHome, authority);
|
|
3265
3278
|
const configPath = join4(piCodingAgentDir, "mcp.json");
|
|
3266
3279
|
const directToolNames = directCatalog?.tools.map((tool) => tool.exposedName) ?? [];
|
|
@@ -3274,7 +3287,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
3274
3287
|
const config = {
|
|
3275
3288
|
settings: {
|
|
3276
3289
|
toolPrefix: "none",
|
|
3277
|
-
...
|
|
3290
|
+
...mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE ? { disableProxyTool: true } : {}
|
|
3278
3291
|
},
|
|
3279
3292
|
mcpServers: {
|
|
3280
3293
|
[SUPPORTED_SERVER_NAME2]: serverConfig
|
|
@@ -3319,6 +3332,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
3319
3332
|
name: tool.exposedName,
|
|
3320
3333
|
schemaHash: tool.effectiveSchemaHash
|
|
3321
3334
|
}))),
|
|
3335
|
+
proxyMode: mcpToolMode === MANAGED_PI_HYBRID_MCP_TOOL_MODE ? "required" : "forbidden",
|
|
3322
3336
|
attestorSourceSha256,
|
|
3323
3337
|
configSha256: sha256(readFileSync3(configPath)),
|
|
3324
3338
|
cacheSha256
|
|
@@ -3333,10 +3347,12 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
3333
3347
|
configPath,
|
|
3334
3348
|
configSha256: sha256(readFileSync3(configPath)),
|
|
3335
3349
|
attestorSourceSha256,
|
|
3336
|
-
effectiveSetHash: manifest.effectiveSetHash
|
|
3350
|
+
effectiveSetHash: manifest.effectiveSetHash,
|
|
3351
|
+
proxyMode: manifest.proxyMode
|
|
3337
3352
|
};
|
|
3338
3353
|
}
|
|
3339
3354
|
const env = {
|
|
3355
|
+
...seededRuntime.settingsEnv,
|
|
3340
3356
|
...buildIsolatedEnvironment2(input.baseEnv, input.commandEnv),
|
|
3341
3357
|
HOME: home,
|
|
3342
3358
|
PI_AGENT_HOME: piAgentHome,
|
|
@@ -3365,7 +3381,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
3365
3381
|
...executorAttestation,
|
|
3366
3382
|
mcpAdapterVersion: seededRuntime.adapterVersion,
|
|
3367
3383
|
mcpToolMode,
|
|
3368
|
-
mcpArgsNormalization:
|
|
3384
|
+
mcpArgsNormalization: mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE ? "none" : MANAGED_PI_MCP_ARGS_NORMALIZATION,
|
|
3369
3385
|
...directCatalog ? {
|
|
3370
3386
|
catalogSetHash: directCatalog.setHash,
|
|
3371
3387
|
...effectiveToolsAttestation
|
|
@@ -3387,11 +3403,10 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
3387
3403
|
configPath,
|
|
3388
3404
|
markerPath,
|
|
3389
3405
|
env,
|
|
3390
|
-
toolAllowlist:
|
|
3406
|
+
toolAllowlist: mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE ? [...directToolNames] : null,
|
|
3391
3407
|
protectedValues: [.../* @__PURE__ */ new Set([
|
|
3392
3408
|
sessionToken,
|
|
3393
3409
|
...seededRuntime.protectedValues,
|
|
3394
|
-
...MANAGED_TELEMETRY_PROTECTED_ENV_NAMES.map((name) => input.baseEnv?.[name]).filter((value) => typeof value === "string" && value.length > 0),
|
|
3395
3410
|
...MANAGED_PI_PROVIDER_PROTECTED_ENV_NAMES.map((name) => input.commandEnv?.[name]).filter((value) => typeof value === "string" && value.length > 0)
|
|
3396
3411
|
])],
|
|
3397
3412
|
attestation: {
|
|
@@ -3408,6 +3423,9 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
3408
3423
|
function prepareDelegatedPiMcpProfile2(input) {
|
|
3409
3424
|
assertInvocationIsolation2(input);
|
|
3410
3425
|
const { gateway, gatewayUrl, sessionToken, headers, runId, mcpToolMode, directCatalog } = validateAuthority2(input);
|
|
3426
|
+
if (mcpToolMode === MANAGED_PI_HYBRID_MCP_TOOL_MODE) {
|
|
3427
|
+
throw new Error("pi_delegated_mcp_hybrid_unsupported: managed effective-tool attestation is required");
|
|
3428
|
+
}
|
|
3411
3429
|
const runDir = resolve2(nonEmpty2(input.runDir, "runDir"));
|
|
3412
3430
|
const cwd = resolve2(nonEmpty2(input.cwd, "cwd"));
|
|
3413
3431
|
if (!within4(cwd, runDir)) throw new Error("pi_delegated_mcp_owner_mismatch: cwd is outside the managed run");
|
|
@@ -3453,7 +3471,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
3453
3471
|
...sourceMcp,
|
|
3454
3472
|
settings: {
|
|
3455
3473
|
...record8(sourceMcp.settings),
|
|
3456
|
-
...
|
|
3474
|
+
...mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE ? { disableProxyTool: true } : {}
|
|
3457
3475
|
},
|
|
3458
3476
|
mcpServers: {
|
|
3459
3477
|
...record8(sourceMcp.mcpServers),
|
|
@@ -4043,6 +4061,39 @@ function retainedSourceExecutorEntry(entry, executorKind) {
|
|
|
4043
4061
|
};
|
|
4044
4062
|
}
|
|
4045
4063
|
|
|
4064
|
+
// src/amaster-runtime-daemon/task-context-policy.mjs
|
|
4065
|
+
var TASK_CONTEXT_MANIFEST_VERSION = "task-context-v1";
|
|
4066
|
+
function resolveTaskContextMemoryPolicy(context) {
|
|
4067
|
+
const contextRecord = asRecord(context);
|
|
4068
|
+
const hasManifest = Object.prototype.hasOwnProperty.call(contextRecord, "taskContextManifest");
|
|
4069
|
+
const manifest = asRecord(contextRecord.taskContextManifest);
|
|
4070
|
+
const version = readString(manifest.version);
|
|
4071
|
+
if (!hasManifest) {
|
|
4072
|
+
return {
|
|
4073
|
+
governed: false,
|
|
4074
|
+
memoryScope: null,
|
|
4075
|
+
allowAutomaticHistoricalContext: true,
|
|
4076
|
+
allowCompanyMemoryMount: true
|
|
4077
|
+
};
|
|
4078
|
+
}
|
|
4079
|
+
if (!version) throw new Error("task_context_manifest_version_required");
|
|
4080
|
+
if (version !== TASK_CONTEXT_MANIFEST_VERSION) {
|
|
4081
|
+
throw new Error(`task_context_manifest_version_unsupported:${version}`);
|
|
4082
|
+
}
|
|
4083
|
+
const memoryScope = readString(manifest.memoryScope);
|
|
4084
|
+
if (memoryScope !== "none" && memoryScope !== "task") {
|
|
4085
|
+
throw new Error("task_context_manifest_memory_scope_invalid");
|
|
4086
|
+
}
|
|
4087
|
+
return {
|
|
4088
|
+
governed: true,
|
|
4089
|
+
memoryScope,
|
|
4090
|
+
// The current runtime has Company memory, not a task-scoped memory store.
|
|
4091
|
+
// Governed scopes therefore never authorize Company history implicitly.
|
|
4092
|
+
allowAutomaticHistoricalContext: false,
|
|
4093
|
+
allowCompanyMemoryMount: false
|
|
4094
|
+
};
|
|
4095
|
+
}
|
|
4096
|
+
|
|
4046
4097
|
// src/amaster-runtime-daemon/prompt-compiler.mjs
|
|
4047
4098
|
var DEADLINE_POSTURE_GUARD = "If a named time window or milestone is missed, skip that window and keep the task moving: never lower quality, bypass approvals, fabricate results, or stop the whole task because of the miss. Record a deadline-posture receipt with targetMilestoneRef, posture, onMiss=skip_this_window_and_continue, taskContinuation, and the next owner/action; the receipt is an execution signal, not Server-side proof.";
|
|
4048
4099
|
var MIN_PROMPT_BUDGET_CHARS = 8192;
|
|
@@ -4295,14 +4346,15 @@ function resolvedDependencySections(context, input, contextScope, snapshotFreshn
|
|
|
4295
4346
|
"Compare each returned latestRevisionId with the expected value. On revision mismatch, do not perform downstream writes; report it.",
|
|
4296
4347
|
...tuples.flatMap((tuple, index) => {
|
|
4297
4348
|
const readArguments = { issueId: tuple.blockerSelector, key: tuple.key };
|
|
4298
|
-
const
|
|
4349
|
+
const directToolName = managedDirectToolName(input, "amaster.read_issue_document");
|
|
4350
|
+
const call = directToolName ? readArguments : input.executorKind === "pi" && managedPiMcpProxyAvailable(input) ? {
|
|
4299
4351
|
server: "amaster",
|
|
4300
4352
|
tool: "amaster.read_issue_document",
|
|
4301
4353
|
args: JSON.stringify(readArguments)
|
|
4302
4354
|
} : readArguments;
|
|
4303
4355
|
return [
|
|
4304
4356
|
`- Required read ${index + 1}: issue ${JSON.stringify(tuple.blockerSelector)}${tuple.blockerId ? ` (id ${JSON.stringify(tuple.blockerId)})` : ""}; document ${JSON.stringify(tuple.documentId)}; key ${JSON.stringify(tuple.key)}; expected latestRevisionId ${JSON.stringify(tuple.expectedLatestRevisionId)}${tuple.expectedLatestRevisionNumber != null ? `; revisionNumber ${tuple.expectedLatestRevisionNumber}` : ""}.`,
|
|
4305
|
-
input.executorKind === "pi" && input
|
|
4357
|
+
directToolName ? ` Call \`${directToolName}\` with these exact object arguments: ${JSON.stringify(call)}` : input.executorKind === "pi" && managedPiMcpProxyAvailable(input) ? ` Exact Pi \`mcp\` arguments: ${JSON.stringify(call)}` : ` Call amaster.read_issue_document with these exact arguments: ${JSON.stringify(call)}`
|
|
4306
4358
|
];
|
|
4307
4359
|
})
|
|
4308
4360
|
].join("\n") : "";
|
|
@@ -4372,6 +4424,7 @@ function wikiAccessRuleLine(input) {
|
|
|
4372
4424
|
return "";
|
|
4373
4425
|
}
|
|
4374
4426
|
function optionalTaskWikiContextSection(context) {
|
|
4427
|
+
if (!resolveTaskContextMemoryPolicy(context).allowAutomaticHistoricalContext) return null;
|
|
4375
4428
|
const snapshot = asRecord(context.mirrorxTaskWikiContext);
|
|
4376
4429
|
if (readString(snapshot.schemaVersion) !== "mirrorx.task-wiki-context.v1") return null;
|
|
4377
4430
|
const querySeeds = (Array.isArray(snapshot.querySeeds) ? snapshot.querySeeds : []).map(readString).filter(Boolean).slice(0, 3);
|
|
@@ -4426,6 +4479,31 @@ function optionalTaskWikiContextSection(context) {
|
|
|
4426
4479
|
truncationReason: ready ? null : `wiki_optional_context_gap:${readString(snapshot.gapCode) ?? "invalid_snapshot"}`
|
|
4427
4480
|
};
|
|
4428
4481
|
}
|
|
4482
|
+
function taskContextAuthoritySection(context) {
|
|
4483
|
+
const manifest = asRecord(context.taskContextManifest);
|
|
4484
|
+
if (readString(manifest.version) !== "task-context-v1") return null;
|
|
4485
|
+
const sourceRefs = (Array.isArray(manifest.sourceRefs) ? manifest.sourceRefs : []).map(asRecord).map((ref) => ({
|
|
4486
|
+
kind: readString(ref.kind),
|
|
4487
|
+
id: readString(ref.id),
|
|
4488
|
+
revision: readString(ref.revision),
|
|
4489
|
+
scope: readString(ref.scope),
|
|
4490
|
+
useReason: readString(ref.useReason)
|
|
4491
|
+
})).filter((ref) => ref.kind && ref.id && ref.revision && ref.scope);
|
|
4492
|
+
if (sourceRefs.length === 0) return null;
|
|
4493
|
+
return {
|
|
4494
|
+
content: [
|
|
4495
|
+
"Immutable Task admission context authority. It identifies admitted sources and automatic memory policy; it does not replace the runtime Context Manifest below.",
|
|
4496
|
+
jsonText({
|
|
4497
|
+
version: manifest.version,
|
|
4498
|
+
memoryScope: readString(manifest.memoryScope),
|
|
4499
|
+
freshness: readString(manifest.freshness),
|
|
4500
|
+
sourceRefs
|
|
4501
|
+
})
|
|
4502
|
+
].join("\n"),
|
|
4503
|
+
sourceRef: sourceRefs.map((ref) => `${ref.kind}:${ref.id}@${ref.revision}`),
|
|
4504
|
+
scope: sourceRefs.map((ref) => ref.scope)
|
|
4505
|
+
};
|
|
4506
|
+
}
|
|
4429
4507
|
function fixedRules(input, includeIssueLine) {
|
|
4430
4508
|
const issue = asRecord(asRecord(input.context).paperclipIssue);
|
|
4431
4509
|
const businessOutcome = asRecord(asRecord(issue.taskRequirements).businessOutcome);
|
|
@@ -4452,7 +4530,7 @@ function fixedRules(input, includeIssueLine) {
|
|
|
4452
4530
|
wikiAccessRuleLine(input),
|
|
4453
4531
|
"- Runtime Artifact lineage fields sourceWorkProductId and sourceWorkProductIds accept only current artifact work product ids returned as result.effectResult.workProductId by a succeeded upload_artifact action. Never pass a documentId or revisionId as artifact lineage.",
|
|
4454
4532
|
"- When all inputs are issue documents and there is no source artifact work product, persist the derived result with upsert_document and do not call upload_artifact for a derived or review artifact.",
|
|
4455
|
-
input.hasGovernedMcp && input.executorKind === "pi" && input.managedMcpToolMode === "proxy_only" ? "- For proxy-only Pi MCP writes, put the complete target argument object directly in actual `mcp` string `args` as strict JSON; escape quotes, backslashes, and control characters. Do not stage or print tool calls. If inner JSON syntax fails, correct it once without changing values; never repeat a possibly accepted call. After `runtime_action.describe`, emit the write." : ""
|
|
4533
|
+
input.hasGovernedMcp && input.executorKind === "pi" && input.managedMcpToolMode === "proxy_only" ? "- For proxy-only Pi MCP writes, put the complete target argument object directly in actual `mcp` string `args` as strict JSON; escape quotes, backslashes, and control characters. Do not stage or print tool calls. If inner JSON syntax fails, correct it once without changing values; never repeat a possibly accepted call. After `runtime_action.describe`, emit the write." : input.hasGovernedMcp && input.executorKind === "pi" && input.managedMcpToolMode === "hybrid" ? "- For hybrid Pi MCP writes, call direct `runtime_action_describe`, then put long-tail write arguments in `mcp.args` as strict JSON. Never stage, print, or repeat a possibly accepted call." : ""
|
|
4456
4534
|
].filter(Boolean).join("\n");
|
|
4457
4535
|
}
|
|
4458
4536
|
function approvalContinuationText(input) {
|
|
@@ -4542,12 +4620,15 @@ function continuationRuntimeActionEnvelope(context) {
|
|
|
4542
4620
|
return envelope;
|
|
4543
4621
|
}
|
|
4544
4622
|
function managedDirectToolName(input, canonicalName) {
|
|
4545
|
-
if (input.managedMcpToolMode !== "direct_typed") return null;
|
|
4623
|
+
if (input.managedMcpToolMode !== "direct_typed" && input.managedMcpToolMode !== "hybrid") return null;
|
|
4546
4624
|
const catalog = asRecord(input.managedMcpToolCatalog);
|
|
4547
4625
|
const tools = Array.isArray(catalog.tools) ? catalog.tools.map(asRecord) : [];
|
|
4548
4626
|
const match = tools.find((tool) => readString(tool.name) === canonicalName);
|
|
4549
4627
|
return readString(match?.exposedName) ?? null;
|
|
4550
4628
|
}
|
|
4629
|
+
function managedPiMcpProxyAvailable(input) {
|
|
4630
|
+
return input.managedMcpToolMode === "proxy_only" || input.managedMcpToolMode === "hybrid";
|
|
4631
|
+
}
|
|
4551
4632
|
function runtimeActionContinuationOptionText(input) {
|
|
4552
4633
|
if (!isRecoveryWakeReason(input.wakeReason)) return "";
|
|
4553
4634
|
const heading = "### Runtime Action Continuation Option";
|
|
@@ -4566,12 +4647,8 @@ Runtime Action continuation is unavailable: managed governed MCP capability is m
|
|
|
4566
4647
|
Runtime Action continuation is unavailable: continuationRuntimeActionEnvelope is missing or invalid. Do not guess a tool call.`;
|
|
4567
4648
|
}
|
|
4568
4649
|
if (input.executorKind === "pi") {
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
if (!toolName) {
|
|
4572
|
-
return `${heading}
|
|
4573
|
-
Runtime Action continuation is unavailable: the run catalog does not advertise the required typed submit tool. Do not guess a tool call.`;
|
|
4574
|
-
}
|
|
4650
|
+
const toolName = managedDirectToolName(input, "runtime_action.submit");
|
|
4651
|
+
if (toolName) {
|
|
4575
4652
|
return [
|
|
4576
4653
|
heading,
|
|
4577
4654
|
`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.`,
|
|
@@ -4580,7 +4657,11 @@ Runtime Action continuation is unavailable: the run catalog does not advertise t
|
|
|
4580
4657
|
"```"
|
|
4581
4658
|
].join("\n");
|
|
4582
4659
|
}
|
|
4583
|
-
if (input
|
|
4660
|
+
if (!managedPiMcpProxyAvailable(input)) {
|
|
4661
|
+
if (input.managedMcpToolMode === "direct_typed") {
|
|
4662
|
+
return `${heading}
|
|
4663
|
+
Runtime Action continuation is unavailable: the run catalog does not advertise the required typed submit tool. Do not guess a tool call.`;
|
|
4664
|
+
}
|
|
4584
4665
|
return `${heading}
|
|
4585
4666
|
Runtime Action continuation is unavailable: managed Pi MCP tool mode is not proxy_only. Do not guess a proxy or direct-tool call.`;
|
|
4586
4667
|
}
|
|
@@ -4692,7 +4773,7 @@ function runtimeDecompositionRequirementText(context) {
|
|
|
4692
4773
|
}
|
|
4693
4774
|
function deliveryReadCallText(input) {
|
|
4694
4775
|
const args = { issueId: input.issueId };
|
|
4695
|
-
if (input.executorKind === "pi" && input
|
|
4776
|
+
if (input.executorKind === "pi" && managedPiMcpProxyAvailable(input)) {
|
|
4696
4777
|
return `emit an mcp proxy call: ${JSON.stringify({
|
|
4697
4778
|
server: "amaster",
|
|
4698
4779
|
tool: "amaster.read_issue_delivery",
|
|
@@ -4763,7 +4844,11 @@ function runtimeDeliveryReadinessText(context, input) {
|
|
|
4763
4844
|
}
|
|
4764
4845
|
function readIssueEvidenceCommentCallText(issueId, commentId, options) {
|
|
4765
4846
|
const readArguments = { refs: [{ kind: "issue_comment", issueId, commentId }] };
|
|
4766
|
-
|
|
4847
|
+
const directToolName = managedDirectToolName(options ?? {}, "amaster.read_issue_evidence");
|
|
4848
|
+
if (directToolName) {
|
|
4849
|
+
return `call \`${directToolName}\` with these exact object arguments: ${JSON.stringify(readArguments)}`;
|
|
4850
|
+
}
|
|
4851
|
+
if (options?.executorKind === "pi" && managedPiMcpProxyAvailable(options)) {
|
|
4767
4852
|
return `emit an mcp proxy call: ${JSON.stringify({ server: "amaster", tool: "amaster.read_issue_evidence", args: JSON.stringify(readArguments) })}`;
|
|
4768
4853
|
}
|
|
4769
4854
|
return `call amaster.read_issue_evidence with these exact arguments: ${JSON.stringify(readArguments)}`;
|
|
@@ -4781,36 +4866,37 @@ function taskCommentRefGuidance(input) {
|
|
|
4781
4866
|
return `References like comment:<id> above mark truncated comment bodies. Fetch the full text before relying on them \u2014 ${call} (replace <id> with the referenced comment id).`;
|
|
4782
4867
|
}
|
|
4783
4868
|
function piMcpProxyExamplesText(input) {
|
|
4784
|
-
if (!input.hasGovernedMcp || input.executorKind !== "pi" || input
|
|
4869
|
+
if (!input.hasGovernedMcp || input.executorKind !== "pi" || !managedPiMcpProxyAvailable(input) || isRecoveryWakeReason(input.wakeReason)) return "";
|
|
4870
|
+
const hybrid = input.managedMcpToolMode === "hybrid";
|
|
4785
4871
|
const proxy = (tool, args) => JSON.stringify({
|
|
4786
4872
|
server: "amaster",
|
|
4787
4873
|
tool,
|
|
4788
4874
|
args: JSON.stringify(args)
|
|
4789
4875
|
});
|
|
4790
4876
|
return [
|
|
4791
|
-
"The Pi native tool is the outer `mcp` proxy. Emit these as actual tool calls; `args` is the stringified inner canonical object. Pi validates this string schema before extension hooks, so never send object-valued `args`:",
|
|
4877
|
+
hybrid ? "For governed tools not exposed in the direct typed list, use the outer `mcp` proxy. Before the first long-tail proxy call, describe that exact canonical tool; `args` is the stringified inner canonical object and must never be object-valued." : "The Pi native tool is the outer `mcp` proxy. Emit these as actual tool calls; `args` is the stringified inner canonical object. Pi validates this string schema before extension hooks, so never send object-valued `args`:",
|
|
4792
4878
|
"Keep review payload strings short. Reference the exact document key and revision in `target`; do not duplicate the reviewed document body in `prompt` or `detailsMarkdown`.",
|
|
4793
4879
|
"payload.supersedesInteractionId is invalid. provenance.supersedesInteractionId is only for replacing a currently pending governed interaction; after changes_requested or rejected resolution, do not send a supersession id.",
|
|
4794
4880
|
"update_parent.comment creates a separate persistent issue comment. Omit it when add_comment already recorded the message.",
|
|
4795
|
-
`- describe: ${proxy("runtime_action.describe", { schemaVersion: "runtime-action-v1", actionType: "update_parent" })}
|
|
4881
|
+
...!hybrid ? [`- describe: ${proxy("runtime_action.describe", { schemaVersion: "runtime-action-v1", actionType: "update_parent" })}`] : [],
|
|
4796
4882
|
`- submit: ${proxy("runtime_action.submit", { schemaVersion: "runtime-action-v1", idempotencyKey: "task-123-progress", action: { type: "update_parent", status: "in_progress" } })}`,
|
|
4797
4883
|
`- submit intermediate document review interaction: ${proxy("runtime_action.submit", { schemaVersion: "runtime-action-v1", idempotencyKey: "task-123-review", action: { type: "create_interaction", kind: "request_confirmation", continuationPolicy: "wake_assignee_on_accept", provenance: { purposeCode: "review_document_revision", requirementRefs: ["acceptance:document_review"], attentionOwner: { kind: "board", id: "board" }, epochKey: "document_revision:22222222-2222-4222-8222-222222222222" }, payload: { version: 1, resolutionMode: "review", prompt: "Review `plan` revision 1.", target: { type: "issue_document", issueId: "11111111-1111-4111-8111-111111111111", documentId: "33333333-3333-4333-8333-333333333333", key: "plan", revisionId: "22222222-2222-4222-8222-222222222222", revisionNumber: 1 } } } })}`,
|
|
4798
4884
|
`- plan: ${proxy("runtime_action.plan", { schemaVersion: "runtime-action-v1", idempotencyKey: "task-123-plan", actions: [{ type: "update_parent", status: "in_progress" }] })}`,
|
|
4799
4885
|
`- commit the returned plan revision: ${proxy("runtime_action.commit", { schemaVersion: "runtime-action-v1", planId: "11111111-1111-4111-8111-111111111111", revision: "plan-revision-1" })}`,
|
|
4800
|
-
`- read document: ${proxy("amaster.read_issue_document", { issueId: "AM-123", key: "plan" })}`
|
|
4886
|
+
...!hybrid ? [`- read document: ${proxy("amaster.read_issue_document", { issueId: "AM-123", key: "plan" })}`] : []
|
|
4801
4887
|
].join("\n");
|
|
4802
4888
|
}
|
|
4803
4889
|
function piDirectTypedToolsText(input) {
|
|
4804
|
-
if (!input.hasGovernedMcp || input.executorKind !== "pi" || input.managedMcpToolMode !== "direct_typed") return "";
|
|
4890
|
+
if (!input.hasGovernedMcp || input.executorKind !== "pi" || input.managedMcpToolMode !== "direct_typed" && input.managedMcpToolMode !== "hybrid") return "";
|
|
4805
4891
|
const catalog = asRecord(input.managedMcpToolCatalog);
|
|
4806
4892
|
const tools = (Array.isArray(catalog.tools) ? catalog.tools : []).map(asRecord).map((tool) => ({ name: readString(tool.exposedName), description: readString(tool.description) })).filter((tool) => tool.name);
|
|
4807
4893
|
if (tools.length === 0) {
|
|
4808
4894
|
return "Direct typed governed tools are unavailable because the run catalog snapshot is empty. Do not guess a proxy or tool name.";
|
|
4809
4895
|
}
|
|
4810
4896
|
return [
|
|
4811
|
-
"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.",
|
|
4897
|
+
input.managedMcpToolMode === "hybrid" ? "This run exposes the attested high-frequency Governed MCP tools below as direct typed tools. Call these exact names with object arguments and do not send them through the `mcp` proxy." : "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.",
|
|
4812
4898
|
...tools.map((tool) => `- ${tool.name}${tool.description ? `: ${tool.description}` : ""}`),
|
|
4813
|
-
"A tool not listed above is unavailable in this run. Do not infer a namespace or fall back to REST/bare MCP."
|
|
4899
|
+
input.managedMcpToolMode === "hybrid" ? "For a canonical tool not listed above, use the single managed `mcp` proxy only after exact describe. Never infer an alias, use REST, or bypass the governed Gateway." : "A tool not listed above is unavailable in this run. Do not infer a namespace or fall back to REST/bare MCP."
|
|
4814
4900
|
].join("\n");
|
|
4815
4901
|
}
|
|
4816
4902
|
function sectionText(section) {
|
|
@@ -4919,9 +5005,14 @@ function compileCommandPromptWithManifest(input, options = {}) {
|
|
|
4919
5005
|
resolvedDependencies.details.content ? `Auxiliary predecessor context (may be truncated):
|
|
4920
5006
|
${resolvedDependencies.details.content}` : ""
|
|
4921
5007
|
].filter(Boolean).join("\n\n") : "";
|
|
4922
|
-
const
|
|
5008
|
+
const piDirectTypedTools = piDirectTypedToolsText(input);
|
|
5009
|
+
const piMcpProxyExamples = [
|
|
5010
|
+
resolvedDependencies.required.content ? "" : piMcpProxyExamplesText(input),
|
|
5011
|
+
piDirectTypedTools
|
|
5012
|
+
].filter(Boolean).join("\n");
|
|
4923
5013
|
const deliveryReadinessContent = runtimeDeliveryReadinessText(context, input);
|
|
4924
5014
|
const optionalTaskWikiContext = optionalTaskWikiContextSection(context);
|
|
5015
|
+
const taskContextAuthority = taskContextAuthoritySection(context);
|
|
4925
5016
|
const rawSections = [
|
|
4926
5017
|
{ name: "recovery_instruction", title: "Recovery Instruction", priority: 100, sourceRef: `run:${input.runId ?? "unknown"}`, content: completeRecoveryInstruction, truncationReason: completeRecoveryInstruction ? null : "mode_selection" },
|
|
4927
5018
|
{ name: "approval_continuation", title: "Approved Runtime Action Continuation", priority: 99, sourceRef: `run:${input.runId ?? "unknown"}`, content: approvalContinuationText(input), truncationReason: mode === "continuation" ? null : "mode_selection" },
|
|
@@ -4940,8 +5031,15 @@ ${resolvedDependencies.details.content}` : ""
|
|
|
4940
5031
|
{ name: "runtime_rules", title: "", priority: 100, sourceRef: `command:${input.commandId}`, content: fixedRules(input, !hasTask) },
|
|
4941
5032
|
{ name: "runtime_authorization", title: "Runtime Action Contract", priority: 98, sourceRef: `run:${input.runId ?? "unknown"}`, content: runtimeAuthorizationText(context, mode, { suppressOrdinaryCompletionContract }) },
|
|
4942
5033
|
{ name: "runtime_decomposition_requirement", title: "Required Task Decomposition", priority: 98, sourceRef: `issue:${input.issueId ?? "unknown"}`, content: runtimeDecompositionRequirementText(context) },
|
|
5034
|
+
...taskContextAuthority ? [{ name: "task_context_authority", title: "Task Context Authority", priority: 98, ...taskContextAuthority }] : [],
|
|
4943
5035
|
...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 }] : [],
|
|
4944
|
-
...piMcpProxyExamples ? [{
|
|
5036
|
+
...piMcpProxyExamples ? [{
|
|
5037
|
+
name: "pi_mcp_proxy_examples",
|
|
5038
|
+
title: piDirectTypedTools ? "Pi Governed MCP Tools" : "Pi MCP Proxy Examples",
|
|
5039
|
+
priority: 96,
|
|
5040
|
+
sourceRef: "amaster_governed_mcp_proxy_contract",
|
|
5041
|
+
content: piMcpProxyExamples
|
|
5042
|
+
}] : [],
|
|
4945
5043
|
{ 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 },
|
|
4946
5044
|
...optionalTaskWikiContext ? [optionalTaskWikiContext] : [],
|
|
4947
5045
|
{ name: "agent_instructions", title: "Agent Instructions", priority: 100, sourceRef: "agent_instructions_bundle", content: readString(input.agentInstructions) ?? "" },
|
|
@@ -9546,7 +9644,7 @@ function assertSourceAcquisitionRuntimeAuthority({
|
|
|
9546
9644
|
}
|
|
9547
9645
|
|
|
9548
9646
|
// src/amaster-runtime-daemon.mjs
|
|
9549
|
-
var CONNECTOR_VERSION = "0.1.1-beta.
|
|
9647
|
+
var CONNECTOR_VERSION = "0.1.1-beta.17";
|
|
9550
9648
|
var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
|
|
9551
9649
|
var SOURCE_ACQUISITION_CAPABILITY = "source_acquisition_v1";
|
|
9552
9650
|
var SOURCE_ACQUISITION_PROFILE_VERSION = "source_acquisition_v1";
|
|
@@ -14027,6 +14125,9 @@ async function executeRunCommand(config, command) {
|
|
|
14027
14125
|
throw new Error(`runtime_actions_v2_preflight_failed: ${executor.kind} command lacks an exact managed governed MCP profile`);
|
|
14028
14126
|
}
|
|
14029
14127
|
const workspace = resolveExecutionWorkspace(config, command, { executorKind: executor.kind });
|
|
14128
|
+
const taskContextMemoryPolicy = resolveTaskContextMemoryPolicy(
|
|
14129
|
+
asRecord(asRecord(command.payload).contextSnapshot)
|
|
14130
|
+
);
|
|
14030
14131
|
const cwd = workspace.cwd;
|
|
14031
14132
|
try {
|
|
14032
14133
|
await materializeAgentInstructionsBundle(config, command, workspace);
|
|
@@ -14238,20 +14339,26 @@ async function executeRunCommand(config, command) {
|
|
|
14238
14339
|
}
|
|
14239
14340
|
if (piChildAllocator2) {
|
|
14240
14341
|
try {
|
|
14241
|
-
const
|
|
14242
|
-
|
|
14243
|
-
|
|
14244
|
-
|
|
14245
|
-
|
|
14246
|
-
|
|
14247
|
-
|
|
14248
|
-
|
|
14249
|
-
|
|
14342
|
+
const companyMemoryGroup = taskContextMemoryPolicy.allowCompanyMemoryMount ? (() => {
|
|
14343
|
+
const companyId = readString(commandRuntimeAuth(command).companyId) ?? readString(asRecord(command.payload).companyId);
|
|
14344
|
+
if (!companyId) throw new Error("pi_company_memory_company_id_required");
|
|
14345
|
+
return {
|
|
14346
|
+
companyId,
|
|
14347
|
+
...resolveCompanyPiMemoryGroup({
|
|
14348
|
+
root: companyPiHomeRoot(process.env),
|
|
14349
|
+
companyId
|
|
14350
|
+
})
|
|
14351
|
+
};
|
|
14352
|
+
})() : null;
|
|
14353
|
+
const assignment = piChildAllocator2.acquire(
|
|
14354
|
+
commandRunId(command),
|
|
14355
|
+
companyMemoryGroup ? { gid: companyMemoryGroup.gid } : {}
|
|
14356
|
+
);
|
|
14250
14357
|
piChildAssignmentAcquired = true;
|
|
14251
|
-
if (managedMcpProfile) {
|
|
14358
|
+
if (managedMcpProfile && companyMemoryGroup) {
|
|
14252
14359
|
piCompanyMemory = prepareCompanyPiMemory({
|
|
14253
14360
|
root: companyMemoryGroup.root,
|
|
14254
|
-
companyId,
|
|
14361
|
+
companyId: companyMemoryGroup.companyId,
|
|
14255
14362
|
gid: companyMemoryGroup.gid,
|
|
14256
14363
|
profileRoot: managedMcpProfile.profileRoot,
|
|
14257
14364
|
profileHome: managedMcpProfile.env.PI_AGENT_HOME,
|
package/dist/amaster-runtime.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { basename, dirname, join, resolve } from "node:path";
|
|
|
6
6
|
import { homedir, hostname } from "node:os";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
|
|
9
|
-
const CONNECTOR_VERSION = "0.1.1-beta.
|
|
9
|
+
const CONNECTOR_VERSION = "0.1.1-beta.17";
|
|
10
10
|
|
|
11
11
|
const CAPABILITIES = [
|
|
12
12
|
"remote_registration",
|