@amaster.ai/employee-runtime-connector 0.1.1-beta.0 → 0.1.1-beta.2
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/README.md +1 -1
- package/dist/amaster-runtime-daemon.mjs +430 -130
- package/dist/amaster-runtime.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ Pi execution uses three separate evidence layers:
|
|
|
40
40
|
2. a durable, inspectable Runtime Action receipt or finalized Runtime Artifact;
|
|
41
41
|
3. process cleanup disposition.
|
|
42
42
|
|
|
43
|
-
An exact process-kill `EPERM` error emitted only after the first two layers have completed may be isolated as a failed `cleanupDisposition` warning without changing the command's successful business result. Both accepted shapes require `kill` and `EPERM`; generic filesystem/process permission text such as `EPERM: operation not permitted, unlink ...` is a business error. A `runtime_action.status` readback is evidence only when its call/plan ref matches an earlier submit/commit receipt in the same transcript. The diagnostic and durable evidence reference remain in the result. Text-only or action-only-without-assistant-output streams, standalone governed reads, non-effect Runtime Action tools, rejected or pending effects, pre-terminal errors, provider failures, timeout, cancellation, resource limits, any signal, live residue, and uncertain ownership remain failures.
|
|
43
|
+
An exact process-kill `EPERM` error emitted only after the first two layers have completed may be isolated as a failed `cleanupDisposition` warning without changing the command's successful business result. Both accepted shapes require `kill` and `EPERM`; generic filesystem/process permission text such as `EPERM: operation not permitted, unlink ...` is a business error. Durable evidence is limited to a completed Runtime Action, a finalized Runtime Artifact, or an accepted `company_diagnosis_brief` provider receipt whose invocation and returned Diagnosis/document/work-product identities are exact. A `runtime_action.status` readback is evidence only when its call/plan ref matches an earlier submit/commit receipt in the same transcript. The diagnostic and durable evidence reference remain in the result. Text-only or action-only-without-assistant-output streams, standalone governed reads, non-effect Runtime Action tools, rejected or pending effects, pre-terminal errors, provider failures, timeout, cancellation, resource limits, any signal, live residue, and uncertain ownership remain failures.
|
|
44
44
|
|
|
45
45
|
This isolation does not schedule a retry or a second business continuation. Command result delivery and the result outbox remain the sole idempotency boundary.
|
|
46
46
|
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// MirrorX runtime connector daemon bundle.
|
|
3
3
|
|
|
4
4
|
// src/amaster-runtime-daemon.mjs
|
|
5
|
-
import { createHash as
|
|
6
|
-
import { chmodSync as chmodSync6, copyFileSync as copyFileSync3, existsSync as existsSync14, lstatSync as lstatSync7, mkdirSync as mkdirSync9, 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
|
-
import { arch as arch3, homedir as homedir3, hostname as hostname2, platform as platform3 } from "node:os";
|
|
5
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
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
|
+
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";
|
|
9
9
|
import { spawn as spawn2, spawnSync as spawnSync6 } from "node:child_process";
|
|
10
10
|
|
|
@@ -1607,7 +1607,7 @@ var MANAGED_PI_PROVIDER_PROTECTED_ENV_NAMES = Object.freeze([
|
|
|
1607
1607
|
function isRecord(value) {
|
|
1608
1608
|
return value && typeof value === "object" && !Array.isArray(value);
|
|
1609
1609
|
}
|
|
1610
|
-
function
|
|
1610
|
+
function readJsonFile(filePath) {
|
|
1611
1611
|
try {
|
|
1612
1612
|
const parsed = JSON.parse(readFileSync2(filePath, "utf8"));
|
|
1613
1613
|
return asRecord(parsed);
|
|
@@ -1679,7 +1679,7 @@ function syncAmasterProviderModels(agentDir, executorEnv) {
|
|
|
1679
1679
|
const apiKey = readString(executorEnv.AMASTER_API_KEY);
|
|
1680
1680
|
if (!apiKey) return false;
|
|
1681
1681
|
const modelsPath = join3(agentDir, "models.json");
|
|
1682
|
-
const config =
|
|
1682
|
+
const config = readJsonFile(modelsPath);
|
|
1683
1683
|
const providers = asRecord(config.providers);
|
|
1684
1684
|
const amaster = { ...asRecord(providers.amaster) };
|
|
1685
1685
|
amaster.apiKey = managedApiKeyConfigValue(executorEnv, apiKey);
|
|
@@ -1707,7 +1707,7 @@ function syncAmasterProviderSettings(agentDir, executorEnv) {
|
|
|
1707
1707
|
if (!apiKey) return false;
|
|
1708
1708
|
const settingsPath = join3(agentDir, "settings.json");
|
|
1709
1709
|
if (!existsSync2(settingsPath)) return false;
|
|
1710
|
-
const settings =
|
|
1710
|
+
const settings = readJsonFile(settingsPath);
|
|
1711
1711
|
const baseUrl = readString(executorEnv.AMASTER_PROVIDER_BASE_URL);
|
|
1712
1712
|
const defaultModel = readString(executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL);
|
|
1713
1713
|
const imageGenBaseUrl = imageGenBaseUrlFromProviderBaseUrl(baseUrl);
|
|
@@ -1828,19 +1828,161 @@ function escapeLiteralJsonStringControlCharacters(value) {
|
|
|
1828
1828
|
}
|
|
1829
1829
|
return changed ? output : value;
|
|
1830
1830
|
}
|
|
1831
|
+
function escapeLikelyLiteralJsonStringQuotes(value) {
|
|
1832
|
+
let output = "";
|
|
1833
|
+
let inString = false;
|
|
1834
|
+
let escaped = false;
|
|
1835
|
+
let changed = false;
|
|
1836
|
+
let stringRole = null;
|
|
1837
|
+
let previousSignificantCharacter = null;
|
|
1838
|
+
function followingObjectProperty(offset) {
|
|
1839
|
+
let cursor = offset;
|
|
1840
|
+
while (cursor < value.length && /\s/u.test(value[cursor])) cursor += 1;
|
|
1841
|
+
if (value[cursor] !== '"') return { valid: false, simpleIdentifier: false };
|
|
1842
|
+
cursor += 1;
|
|
1843
|
+
let propertyName = "";
|
|
1844
|
+
let propertyEscaped = false;
|
|
1845
|
+
for (; cursor < value.length; cursor += 1) {
|
|
1846
|
+
const propertyCharacter = value[cursor];
|
|
1847
|
+
if (propertyEscaped) {
|
|
1848
|
+
propertyName += propertyCharacter;
|
|
1849
|
+
propertyEscaped = false;
|
|
1850
|
+
continue;
|
|
1851
|
+
}
|
|
1852
|
+
if (propertyCharacter === "\\") {
|
|
1853
|
+
propertyEscaped = true;
|
|
1854
|
+
continue;
|
|
1855
|
+
}
|
|
1856
|
+
if (propertyCharacter !== '"') {
|
|
1857
|
+
propertyName += propertyCharacter;
|
|
1858
|
+
continue;
|
|
1859
|
+
}
|
|
1860
|
+
cursor += 1;
|
|
1861
|
+
while (cursor < value.length && /\s/u.test(value[cursor])) cursor += 1;
|
|
1862
|
+
return {
|
|
1863
|
+
valid: value[cursor] === ":",
|
|
1864
|
+
simpleIdentifier: /^[A-Za-z_][A-Za-z0-9_-]*$/u.test(propertyName)
|
|
1865
|
+
};
|
|
1866
|
+
}
|
|
1867
|
+
return { valid: false, simpleIdentifier: false };
|
|
1868
|
+
}
|
|
1869
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
1870
|
+
const character = value[index];
|
|
1871
|
+
if (!inString) {
|
|
1872
|
+
output += character;
|
|
1873
|
+
if (character === '"') {
|
|
1874
|
+
inString = true;
|
|
1875
|
+
stringRole = previousSignificantCharacter === ":" ? "object_value" : null;
|
|
1876
|
+
} else if (!/\s/u.test(character)) {
|
|
1877
|
+
previousSignificantCharacter = character;
|
|
1878
|
+
}
|
|
1879
|
+
continue;
|
|
1880
|
+
}
|
|
1881
|
+
if (escaped) {
|
|
1882
|
+
output += character;
|
|
1883
|
+
escaped = false;
|
|
1884
|
+
continue;
|
|
1885
|
+
}
|
|
1886
|
+
if (character === "\\") {
|
|
1887
|
+
output += character;
|
|
1888
|
+
escaped = true;
|
|
1889
|
+
continue;
|
|
1890
|
+
}
|
|
1891
|
+
if (character !== '"') {
|
|
1892
|
+
output += character;
|
|
1893
|
+
continue;
|
|
1894
|
+
}
|
|
1895
|
+
let nextIndex = index + 1;
|
|
1896
|
+
while (nextIndex < value.length && /\s/u.test(value[nextIndex])) nextIndex += 1;
|
|
1897
|
+
const nextCharacter = value[nextIndex];
|
|
1898
|
+
if (nextCharacter === "," && stringRole === "object_value") {
|
|
1899
|
+
const following = followingObjectProperty(nextIndex + 1);
|
|
1900
|
+
if (!following.valid && !following.simpleIdentifier) {
|
|
1901
|
+
output += '\\"';
|
|
1902
|
+
changed = true;
|
|
1903
|
+
continue;
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
if (nextCharacter === void 0 || [":", ",", "}", "]"].includes(nextCharacter)) {
|
|
1907
|
+
output += character;
|
|
1908
|
+
inString = false;
|
|
1909
|
+
stringRole = null;
|
|
1910
|
+
previousSignificantCharacter = character;
|
|
1911
|
+
} else {
|
|
1912
|
+
output += '\\"';
|
|
1913
|
+
changed = true;
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
return changed ? output : value;
|
|
1917
|
+
}
|
|
1918
|
+
function insertSingleMissingObjectPropertyComma(value) {
|
|
1919
|
+
let parseError;
|
|
1920
|
+
try {
|
|
1921
|
+
JSON.parse(value);
|
|
1922
|
+
return value;
|
|
1923
|
+
} catch (error) {
|
|
1924
|
+
parseError = error;
|
|
1925
|
+
}
|
|
1926
|
+
const positionMatch = String(parseError?.message ?? "").match(
|
|
1927
|
+
/Expected ',' or '\}' after property value in JSON at position (\d+)/u
|
|
1928
|
+
);
|
|
1929
|
+
if (!positionMatch) return value;
|
|
1930
|
+
const position = Number(positionMatch[1]);
|
|
1931
|
+
if (!Number.isSafeInteger(position) || position < 1 || position >= value.length) return value;
|
|
1932
|
+
let propertyStart = position;
|
|
1933
|
+
while (propertyStart < value.length && /\s/u.test(value[propertyStart])) propertyStart += 1;
|
|
1934
|
+
if (value[propertyStart] !== '"') return value;
|
|
1935
|
+
let cursor = propertyStart + 1;
|
|
1936
|
+
let escaped = false;
|
|
1937
|
+
let propertyName = "";
|
|
1938
|
+
for (; cursor < value.length; cursor += 1) {
|
|
1939
|
+
const character = value[cursor];
|
|
1940
|
+
if (escaped) {
|
|
1941
|
+
propertyName += character;
|
|
1942
|
+
escaped = false;
|
|
1943
|
+
continue;
|
|
1944
|
+
}
|
|
1945
|
+
if (character === "\\") {
|
|
1946
|
+
escaped = true;
|
|
1947
|
+
continue;
|
|
1948
|
+
}
|
|
1949
|
+
if (character === '"') break;
|
|
1950
|
+
propertyName += character;
|
|
1951
|
+
}
|
|
1952
|
+
if (cursor >= value.length || !/^[A-Za-z_][A-Za-z0-9_-]*$/u.test(propertyName)) return value;
|
|
1953
|
+
cursor += 1;
|
|
1954
|
+
while (cursor < value.length && /\s/u.test(value[cursor])) cursor += 1;
|
|
1955
|
+
if (value[cursor] !== ":") return value;
|
|
1956
|
+
let previous = position - 1;
|
|
1957
|
+
while (previous >= 0 && /\s/u.test(value[previous])) previous -= 1;
|
|
1958
|
+
if (previous < 0 || !['"', "}", "]", "e", "l"].includes(value[previous]) && !/[0-9]/u.test(value[previous])) {
|
|
1959
|
+
return value;
|
|
1960
|
+
}
|
|
1961
|
+
const candidate = `${value.slice(0, position)},${value.slice(position)}`;
|
|
1962
|
+
try {
|
|
1963
|
+
return isJsonObject(JSON.parse(candidate)) ? candidate : value;
|
|
1964
|
+
} catch {
|
|
1965
|
+
return value;
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1831
1968
|
function normalizePiMcpProxyArgs(value) {
|
|
1832
1969
|
if (typeof value !== "string") return { value, repaired: false };
|
|
1833
1970
|
try {
|
|
1834
1971
|
JSON.parse(value);
|
|
1835
1972
|
return { value, repaired: false };
|
|
1836
1973
|
} catch {
|
|
1837
|
-
const
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1974
|
+
const repairedControlCharacters = escapeLiteralJsonStringControlCharacters(value);
|
|
1975
|
+
const repairedValue = escapeLikelyLiteralJsonStringQuotes(repairedControlCharacters);
|
|
1976
|
+
if (repairedValue !== value) {
|
|
1977
|
+
try {
|
|
1978
|
+
if (isJsonObject(JSON.parse(repairedValue))) {
|
|
1979
|
+
return { value: repairedValue, repaired: true };
|
|
1980
|
+
}
|
|
1981
|
+
} catch {
|
|
1982
|
+
}
|
|
1843
1983
|
}
|
|
1984
|
+
const commaRepairedValue = insertSingleMissingObjectPropertyComma(repairedControlCharacters);
|
|
1985
|
+
return commaRepairedValue !== value ? { value: commaRepairedValue, repaired: true } : { value, repaired: false };
|
|
1844
1986
|
}
|
|
1845
1987
|
}
|
|
1846
1988
|
function registerManagedPiMcpArgsNormalizer(pi) {
|
|
@@ -1854,6 +1996,8 @@ function managedPiMcpArgsNormalizerExtensionSource() {
|
|
|
1854
1996
|
return [
|
|
1855
1997
|
isJsonObject.toString(),
|
|
1856
1998
|
escapeLiteralJsonStringControlCharacters.toString(),
|
|
1999
|
+
escapeLikelyLiteralJsonStringQuotes.toString(),
|
|
2000
|
+
insertSingleMissingObjectPropertyComma.toString(),
|
|
1857
2001
|
normalizePiMcpProxyArgs.toString(),
|
|
1858
2002
|
`export default ${registerManagedPiMcpArgsNormalizer.toString()};`,
|
|
1859
2003
|
""
|
|
@@ -2264,7 +2408,12 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2264
2408
|
if (!existsSync3(packagePath) || lstatSync2(packagePath).isSymbolicLink() || !lstatSync2(packagePath).isFile()) {
|
|
2265
2409
|
throw new Error(`pi_managed_mcp_attestation_failed: configured ${MANAGED_WEB_ACCESS_PACKAGE} package is unavailable`);
|
|
2266
2410
|
}
|
|
2267
|
-
|
|
2411
|
+
let packageMetadata;
|
|
2412
|
+
try {
|
|
2413
|
+
packageMetadata = JSON.parse(readFileSync3(packagePath, "utf8"));
|
|
2414
|
+
} catch {
|
|
2415
|
+
throw new Error(`pi_managed_mcp_attestation_failed: configured ${MANAGED_WEB_ACCESS_PACKAGE} package metadata is invalid`);
|
|
2416
|
+
}
|
|
2268
2417
|
if (!packageMetadata || packageMetadata.name !== MANAGED_WEB_ACCESS_PACKAGE) {
|
|
2269
2418
|
throw new Error(`pi_managed_mcp_attestation_failed: configured ${MANAGED_WEB_ACCESS_PACKAGE} package identity mismatch`);
|
|
2270
2419
|
}
|
|
@@ -2318,44 +2467,11 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2318
2467
|
}
|
|
2319
2468
|
}
|
|
2320
2469
|
const browserUse = selectManagedBrowserUse(sourceSettings, npmSource);
|
|
2321
|
-
const webAccess = selectManagedWebAccess(sourceSettings, npmSource);
|
|
2470
|
+
const webAccess = sourceAcquisition ? null : selectManagedWebAccess(sourceSettings, npmSource);
|
|
2322
2471
|
const telemetry = selectManagedTelemetry(sourceSettings, npmSource);
|
|
2323
|
-
if (sourceAcquisition &&
|
|
2472
|
+
if (sourceAcquisition && !browserUse) {
|
|
2324
2473
|
throw new Error("pi_managed_mcp_source_acquisition_packages_missing");
|
|
2325
2474
|
}
|
|
2326
|
-
const sourceProfile = record6(sourceAcquisition?.profile);
|
|
2327
|
-
const sourceAccess = record6(sourceProfile.access);
|
|
2328
|
-
const sourceTransport = record6(sourceProfile.transport);
|
|
2329
|
-
const sourceObservation = sourceAcquisition ? {
|
|
2330
|
-
runId: sourceProfile.runId,
|
|
2331
|
-
retention: sourceProfile.retention
|
|
2332
|
-
} : null;
|
|
2333
|
-
const sourceWebAccessConfig = sourceAcquisition ? {
|
|
2334
|
-
...webAccess.config,
|
|
2335
|
-
fetch: {
|
|
2336
|
-
...record6(webAccess.config.fetch),
|
|
2337
|
-
mode: sourceTransport.webFetchMode,
|
|
2338
|
-
observation: sourceObservation,
|
|
2339
|
-
...!record6(webAccess.config.fetch).provider && !record6(webAccess.config.fetch).summary && typeof sourceSettings.defaultProvider === "string" && typeof sourceSettings.defaultModel === "string" ? { summary: { provider: sourceSettings.defaultProvider, model: sourceSettings.defaultModel } } : {}
|
|
2340
|
-
}
|
|
2341
|
-
} : null;
|
|
2342
|
-
const sourceBrowserConfig = sourceAcquisition ? {
|
|
2343
|
-
...browserUse.config,
|
|
2344
|
-
sessionMode: sourceTransport.browserMode,
|
|
2345
|
-
...sourceAccess.mode === "authenticated" ? { userDataDir: sourceAcquisition.userDataDir } : {},
|
|
2346
|
-
readPolicy: {
|
|
2347
|
-
version: "browser_read_policy_v1",
|
|
2348
|
-
accessMode: sourceAccess.mode,
|
|
2349
|
-
allowedTopLevelLocators: [sourceAccess.exactLocator, ...Array.isArray(sourceAccess.declaredPageLocators) ? sourceAccess.declaredPageLocators : []],
|
|
2350
|
-
allowedTopLevelOrigins: sourceAccess.allowedTopLevelOrigins,
|
|
2351
|
-
subresources: "public_or_same_origin",
|
|
2352
|
-
privateCrossOriginSubresources: "deny",
|
|
2353
|
-
popups: "deny",
|
|
2354
|
-
downloads: "deny",
|
|
2355
|
-
newTargets: "deny",
|
|
2356
|
-
observation: sourceObservation
|
|
2357
|
-
}
|
|
2358
|
-
} : null;
|
|
2359
2475
|
const settings = {
|
|
2360
2476
|
...typeof sourceSettings.defaultProvider === "string" ? { defaultProvider: sourceSettings.defaultProvider } : {},
|
|
2361
2477
|
...typeof sourceSettings.defaultModel === "string" ? { defaultModel: sourceSettings.defaultModel } : {},
|
|
@@ -2363,15 +2479,15 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2363
2479
|
"npm:pi-mcp-adapter",
|
|
2364
2480
|
...telemetry ? [telemetry.packageSpec] : [],
|
|
2365
2481
|
...webAccess ? [webAccess.packageSpec] : [],
|
|
2366
|
-
|
|
2482
|
+
...!sourceAcquisition && browserUse ? [browserUse.packageSpec] : []
|
|
2367
2483
|
],
|
|
2368
2484
|
...telemetry ? { "pi-telemetry": telemetry.config } : {},
|
|
2369
|
-
...webAccess ? { "pi-web-access":
|
|
2370
|
-
|
|
2485
|
+
...webAccess ? { "pi-web-access": webAccess.config } : {},
|
|
2486
|
+
...!sourceAcquisition && browserUse ? {
|
|
2371
2487
|
plugins: {
|
|
2372
2488
|
[MANAGED_BROWSER_USE_PLUGIN]: browserUse.plugin
|
|
2373
2489
|
},
|
|
2374
|
-
"pi-browser-use":
|
|
2490
|
+
"pi-browser-use": browserUse.config
|
|
2375
2491
|
} : {}
|
|
2376
2492
|
};
|
|
2377
2493
|
writePrivateFile2(join4(agentDir, "settings.json"), `${JSON.stringify(settings, null, 2)}
|
|
@@ -2382,6 +2498,12 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
2382
2498
|
join4(extensionsDir, MANAGED_PI_MCP_ARGS_NORMALIZER_FILENAME),
|
|
2383
2499
|
managedPiMcpArgsNormalizerExtensionSource()
|
|
2384
2500
|
);
|
|
2501
|
+
if (sourceAcquisition && !copyPrivateFile(
|
|
2502
|
+
join4(source, "extensions", "amaster-source-acquisition.js"),
|
|
2503
|
+
join4(extensionsDir, "amaster-source-acquisition.js")
|
|
2504
|
+
)) {
|
|
2505
|
+
throw new Error("pi_managed_mcp_source_acquisition_extension_missing");
|
|
2506
|
+
}
|
|
2385
2507
|
copyPrivateFile(join4(source, "models.json"), join4(agentDir, "models.json"));
|
|
2386
2508
|
const authSource = join4(source, "auth.json");
|
|
2387
2509
|
const protectedValues = [];
|
|
@@ -2501,6 +2623,9 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
2501
2623
|
const restoredNativeSession = restoreManagedPiSessionRollout(input, sessionsRoot, runDir, executorHome, authority);
|
|
2502
2624
|
const configPath = join4(piCodingAgentDir, "mcp.json");
|
|
2503
2625
|
const config = {
|
|
2626
|
+
settings: {
|
|
2627
|
+
toolPrefix: "none"
|
|
2628
|
+
},
|
|
2504
2629
|
mcpServers: {
|
|
2505
2630
|
[SUPPORTED_SERVER_NAME2]: {
|
|
2506
2631
|
type: "http",
|
|
@@ -2523,8 +2648,6 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
2523
2648
|
PI_AGENT_MCP_SERVERS_FILE: configPath,
|
|
2524
2649
|
TMPDIR: tmp,
|
|
2525
2650
|
...input.sourceAcquisition ? {
|
|
2526
|
-
PI_WEB_ACCESS_RUNTIME_FETCH_MODE: record6(input.sourceAcquisition.profile).transport?.webFetchMode,
|
|
2527
|
-
PI_WEB_ACCESS_RUNTIME_OBSERVATION: "required",
|
|
2528
2651
|
PI_BROWSER_USE_RUNTIME_READ_POLICY: "required"
|
|
2529
2652
|
} : {}
|
|
2530
2653
|
};
|
|
@@ -3393,13 +3516,16 @@ function wikiAccessRuleLine(input) {
|
|
|
3393
3516
|
return "";
|
|
3394
3517
|
}
|
|
3395
3518
|
function fixedRules(input, includeIssueLine) {
|
|
3519
|
+
const issue = asRecord(asRecord(input.context).paperclipIssue);
|
|
3520
|
+
const businessOutcome = asRecord(asRecord(issue.taskRequirements).businessOutcome);
|
|
3521
|
+
const serverOwnedBusinessOutcomeReview = businessOutcome.mode === "required";
|
|
3396
3522
|
return [
|
|
3397
3523
|
"## AMaster Runtime Connector Task",
|
|
3398
3524
|
"MirrorX task.",
|
|
3399
3525
|
"Use only the declared workspace; make concrete progress and report concisely.",
|
|
3400
3526
|
"Before changing the task status to done, audit every explicit requirement in the task against the final evidence. A successful tool or document write proves delivery, not acceptance: inspect the delivered content for required sections, diagrams, tables, and factual constraints.",
|
|
3401
3527
|
"Do not leave stale in-progress wording such as \u201Ccurrent run\u201D in a terminal deliverable; rewrite it to the final observed state. Do not list finalization itself as remaining or next work in a terminal deliverable.",
|
|
3402
|
-
"If any requirement is missing or cannot be verified, do not mark done. To request review, use create_interaction with kind request_confirmation and payload.resolutionMode review; never call update_parent with status in_review. Otherwise keep the issue todo or blocked with the exact gap and next owner.",
|
|
3528
|
+
serverOwnedBusinessOutcomeReview ? "If any requirement is missing or cannot be verified, do not mark done or request final completion or Business Outcome review. Keep the issue in_progress or blocked with the exact gap and next owner. An intermediate review remains available only for an exact document revision that must be approved before execution can continue: use create_interaction with kind request_confirmation, payload.resolutionMode review, and purposeCode review_document_revision; never use that interaction as final completion or Outcome acceptance." : "If any requirement is missing or cannot be verified, do not mark done. To request review, use create_interaction with kind request_confirmation and payload.resolutionMode review; never call update_parent with status in_review. Otherwise keep the issue todo or blocked with the exact gap and next owner.",
|
|
3403
3529
|
DEADLINE_POSTURE_GUARD,
|
|
3404
3530
|
"Do not install operating-system or user-global packages, and do not use host package managers such as brew, apt, yum, or global pip/npm installs. Use tools already available or workspace-local dependencies or virtual environments. If a required renderer or evaluator is unavailable, keep the source artifact, record the exact verification gap, and do not mutate the host.",
|
|
3405
3531
|
`- command id: ${input.commandId}`,
|
|
@@ -3433,7 +3559,7 @@ function interactionResolutionText(context) {
|
|
|
3433
3559
|
if (Object.keys(resolution).length === 0) return "";
|
|
3434
3560
|
const target = asRecord(resolution.target);
|
|
3435
3561
|
const exactDocumentRevisionDirective = readString(resolution.status) === "changes_requested" && readString(target.type) === "issue_document" && readString(target.issueId) && readString(target.documentId) && readString(target.key) && readString(target.revisionId) ? [
|
|
3436
|
-
"The review target is an exact issue_document revision. Revise that same document with upsert_document_revision: copy target.issueId, target.documentId, and target.key,
|
|
3562
|
+
"The review target is an exact issue_document revision. Revise that same document with upsert_document_revision: copy target.issueId, target.documentId, and target.key, use target.revisionId as baseRevisionId, and put the complete revised markdown in the required action.body; metadata-only revisions are invalid.",
|
|
3437
3563
|
"Do not copy the reviewed document into the current issue and do not restart its revision lineage at 1."
|
|
3438
3564
|
].join(" ") : "";
|
|
3439
3565
|
return [
|
|
@@ -3544,7 +3670,10 @@ function runtimeAuthorizationText(context, mode, { suppressOrdinaryCompletionCon
|
|
|
3544
3670
|
optionId: readString(optionId)
|
|
3545
3671
|
})).filter((entry) => entry.optionId && !allowed.has(entry.authorizationClass));
|
|
3546
3672
|
const issue = asRecord(context.paperclipIssue);
|
|
3547
|
-
const
|
|
3673
|
+
const requirements = asRecord(issue.taskRequirements);
|
|
3674
|
+
const completion = asRecord(requirements.completion);
|
|
3675
|
+
const delivery = asRecord(requirements.delivery);
|
|
3676
|
+
const businessOutcome = asRecord(requirements.businessOutcome);
|
|
3548
3677
|
const completionRole = readString(completion.role);
|
|
3549
3678
|
const completionDeliverable = readString(completion.deliverable);
|
|
3550
3679
|
const manifestRefreshOnly = isManifestRefreshOnly(context);
|
|
@@ -3554,13 +3683,26 @@ function runtimeAuthorizationText(context, mode, { suppressOrdinaryCompletionCon
|
|
|
3554
3683
|
firstDocumentCheckpoint,
|
|
3555
3684
|
"If work remains in an ordinary productive run, call update_parent with status: in_progress and a concrete next action so bounded continuation recovery can preserve a live path. Status: todo does not queue a normal continuation from an ordinary productive run. Only a server-issued successful-run handoff recovery may use status: todo, and only according to its exact Recovery Instruction. Otherwise use a supported terminal or waiting disposition."
|
|
3556
3685
|
].filter(Boolean).join(" ") : "";
|
|
3686
|
+
const businessOutcomeOwnershipContract = businessOutcome.mode === "required" ? [
|
|
3687
|
+
"Business Outcome review is owned by the Server terminal reconciler.",
|
|
3688
|
+
"Do not create a generic review-mode request_confirmation to ask the Board to accept final completion or the Outcome, and do not mark the issue done yourself. This does not prohibit an explicit intermediate review of an exact document revision before execution continues."
|
|
3689
|
+
].join(" ") : "";
|
|
3690
|
+
const businessOutcomeTerminalContract = !suppressOrdinaryCompletionContract && businessOutcome.mode === "required" ? [
|
|
3691
|
+
delivery.mode === "required" ? "When every acceptance criterion is satisfied and the exact current Delivery Manifest is ready, record the final execution disposition with update_parent status in_progress and a concise evidence summary, then end the run successfully without creating a final review interaction." : "When every acceptance criterion is satisfied, record the final execution disposition with update_parent status in_progress and a concise evidence summary, then end the run successfully without creating a final review interaction.",
|
|
3692
|
+
delivery.mode === "required" ? "Only after the run and command succeed does the Server bind the exact current Delivery Manifest and terminal Outcome evidence, create the formal Board review before generic continuation handoff is evaluated, and move the issue to in_review. Board acceptance then finalizes the issue as done atomically." : "Only after the run and command succeed does the Server bind the terminal Outcome evidence, create the formal Board review before generic continuation handoff is evaluated, and move the issue to in_review. Board acceptance then finalizes the issue as done atomically."
|
|
3693
|
+
].join(" ") : "";
|
|
3557
3694
|
const authorizationContract = missing.length > 0 ? [
|
|
3558
3695
|
`Current allowed action classes: ${[...allowed].join(", ") || "task_governance"}.`,
|
|
3559
3696
|
"If the task requires a missing runtime action class, create a request_checkbox_confirmation interaction using the exact option id below and wait for its accepted continuation:",
|
|
3560
3697
|
...missing.map((entry) => `- ${entry.authorizationClass}: ${entry.optionId}`),
|
|
3561
3698
|
"Never use request_confirmation to authorize a runtime action class."
|
|
3562
3699
|
].join("\n") : "";
|
|
3563
|
-
return [
|
|
3700
|
+
return [
|
|
3701
|
+
completionContract,
|
|
3702
|
+
businessOutcomeOwnershipContract,
|
|
3703
|
+
businessOutcomeTerminalContract,
|
|
3704
|
+
authorizationContract
|
|
3705
|
+
].filter(Boolean).join("\n");
|
|
3564
3706
|
}
|
|
3565
3707
|
function runtimeDecompositionRequirementText(context) {
|
|
3566
3708
|
const issue = asRecord(context.paperclipIssue);
|
|
@@ -3685,12 +3827,13 @@ function piMcpProxyExamplesText(input) {
|
|
|
3685
3827
|
args: JSON.stringify(args)
|
|
3686
3828
|
});
|
|
3687
3829
|
return [
|
|
3688
|
-
"The Pi native tool is the outer `mcp` proxy. Emit these as actual tool calls; `args` is the stringified inner canonical object
|
|
3830
|
+
"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`:",
|
|
3689
3831
|
"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`.",
|
|
3832
|
+
"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.",
|
|
3690
3833
|
"update_parent.comment creates a separate persistent issue comment. Omit it when add_comment already recorded the message.",
|
|
3691
3834
|
`- describe: ${proxy("runtime_action.describe", { schemaVersion: "runtime-action-v1", actionType: "update_parent" })}`,
|
|
3692
3835
|
`- submit: ${proxy("runtime_action.submit", { schemaVersion: "runtime-action-v1", idempotencyKey: "task-123-progress", action: { type: "update_parent", status: "in_progress" } })}`,
|
|
3693
|
-
`- submit 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 } } } })}`,
|
|
3836
|
+
`- 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 } } } })}`,
|
|
3694
3837
|
`- plan: ${proxy("runtime_action.plan", { schemaVersion: "runtime-action-v1", idempotencyKey: "task-123-plan", actions: [{ type: "update_parent", status: "in_progress" }] })}`,
|
|
3695
3838
|
`- commit the returned plan revision: ${proxy("runtime_action.commit", { schemaVersion: "runtime-action-v1", planId: "11111111-1111-4111-8111-111111111111", revision: "plan-revision-1" })}`,
|
|
3696
3839
|
`- read document: ${proxy("amaster.read_issue_document", { issueId: "AM-123", key: "plan" })}`
|
|
@@ -4177,16 +4320,38 @@ function tcReadNumber(value, fallback = 0) {
|
|
|
4177
4320
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
4178
4321
|
}
|
|
4179
4322
|
var TC_PI_ARGUMENT_VALIDATION_NODE_BUDGET = 4e3;
|
|
4180
|
-
|
|
4181
|
-
|
|
4323
|
+
var TC_PI_ARGUMENT_VALIDATION_PATTERN = /\binvalid(?:[_ -]+)tool(?:[_ -]+)arguments?\b|\binvalid args json\b|\btool[- ]arguments? (?:failed )?validation\b/i;
|
|
4324
|
+
function tcFindPiArgumentValidationText(value, depth = 0, seen = /* @__PURE__ */ new WeakSet(), budget = { remaining: TC_PI_ARGUMENT_VALIDATION_NODE_BUDGET }) {
|
|
4325
|
+
if (budget.remaining <= 0) return null;
|
|
4182
4326
|
budget.remaining -= 1;
|
|
4183
4327
|
if (typeof value === "string") {
|
|
4184
|
-
|
|
4328
|
+
const bounded = value.slice(0, 2e4);
|
|
4329
|
+
return TC_PI_ARGUMENT_VALIDATION_PATTERN.test(bounded) ? bounded : null;
|
|
4185
4330
|
}
|
|
4186
|
-
if (!value || typeof value !== "object" || depth >= 6 || seen.has(value)) return
|
|
4331
|
+
if (!value || typeof value !== "object" || depth >= 6 || seen.has(value)) return null;
|
|
4187
4332
|
seen.add(value);
|
|
4188
4333
|
const entries = Array.isArray(value) ? value.slice(0, 40).map((entry, index) => [String(index), entry]) : Object.entries(value).slice(0, 80);
|
|
4189
|
-
|
|
4334
|
+
for (const [, entry] of entries) {
|
|
4335
|
+
const match = tcFindPiArgumentValidationText(entry, depth + 1, seen, budget);
|
|
4336
|
+
if (match) return match;
|
|
4337
|
+
}
|
|
4338
|
+
return null;
|
|
4339
|
+
}
|
|
4340
|
+
function tcPiArgumentValidationDiagnostic(value) {
|
|
4341
|
+
const text = tcFindPiArgumentValidationText(value);
|
|
4342
|
+
if (!text) return null;
|
|
4343
|
+
const normalized = text.toLowerCase();
|
|
4344
|
+
const validationSource = /\binvalid args json\b/iu.test(text) ? "invalid_args_json" : /\binvalid(?:[_ -]+)tool(?:[_ -]+)arguments?\b/iu.test(text) ? "invalid_tool_arguments" : "tool_argument_validation";
|
|
4345
|
+
const parseErrorKind = validationSource !== "invalid_args_json" ? null : normalized.includes("unexpected end") ? "unexpected_end" : normalized.includes("unexpected token") || normalized.includes("unexpected non-whitespace") ? "unexpected_token" : normalized.includes("unterminated string") ? "unterminated_string" : normalized.includes("bad control character") ? "bad_control_character" : normalized.includes("bad escaped character") || normalized.includes("invalid escape") ? "bad_escape" : /expected (?:','|'\}'|':'|property name|double-quoted property)/u.test(normalized) ? "missing_delimiter" : "other";
|
|
4346
|
+
const rawPosition = validationSource === "invalid_args_json" ? text.match(/\bposition\s+(\d{1,9})\b/iu)?.[1] : null;
|
|
4347
|
+
const parseErrorPosition = rawPosition ? Number(rawPosition) : null;
|
|
4348
|
+
return {
|
|
4349
|
+
validationSource,
|
|
4350
|
+
validationPath: validationSource === "invalid_args_json" ? "$.args" : "$",
|
|
4351
|
+
pathPrecision: validationSource === "invalid_args_json" ? "exact" : "root_only",
|
|
4352
|
+
...parseErrorKind ? { parseErrorKind } : {},
|
|
4353
|
+
...typeof parseErrorPosition === "number" && Number.isSafeInteger(parseErrorPosition) && parseErrorPosition >= 0 ? { parseErrorPosition } : {}
|
|
4354
|
+
};
|
|
4190
4355
|
}
|
|
4191
4356
|
function tcTruncateText(value, maxChars = 16e3) {
|
|
4192
4357
|
const text = String(value ?? "");
|
|
@@ -4559,7 +4724,7 @@ function summarizePiEvent(event) {
|
|
|
4559
4724
|
if (type === "tool_execution_start" || type === "tool_execution_end") {
|
|
4560
4725
|
const toolName = tcReadString(event.toolName) ?? "unknown";
|
|
4561
4726
|
const completed = type === "tool_execution_end";
|
|
4562
|
-
const
|
|
4727
|
+
const argumentValidationDiagnostic = completed && event.isError === true ? tcPiArgumentValidationDiagnostic(event.result) : null;
|
|
4563
4728
|
return {
|
|
4564
4729
|
stream: "system",
|
|
4565
4730
|
level: completed && event.isError === true ? "error" : "info",
|
|
@@ -4570,7 +4735,7 @@ function summarizePiEvent(event) {
|
|
|
4570
4735
|
toolName,
|
|
4571
4736
|
toolCallId: tcReadString(event.toolCallId),
|
|
4572
4737
|
status: completed ? event.isError === true ? "failed" : "completed" : "started",
|
|
4573
|
-
...
|
|
4738
|
+
...argumentValidationDiagnostic ? { errorCode: "invalid_tool_arguments", ...argumentValidationDiagnostic } : {}
|
|
4574
4739
|
}
|
|
4575
4740
|
};
|
|
4576
4741
|
}
|
|
@@ -4726,6 +4891,7 @@ function governedMcpToolResult(structuredContent) {
|
|
|
4726
4891
|
if (!status) return null;
|
|
4727
4892
|
const invocationId = readString(structuredContent.invocationId);
|
|
4728
4893
|
const providerContent = asRecord(structuredContent.content);
|
|
4894
|
+
const providerReceipt = asRecord(structuredContent.providerReceipt);
|
|
4729
4895
|
const providerStatus = readString(providerContent.status);
|
|
4730
4896
|
const providerResult = asRecord(providerContent.result);
|
|
4731
4897
|
const effectResult = asRecord(providerResult.effectResult);
|
|
@@ -4742,12 +4908,23 @@ function governedMcpToolResult(structuredContent) {
|
|
|
4742
4908
|
...readString(providerResult.planId) ? { planId: readString(providerResult.planId) } : {},
|
|
4743
4909
|
...readString(providerResult.status) ? { resultStatus: readString(providerResult.status) } : {}
|
|
4744
4910
|
} : null;
|
|
4911
|
+
const diagnosisId = readString(providerContent.diagnosisId);
|
|
4912
|
+
const diagnosisRevision = readNumber(providerContent.diagnosisRevision, 0);
|
|
4913
|
+
const documentRevisionId = readString(providerContent.documentRevisionId);
|
|
4914
|
+
const workProductId = readString(providerContent.workProductId);
|
|
4915
|
+
const diagnosisBrief = status === "succeeded" && invocationId && readString(providerReceipt.provider) === "amaster_actions" && readString(providerReceipt.invocationId) === invocationId && readString(providerReceipt.status) === "accepted" && readString(providerReceipt.writeKind) === "company_diagnosis_brief" && diagnosisId && Number.isSafeInteger(diagnosisRevision) && diagnosisRevision > 0 && documentRevisionId && workProductId ? {
|
|
4916
|
+
diagnosisId,
|
|
4917
|
+
diagnosisRevision,
|
|
4918
|
+
documentRevisionId,
|
|
4919
|
+
workProductId
|
|
4920
|
+
} : null;
|
|
4745
4921
|
return {
|
|
4746
4922
|
...invocationId ? { invocationId } : {},
|
|
4747
4923
|
status,
|
|
4748
4924
|
...providerStatus ? { providerStatus } : {},
|
|
4749
4925
|
...artifactIntent ? { artifactIntent } : {},
|
|
4750
|
-
...runtimeAction ? { runtimeAction } : {}
|
|
4926
|
+
...runtimeAction ? { runtimeAction } : {},
|
|
4927
|
+
...diagnosisBrief ? { diagnosisBrief } : {}
|
|
4751
4928
|
};
|
|
4752
4929
|
}
|
|
4753
4930
|
function dedupeGovernedMcpToolResults(results) {
|
|
@@ -4820,10 +4997,23 @@ function finalizedPiRuntimeArtifactEvidence(runtimeArtifacts) {
|
|
|
4820
4997
|
...intentId ? { intentId } : {}
|
|
4821
4998
|
};
|
|
4822
4999
|
}
|
|
5000
|
+
function durablePiDiagnosisBriefEvidence(results) {
|
|
5001
|
+
const result3 = (Array.isArray(results) ? results : []).map(asRecord).find((entry) => readString(entry.status) === "succeeded" && Object.keys(asRecord(entry.diagnosisBrief)).length > 0);
|
|
5002
|
+
if (!result3) return null;
|
|
5003
|
+
const brief = asRecord(result3.diagnosisBrief);
|
|
5004
|
+
return {
|
|
5005
|
+
kind: "company_diagnosis_brief",
|
|
5006
|
+
invocationId: readString(result3.invocationId),
|
|
5007
|
+
diagnosisId: readString(brief.diagnosisId),
|
|
5008
|
+
diagnosisRevision: readNumber(brief.diagnosisRevision, 0),
|
|
5009
|
+
documentRevisionId: readString(brief.documentRevisionId),
|
|
5010
|
+
workProductId: readString(brief.workProductId)
|
|
5011
|
+
};
|
|
5012
|
+
}
|
|
4823
5013
|
function classifyPiTerminalCleanupDisposition(parsed, runtimeArtifacts) {
|
|
4824
5014
|
const diagnostics = Array.isArray(parsed?.cleanupDiagnostics) ? parsed.cleanupDiagnostics.map(asRecord) : [];
|
|
4825
5015
|
if (parsed?.terminalEventType !== "agent_end" || readString(parsed?.stopReason) || parsed?.hasAssistantOutput !== true || diagnostics.length === 0 || diagnostics.some((diagnostic) => readString(diagnostic.phase) !== "post_terminal" || readString(diagnostic.code) !== "pi_terminal_cleanup_permission_denied") || readNumber(parsed?.nonCleanupErrorCount, 0) > 0) return null;
|
|
4826
|
-
const durableEvidence = durablePiRuntimeActionEvidence(parsed?.mcpToolResults) ?? finalizedPiRuntimeArtifactEvidence(runtimeArtifacts);
|
|
5016
|
+
const durableEvidence = durablePiRuntimeActionEvidence(parsed?.mcpToolResults) ?? durablePiDiagnosisBriefEvidence(parsed?.mcpToolResults) ?? finalizedPiRuntimeArtifactEvidence(runtimeArtifacts);
|
|
4827
5017
|
if (!durableEvidence) return null;
|
|
4828
5018
|
return {
|
|
4829
5019
|
status: "failed",
|
|
@@ -6764,7 +6954,7 @@ function within3(candidate, root) {
|
|
|
6764
6954
|
const rel = relative6(root, candidate);
|
|
6765
6955
|
return rel === "" || !rel.startsWith("..") && !isAbsolute6(rel);
|
|
6766
6956
|
}
|
|
6767
|
-
function
|
|
6957
|
+
function readJsonFile2(path, label, fallback = {}) {
|
|
6768
6958
|
if (!existsSync11(path)) return fallback;
|
|
6769
6959
|
const stat = lstatSync6(path);
|
|
6770
6960
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
@@ -6815,8 +7005,8 @@ function copyTreeNoLinks(source, target) {
|
|
|
6815
7005
|
chmodSync5(target, 384 | stat.mode & 73);
|
|
6816
7006
|
}
|
|
6817
7007
|
function mergeMcp(seedRoot, overlayRoot, governedConfig) {
|
|
6818
|
-
const seed = record5(
|
|
6819
|
-
const overlay = record5(
|
|
7008
|
+
const seed = record5(readJsonFile2(join12(seedRoot, "mcp.json"), "seed_mcp", { mcpServers: {} }));
|
|
7009
|
+
const overlay = record5(readJsonFile2(join12(overlayRoot, "mcp.json"), "overlay_mcp", { mcpServers: {} }));
|
|
6820
7010
|
assertNoPersistentSecrets(seed, ["seed", "mcp.json"]);
|
|
6821
7011
|
assertNoPersistentSecrets(overlay, ["overlay", "mcp.json"]);
|
|
6822
7012
|
const seedServers = record5(seed.mcpServers);
|
|
@@ -6852,7 +7042,7 @@ function assertEnabledPackagesAvailable(settings, npmRoot) {
|
|
|
6852
7042
|
}
|
|
6853
7043
|
for (const name of requiredNames) {
|
|
6854
7044
|
const metadataPath = join12(npmRoot, "node_modules", ...name.split("/"), "package.json");
|
|
6855
|
-
const metadata =
|
|
7045
|
+
const metadata = readJsonFile2(metadataPath, `package:${name}`, null);
|
|
6856
7046
|
if (!metadata || metadata.name !== name) {
|
|
6857
7047
|
throw new Error(`pi_trusted_runtime_package_unavailable:${name}`);
|
|
6858
7048
|
}
|
|
@@ -6880,8 +7070,8 @@ function materializeTrustedPiRuntimeProfile(input) {
|
|
|
6880
7070
|
}
|
|
6881
7071
|
const mergedJson = {};
|
|
6882
7072
|
for (const entry of JSON_ENTRIES) {
|
|
6883
|
-
const seed =
|
|
6884
|
-
const overlay =
|
|
7073
|
+
const seed = readJsonFile2(join12(seedRoot, entry), `seed_${entry}`, {});
|
|
7074
|
+
const overlay = readJsonFile2(join12(overlayRoot, entry), `overlay_${entry}`, {});
|
|
6885
7075
|
const merged = deepMerge(seed, overlay);
|
|
6886
7076
|
if (entry === "settings.json") {
|
|
6887
7077
|
merged["pi-security"] = {
|
|
@@ -6901,7 +7091,7 @@ function materializeTrustedPiRuntimeProfile(input) {
|
|
|
6901
7091
|
chmodSync5(join12(agentDir, entry), 384);
|
|
6902
7092
|
mergedJson[entry] = merged;
|
|
6903
7093
|
}
|
|
6904
|
-
const governedConfig =
|
|
7094
|
+
const governedConfig = readJsonFile2(input.governedMcpConfigPath, "governed_mcp");
|
|
6905
7095
|
const mcp = mergeMcp(seedRoot, overlayRoot, governedConfig);
|
|
6906
7096
|
writeFileSync8(input.governedMcpConfigPath, `${JSON.stringify(mcp, null, 2)}
|
|
6907
7097
|
`, { mode: 384 });
|
|
@@ -7947,20 +8137,17 @@ async function executeBrowserSessionCommand(command, dependencies = {}) {
|
|
|
7947
8137
|
}
|
|
7948
8138
|
|
|
7949
8139
|
// src/amaster-runtime-daemon/source-acquisition-invocation.mjs
|
|
8140
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
7950
8141
|
var SOURCE_ACQUISITION_PUBLIC_TOOLS = Object.freeze([
|
|
7951
|
-
"
|
|
7952
|
-
"
|
|
7953
|
-
"
|
|
7954
|
-
"
|
|
7955
|
-
"
|
|
7956
|
-
"browser_analyze_screenshot",
|
|
7957
|
-
"browser_wait_for",
|
|
8142
|
+
"source_open",
|
|
8143
|
+
"source_snapshot",
|
|
8144
|
+
"source_screenshot",
|
|
8145
|
+
"source_analyze_screenshot",
|
|
8146
|
+
"source_wait",
|
|
7958
8147
|
"runtime_action.submit",
|
|
7959
8148
|
"runtime_action.status"
|
|
7960
8149
|
]);
|
|
7961
|
-
var SOURCE_ACQUISITION_AUTHENTICATED_TOOLS =
|
|
7962
|
-
SOURCE_ACQUISITION_PUBLIC_TOOLS.filter((tool) => tool !== "web_fetch")
|
|
7963
|
-
);
|
|
8150
|
+
var SOURCE_ACQUISITION_AUTHENTICATED_TOOLS = SOURCE_ACQUISITION_PUBLIC_TOOLS;
|
|
7964
8151
|
function exactToolsFor(profile) {
|
|
7965
8152
|
if (profile?.access?.mode === "public") return SOURCE_ACQUISITION_PUBLIC_TOOLS;
|
|
7966
8153
|
if (profile?.access?.mode === "authenticated") return SOURCE_ACQUISITION_AUTHENTICATED_TOOLS;
|
|
@@ -7982,6 +8169,34 @@ function sourceAcquisitionPiInvocationArgs(profile) {
|
|
|
7982
8169
|
"--no-session"
|
|
7983
8170
|
];
|
|
7984
8171
|
}
|
|
8172
|
+
function serializeSourceAcquisitionProfile(profile) {
|
|
8173
|
+
if (!profile || typeof profile !== "object" || Array.isArray(profile)) return null;
|
|
8174
|
+
const input = Buffer.from(JSON.stringify(profile), "utf8");
|
|
8175
|
+
return {
|
|
8176
|
+
input,
|
|
8177
|
+
sha256: createHash10("sha256").update(input).digest("hex")
|
|
8178
|
+
};
|
|
8179
|
+
}
|
|
8180
|
+
function sourceAcquisitionManagedInputs(options) {
|
|
8181
|
+
return [
|
|
8182
|
+
options.managedInput ? { fd: 3, input: options.managedInput, code: "managed_runtime_assertion" } : null,
|
|
8183
|
+
options.sourceProfileInput ? { fd: 4, input: options.sourceProfileInput, code: "source_acquisition_profile" } : null
|
|
8184
|
+
].filter(Boolean);
|
|
8185
|
+
}
|
|
8186
|
+
function sourceAcquisitionManagedStdio(inputs) {
|
|
8187
|
+
const stdio = ["pipe", "pipe", "pipe"];
|
|
8188
|
+
for (const { fd } of inputs) {
|
|
8189
|
+
while (stdio.length <= fd) stdio.push("ignore");
|
|
8190
|
+
stdio[fd] = "pipe";
|
|
8191
|
+
}
|
|
8192
|
+
return stdio;
|
|
8193
|
+
}
|
|
8194
|
+
function deliverSourceAcquisitionManagedInputs(child, inputs, onError) {
|
|
8195
|
+
for (const { fd, input, code } of inputs) {
|
|
8196
|
+
child.stdio[fd].once("error", (error) => onError(code, error));
|
|
8197
|
+
child.stdio[fd].end(input);
|
|
8198
|
+
}
|
|
8199
|
+
}
|
|
7985
8200
|
function assertSourceAcquisitionRuntimeAuthority({
|
|
7986
8201
|
profile,
|
|
7987
8202
|
executorKind,
|
|
@@ -7995,17 +8210,17 @@ function assertSourceAcquisitionRuntimeAuthority({
|
|
|
7995
8210
|
}
|
|
7996
8211
|
|
|
7997
8212
|
// src/amaster-runtime-daemon.mjs
|
|
7998
|
-
var CONNECTOR_VERSION = "0.1.1-beta.
|
|
8213
|
+
var CONNECTOR_VERSION = "0.1.1-beta.2";
|
|
7999
8214
|
var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
|
|
8000
8215
|
var SOURCE_ACQUISITION_CAPABILITY = "source_acquisition_v1";
|
|
8001
8216
|
var SOURCE_ACQUISITION_PROFILE_VERSION = "source_acquisition_v1";
|
|
8002
8217
|
var SOURCE_ACQUISITION_RETENTION_VERSION = "source_summary_only_v1";
|
|
8003
8218
|
var SOURCE_ACQUISITION_ACTION_VERSION = "complete_source_acquisition_v1";
|
|
8219
|
+
var SOURCE_ACQUISITION_HEADLESS_ADAPTER = "pi_browser_use_headless_v1";
|
|
8220
|
+
var SOURCE_ACQUISITION_DESKTOP_ADAPTER = "browser_skill_desktop_v1";
|
|
8004
8221
|
var SOURCE_ACQUISITION_PACKAGE_VERSIONS = Object.freeze({
|
|
8005
|
-
"@amaster.ai/pi-web-access": "0.1.2-beta.52",
|
|
8006
8222
|
"@amaster.ai/pi-browser-use": "0.1.2-beta.52"
|
|
8007
8223
|
});
|
|
8008
|
-
var SOURCE_ACQUISITION_CONNECTOR_VERSION = "0.1.1-beta.0";
|
|
8009
8224
|
var MAX_CHECKPOINT_BYTES = 20 * 1024 * 1024;
|
|
8010
8225
|
var CHECKPOINT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
8011
8226
|
var AMASTER_PI_PROHIBITED_EXTRA_ARGS = /* @__PURE__ */ new Set(["--no-extensions", "--no-skills", "--no-tools", "--no-session"]);
|
|
@@ -8536,14 +8751,11 @@ function sourceAcquisitionPackageMetadata(packageName2) {
|
|
|
8536
8751
|
if (!existsSync14(packagePath)) return null;
|
|
8537
8752
|
const stat = lstatSync7(packagePath);
|
|
8538
8753
|
if (!stat.isFile() || stat.isSymbolicLink()) return null;
|
|
8539
|
-
const metadata =
|
|
8754
|
+
const metadata = readJsonFile3(packagePath);
|
|
8540
8755
|
return metadata.name === packageName2 && readString(metadata.version) ? metadata : null;
|
|
8541
8756
|
}
|
|
8542
8757
|
function sourceAcquisitionRuntimeReadiness(config) {
|
|
8543
8758
|
const unavailable = (reason) => ({ ready: false, reason });
|
|
8544
|
-
if (CONNECTOR_VERSION !== SOURCE_ACQUISITION_CONNECTOR_VERSION) {
|
|
8545
|
-
return unavailable("source_acquisition_connector_version_mismatch");
|
|
8546
|
-
}
|
|
8547
8759
|
const piExecutor = config.executors.find((executor) => executor.kind === "pi");
|
|
8548
8760
|
if (!piExecutor || !commandExists(piExecutor.command, {
|
|
8549
8761
|
...process.env,
|
|
@@ -8565,9 +8777,16 @@ function sourceAcquisitionRuntimeReadiness(config) {
|
|
|
8565
8777
|
return unavailable("source_acquisition_trusted_runtime_invalid");
|
|
8566
8778
|
}
|
|
8567
8779
|
const packageDigests = {
|
|
8568
|
-
"@amaster.ai/pi-web-access": readString(process.env.AMASTER_SOURCE_ACQUISITION_PI_WEB_ACCESS_DIGEST),
|
|
8569
8780
|
"@amaster.ai/pi-browser-use": readString(process.env.AMASTER_SOURCE_ACQUISITION_PI_BROWSER_USE_DIGEST)
|
|
8570
8781
|
};
|
|
8782
|
+
const extensionDigest = readString(process.env.AMASTER_SOURCE_ACQUISITION_EXTENSION_DIGEST);
|
|
8783
|
+
if (!extensionDigest || !/^[a-f0-9]{64}$/.test(extensionDigest)) {
|
|
8784
|
+
return unavailable("source_acquisition_extension_digest_unavailable");
|
|
8785
|
+
}
|
|
8786
|
+
const adapters = (readString(process.env.AMASTER_SOURCE_ACQUISITION_ADAPTERS) ?? "").split(",").map((value) => value.trim()).filter(Boolean);
|
|
8787
|
+
if (adapters.length === 0 || adapters.some((adapter) => ![SOURCE_ACQUISITION_HEADLESS_ADAPTER, SOURCE_ACQUISITION_DESKTOP_ADAPTER].includes(adapter))) {
|
|
8788
|
+
return unavailable("source_acquisition_adapter_attestation_invalid");
|
|
8789
|
+
}
|
|
8571
8790
|
const connectorDigest = readString(process.env.AMASTER_SOURCE_ACQUISITION_CONNECTOR_DIGEST);
|
|
8572
8791
|
if (!connectorDigest || !/^[a-f0-9]{64}$/.test(connectorDigest)) {
|
|
8573
8792
|
return unavailable("source_acquisition_connector_digest_unavailable");
|
|
@@ -8589,6 +8808,8 @@ function sourceAcquisitionRuntimeReadiness(config) {
|
|
|
8589
8808
|
profileVersion: SOURCE_ACQUISITION_PROFILE_VERSION,
|
|
8590
8809
|
retentionVersion: SOURCE_ACQUISITION_RETENTION_VERSION,
|
|
8591
8810
|
actionVersion: SOURCE_ACQUISITION_ACTION_VERSION,
|
|
8811
|
+
extension: { digest: extensionDigest },
|
|
8812
|
+
adapters,
|
|
8592
8813
|
connector: {
|
|
8593
8814
|
version: CONNECTOR_VERSION,
|
|
8594
8815
|
digest: connectorDigest
|
|
@@ -8703,10 +8924,10 @@ function piAgentSystemDataDir(config) {
|
|
|
8703
8924
|
return configured ? resolve12(expandHomePath(configured)) : null;
|
|
8704
8925
|
}
|
|
8705
8926
|
function readPiAgentLocalPlatformCredential(credentialsDir) {
|
|
8706
|
-
const pointer =
|
|
8927
|
+
const pointer = readJsonFile3(join15(credentialsDir, "latest.json"));
|
|
8707
8928
|
const credentialRef = readString(pointer.credentialRef);
|
|
8708
8929
|
if (!credentialRef || !/^[a-f0-9]{64}$/i.test(credentialRef)) return null;
|
|
8709
|
-
const credential =
|
|
8930
|
+
const credential = readJsonFile3(join15(credentialsDir, `${credentialRef}.json`));
|
|
8710
8931
|
const organizationId = readString(credential.organizationId);
|
|
8711
8932
|
const apiKey = readString(credential.apiKey);
|
|
8712
8933
|
if (credential.version !== 1 || !organizationId || !apiKey) return null;
|
|
@@ -9270,16 +9491,16 @@ function sourceAcquisitionRuntimeProfile(config, command) {
|
|
|
9270
9491
|
const access = asRecord(profile.access);
|
|
9271
9492
|
const transport = asRecord(profile.transport);
|
|
9272
9493
|
const tools = asRecord(profile.tools);
|
|
9273
|
-
if (profile.purpose !== "source_acquisition_v1" || profile.retention !== "source_summary_only_v1" || readString(profile.runId) !== commandRunId(command) || !Array.isArray(tools.exactAllowlist) || tools.exactAllowlist.length === 0 || !["public", "authenticated"].includes(access.mode) || !["isolated", "existing"].includes(transport.browserMode) || ![
|
|
9494
|
+
if (profile.purpose !== "source_acquisition_v1" || profile.retention !== "source_summary_only_v1" || readString(profile.runId) !== commandRunId(command) || !Array.isArray(tools.exactAllowlist) || tools.exactAllowlist.length === 0 || !["public", "authenticated"].includes(access.mode) || !["isolated", "existing"].includes(transport.browserMode) || ![SOURCE_ACQUISITION_HEADLESS_ADAPTER, SOURCE_ACQUISITION_DESKTOP_ADAPTER].includes(transport.adapter)) {
|
|
9274
9495
|
throw new Error("source_acquisition_profile_invalid");
|
|
9275
9496
|
}
|
|
9276
9497
|
if (access.mode === "public") {
|
|
9277
|
-
if (transport.browserMode !== "isolated" || transport.
|
|
9498
|
+
if (transport.browserMode !== "isolated" || transport.adapter !== SOURCE_ACQUISITION_HEADLESS_ADAPTER) {
|
|
9278
9499
|
throw new Error("source_acquisition_profile_invalid");
|
|
9279
9500
|
}
|
|
9280
9501
|
return { profile };
|
|
9281
9502
|
}
|
|
9282
|
-
if (transport.browserMode !== "existing" || transport.
|
|
9503
|
+
if (transport.browserMode !== "existing" || transport.adapter !== SOURCE_ACQUISITION_DESKTOP_ADAPTER) {
|
|
9283
9504
|
throw new Error("source_acquisition_profile_invalid");
|
|
9284
9505
|
}
|
|
9285
9506
|
const companyId = readString(profile.companyId);
|
|
@@ -9288,12 +9509,12 @@ function sourceAcquisitionRuntimeProfile(config, command) {
|
|
|
9288
9509
|
if (!companyId || !bindingId || !/^profile_[a-z0-9]{16,64}$/i.test(localOpaqueRef ?? "")) {
|
|
9289
9510
|
throw new Error("source_acquisition_profile_invalid");
|
|
9290
9511
|
}
|
|
9291
|
-
const profileName2 =
|
|
9512
|
+
const profileName2 = createHash11("sha256").update(`${companyId}\0${bindingId}\0${localOpaqueRef}`).digest("hex");
|
|
9292
9513
|
const stateRoot = resolve12(config.browserSessionStateRoot);
|
|
9293
9514
|
const userDataDir = resolve12(stateRoot, profileName2);
|
|
9294
9515
|
if (!pathWithin2(userDataDir, stateRoot)) throw new Error("source_acquisition_browser_profile_invalid");
|
|
9295
9516
|
const markerPath = join15(userDataDir, ".amaster-browser-session.json");
|
|
9296
|
-
const marker =
|
|
9517
|
+
const marker = readJsonFile3(markerPath);
|
|
9297
9518
|
if (marker.version !== 1 || marker.companyId !== companyId || marker.bindingId !== bindingId || marker.localOpaqueRef !== localOpaqueRef || Object.keys(marker).length !== 4) {
|
|
9298
9519
|
throw new Error("source_acquisition_browser_profile_invalid");
|
|
9299
9520
|
}
|
|
@@ -9309,7 +9530,7 @@ function trustedPiRuntimeSources(config) {
|
|
|
9309
9530
|
policyFile: config.piRuntimeEffectivePolicyFile
|
|
9310
9531
|
};
|
|
9311
9532
|
}
|
|
9312
|
-
function
|
|
9533
|
+
function readJsonFile3(filePath) {
|
|
9313
9534
|
try {
|
|
9314
9535
|
const parsed = JSON.parse(readFileSync11(filePath, "utf8"));
|
|
9315
9536
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
@@ -9554,6 +9775,60 @@ function buildExecutorEnv(config, command, workspace) {
|
|
|
9554
9775
|
AMASTER_EMPLOYEE_COMPANY_ID: companyId
|
|
9555
9776
|
};
|
|
9556
9777
|
}
|
|
9778
|
+
function copyPiModelCallConfig(sourceRoot, targetRoot, fileName, required) {
|
|
9779
|
+
const source = join15(sourceRoot, fileName);
|
|
9780
|
+
if (!existsSync14(source)) {
|
|
9781
|
+
if (required) throw new Error(`pi_model_call_profile_missing: ${fileName}`);
|
|
9782
|
+
return;
|
|
9783
|
+
}
|
|
9784
|
+
const sourceStat = lstatSync7(source);
|
|
9785
|
+
if (!sourceStat.isFile() || sourceStat.isSymbolicLink()) {
|
|
9786
|
+
throw new Error(`pi_model_call_profile_unsafe: ${fileName}`);
|
|
9787
|
+
}
|
|
9788
|
+
const target = join15(targetRoot, fileName);
|
|
9789
|
+
copyFileSync3(source, target);
|
|
9790
|
+
chmodSync6(target, 384);
|
|
9791
|
+
}
|
|
9792
|
+
function preparePiModelCallProfile(commandId, baseEnv) {
|
|
9793
|
+
const sourceRoot = readString(process.env.PI_CODING_AGENT_DIR) ?? readString(process.env.PI_AGENT_HOME) ?? readString(process.env["AMASTER-CLI_CODING_AGENT_DIR"]);
|
|
9794
|
+
if (!sourceRoot) throw new Error("pi_model_call_profile_missing: source Pi home");
|
|
9795
|
+
const sourceStat = lstatSync7(sourceRoot);
|
|
9796
|
+
if (!sourceStat.isDirectory() || sourceStat.isSymbolicLink()) {
|
|
9797
|
+
throw new Error("pi_model_call_profile_unsafe: source Pi home");
|
|
9798
|
+
}
|
|
9799
|
+
const profileRoot = mkdtempSync(join15(tmpdir(), "amaster-pi-model-call-"));
|
|
9800
|
+
const home = join15(profileRoot, "home");
|
|
9801
|
+
const agentDir = join15(profileRoot, "agent");
|
|
9802
|
+
const sessionsDir = join15(profileRoot, "sessions");
|
|
9803
|
+
const tempDir = join15(profileRoot, "tmp");
|
|
9804
|
+
for (const directory of [home, agentDir, sessionsDir, tempDir]) {
|
|
9805
|
+
mkdirSync9(directory, { recursive: true, mode: 448 });
|
|
9806
|
+
}
|
|
9807
|
+
try {
|
|
9808
|
+
copyPiModelCallConfig(sourceRoot, agentDir, "models.json", true);
|
|
9809
|
+
copyPiModelCallConfig(sourceRoot, agentDir, "auth.json", false);
|
|
9810
|
+
return {
|
|
9811
|
+
profileRoot,
|
|
9812
|
+
env: {
|
|
9813
|
+
...baseEnv,
|
|
9814
|
+
HOME: home,
|
|
9815
|
+
PI_AGENT_HOME: agentDir,
|
|
9816
|
+
PI_CODING_AGENT_DIR: agentDir,
|
|
9817
|
+
"AMASTER-CLI_CODING_AGENT_DIR": agentDir,
|
|
9818
|
+
PI_CODING_AGENT_SESSION_DIR: sessionsDir,
|
|
9819
|
+
"AMASTER-CLI_CODING_AGENT_SESSION_DIR": sessionsDir,
|
|
9820
|
+
TMPDIR: tempDir,
|
|
9821
|
+
AMASTER_RUNTIME_COMMAND_ID: commandId
|
|
9822
|
+
}
|
|
9823
|
+
};
|
|
9824
|
+
} catch (error) {
|
|
9825
|
+
rmSync7(profileRoot, { recursive: true, force: true });
|
|
9826
|
+
throw error;
|
|
9827
|
+
}
|
|
9828
|
+
}
|
|
9829
|
+
function cleanupPiModelCallProfile(profile) {
|
|
9830
|
+
if (profile?.profileRoot) rmSync7(profile.profileRoot, { recursive: true, force: true });
|
|
9831
|
+
}
|
|
9557
9832
|
function splitExtraArgs(value) {
|
|
9558
9833
|
return splitList(value).flatMap((entry) => entry.split(/\s+/).filter(Boolean));
|
|
9559
9834
|
}
|
|
@@ -9714,15 +9989,27 @@ async function executeModelCallCommand(config, command, signal) {
|
|
|
9714
9989
|
purpose: readString(payload.purpose) ?? null,
|
|
9715
9990
|
promptBytes: Buffer.byteLength(prompt, "utf8")
|
|
9716
9991
|
});
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9720
|
-
|
|
9721
|
-
|
|
9722
|
-
|
|
9723
|
-
|
|
9724
|
-
|
|
9725
|
-
|
|
9992
|
+
let piModelCallProfile = null;
|
|
9993
|
+
let execution;
|
|
9994
|
+
try {
|
|
9995
|
+
const baseEnv = buildExecutorEnv(config, command, {
|
|
9996
|
+
managed: false,
|
|
9997
|
+
cwd: process.cwd(),
|
|
9998
|
+
sourceWorkspacePath: process.cwd()
|
|
9999
|
+
});
|
|
10000
|
+
piModelCallProfile = executor.kind === "pi" ? preparePiModelCallProfile(command.commandId, baseEnv) : null;
|
|
10001
|
+
execution = await runExecutor(invocation.command, invocation.args, {
|
|
10002
|
+
cwd: process.cwd(),
|
|
10003
|
+
env: piModelCallProfile?.env ?? baseEnv,
|
|
10004
|
+
stdin: invocation.stdin === "prompt" ? prompt : "",
|
|
10005
|
+
timeoutSeconds,
|
|
10006
|
+
maxOutputBytes,
|
|
10007
|
+
executorKind: executor.kind,
|
|
10008
|
+
signal
|
|
10009
|
+
});
|
|
10010
|
+
} finally {
|
|
10011
|
+
cleanupPiModelCallProfile(piModelCallProfile);
|
|
10012
|
+
}
|
|
9726
10013
|
if (execution.stdout) {
|
|
9727
10014
|
await ingestLog(config, command, "stdout", "info", truncateText(execution.stdout, 4e3));
|
|
9728
10015
|
}
|
|
@@ -10330,11 +10617,12 @@ function runExecutor(command, args, options) {
|
|
|
10330
10617
|
const maxRssMb = parsePositiveInteger(options.maxRssMb, 0);
|
|
10331
10618
|
const maxRssBytes = maxRssMb * 1024 * 1024;
|
|
10332
10619
|
const spawnInvocation = managedChildSpawnInvocation(command, args, options.spawnIdentity);
|
|
10620
|
+
const managedInputs = sourceAcquisitionManagedInputs(options);
|
|
10333
10621
|
const child = spawn2(spawnInvocation.command, spawnInvocation.args, {
|
|
10334
10622
|
cwd: options.cwd,
|
|
10335
10623
|
env: options.env,
|
|
10336
10624
|
detached: process.platform !== "win32",
|
|
10337
|
-
stdio:
|
|
10625
|
+
stdio: sourceAcquisitionManagedStdio(managedInputs),
|
|
10338
10626
|
...spawnInvocation.spawnIdentity
|
|
10339
10627
|
});
|
|
10340
10628
|
const processGroupId = processGroupIdForChild(child);
|
|
@@ -10370,13 +10658,10 @@ function runExecutor(command, args, options) {
|
|
|
10370
10658
|
signalExecutorProcess(child, "SIGTERM", processGroupId);
|
|
10371
10659
|
scheduleStopKill();
|
|
10372
10660
|
};
|
|
10373
|
-
|
|
10374
|
-
|
|
10375
|
-
|
|
10376
|
-
|
|
10377
|
-
});
|
|
10378
|
-
child.stdio[3].end(options.managedInput);
|
|
10379
|
-
}
|
|
10661
|
+
deliverSourceAcquisitionManagedInputs(child, managedInputs, (code, error) => {
|
|
10662
|
+
spawnError = `${code}_delivery_failed: ${error.message}`;
|
|
10663
|
+
requestStop(`${code}_delivery_failed`);
|
|
10664
|
+
});
|
|
10380
10665
|
const reapStoppedWorkspaceResidents = () => {
|
|
10381
10666
|
if (settled || !stopReason || stopReason === "completion_cleanup") return;
|
|
10382
10667
|
const residents = listWorkspaceResidentProcesses(options.cwd, processGroupId, {
|
|
@@ -10980,6 +11265,7 @@ async function executeRunExitClosureTurn(config, inputState, options = {}) {
|
|
|
10980
11265
|
executorKind,
|
|
10981
11266
|
...readNumber(storedSpawnIdentity.uid, 0) > 0 ? { spawnIdentity: storedSpawnIdentity } : {},
|
|
10982
11267
|
...readString(executionConfig.managedInput) ? { managedInput: readString(executionConfig.managedInput) } : {},
|
|
11268
|
+
...readString(executionConfig.sourceProfileInput) ? { sourceProfileInput: readString(executionConfig.sourceProfileInput) } : {},
|
|
10983
11269
|
onOutput: (stream, chunk, rawBytes) => {
|
|
10984
11270
|
noteActiveRunOutput(command, stream, chunk, rawBytes);
|
|
10985
11271
|
liveOutputLogger.write(stream, chunk);
|
|
@@ -10995,24 +11281,24 @@ async function executeRunExitClosureTurn(config, inputState, options = {}) {
|
|
|
10995
11281
|
const memoryLimit = asRecord(execution.memoryLimit);
|
|
10996
11282
|
const hasMemoryLimit = readNumber(memoryLimit.rssBytes, 0) > 0;
|
|
10997
11283
|
const parsed = parseExecutorTurnOutput(executorKind, execution, liveOutputLogger, hasOutputFlood);
|
|
11284
|
+
const mcpToolResults = dedupeGovernedMcpToolResults([
|
|
11285
|
+
...Array.isArray(parsed.mcpToolResults) ? parsed.mcpToolResults.map(asRecord) : [],
|
|
11286
|
+
...liveOutputLogger.mcpToolResults().map(asRecord)
|
|
11287
|
+
]);
|
|
10998
11288
|
const outputTelemetry = liveOutputLogger.snapshot({
|
|
10999
11289
|
outputBytes: execution.outputBytes,
|
|
11000
11290
|
floodLimitBytes: Math.max(1, readNumber(executionConfig.maxOutputBytes, config.executorMaxOutputBytes)),
|
|
11001
11291
|
outputTokens: readNumber(parsed.usage?.outputTokens, 0)
|
|
11002
11292
|
});
|
|
11003
11293
|
const completionOutputStopped = executorKind === "pi" && piCompletionOutputStopped(parsed, execution);
|
|
11004
|
-
const cleanupDisposition = executorKind === "pi" && execution.cancelled !== true && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError && execution.signal === null ? classifyPiTerminalCleanupDisposition(parsed, []) : null;
|
|
11294
|
+
const cleanupDisposition = executorKind === "pi" && execution.cancelled !== true && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError && execution.signal === null ? classifyPiTerminalCleanupDisposition({ ...parsed, mcpToolResults }, []) : null;
|
|
11005
11295
|
const parsedForValidation = cleanupDisposition ? { ...parsed, errorMessage: null } : parsed;
|
|
11006
11296
|
const piInvalidOutputError = executorKind === "pi" ? piOutputValidationError(parsedForValidation, {
|
|
11007
11297
|
allowMissingTurnEnd: completionOutputStopped || Boolean(cleanupDisposition),
|
|
11008
11298
|
allowMissingAssistantOutput: false
|
|
11009
11299
|
}) : null;
|
|
11010
|
-
const parsedError = hasOutputFlood ? "Run-exit closure output exceeded the configured limit" : hasMemoryLimit ? "Run-exit closure exceeded the configured memory limit" : execution.timedOut ? "Run-exit closure timed out" : execution.spawnError ?? piInvalidOutputError ?? parsedForValidation.errorMessage ?? ((execution.exitCode ?? 0) === 0 ? null : `Run-exit closure exited with code ${execution.exitCode ?? "unknown"}`);
|
|
11300
|
+
const parsedError = hasOutputFlood ? "Run-exit closure output exceeded the configured limit" : hasMemoryLimit ? "Run-exit closure exceeded the configured memory limit" : execution.timedOut ? "Run-exit closure timed out" : execution.spawnError ?? piInvalidOutputError ?? parsedForValidation.errorMessage ?? ((execution.exitCode ?? 0) === 0 || cleanupDisposition ? null : `Run-exit closure exited with code ${execution.exitCode ?? "unknown"}`);
|
|
11011
11301
|
const succeeded = execution.cancelled !== true && !hasOutputFlood && !hasMemoryLimit && (execution.exitCode === 0 || completionOutputStopped || Boolean(cleanupDisposition)) && !execution.timedOut && !execution.spawnError && !parsedError;
|
|
11012
|
-
const mcpToolResults = dedupeGovernedMcpToolResults([
|
|
11013
|
-
...Array.isArray(parsed.mcpToolResults) ? parsed.mcpToolResults.map(asRecord) : [],
|
|
11014
|
-
...liveOutputLogger.mcpToolResults().map(asRecord)
|
|
11015
|
-
]);
|
|
11016
11302
|
await ingestLog(config, command, "system", succeeded ? "info" : "error", succeeded ? "Run-exit disposition closure turn completed" : `Run-exit disposition closure turn failed: ${parsedError}`, {
|
|
11017
11303
|
presentationKind: "run_exit_disposition_closure",
|
|
11018
11304
|
closureAttempt: 1,
|
|
@@ -11033,6 +11319,7 @@ async function executeRunExitClosureTurn(config, inputState, options = {}) {
|
|
|
11033
11319
|
timedOut: execution.timedOut,
|
|
11034
11320
|
summary: truncateText(readString(parsed.summary) ?? "", 2e3),
|
|
11035
11321
|
outputTelemetry,
|
|
11322
|
+
cleanupDisposition,
|
|
11036
11323
|
toolResults: mcpToolResults.slice(0, 10).map((result3) => ({
|
|
11037
11324
|
status: readString(result3.status),
|
|
11038
11325
|
toolName: readString(result3.toolName) ?? readString(result3.name) ?? readString(asRecord(result3.runtimeAction).toolName),
|
|
@@ -11955,7 +12242,7 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
11955
12242
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
11956
12243
|
writeFileSync9(targetPath, body);
|
|
11957
12244
|
const attachmentId = readString(attachment.id);
|
|
11958
|
-
const actualSha256 =
|
|
12245
|
+
const actualSha256 = createHash11("sha256").update(body).digest("hex");
|
|
11959
12246
|
const lineageCandidates = lineageCandidatesByAttachmentId.get(attachmentId) ?? [];
|
|
11960
12247
|
const lineage = selectAttachmentLineage(lineageCandidates, actualSha256);
|
|
11961
12248
|
if (lineageCandidates.length > 0 && !lineage) {
|
|
@@ -12047,7 +12334,7 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
12047
12334
|
throw new Error(`artifact_input_manifest_invalid: entry ${index} contentPath does not match attachmentId`);
|
|
12048
12335
|
}
|
|
12049
12336
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
12050
|
-
const actualSha256 =
|
|
12337
|
+
const actualSha256 = createHash11("sha256").update(body).digest("hex");
|
|
12051
12338
|
if (body.byteLength !== byteSize || actualSha256 !== sha256) {
|
|
12052
12339
|
throw new Error(
|
|
12053
12340
|
`artifact_input_integrity_mismatch: workProductId=${workProductId} expectedBytes=${byteSize} actualBytes=${body.byteLength} expectedSha256=${sha256} actualSha256=${actualSha256}`
|
|
@@ -12117,7 +12404,7 @@ function safeCheckpointRelativePath(rawPath) {
|
|
|
12117
12404
|
return normalized;
|
|
12118
12405
|
}
|
|
12119
12406
|
function hashFileSha256(filePath) {
|
|
12120
|
-
return
|
|
12407
|
+
return createHash11("sha256").update(readFileSync11(filePath)).digest("hex");
|
|
12121
12408
|
}
|
|
12122
12409
|
async function materializeIssueCheckpoint(config, command, workspace) {
|
|
12123
12410
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
@@ -12330,6 +12617,7 @@ async function executeRunCommand(config, command) {
|
|
|
12330
12617
|
};
|
|
12331
12618
|
let completionOwnsManagedMcpProfile = false;
|
|
12332
12619
|
const sourceAcquisition = sourceAcquisitionRuntimeProfile(config, command);
|
|
12620
|
+
const sourceProfile = serializeSourceAcquisitionProfile(sourceAcquisition?.profile ?? null);
|
|
12333
12621
|
const trustedPiRuntimeAssertion = commandTrustedPiRuntimeAssertion(command);
|
|
12334
12622
|
assertSourceAcquisitionRuntimeAuthority({
|
|
12335
12623
|
profile: sourceAcquisition,
|
|
@@ -12457,6 +12745,13 @@ async function executeRunCommand(config, command) {
|
|
|
12457
12745
|
inheritedEntries: trustedPiRuntimeProfile.facts.inheritedEntries
|
|
12458
12746
|
});
|
|
12459
12747
|
}
|
|
12748
|
+
if (sourceProfile) {
|
|
12749
|
+
executorEnv = {
|
|
12750
|
+
...executorEnv,
|
|
12751
|
+
AMASTER_SOURCE_ACQUISITION_PROFILE_FD: "4",
|
|
12752
|
+
AMASTER_SOURCE_ACQUISITION_PROFILE_SHA256: sourceProfile.sha256
|
|
12753
|
+
};
|
|
12754
|
+
}
|
|
12460
12755
|
if (executor.kind === "pi" && piResolvedProviderConfig) {
|
|
12461
12756
|
const agentDir = managedMcpProfile ? readString(managedMcpProfile.env.PI_CODING_AGENT_DIR) ?? readString(managedMcpProfile.env.PI_AGENT_HOME) ?? null : piAgentLocalPlatformRunnerEnabled(config) ? readString(executorEnv.PI_AGENT_HOME) ?? readString(executorEnv.PI_CODING_AGENT_DIR) ?? null : readString(executorEnv.PI_CODING_AGENT_DIR) ?? readString(executorEnv.PI_AGENT_HOME) ?? null;
|
|
12462
12757
|
try {
|
|
@@ -12591,6 +12886,7 @@ async function executeRunCommand(config, command) {
|
|
|
12591
12886
|
managedInput: `${JSON.stringify(trustedPiRuntimeAssertion)}
|
|
12592
12887
|
`
|
|
12593
12888
|
} : {},
|
|
12889
|
+
...sourceProfile ? { sourceProfileInput: sourceProfile.input } : {},
|
|
12594
12890
|
onOutput: (stream, chunk, rawBytes) => {
|
|
12595
12891
|
noteActiveRunOutput(command, stream, chunk, rawBytes);
|
|
12596
12892
|
liveOutputLogger.write(stream, chunk);
|
|
@@ -12759,7 +13055,10 @@ async function executeRunCommand(config, command) {
|
|
|
12759
13055
|
const memoryLimitError = hasMemoryLimit ? `${executor.kind === "pi" ? "Pi Agent" : "Executor"} memory limit exceeded: RSS ${readNumber(memoryLimit.rssBytes, 0)} bytes exceeded ${readNumber(memoryLimit.limitBytes, config.executorMaxRssMb * 1024 * 1024)} bytes` : null;
|
|
12760
13056
|
const piUsageDiagnostic = executor.kind === "pi" && !hasOutputFlood && piOutputUsageMetadataMissing(parsed) ? "Pi Agent exited without usage metadata" : null;
|
|
12761
13057
|
const completionOutputStopped = executor.kind === "pi" && piCompletionOutputStopped(parsed, execution);
|
|
12762
|
-
const cleanupDisposition = executor.kind === "pi" && !cancelled && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError && execution.signal === null ? classifyPiTerminalCleanupDisposition(
|
|
13058
|
+
const cleanupDisposition = executor.kind === "pi" && !cancelled && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError && execution.signal === null ? classifyPiTerminalCleanupDisposition(
|
|
13059
|
+
{ ...parsed, mcpToolResults },
|
|
13060
|
+
runtimeArtifacts
|
|
13061
|
+
) : null;
|
|
12763
13062
|
if (cleanupDisposition) {
|
|
12764
13063
|
await ingestLog(
|
|
12765
13064
|
config,
|
|
@@ -12933,7 +13232,8 @@ async function executeRunCommand(config, command) {
|
|
|
12933
13232
|
maxRssMb: config.executorMaxRssMb,
|
|
12934
13233
|
...piChildIsolation ? { spawnIdentity: piChildIsolation.spawn } : {},
|
|
12935
13234
|
...trustedPiRuntime ? { managedInput: `${JSON.stringify(trustedPiRuntimeAssertion)}
|
|
12936
|
-
` } : {}
|
|
13235
|
+
` } : {},
|
|
13236
|
+
...sourceProfile ? { sourceProfileInput: sourceProfile.input } : {}
|
|
12937
13237
|
}
|
|
12938
13238
|
},
|
|
12939
13239
|
completionRequest: {
|
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.2";
|
|
9
9
|
|
|
10
10
|
const CAPABILITIES = [
|
|
11
11
|
"remote_registration",
|