@amaster.ai/employee-runtime-connector 0.1.1-beta.67 → 0.1.1-beta.69
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 +538 -146
- package/dist/amaster-runtime.mjs +1 -1
- package/package.json +4 -2
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
// MirrorX runtime connector daemon bundle.
|
|
3
3
|
|
|
4
4
|
// src/amaster-runtime-daemon.mjs
|
|
5
|
-
import { createHash as
|
|
6
|
-
import {
|
|
5
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
6
|
+
import { createRequire } from "node:module";
|
|
7
|
+
import { chmodSync as chmodSync5, copyFileSync as copyFileSync2, existsSync as existsSync12, lstatSync as lstatSync6, mkdirSync as mkdirSync8, mkdtempSync, readFileSync as readFileSync11, readdirSync as readdirSync9, realpathSync as realpathSync5, renameSync as renameSync6, rmSync as rmSync6, statSync as statSync9, symlinkSync as symlinkSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync8 } from "node:fs";
|
|
7
8
|
import { arch as arch3, homedir as homedir3, hostname as hostname2, platform as platform3, tmpdir } from "node:os";
|
|
8
|
-
import { basename as basename6, delimiter as delimiter3, dirname as
|
|
9
|
+
import { basename as basename6, delimiter as delimiter3, dirname as dirname8, extname as extname2, isAbsolute as isAbsolute6, join as join13, relative as relative7, resolve as resolve10 } from "node:path";
|
|
9
10
|
import { spawn, spawnSync as spawnSync5 } from "node:child_process";
|
|
10
11
|
|
|
11
12
|
// src/amaster-runtime-daemon/common.mjs
|
|
@@ -3671,6 +3672,18 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
3671
3672
|
const env = {
|
|
3672
3673
|
PI_BROWSER_USE_RUNTIME_READ_POLICY: "required"
|
|
3673
3674
|
};
|
|
3675
|
+
if (sourceAcquisition?.profile?.transport?.browserMode === "existing") {
|
|
3676
|
+
const userDataDir = sourceAcquisition.userDataDir;
|
|
3677
|
+
const leaseId = sourceAcquisition.profile?.access?.browserLeaseId;
|
|
3678
|
+
if (!isAbsolute2(userDataDir ?? "") || typeof leaseId !== "string" || !leaseId) {
|
|
3679
|
+
throw new Error("source_acquisition_browser_profile_invalid");
|
|
3680
|
+
}
|
|
3681
|
+
return {
|
|
3682
|
+
...env,
|
|
3683
|
+
PI_BROWSER_USE_EXISTING_PROFILE_DIR: userDataDir,
|
|
3684
|
+
PI_BROWSER_USE_EXISTING_PROFILE_LEASE_ID: leaseId
|
|
3685
|
+
};
|
|
3686
|
+
}
|
|
3674
3687
|
if (sourceAcquisition?.profile?.transport?.browserMode !== "isolated") return env;
|
|
3675
3688
|
const executable = typeof baseEnv?.AMASTER_BROWSER_EXECUTABLE_PATH === "string" ? baseEnv.AMASTER_BROWSER_EXECUTABLE_PATH.trim() : "";
|
|
3676
3689
|
if (!executable || !isAbsolute2(executable)) {
|
|
@@ -4397,14 +4410,14 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
4397
4410
|
throw error;
|
|
4398
4411
|
}
|
|
4399
4412
|
}
|
|
4400
|
-
function restoreManagedPiRunExitClosureBaseline2(input,
|
|
4413
|
+
function restoreManagedPiRunExitClosureBaseline2(input, expectedOwner2) {
|
|
4401
4414
|
if (!input) return { status: "not_required" };
|
|
4402
4415
|
const baseline = record6(input);
|
|
4403
4416
|
if (baseline.schemaVersion !== "amaster.pi-run-exit-closure-baseline.v1") {
|
|
4404
4417
|
throw new Error("pi_run_exit_closure_baseline_invalid: unsupported schema version");
|
|
4405
4418
|
}
|
|
4406
4419
|
const owner = record6(baseline.owner);
|
|
4407
|
-
if (owner.commandId !==
|
|
4420
|
+
if (owner.commandId !== expectedOwner2?.commandId || owner.runId !== expectedOwner2?.runId) {
|
|
4408
4421
|
throw new Error("pi_run_exit_closure_baseline_owner_mismatch");
|
|
4409
4422
|
}
|
|
4410
4423
|
const profileRoot = resolve3(nonEmpty2(baseline.profileRoot, "runExitClosureBaseline.profileRoot"));
|
|
@@ -4458,11 +4471,11 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
4458
4471
|
}
|
|
4459
4472
|
return { status: "restored", cacheSha256 };
|
|
4460
4473
|
}
|
|
4461
|
-
function inspectManagedPiRunExitClosureAttestation2(input,
|
|
4474
|
+
function inspectManagedPiRunExitClosureAttestation2(input, expectedOwner2) {
|
|
4462
4475
|
if (!input) return { status: "not_required" };
|
|
4463
4476
|
const baseline = record6(input);
|
|
4464
4477
|
const owner = record6(baseline.owner);
|
|
4465
|
-
if (owner.commandId !==
|
|
4478
|
+
if (owner.commandId !== expectedOwner2?.commandId || owner.runId !== expectedOwner2?.runId) {
|
|
4466
4479
|
throw new Error("pi_run_exit_closure_baseline_owner_mismatch");
|
|
4467
4480
|
}
|
|
4468
4481
|
const profileRoot = resolve3(nonEmpty2(baseline.profileRoot, "runExitClosureBaseline.profileRoot"));
|
|
@@ -4570,9 +4583,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
4570
4583
|
PI_CODING_AGENT_SESSION_DIR: sessionsRoot,
|
|
4571
4584
|
"AMASTER-CLI_CODING_AGENT_SESSION_DIR": sessionsRoot,
|
|
4572
4585
|
TMPDIR: tmp,
|
|
4573
|
-
...input.sourceAcquisition ? {
|
|
4574
|
-
PI_BROWSER_USE_RUNTIME_READ_POLICY: "required"
|
|
4575
|
-
} : {}
|
|
4586
|
+
...input.sourceAcquisition ? sourceAcquisitionBrowserEnvironment(input.sourceAcquisition, input.baseEnv) : {}
|
|
4576
4587
|
};
|
|
4577
4588
|
const attestationFacts = {
|
|
4578
4589
|
connectorVersion: nonEmpty2(input.connectorVersion, "connectorVersion"),
|
|
@@ -9501,7 +9512,7 @@ async function postRuntimeConnectorJsonWithRetry(config, path, payload, options
|
|
|
9501
9512
|
} catch (error) {
|
|
9502
9513
|
lastError = error;
|
|
9503
9514
|
if (attempt >= maxAttempts || !retryableRuntimeConnectorPost(error)) throw error;
|
|
9504
|
-
if (delayMs > 0) await new Promise((
|
|
9515
|
+
if (delayMs > 0) await new Promise((resolve11) => setTimeout(resolve11, delayMs));
|
|
9505
9516
|
}
|
|
9506
9517
|
}
|
|
9507
9518
|
throw lastError;
|
|
@@ -10757,7 +10768,7 @@ function parseLocator(value, exactOrigin = false) {
|
|
|
10757
10768
|
} catch {
|
|
10758
10769
|
return null;
|
|
10759
10770
|
}
|
|
10760
|
-
if (url.protocol !== "https:"
|
|
10771
|
+
if (url.protocol !== "https:" || url.username || url.password) return null;
|
|
10761
10772
|
if (exactOrigin && (value !== url.origin || url.pathname !== "/" || url.search || url.hash)) {
|
|
10762
10773
|
return null;
|
|
10763
10774
|
}
|
|
@@ -10863,6 +10874,301 @@ async function executeBrowserSessionCommand(command, dependencies = {}) {
|
|
|
10863
10874
|
}
|
|
10864
10875
|
}
|
|
10865
10876
|
|
|
10877
|
+
// src/amaster-runtime-daemon/browser-session-broker.mjs
|
|
10878
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
10879
|
+
import {
|
|
10880
|
+
chmodSync as chmodSync4,
|
|
10881
|
+
existsSync as existsSync11,
|
|
10882
|
+
lstatSync as lstatSync5,
|
|
10883
|
+
mkdirSync as mkdirSync7,
|
|
10884
|
+
readFileSync as readFileSync10,
|
|
10885
|
+
rmSync as rmSync5,
|
|
10886
|
+
statSync as statSync8,
|
|
10887
|
+
writeFileSync as writeFileSync7
|
|
10888
|
+
} from "node:fs";
|
|
10889
|
+
import { dirname as dirname7, join as join12, relative as relative6, resolve as resolve9 } from "node:path";
|
|
10890
|
+
var MARKER_NAME = ".amaster-browser-session.json";
|
|
10891
|
+
var HUMAN_LEASE_HARD_CAP_MS = 2 * 60 * 60 * 1e3;
|
|
10892
|
+
function brokerError(code) {
|
|
10893
|
+
return Object.assign(new Error(code), { code });
|
|
10894
|
+
}
|
|
10895
|
+
function pathWithin3(candidate, root) {
|
|
10896
|
+
const value = relative6(root, candidate);
|
|
10897
|
+
return value === "" || !value.startsWith("..") && !value.startsWith("/");
|
|
10898
|
+
}
|
|
10899
|
+
function ensureExecutable(path) {
|
|
10900
|
+
if (!path) return false;
|
|
10901
|
+
try {
|
|
10902
|
+
const stat = statSync8(path);
|
|
10903
|
+
return stat.isFile() && (stat.mode & 73) !== 0;
|
|
10904
|
+
} catch {
|
|
10905
|
+
return false;
|
|
10906
|
+
}
|
|
10907
|
+
}
|
|
10908
|
+
function ensurePrivateRoot(stateRoot) {
|
|
10909
|
+
const root = resolve9(stateRoot);
|
|
10910
|
+
if (existsSync11(root) && lstatSync5(root).isSymbolicLink()) {
|
|
10911
|
+
throw brokerError("browser_session_profile_root_symlink");
|
|
10912
|
+
}
|
|
10913
|
+
mkdirSync7(root, { recursive: true, mode: 448 });
|
|
10914
|
+
chmodSync4(root, 448);
|
|
10915
|
+
if (lstatSync5(root).isSymbolicLink()) {
|
|
10916
|
+
throw brokerError("browser_session_profile_root_symlink");
|
|
10917
|
+
}
|
|
10918
|
+
return root;
|
|
10919
|
+
}
|
|
10920
|
+
function profileName(payload) {
|
|
10921
|
+
return createHash12("sha256").update(`${payload.companyId}\0${payload.bindingId}\0${payload.localOpaqueRef}`).digest("hex");
|
|
10922
|
+
}
|
|
10923
|
+
function expectedOwner(payload) {
|
|
10924
|
+
return {
|
|
10925
|
+
version: 1,
|
|
10926
|
+
companyId: payload.companyId,
|
|
10927
|
+
bindingId: payload.bindingId,
|
|
10928
|
+
localOpaqueRef: payload.localOpaqueRef,
|
|
10929
|
+
provider: payload.provider,
|
|
10930
|
+
origin: payload.origin
|
|
10931
|
+
};
|
|
10932
|
+
}
|
|
10933
|
+
function exactProfile(stateRoot, payload, { create = false } = {}) {
|
|
10934
|
+
const root = ensurePrivateRoot(stateRoot);
|
|
10935
|
+
const profilePath = resolve9(root, profileName(payload));
|
|
10936
|
+
if (!pathWithin3(profilePath, root) || dirname7(profilePath) !== root) {
|
|
10937
|
+
throw brokerError("browser_session_profile_path_invalid");
|
|
10938
|
+
}
|
|
10939
|
+
if (existsSync11(profilePath) && lstatSync5(profilePath).isSymbolicLink()) {
|
|
10940
|
+
throw brokerError("browser_session_profile_symlink");
|
|
10941
|
+
}
|
|
10942
|
+
if (!existsSync11(profilePath)) {
|
|
10943
|
+
if (!create) throw brokerError("browser_session_profile_not_found");
|
|
10944
|
+
mkdirSync7(profilePath, { mode: 448 });
|
|
10945
|
+
chmodSync4(profilePath, 448);
|
|
10946
|
+
writeFileSync7(
|
|
10947
|
+
join12(profilePath, MARKER_NAME),
|
|
10948
|
+
`${JSON.stringify(expectedOwner(payload))}
|
|
10949
|
+
`,
|
|
10950
|
+
{ encoding: "utf8", mode: 384, flag: "wx" }
|
|
10951
|
+
);
|
|
10952
|
+
}
|
|
10953
|
+
if (!lstatSync5(profilePath).isDirectory() || lstatSync5(profilePath).isSymbolicLink()) {
|
|
10954
|
+
throw brokerError("browser_session_profile_path_invalid");
|
|
10955
|
+
}
|
|
10956
|
+
let owner;
|
|
10957
|
+
try {
|
|
10958
|
+
owner = JSON.parse(readFileSync10(join12(profilePath, MARKER_NAME), "utf8"));
|
|
10959
|
+
} catch {
|
|
10960
|
+
throw brokerError("browser_session_profile_owner_invalid");
|
|
10961
|
+
}
|
|
10962
|
+
if (JSON.stringify(owner) !== JSON.stringify(expectedOwner(payload))) {
|
|
10963
|
+
throw brokerError("browser_session_profile_owner_mismatch");
|
|
10964
|
+
}
|
|
10965
|
+
return profilePath;
|
|
10966
|
+
}
|
|
10967
|
+
function validateHumanLease(payload, now) {
|
|
10968
|
+
const expiry = Date.parse(payload.leaseExpiresAt);
|
|
10969
|
+
const nowMs = now().getTime();
|
|
10970
|
+
if (!Number.isFinite(expiry) || expiry <= nowMs) {
|
|
10971
|
+
throw brokerError("browser_session_lease_expired");
|
|
10972
|
+
}
|
|
10973
|
+
if (expiry > nowMs + HUMAN_LEASE_HARD_CAP_MS) {
|
|
10974
|
+
throw brokerError("browser_session_lease_hard_cap_exceeded");
|
|
10975
|
+
}
|
|
10976
|
+
}
|
|
10977
|
+
function validateHttpsLocator(payload) {
|
|
10978
|
+
let locator;
|
|
10979
|
+
let origin;
|
|
10980
|
+
try {
|
|
10981
|
+
locator = new URL(payload.locator);
|
|
10982
|
+
origin = new URL(payload.origin);
|
|
10983
|
+
} catch {
|
|
10984
|
+
throw brokerError("browser_session_locator_invalid");
|
|
10985
|
+
}
|
|
10986
|
+
if (locator.protocol !== "https:" || origin.protocol !== "https:" || locator.username || locator.password || origin.username || origin.password || payload.origin !== origin.origin || locator.origin !== origin.origin) {
|
|
10987
|
+
throw brokerError("browser_session_locator_invalid");
|
|
10988
|
+
}
|
|
10989
|
+
}
|
|
10990
|
+
function browserSessionBrokerReadiness({
|
|
10991
|
+
stateRoot,
|
|
10992
|
+
browserExecutable,
|
|
10993
|
+
runtimeAvailable = true,
|
|
10994
|
+
displayAvailable = process.platform !== "linux" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY)
|
|
10995
|
+
}) {
|
|
10996
|
+
if (!runtimeAvailable) {
|
|
10997
|
+
return {
|
|
10998
|
+
capability: "headed_browser_auth",
|
|
10999
|
+
advertised: false,
|
|
11000
|
+
ready: false,
|
|
11001
|
+
reason: "browser_session_runtime_unavailable"
|
|
11002
|
+
};
|
|
11003
|
+
}
|
|
11004
|
+
if (!ensureExecutable(browserExecutable)) {
|
|
11005
|
+
return {
|
|
11006
|
+
capability: "headed_browser_auth",
|
|
11007
|
+
advertised: false,
|
|
11008
|
+
ready: false,
|
|
11009
|
+
reason: "browser_session_browser_executable_unavailable"
|
|
11010
|
+
};
|
|
11011
|
+
}
|
|
11012
|
+
if (!displayAvailable) {
|
|
11013
|
+
return {
|
|
11014
|
+
capability: "headed_browser_auth",
|
|
11015
|
+
advertised: false,
|
|
11016
|
+
ready: false,
|
|
11017
|
+
reason: "browser_session_display_unavailable"
|
|
11018
|
+
};
|
|
11019
|
+
}
|
|
11020
|
+
try {
|
|
11021
|
+
ensurePrivateRoot(stateRoot);
|
|
11022
|
+
} catch (error) {
|
|
11023
|
+
return {
|
|
11024
|
+
capability: "headed_browser_auth",
|
|
11025
|
+
advertised: false,
|
|
11026
|
+
ready: false,
|
|
11027
|
+
reason: typeof error?.code === "string" ? error.code : "browser_session_profile_root_unavailable"
|
|
11028
|
+
};
|
|
11029
|
+
}
|
|
11030
|
+
return { capability: "headed_browser_auth", advertised: true, ready: true };
|
|
11031
|
+
}
|
|
11032
|
+
function createBrowserSessionBroker({
|
|
11033
|
+
stateRoot,
|
|
11034
|
+
browserExecutable,
|
|
11035
|
+
chromium,
|
|
11036
|
+
now = () => /* @__PURE__ */ new Date()
|
|
11037
|
+
}) {
|
|
11038
|
+
const active = /* @__PURE__ */ new Map();
|
|
11039
|
+
const readers = /* @__PURE__ */ new Map();
|
|
11040
|
+
async function open(payload, { replace = false } = {}) {
|
|
11041
|
+
validateHttpsLocator(payload);
|
|
11042
|
+
validateHumanLease(payload, now);
|
|
11043
|
+
const profilePath = exactProfile(stateRoot, payload, { create: true });
|
|
11044
|
+
const existing = active.get(payload.localOpaqueRef);
|
|
11045
|
+
if (existing) {
|
|
11046
|
+
if (existing.owner.companyId !== payload.companyId || existing.owner.bindingId !== payload.bindingId) {
|
|
11047
|
+
throw brokerError("browser_session_profile_owner_mismatch");
|
|
11048
|
+
}
|
|
11049
|
+
if (existing.leaseId !== payload.leaseId && !replace) {
|
|
11050
|
+
throw brokerError("browser_session_lease_conflict");
|
|
11051
|
+
}
|
|
11052
|
+
if (existing.leaseId === payload.leaseId && !replace) {
|
|
11053
|
+
return {
|
|
11054
|
+
bindingId: payload.bindingId,
|
|
11055
|
+
localOpaqueRef: payload.localOpaqueRef,
|
|
11056
|
+
state: "human_ready"
|
|
11057
|
+
};
|
|
11058
|
+
}
|
|
11059
|
+
await existing.context.close();
|
|
11060
|
+
active.delete(payload.localOpaqueRef);
|
|
11061
|
+
}
|
|
11062
|
+
if (!chromium || typeof chromium.launchPersistentContext !== "function") {
|
|
11063
|
+
throw brokerError("browser_session_runtime_unavailable");
|
|
11064
|
+
}
|
|
11065
|
+
const context = await chromium.launchPersistentContext(profilePath, {
|
|
11066
|
+
executablePath: browserExecutable,
|
|
11067
|
+
headless: false,
|
|
11068
|
+
acceptDownloads: false
|
|
11069
|
+
});
|
|
11070
|
+
const leaseState = {
|
|
11071
|
+
context,
|
|
11072
|
+
leaseId: payload.leaseId,
|
|
11073
|
+
owner: expectedOwner(payload),
|
|
11074
|
+
lastActivityAt: now().toISOString()
|
|
11075
|
+
};
|
|
11076
|
+
if (typeof context.exposeBinding === "function" && typeof context.addInitScript === "function") {
|
|
11077
|
+
await context.exposeBinding("__mirrorxBrowserAuthActivity", () => {
|
|
11078
|
+
leaseState.lastActivityAt = now().toISOString();
|
|
11079
|
+
});
|
|
11080
|
+
await context.addInitScript(() => {
|
|
11081
|
+
const report = () => globalThis.__mirrorxBrowserAuthActivity?.().catch?.(() => {
|
|
11082
|
+
});
|
|
11083
|
+
globalThis.addEventListener("pointerdown", report, { capture: true, passive: true });
|
|
11084
|
+
globalThis.addEventListener("keydown", report, { capture: true, passive: true });
|
|
11085
|
+
globalThis.addEventListener("touchstart", report, { capture: true, passive: true });
|
|
11086
|
+
});
|
|
11087
|
+
}
|
|
11088
|
+
const page = context.pages()[0] ?? await context.newPage();
|
|
11089
|
+
await page.goto(payload.locator);
|
|
11090
|
+
active.set(payload.localOpaqueRef, leaseState);
|
|
11091
|
+
return {
|
|
11092
|
+
bindingId: payload.bindingId,
|
|
11093
|
+
localOpaqueRef: payload.localOpaqueRef,
|
|
11094
|
+
state: "human_ready"
|
|
11095
|
+
};
|
|
11096
|
+
}
|
|
11097
|
+
async function revokeExact(payload) {
|
|
11098
|
+
const existing = active.get(payload.localOpaqueRef);
|
|
11099
|
+
if (existing) {
|
|
11100
|
+
if (existing.owner.companyId !== payload.companyId || existing.owner.bindingId !== payload.bindingId) {
|
|
11101
|
+
throw brokerError("browser_session_profile_owner_mismatch");
|
|
11102
|
+
}
|
|
11103
|
+
}
|
|
11104
|
+
const profilePath = exactProfile(stateRoot, payload);
|
|
11105
|
+
if (existing) {
|
|
11106
|
+
await existing.context.close();
|
|
11107
|
+
active.delete(payload.localOpaqueRef);
|
|
11108
|
+
}
|
|
11109
|
+
rmSync5(profilePath, { recursive: true, force: false });
|
|
11110
|
+
return {
|
|
11111
|
+
bindingId: payload.bindingId,
|
|
11112
|
+
localOpaqueRef: payload.localOpaqueRef,
|
|
11113
|
+
state: "revoked"
|
|
11114
|
+
};
|
|
11115
|
+
}
|
|
11116
|
+
return {
|
|
11117
|
+
openHumanSession: (payload) => open(payload),
|
|
11118
|
+
reopenHumanSession: (payload) => open(payload, { replace: true }),
|
|
11119
|
+
switchAccount: async (payload) => {
|
|
11120
|
+
await revokeExact({
|
|
11121
|
+
...payload,
|
|
11122
|
+
bindingId: payload.previousBinding.bindingId,
|
|
11123
|
+
localOpaqueRef: payload.previousBinding.localOpaqueRef
|
|
11124
|
+
});
|
|
11125
|
+
return open(payload);
|
|
11126
|
+
},
|
|
11127
|
+
revokeBinding: revokeExact,
|
|
11128
|
+
acquireAgentRead: async (payload) => {
|
|
11129
|
+
const expiry = Date.parse(payload.leaseExpiresAt);
|
|
11130
|
+
if (!Number.isFinite(expiry) || expiry <= now().getTime()) {
|
|
11131
|
+
throw brokerError("browser_session_agent_lease_expired");
|
|
11132
|
+
}
|
|
11133
|
+
const root = ensurePrivateRoot(stateRoot);
|
|
11134
|
+
const expectedPath = resolve9(root, profileName(payload));
|
|
11135
|
+
if (resolve9(payload.userDataDir) !== expectedPath) {
|
|
11136
|
+
throw brokerError("browser_session_profile_path_invalid");
|
|
11137
|
+
}
|
|
11138
|
+
const marker = JSON.parse(readFileSync10(join12(expectedPath, MARKER_NAME), "utf8"));
|
|
11139
|
+
if (marker.version !== 1 || typeof marker.provider !== "string" || !marker.provider.trim() || marker.companyId !== payload.companyId || marker.bindingId !== payload.bindingId || marker.localOpaqueRef !== payload.localOpaqueRef || marker.origin !== payload.origin) {
|
|
11140
|
+
throw brokerError("browser_session_profile_owner_mismatch");
|
|
11141
|
+
}
|
|
11142
|
+
const existingReader = readers.get(payload.localOpaqueRef);
|
|
11143
|
+
if (existingReader && existingReader !== payload.leaseId) {
|
|
11144
|
+
throw brokerError("browser_session_lease_conflict");
|
|
11145
|
+
}
|
|
11146
|
+
const human = active.get(payload.localOpaqueRef);
|
|
11147
|
+
if (human) {
|
|
11148
|
+
if (human.owner.companyId !== payload.companyId || human.owner.bindingId !== payload.bindingId) {
|
|
11149
|
+
throw brokerError("browser_session_profile_owner_mismatch");
|
|
11150
|
+
}
|
|
11151
|
+
await human.context.close();
|
|
11152
|
+
active.delete(payload.localOpaqueRef);
|
|
11153
|
+
}
|
|
11154
|
+
readers.set(payload.localOpaqueRef, payload.leaseId);
|
|
11155
|
+
return () => {
|
|
11156
|
+
if (readers.get(payload.localOpaqueRef) === payload.leaseId) {
|
|
11157
|
+
readers.delete(payload.localOpaqueRef);
|
|
11158
|
+
}
|
|
11159
|
+
};
|
|
11160
|
+
},
|
|
11161
|
+
status: () => ({
|
|
11162
|
+
activeHumanLeases: [...active.values()].map((entry) => ({
|
|
11163
|
+
companyId: entry.owner.companyId,
|
|
11164
|
+
bindingId: entry.owner.bindingId,
|
|
11165
|
+
leaseId: entry.leaseId,
|
|
11166
|
+
lastActivityAt: entry.lastActivityAt
|
|
11167
|
+
}))
|
|
11168
|
+
})
|
|
11169
|
+
};
|
|
11170
|
+
}
|
|
11171
|
+
|
|
10866
11172
|
// ../shared/src/source-acquisition-compatibility.json
|
|
10867
11173
|
var source_acquisition_compatibility_default = {
|
|
10868
11174
|
schemaVersion: "mirrorx.source-acquisition-compatibility.v1",
|
|
@@ -10879,12 +11185,14 @@ var source_acquisition_compatibility_default = {
|
|
|
10879
11185
|
};
|
|
10880
11186
|
|
|
10881
11187
|
// src/amaster-runtime-daemon.mjs
|
|
10882
|
-
var CONNECTOR_VERSION = "0.1.1-beta.
|
|
11188
|
+
var CONNECTOR_VERSION = "0.1.1-beta.69";
|
|
10883
11189
|
var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
|
|
10884
11190
|
var SOURCE_ACQUISITION_CAPABILITY = source_acquisition_compatibility_default.profileVersion;
|
|
11191
|
+
var daemonRequire = createRequire(import.meta.url);
|
|
10885
11192
|
var SOURCE_ACQUISITION_PROFILE_VERSION = source_acquisition_compatibility_default.profileVersion;
|
|
10886
11193
|
var SOURCE_ACQUISITION_RETENTION_VERSION = source_acquisition_compatibility_default.retentionVersion;
|
|
10887
11194
|
var SOURCE_ACQUISITION_ACTION_VERSION = source_acquisition_compatibility_default.actionVersion;
|
|
11195
|
+
var SOURCE_ACQUISITION_BROWSER_POLICY_VERSION = source_acquisition_compatibility_default.policyVersion;
|
|
10888
11196
|
var SOURCE_ACQUISITION_HEADLESS_ADAPTER = source_acquisition_compatibility_default.adapters[0];
|
|
10889
11197
|
var SOURCE_ACQUISITION_DESKTOP_ADAPTER = "browser_skill_desktop_v1";
|
|
10890
11198
|
var SOURCE_ACQUISITION_PACKAGE_VERSIONS = Object.freeze(
|
|
@@ -10917,11 +11225,11 @@ function updateActiveRunWorkspaceManifest(commandId, manifestPath, patch = {}) {
|
|
|
10917
11225
|
}
|
|
10918
11226
|
function resultOutboxPendingCount(config) {
|
|
10919
11227
|
const dir = resultOutboxDir(config);
|
|
10920
|
-
if (!
|
|
11228
|
+
if (!existsSync12(dir)) return 0;
|
|
10921
11229
|
try {
|
|
10922
11230
|
let pending = 0;
|
|
10923
11231
|
for (const file of readdirSync9(dir).filter((name) => name.endsWith(".json"))) {
|
|
10924
|
-
if (readValidResultOutboxEntryOrQuarantine(config, file,
|
|
11232
|
+
if (readValidResultOutboxEntryOrQuarantine(config, file, join13(dir, file))) {
|
|
10925
11233
|
pending += 1;
|
|
10926
11234
|
}
|
|
10927
11235
|
}
|
|
@@ -10932,16 +11240,16 @@ function resultOutboxPendingCount(config) {
|
|
|
10932
11240
|
}
|
|
10933
11241
|
function runCompletionStateDir(config) {
|
|
10934
11242
|
const explicit = readString(process.env.AMASTER_RUN_COMPLETION_STATE_DIR);
|
|
10935
|
-
if (explicit) return
|
|
10936
|
-
return
|
|
11243
|
+
if (explicit) return resolve10(expandHomePath(explicit));
|
|
11244
|
+
return join13(dirname8(stateFilePath(process.env)), "run-completion-state");
|
|
10937
11245
|
}
|
|
10938
11246
|
function runCompletionStateInvalidDir(config) {
|
|
10939
|
-
return
|
|
11247
|
+
return join13(runCompletionStateDir(config), "invalid");
|
|
10940
11248
|
}
|
|
10941
11249
|
function quarantineInvalidRunCompletionState(config, filePath, reason) {
|
|
10942
11250
|
const invalidDir = runCompletionStateInvalidDir(config);
|
|
10943
|
-
|
|
10944
|
-
const destination =
|
|
11251
|
+
mkdirSync8(invalidDir, { recursive: true, mode: 448 });
|
|
11252
|
+
const destination = join13(invalidDir, basename6(filePath));
|
|
10945
11253
|
try {
|
|
10946
11254
|
renameSync6(filePath, destination);
|
|
10947
11255
|
} catch {
|
|
@@ -10994,11 +11302,11 @@ function piCompletionOutputType(event) {
|
|
|
10994
11302
|
}
|
|
10995
11303
|
function resultOutboxActiveRunCommands(config) {
|
|
10996
11304
|
const dir = resultOutboxDir(config);
|
|
10997
|
-
if (!
|
|
11305
|
+
if (!existsSync12(dir)) return [];
|
|
10998
11306
|
const outboxPending = resultOutboxPendingCount(config);
|
|
10999
11307
|
const entries = [];
|
|
11000
11308
|
for (const file of readdirSync9(dir).filter((name) => name.endsWith(".json")).sort()) {
|
|
11001
|
-
const entry = readValidResultOutboxEntryOrQuarantine(config, file,
|
|
11309
|
+
const entry = readValidResultOutboxEntryOrQuarantine(config, file, join13(dir, file));
|
|
11002
11310
|
if (!entry) continue;
|
|
11003
11311
|
const activeRun = asRecord(entry.activeRun);
|
|
11004
11312
|
const commandId = readString(activeRun.commandId) ?? readString(entry.commandId);
|
|
@@ -11028,12 +11336,12 @@ function resultOutboxActiveRunCommands(config) {
|
|
|
11028
11336
|
}
|
|
11029
11337
|
function resultOutboxFailedRunCommands(config) {
|
|
11030
11338
|
const dir = resultOutboxInvalidDir(config);
|
|
11031
|
-
if (!
|
|
11339
|
+
if (!existsSync12(dir)) return [];
|
|
11032
11340
|
const entries = [];
|
|
11033
11341
|
for (const file of readdirSync9(dir).filter((name) => name.endsWith(".json")).sort().slice(-100)) {
|
|
11034
11342
|
let entry;
|
|
11035
11343
|
try {
|
|
11036
|
-
entry = asRecord(JSON.parse(
|
|
11344
|
+
entry = asRecord(JSON.parse(readFileSync11(join13(dir, file), "utf8")));
|
|
11037
11345
|
} catch {
|
|
11038
11346
|
continue;
|
|
11039
11347
|
}
|
|
@@ -11096,11 +11404,11 @@ function piExtraArgsDiagnostics(value) {
|
|
|
11096
11404
|
}
|
|
11097
11405
|
function safeExpandPath(value) {
|
|
11098
11406
|
const text = readString(value);
|
|
11099
|
-
return text ?
|
|
11407
|
+
return text ? resolve10(expandHomePath(text)) : null;
|
|
11100
11408
|
}
|
|
11101
11409
|
function safeJsonObjectFromFile(filePath) {
|
|
11102
11410
|
try {
|
|
11103
|
-
const parsed = JSON.parse(
|
|
11411
|
+
const parsed = JSON.parse(readFileSync11(filePath, "utf8"));
|
|
11104
11412
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
11105
11413
|
} catch {
|
|
11106
11414
|
return null;
|
|
@@ -11111,7 +11419,7 @@ function safeDirectorySummary(pathValue) {
|
|
|
11111
11419
|
return { configured: false, available: false, entryCount: 0 };
|
|
11112
11420
|
}
|
|
11113
11421
|
try {
|
|
11114
|
-
const stat =
|
|
11422
|
+
const stat = statSync9(pathValue);
|
|
11115
11423
|
if (!stat.isDirectory()) {
|
|
11116
11424
|
return { configured: true, available: false, entryCount: 0, reason: "not_directory" };
|
|
11117
11425
|
}
|
|
@@ -11143,10 +11451,10 @@ function safeSkillRootSummary(kind, source, pathValue) {
|
|
|
11143
11451
|
try {
|
|
11144
11452
|
for (const name of readdirSync9(pathValue)) {
|
|
11145
11453
|
if (name.startsWith(".")) continue;
|
|
11146
|
-
const skillDir =
|
|
11454
|
+
const skillDir = join13(pathValue, name);
|
|
11147
11455
|
try {
|
|
11148
|
-
if (!
|
|
11149
|
-
if (!
|
|
11456
|
+
if (!statSync9(skillDir).isDirectory()) continue;
|
|
11457
|
+
if (!existsSync12(join13(skillDir, "SKILL.md"))) continue;
|
|
11150
11458
|
skillCount += 1;
|
|
11151
11459
|
if (skillCount >= MAX_PI_CAPABILITY_SOURCE_ENTRIES) {
|
|
11152
11460
|
truncated = true;
|
|
@@ -11174,7 +11482,7 @@ function safeJsonConfigSummary(source, pathValue, counter) {
|
|
|
11174
11482
|
return { source, configured: false, available: false, parseable: false };
|
|
11175
11483
|
}
|
|
11176
11484
|
try {
|
|
11177
|
-
const stat =
|
|
11485
|
+
const stat = statSync9(pathValue);
|
|
11178
11486
|
if (!stat.isFile()) {
|
|
11179
11487
|
return { source, configured: true, available: false, parseable: false, reason: "not_file" };
|
|
11180
11488
|
}
|
|
@@ -11197,7 +11505,7 @@ function objectKeyCount(value) {
|
|
|
11197
11505
|
return value && typeof value === "object" && !Array.isArray(value) ? Object.keys(value).length : 0;
|
|
11198
11506
|
}
|
|
11199
11507
|
function defaultPiCodingAgentDir() {
|
|
11200
|
-
return
|
|
11508
|
+
return join13(homedir3(), ".pi", "agent");
|
|
11201
11509
|
}
|
|
11202
11510
|
function piCapabilitySourcesDiagnostics() {
|
|
11203
11511
|
const configuredPiCodingAgentDir = safeExpandPath(process.env.PI_CODING_AGENT_DIR);
|
|
@@ -11206,14 +11514,14 @@ function piCapabilitySourcesDiagnostics() {
|
|
|
11206
11514
|
const configuredPiAgentHome = safeExpandPath(process.env.PI_AGENT_HOME);
|
|
11207
11515
|
const piAgentHome = configuredPiAgentHome ?? piCodingAgentDir;
|
|
11208
11516
|
const piAgentHomeSource = configuredPiAgentHome ? "PI_AGENT_HOME" : piCodingAgentDirSource;
|
|
11209
|
-
const userSkillsPath = piAgentHome ?
|
|
11517
|
+
const userSkillsPath = piAgentHome ? join13(piAgentHome, "skills") : null;
|
|
11210
11518
|
const configuredMarketplaceSkillsPath = safeExpandPath(
|
|
11211
11519
|
process.env.PI_AGENT_MARKETPLACE_SKILLS_DIR
|
|
11212
11520
|
);
|
|
11213
|
-
const marketplaceSkillsPath = configuredMarketplaceSkillsPath ?? (piAgentHome ?
|
|
11521
|
+
const marketplaceSkillsPath = configuredMarketplaceSkillsPath ?? (piAgentHome ? join13(piAgentHome, "marketplace", "skills") : null);
|
|
11214
11522
|
const builtinSkillsPath = safeExpandPath(process.env.PI_AGENT_BUILTIN_SKILLS_DIR) ?? safeExpandPath(process.env.AMASTER_BUILTIN_SKILLS);
|
|
11215
|
-
const mcpConfigPath = safeExpandPath(process.env.PI_AGENT_MCP_SERVERS_FILE) ?? (piAgentHome ?
|
|
11216
|
-
const settingsConfigPath = piCodingAgentDir ?
|
|
11523
|
+
const mcpConfigPath = safeExpandPath(process.env.PI_AGENT_MCP_SERVERS_FILE) ?? (piAgentHome ? join13(piAgentHome, "mcp.json") : null);
|
|
11524
|
+
const settingsConfigPath = piCodingAgentDir ? join13(piCodingAgentDir, "settings.json") : null;
|
|
11217
11525
|
const skillRoots = [
|
|
11218
11526
|
safeSkillRootSummary("user", `${piAgentHomeSource}/skills`, userSkillsPath),
|
|
11219
11527
|
safeSkillRootSummary(
|
|
@@ -11333,15 +11641,15 @@ function buildExecutorReadiness(config) {
|
|
|
11333
11641
|
function sourceAcquisitionPackageMetadata(packageName) {
|
|
11334
11642
|
const agentDir = readString(process.env.PI_CODING_AGENT_DIR ?? process.env.PI_AGENT_HOME);
|
|
11335
11643
|
if (!agentDir) return null;
|
|
11336
|
-
const packagePath =
|
|
11337
|
-
|
|
11644
|
+
const packagePath = join13(
|
|
11645
|
+
resolve10(expandHomePath(agentDir)),
|
|
11338
11646
|
"npm",
|
|
11339
11647
|
"node_modules",
|
|
11340
11648
|
...packageName.split("/"),
|
|
11341
11649
|
"package.json"
|
|
11342
11650
|
);
|
|
11343
|
-
if (!
|
|
11344
|
-
const stat =
|
|
11651
|
+
if (!existsSync12(packagePath)) return null;
|
|
11652
|
+
const stat = lstatSync6(packagePath);
|
|
11345
11653
|
if (!stat.isFile() || stat.isSymbolicLink()) return null;
|
|
11346
11654
|
const metadata = readJsonFile2(packagePath);
|
|
11347
11655
|
return metadata.name === packageName && readString(metadata.version) ? metadata : null;
|
|
@@ -11350,7 +11658,7 @@ function sourceAcquisitionBrowserExecutableReady() {
|
|
|
11350
11658
|
const executable = readString(process.env.AMASTER_BROWSER_EXECUTABLE_PATH);
|
|
11351
11659
|
if (!executable || !isAbsolute6(executable)) return false;
|
|
11352
11660
|
try {
|
|
11353
|
-
const stat =
|
|
11661
|
+
const stat = statSync9(executable);
|
|
11354
11662
|
return stat.isFile() && (stat.mode & 73) !== 0;
|
|
11355
11663
|
} catch {
|
|
11356
11664
|
return false;
|
|
@@ -11376,6 +11684,20 @@ function sourceAcquisitionRuntimeReadiness(config) {
|
|
|
11376
11684
|
if (adapters.length === 0 || adapters.some((adapter) => ![SOURCE_ACQUISITION_HEADLESS_ADAPTER, SOURCE_ACQUISITION_DESKTOP_ADAPTER].includes(adapter))) {
|
|
11377
11685
|
return unavailable("source_acquisition_adapter_attestation_invalid");
|
|
11378
11686
|
}
|
|
11687
|
+
let browserSkill;
|
|
11688
|
+
if (adapters.includes(SOURCE_ACQUISITION_DESKTOP_ADAPTER)) {
|
|
11689
|
+
browserSkill = {
|
|
11690
|
+
runtimeVersion: readString(process.env.AMASTER_SOURCE_ACQUISITION_BROWSER_SKILL_RUNTIME_VERSION),
|
|
11691
|
+
runtimeDigest: readString(process.env.AMASTER_SOURCE_ACQUISITION_BROWSER_SKILL_RUNTIME_DIGEST),
|
|
11692
|
+
assetVersion: readString(process.env.AMASTER_SOURCE_ACQUISITION_BROWSER_SKILL_ASSET_VERSION),
|
|
11693
|
+
assetDigest: readString(process.env.AMASTER_SOURCE_ACQUISITION_BROWSER_SKILL_ASSET_DIGEST),
|
|
11694
|
+
policyVersion: SOURCE_ACQUISITION_BROWSER_POLICY_VERSION,
|
|
11695
|
+
policyDigest: readString(process.env.AMASTER_SOURCE_ACQUISITION_BROWSER_SKILL_POLICY_DIGEST)
|
|
11696
|
+
};
|
|
11697
|
+
if (!browserSkill.runtimeVersion || !browserSkill.assetVersion || !/^[a-f0-9]{64}$/u.test(browserSkill.runtimeDigest ?? "") || !/^[a-f0-9]{64}$/u.test(browserSkill.assetDigest ?? "") || !/^[a-f0-9]{64}$/u.test(browserSkill.policyDigest ?? "")) {
|
|
11698
|
+
return unavailable("source_acquisition_browser_skill_attestation_invalid");
|
|
11699
|
+
}
|
|
11700
|
+
}
|
|
11379
11701
|
if (adapters.includes(SOURCE_ACQUISITION_HEADLESS_ADAPTER) && !sourceAcquisitionBrowserExecutableReady()) {
|
|
11380
11702
|
return unavailable("source_acquisition_browser_executable_unavailable");
|
|
11381
11703
|
}
|
|
@@ -11402,6 +11724,7 @@ function sourceAcquisitionRuntimeReadiness(config) {
|
|
|
11402
11724
|
actionVersion: SOURCE_ACQUISITION_ACTION_VERSION,
|
|
11403
11725
|
extension: { digest: extensionDigest },
|
|
11404
11726
|
adapters,
|
|
11727
|
+
...browserSkill ? { browserSkill } : {},
|
|
11405
11728
|
connector: {
|
|
11406
11729
|
version: CONNECTOR_VERSION,
|
|
11407
11730
|
digest: connectorDigest
|
|
@@ -11409,12 +11732,46 @@ function sourceAcquisitionRuntimeReadiness(config) {
|
|
|
11409
11732
|
packages
|
|
11410
11733
|
};
|
|
11411
11734
|
}
|
|
11412
|
-
function
|
|
11413
|
-
|
|
11735
|
+
function browserSessionRuntimeReadiness(config) {
|
|
11736
|
+
let runtimeAvailable = false;
|
|
11737
|
+
try {
|
|
11738
|
+
daemonRequire.resolve("playwright-core");
|
|
11739
|
+
runtimeAvailable = true;
|
|
11740
|
+
} catch {
|
|
11741
|
+
}
|
|
11742
|
+
return browserSessionBrokerReadiness({
|
|
11743
|
+
stateRoot: config.browserSessionStateRoot,
|
|
11744
|
+
browserExecutable: readString(process.env.AMASTER_BROWSER_EXECUTABLE_PATH),
|
|
11745
|
+
runtimeAvailable
|
|
11746
|
+
});
|
|
11747
|
+
}
|
|
11748
|
+
var browserSessionBrokers = /* @__PURE__ */ new Map();
|
|
11749
|
+
function browserSessionBrokerFor(config) {
|
|
11750
|
+
const key = resolve10(config.browserSessionStateRoot);
|
|
11751
|
+
let broker = browserSessionBrokers.get(key);
|
|
11752
|
+
if (!broker) {
|
|
11753
|
+
const { chromium } = daemonRequire("playwright-core");
|
|
11754
|
+
broker = createBrowserSessionBroker({
|
|
11755
|
+
stateRoot: key,
|
|
11756
|
+
browserExecutable: readString(process.env.AMASTER_BROWSER_EXECUTABLE_PATH),
|
|
11757
|
+
chromium
|
|
11758
|
+
});
|
|
11759
|
+
browserSessionBrokers.set(key, broker);
|
|
11760
|
+
}
|
|
11761
|
+
return broker;
|
|
11762
|
+
}
|
|
11763
|
+
function browserSessionRuntimeStatus(config) {
|
|
11764
|
+
const readiness = browserSessionRuntimeReadiness(config);
|
|
11765
|
+
const broker = browserSessionBrokers.get(resolve10(config.browserSessionStateRoot));
|
|
11766
|
+
return broker ? { ...readiness, ...broker.status() } : readiness;
|
|
11767
|
+
}
|
|
11768
|
+
function runtimeAdvertisedCapabilities(config, sourceAcquisition, browserSessionBroker) {
|
|
11769
|
+
return config.capabilities.filter((capability) => (capability !== "headed_browser_auth" || browserSessionBroker.ready === true) && (capability !== SOURCE_ACQUISITION_CAPABILITY || sourceAcquisition.ready === true));
|
|
11414
11770
|
}
|
|
11415
11771
|
function buildRegisterPayload(config) {
|
|
11416
11772
|
const buildCommit = readString(process.env.AMASTER_RUNTIME_BUILD_COMMIT ?? process.env.AMASTER_SOURCE_COMMIT);
|
|
11417
11773
|
const sourceAcquisition = sourceAcquisitionRuntimeReadiness(config);
|
|
11774
|
+
const browserSessionBroker = browserSessionRuntimeReadiness(config);
|
|
11418
11775
|
return {
|
|
11419
11776
|
...config.companyId ? { companyId: config.companyId } : {},
|
|
11420
11777
|
connectorName: config.connectorName,
|
|
@@ -11422,7 +11779,7 @@ function buildRegisterPayload(config) {
|
|
|
11422
11779
|
workspaceBindings: config.workspaceBindings,
|
|
11423
11780
|
networkDomains: config.networkDomains,
|
|
11424
11781
|
executors: config.executors,
|
|
11425
|
-
capabilities: runtimeAdvertisedCapabilities(config, sourceAcquisition),
|
|
11782
|
+
capabilities: runtimeAdvertisedCapabilities(config, sourceAcquisition, browserSessionBroker),
|
|
11426
11783
|
contractVersion: CONNECTOR_CONTRACT_VERSION,
|
|
11427
11784
|
connectorVersion: CONNECTOR_VERSION,
|
|
11428
11785
|
...buildCommit ? { buildCommit } : {},
|
|
@@ -11468,6 +11825,7 @@ function buildHeartbeatPayload(config, options = {}) {
|
|
|
11468
11825
|
const activeRunCount = activeRunCommandList.filter(activeRunCommandCountsAsActive).length;
|
|
11469
11826
|
const executorReadiness = buildExecutorReadiness(config);
|
|
11470
11827
|
const sourceAcquisition = sourceAcquisitionRuntimeReadiness(config);
|
|
11828
|
+
const browserSessionBroker = browserSessionRuntimeStatus(config);
|
|
11471
11829
|
const status = options.status === "offline" ? "offline" : "online";
|
|
11472
11830
|
const daemonStatus = status === "offline" ? "stopping" : "running";
|
|
11473
11831
|
return {
|
|
@@ -11475,7 +11833,7 @@ function buildHeartbeatPayload(config, options = {}) {
|
|
|
11475
11833
|
workspaceBindings: config.workspaceBindings,
|
|
11476
11834
|
networkDomains: config.networkDomains,
|
|
11477
11835
|
executors: config.executors,
|
|
11478
|
-
capabilities: runtimeAdvertisedCapabilities(config, sourceAcquisition),
|
|
11836
|
+
capabilities: runtimeAdvertisedCapabilities(config, sourceAcquisition, browserSessionBroker),
|
|
11479
11837
|
connectorVersion: CONNECTOR_VERSION,
|
|
11480
11838
|
...buildCommit ? { buildCommit } : {},
|
|
11481
11839
|
contractVersion: CONNECTOR_CONTRACT_VERSION,
|
|
@@ -11496,6 +11854,7 @@ function buildHeartbeatPayload(config, options = {}) {
|
|
|
11496
11854
|
stateFile: stateFilePath(process.env),
|
|
11497
11855
|
...executorReadiness.length > 0 ? { executorReadiness } : {},
|
|
11498
11856
|
runnerKind: config.runnerKind,
|
|
11857
|
+
browserSessionBroker,
|
|
11499
11858
|
sourceAcquisition,
|
|
11500
11859
|
...versionDrift.versionDrift || versionDrift.bundleDrift ? versionDrift : {}
|
|
11501
11860
|
},
|
|
@@ -11669,7 +12028,7 @@ AMASTER_WORKSPACE_ALLOWLIST=${quoteShell(config.workspaceBindings.join(","))}
|
|
|
11669
12028
|
AMASTER_EXECUTORS=${quoteShell(executorEnv)}
|
|
11670
12029
|
AMASTER_CAPABILITIES=${quoteShell(config.capabilities.join(","))}
|
|
11671
12030
|
AMASTER_NETWORK_DOMAINS=${quoteShell(config.networkDomains.join(","))}
|
|
11672
|
-
AMASTER_DAEMON_STATE_FILE=${quoteShell(
|
|
12031
|
+
AMASTER_DAEMON_STATE_FILE=${quoteShell(join13(homedir3(), ".amaster-employee", "runtime-connector-state.json"))}
|
|
11673
12032
|
EOF
|
|
11674
12033
|
|
|
11675
12034
|
set -a
|
|
@@ -11895,10 +12254,10 @@ function buildActiveRunCommandStatus(config, entry) {
|
|
|
11895
12254
|
const base = {
|
|
11896
12255
|
...entry,
|
|
11897
12256
|
phase: readString(entry.phase) ?? "executing",
|
|
11898
|
-
managedWorkdirPresent: entry.workspacePath ?
|
|
12257
|
+
managedWorkdirPresent: entry.workspacePath ? existsSync12(entry.workspacePath) : false,
|
|
11899
12258
|
outboxPending: resultOutboxPendingCount(config)
|
|
11900
12259
|
};
|
|
11901
|
-
if (!entry.workspacePath || !
|
|
12260
|
+
if (!entry.workspacePath || !existsSync12(entry.workspacePath)) return base;
|
|
11902
12261
|
const manifestPath = entry.manifestPath ?? workspaceManifestPath(entry.workspacePath);
|
|
11903
12262
|
const status = readWorkspaceStatus(entry.workspacePath, { hashCache: workspaceStatusHashCache });
|
|
11904
12263
|
const artifactCandidates = status.artifacts.slice(0, 20);
|
|
@@ -12077,7 +12436,24 @@ function commandTrustedPiRuntimeAssertion(command) {
|
|
|
12077
12436
|
function commandSourceAcquisitionProfile(command) {
|
|
12078
12437
|
return asRecord(asRecord(asRecord(command.payload).sourceAcquisition).profile);
|
|
12079
12438
|
}
|
|
12080
|
-
function
|
|
12439
|
+
function sourceAcquisitionExactOrigin(value) {
|
|
12440
|
+
const locator = readString(value);
|
|
12441
|
+
let url;
|
|
12442
|
+
try {
|
|
12443
|
+
url = new URL(locator ?? "");
|
|
12444
|
+
} catch {
|
|
12445
|
+
throw Object.assign(new Error("source_acquisition_profile_invalid"), {
|
|
12446
|
+
code: "source_acquisition_profile_invalid"
|
|
12447
|
+
});
|
|
12448
|
+
}
|
|
12449
|
+
if (url.protocol !== "https:" || url.username || url.password) {
|
|
12450
|
+
throw Object.assign(new Error("source_acquisition_profile_invalid"), {
|
|
12451
|
+
code: "source_acquisition_profile_invalid"
|
|
12452
|
+
});
|
|
12453
|
+
}
|
|
12454
|
+
return url.origin;
|
|
12455
|
+
}
|
|
12456
|
+
async function sourceAcquisitionRuntimeProfile(config, command) {
|
|
12081
12457
|
const profile = commandSourceAcquisitionProfile(command);
|
|
12082
12458
|
if (Object.keys(profile).length === 0) return null;
|
|
12083
12459
|
const access = asRecord(profile.access);
|
|
@@ -12098,23 +12474,36 @@ function sourceAcquisitionRuntimeProfile(config, command) {
|
|
|
12098
12474
|
const companyId = readString(profile.companyId);
|
|
12099
12475
|
const bindingId = readString(access.browserBindingId);
|
|
12100
12476
|
const localOpaqueRef = readString(access.localOpaqueRef);
|
|
12101
|
-
|
|
12477
|
+
const browserLeaseId = readString(access.browserLeaseId);
|
|
12478
|
+
const browserLeaseExpiresAt = readString(access.browserLeaseExpiresAt);
|
|
12479
|
+
if (!companyId || !bindingId || !/^profile_[a-z0-9]{16,64}$/i.test(localOpaqueRef ?? "") || !browserLeaseId || !browserLeaseExpiresAt || Date.parse(browserLeaseExpiresAt) <= Date.now()) {
|
|
12102
12480
|
throw new Error("source_acquisition_profile_invalid");
|
|
12103
12481
|
}
|
|
12104
|
-
const
|
|
12105
|
-
const
|
|
12106
|
-
const
|
|
12482
|
+
const exactOrigin = sourceAcquisitionExactOrigin(access.exactLocator);
|
|
12483
|
+
const profileName2 = createHash13("sha256").update(`${companyId}\0${bindingId}\0${localOpaqueRef}`).digest("hex");
|
|
12484
|
+
const stateRoot = resolve10(config.browserSessionStateRoot);
|
|
12485
|
+
const userDataDir = resolve10(stateRoot, profileName2);
|
|
12107
12486
|
if (!pathWithin2(userDataDir, stateRoot)) throw new Error("source_acquisition_browser_profile_invalid");
|
|
12108
|
-
const markerPath =
|
|
12487
|
+
const markerPath = join13(userDataDir, ".amaster-browser-session.json");
|
|
12488
|
+
if (!existsSync12(userDataDir) || lstatSync6(userDataDir).isSymbolicLink() || !lstatSync6(userDataDir).isDirectory() || !existsSync12(markerPath) || lstatSync6(markerPath).isSymbolicLink()) throw new Error("source_acquisition_browser_profile_invalid");
|
|
12109
12489
|
const marker = readJsonFile2(markerPath);
|
|
12110
|
-
if (marker.version !== 1 || marker.companyId !== companyId || marker.bindingId !== bindingId || marker.localOpaqueRef !== localOpaqueRef || Object.keys(marker).length !==
|
|
12490
|
+
if (marker.version !== 1 || marker.companyId !== companyId || marker.bindingId !== bindingId || marker.localOpaqueRef !== localOpaqueRef || !readString(marker.provider) || marker.origin !== exactOrigin || Object.keys(marker).length !== 6) {
|
|
12111
12491
|
throw new Error("source_acquisition_browser_profile_invalid");
|
|
12112
12492
|
}
|
|
12113
|
-
|
|
12493
|
+
const releaseBrowserLease = await browserSessionBrokerFor(config).acquireAgentRead({
|
|
12494
|
+
companyId,
|
|
12495
|
+
bindingId,
|
|
12496
|
+
localOpaqueRef,
|
|
12497
|
+
origin: marker.origin,
|
|
12498
|
+
leaseId: browserLeaseId,
|
|
12499
|
+
leaseExpiresAt: browserLeaseExpiresAt,
|
|
12500
|
+
userDataDir
|
|
12501
|
+
});
|
|
12502
|
+
return { profile, userDataDir, releaseBrowserLease };
|
|
12114
12503
|
}
|
|
12115
12504
|
function readJsonFile2(filePath) {
|
|
12116
12505
|
try {
|
|
12117
|
-
const parsed = JSON.parse(
|
|
12506
|
+
const parsed = JSON.parse(readFileSync11(filePath, "utf8"));
|
|
12118
12507
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
12119
12508
|
} catch {
|
|
12120
12509
|
return {};
|
|
@@ -12159,7 +12548,7 @@ function safeAgentInstructionMaterializationTarget(workspace, filePath) {
|
|
|
12159
12548
|
const segments = normalized.split("/").filter(Boolean);
|
|
12160
12549
|
if (segments.length === 0 || segments.some((segment) => segment === "." || segment === "..")) return null;
|
|
12161
12550
|
const relativePath = segments.join("/");
|
|
12162
|
-
const targetPath =
|
|
12551
|
+
const targetPath = resolve10(workspace.cwd, relativePath);
|
|
12163
12552
|
if (!pathWithin2(targetPath, workspace.cwd)) return null;
|
|
12164
12553
|
return { relativePath, targetPath };
|
|
12165
12554
|
}
|
|
@@ -12173,8 +12562,8 @@ async function materializeAgentInstructionsBundle(config, command, workspace, bu
|
|
|
12173
12562
|
if (!content) continue;
|
|
12174
12563
|
const target = safeAgentInstructionMaterializationTarget(workspace, filePath);
|
|
12175
12564
|
if (!target) continue;
|
|
12176
|
-
|
|
12177
|
-
|
|
12565
|
+
mkdirSync8(dirname8(target.targetPath), { recursive: true });
|
|
12566
|
+
writeFileSync8(target.targetPath, content, "utf8");
|
|
12178
12567
|
materialized.push({
|
|
12179
12568
|
path: target.relativePath,
|
|
12180
12569
|
byteSize: Buffer.byteLength(content, "utf8")
|
|
@@ -12201,11 +12590,11 @@ function wikiTreePathForCommand(command, workspaceBindings) {
|
|
|
12201
12590
|
const candidates = [];
|
|
12202
12591
|
if (root.endsWith("paperclipai.plugin-llm-wiki")) candidates.push(root);
|
|
12203
12592
|
if (basename6(root) === "plugin-data" && companyId) {
|
|
12204
|
-
candidates.push(
|
|
12593
|
+
candidates.push(join13(root, companyId, "paperclipai.plugin-llm-wiki"));
|
|
12205
12594
|
}
|
|
12206
12595
|
for (const candidate of candidates) {
|
|
12207
12596
|
try {
|
|
12208
|
-
if (
|
|
12597
|
+
if (existsSync12(candidate)) return candidate;
|
|
12209
12598
|
} catch {
|
|
12210
12599
|
}
|
|
12211
12600
|
}
|
|
@@ -12345,18 +12734,18 @@ function buildExecutorEnv(config, command, workspace) {
|
|
|
12345
12734
|
};
|
|
12346
12735
|
}
|
|
12347
12736
|
function preparePiModelCallProfile(commandId, baseEnv, options = {}) {
|
|
12348
|
-
const profileRoot = mkdtempSync(
|
|
12349
|
-
const home =
|
|
12350
|
-
const sessionsDir =
|
|
12351
|
-
const tempDir =
|
|
12737
|
+
const profileRoot = mkdtempSync(join13(tmpdir(), "amaster-pi-model-call-"));
|
|
12738
|
+
const home = join13(profileRoot, "home");
|
|
12739
|
+
const sessionsDir = join13(profileRoot, "sessions");
|
|
12740
|
+
const tempDir = join13(profileRoot, "tmp");
|
|
12352
12741
|
for (const directory of [home, sessionsDir, tempDir]) {
|
|
12353
|
-
|
|
12742
|
+
mkdirSync8(directory, { recursive: true, mode: 448 });
|
|
12354
12743
|
}
|
|
12355
12744
|
try {
|
|
12356
12745
|
const extensionArgs = [];
|
|
12357
12746
|
if (options.responseContract) {
|
|
12358
|
-
const extensionPath =
|
|
12359
|
-
|
|
12747
|
+
const extensionPath = join13(profileRoot, "model-call-output-contract.js");
|
|
12748
|
+
writeFileSync8(
|
|
12360
12749
|
extensionPath,
|
|
12361
12750
|
modelCallOutputContractExtensionSource(options.responseContract.maxOutputTokens),
|
|
12362
12751
|
{ mode: 384 }
|
|
@@ -12376,12 +12765,12 @@ function preparePiModelCallProfile(commandId, baseEnv, options = {}) {
|
|
|
12376
12765
|
}
|
|
12377
12766
|
};
|
|
12378
12767
|
} catch (error) {
|
|
12379
|
-
|
|
12768
|
+
rmSync6(profileRoot, { recursive: true, force: true });
|
|
12380
12769
|
throw error;
|
|
12381
12770
|
}
|
|
12382
12771
|
}
|
|
12383
12772
|
function cleanupPiModelCallProfile(profile) {
|
|
12384
|
-
if (profile?.profileRoot)
|
|
12773
|
+
if (profile?.profileRoot) rmSync6(profile.profileRoot, { recursive: true, force: true });
|
|
12385
12774
|
}
|
|
12386
12775
|
function splitExtraArgs(value) {
|
|
12387
12776
|
return splitList(value).flatMap((entry) => entry.split(/\s+/).filter(Boolean));
|
|
@@ -12421,7 +12810,7 @@ function resolveNativeSessionRequest(command, workspace) {
|
|
|
12421
12810
|
try {
|
|
12422
12811
|
cwdMatched = realpathSync5(requestedCwd) === realpathSync5(sourceWorkspacePath);
|
|
12423
12812
|
} catch {
|
|
12424
|
-
cwdMatched =
|
|
12813
|
+
cwdMatched = resolve10(requestedCwd) === resolve10(sourceWorkspacePath);
|
|
12425
12814
|
}
|
|
12426
12815
|
}
|
|
12427
12816
|
const used = Boolean(enabled && requested && sessionId && requestedCwd && cwdMatched);
|
|
@@ -13006,10 +13395,10 @@ function realOrResolvedPath(value) {
|
|
|
13006
13395
|
try {
|
|
13007
13396
|
return realpathSync5(value);
|
|
13008
13397
|
} catch {
|
|
13009
|
-
return
|
|
13398
|
+
return resolve10(value);
|
|
13010
13399
|
}
|
|
13011
13400
|
}
|
|
13012
|
-
var LSOF_COMMAND = process.platform === "darwin" &&
|
|
13401
|
+
var LSOF_COMMAND = process.platform === "darwin" && existsSync12("/usr/sbin/lsof") ? "/usr/sbin/lsof" : "lsof";
|
|
13013
13402
|
function processCwdForPid(pid) {
|
|
13014
13403
|
if (process.platform === "linux") {
|
|
13015
13404
|
try {
|
|
@@ -13131,7 +13520,7 @@ function killWorkspaceResidentProcesses(cwd, processGroupId, options = {}) {
|
|
|
13131
13520
|
}
|
|
13132
13521
|
function walkManagedWorkdirs(root) {
|
|
13133
13522
|
const workdirs = [];
|
|
13134
|
-
if (!root || !
|
|
13523
|
+
if (!root || !existsSync12(root)) return workdirs;
|
|
13135
13524
|
const stack = [root];
|
|
13136
13525
|
while (stack.length > 0) {
|
|
13137
13526
|
const current = stack.pop();
|
|
@@ -13144,8 +13533,8 @@ function walkManagedWorkdirs(root) {
|
|
|
13144
13533
|
}
|
|
13145
13534
|
for (const entry of entries) {
|
|
13146
13535
|
if (!entry.isDirectory()) continue;
|
|
13147
|
-
const fullPath =
|
|
13148
|
-
if (entry.name === "workdir" &&
|
|
13536
|
+
const fullPath = join13(current, entry.name);
|
|
13537
|
+
if (entry.name === "workdir" && existsSync12(workspaceManifestPath(fullPath))) {
|
|
13149
13538
|
workdirs.push(fullPath);
|
|
13150
13539
|
continue;
|
|
13151
13540
|
}
|
|
@@ -13183,7 +13572,7 @@ function manifestMatchesActiveRuntimeRef(manifest, refs, workdir = null) {
|
|
|
13183
13572
|
}
|
|
13184
13573
|
function buildOrphanReaperSample(root, workdir, manifest, residents) {
|
|
13185
13574
|
const relativeWorkdir = (() => {
|
|
13186
|
-
const value =
|
|
13575
|
+
const value = relative7(root, workdir);
|
|
13187
13576
|
return value && !value.startsWith("..") && !isAbsolute6(value) ? value : basename6(workdir);
|
|
13188
13577
|
})();
|
|
13189
13578
|
return {
|
|
@@ -14616,7 +15005,7 @@ async function flushRunCompletionStates(config) {
|
|
|
14616
15005
|
for (const { filePath, state: listedState } of runCompletionStateEntries(config)) {
|
|
14617
15006
|
try {
|
|
14618
15007
|
if (runCompletionFlights.has(listedState.commandId)) continue;
|
|
14619
|
-
if (!
|
|
15008
|
+
if (!existsSync12(filePath)) continue;
|
|
14620
15009
|
const state = readValidRunCompletionStateOrQuarantine(config, filePath);
|
|
14621
15010
|
if (!state) continue;
|
|
14622
15011
|
const outcome = await coordinateRunCompletionSingleFlight(config, state);
|
|
@@ -14803,15 +15192,15 @@ async function completeCommand(config, command, status, result3, error) {
|
|
|
14803
15192
|
}
|
|
14804
15193
|
function resultOutboxDir(config) {
|
|
14805
15194
|
const explicit = readString(process.env.AMASTER_RESULT_OUTBOX_DIR);
|
|
14806
|
-
if (explicit) return
|
|
14807
|
-
return
|
|
15195
|
+
if (explicit) return resolve10(expandHomePath(explicit));
|
|
15196
|
+
return join13(dirname8(stateFilePath(process.env)), "result-outbox");
|
|
14808
15197
|
}
|
|
14809
15198
|
function resultOutboxInvalidDir(config) {
|
|
14810
|
-
return
|
|
15199
|
+
return join13(resultOutboxDir(config), "invalid");
|
|
14811
15200
|
}
|
|
14812
15201
|
function writeResultOutboxEntry(config, entry) {
|
|
14813
15202
|
const dir = resultOutboxDir(config);
|
|
14814
|
-
|
|
15203
|
+
mkdirSync8(dir, { recursive: true });
|
|
14815
15204
|
const body = {
|
|
14816
15205
|
version: 1,
|
|
14817
15206
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -14819,13 +15208,13 @@ function writeResultOutboxEntry(config, entry) {
|
|
|
14819
15208
|
lastAttemptAt: null,
|
|
14820
15209
|
...entry
|
|
14821
15210
|
};
|
|
14822
|
-
|
|
15211
|
+
writeFileSync8(join13(dir, resultOutboxFileName(entry.commandId)), `${JSON.stringify(body, null, 2)}
|
|
14823
15212
|
`, { mode: 384 });
|
|
14824
15213
|
}
|
|
14825
15214
|
function moveResultOutboxEntryToInvalid(config, file, fullPath, reason, detail, original) {
|
|
14826
15215
|
const invalidDir = resultOutboxInvalidDir(config);
|
|
14827
|
-
|
|
14828
|
-
const invalidPath =
|
|
15216
|
+
mkdirSync8(invalidDir, { recursive: true });
|
|
15217
|
+
const invalidPath = join13(invalidDir, file);
|
|
14829
15218
|
if (original === void 0) {
|
|
14830
15219
|
try {
|
|
14831
15220
|
renameSync6(fullPath, invalidPath);
|
|
@@ -14841,14 +15230,14 @@ function moveResultOutboxEntryToInvalid(config, file, fullPath, reason, detail,
|
|
|
14841
15230
|
...detail ? { detail: truncateText(detail, 1e3) } : {},
|
|
14842
15231
|
original
|
|
14843
15232
|
};
|
|
14844
|
-
|
|
15233
|
+
writeFileSync8(invalidPath, `${JSON.stringify(evidence, null, 2)}
|
|
14845
15234
|
`, { mode: 384 });
|
|
14846
15235
|
unlinkSync2(fullPath);
|
|
14847
15236
|
}
|
|
14848
15237
|
function readValidResultOutboxEntryOrQuarantine(config, file, fullPath) {
|
|
14849
15238
|
let entry;
|
|
14850
15239
|
try {
|
|
14851
|
-
entry = JSON.parse(
|
|
15240
|
+
entry = JSON.parse(readFileSync11(fullPath, "utf8"));
|
|
14852
15241
|
} catch (err) {
|
|
14853
15242
|
const message = err instanceof Error ? err.message : String(err);
|
|
14854
15243
|
moveResultOutboxEntryToInvalid(config, file, fullPath, "malformed_result_outbox_json", message);
|
|
@@ -14878,13 +15267,13 @@ function updateResultOutboxAttempt(fullPath, entry, err) {
|
|
|
14878
15267
|
...typeof err?.httpStatus === "number" ? { httpStatus: err.httpStatus } : {},
|
|
14879
15268
|
lastError: truncateText(err instanceof Error ? err.message : String(err), 1e3)
|
|
14880
15269
|
};
|
|
14881
|
-
|
|
15270
|
+
writeFileSync8(fullPath, `${JSON.stringify(next, null, 2)}
|
|
14882
15271
|
`, { mode: 384 });
|
|
14883
15272
|
return next;
|
|
14884
15273
|
}
|
|
14885
15274
|
function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err) {
|
|
14886
15275
|
const invalidDir = resultOutboxInvalidDir(config);
|
|
14887
|
-
|
|
15276
|
+
mkdirSync8(invalidDir, { recursive: true });
|
|
14888
15277
|
const body = {
|
|
14889
15278
|
...entry,
|
|
14890
15279
|
invalidReason: reason,
|
|
@@ -14892,8 +15281,8 @@ function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err)
|
|
|
14892
15281
|
...typeof err?.httpStatus === "number" ? { httpStatus: err.httpStatus } : {},
|
|
14893
15282
|
lastError: truncateText(err instanceof Error ? err.message : String(err), 1e3)
|
|
14894
15283
|
};
|
|
14895
|
-
const invalidPath =
|
|
14896
|
-
|
|
15284
|
+
const invalidPath = join13(invalidDir, file);
|
|
15285
|
+
writeFileSync8(invalidPath, `${JSON.stringify(body, null, 2)}
|
|
14897
15286
|
`, { mode: 384 });
|
|
14898
15287
|
try {
|
|
14899
15288
|
unlinkSync2(fullPath);
|
|
@@ -14907,11 +15296,11 @@ function quarantineResultOutboxEntry(config, fullPath, file, entry, reason, err)
|
|
|
14907
15296
|
}
|
|
14908
15297
|
async function flushResultOutbox(config) {
|
|
14909
15298
|
const dir = resultOutboxDir(config);
|
|
14910
|
-
if (!
|
|
15299
|
+
if (!existsSync12(dir)) return { attempted: 0, completed: 0 };
|
|
14911
15300
|
const files = readdirSync9(dir).filter((name) => name.endsWith(".json")).sort();
|
|
14912
15301
|
let completed = 0;
|
|
14913
15302
|
for (const file of files) {
|
|
14914
|
-
const fullPath =
|
|
15303
|
+
const fullPath = join13(dir, file);
|
|
14915
15304
|
const entry = readValidResultOutboxEntryOrQuarantine(config, file, fullPath);
|
|
14916
15305
|
if (!entry) continue;
|
|
14917
15306
|
try {
|
|
@@ -15108,8 +15497,8 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
15108
15497
|
runtimeAuth,
|
|
15109
15498
|
issueId
|
|
15110
15499
|
);
|
|
15111
|
-
const targetDir =
|
|
15112
|
-
|
|
15500
|
+
const targetDir = join13(workspace.cwd, "input-attachments");
|
|
15501
|
+
mkdirSync8(targetDir, { recursive: true });
|
|
15113
15502
|
const usedFilenames = /* @__PURE__ */ new Set();
|
|
15114
15503
|
const materialized = [];
|
|
15115
15504
|
for (const [index, rawAttachment] of attachments.entries()) {
|
|
@@ -15123,11 +15512,11 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
15123
15512
|
filename = `${stem}-${index + 1}${ext}`;
|
|
15124
15513
|
}
|
|
15125
15514
|
usedFilenames.add(filename);
|
|
15126
|
-
const targetPath =
|
|
15515
|
+
const targetPath = join13(targetDir, filename);
|
|
15127
15516
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
15128
|
-
|
|
15517
|
+
writeFileSync8(targetPath, body);
|
|
15129
15518
|
const attachmentId = readString(attachment.id);
|
|
15130
|
-
const actualSha256 =
|
|
15519
|
+
const actualSha256 = createHash13("sha256").update(body).digest("hex");
|
|
15131
15520
|
const lineageCandidates = lineageCandidatesByAttachmentId.get(attachmentId) ?? [];
|
|
15132
15521
|
const lineage = selectAttachmentLineage(lineageCandidates, actualSha256);
|
|
15133
15522
|
if (lineageCandidates.length > 0 && !lineage) {
|
|
@@ -15150,7 +15539,7 @@ async function materializeIssueAttachments(config, command, workspace) {
|
|
|
15150
15539
|
id: attachmentId,
|
|
15151
15540
|
name: readString(attachment.originalFilename) ?? filename,
|
|
15152
15541
|
path: targetPath,
|
|
15153
|
-
relativePath:
|
|
15542
|
+
relativePath: relative7(workspace.cwd, targetPath),
|
|
15154
15543
|
contentType: readString(attachment.contentType),
|
|
15155
15544
|
byteSize: body.byteLength,
|
|
15156
15545
|
contentPath,
|
|
@@ -15199,9 +15588,9 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
15199
15588
|
if (manifest.version !== 1 || !Array.isArray(manifest.entries)) {
|
|
15200
15589
|
throw new Error("artifact_input_manifest_invalid: expected version 1 entries array");
|
|
15201
15590
|
}
|
|
15202
|
-
const targetRoot =
|
|
15203
|
-
|
|
15204
|
-
|
|
15591
|
+
const targetRoot = join13(workspace.cwd, "input-artifacts");
|
|
15592
|
+
rmSync6(targetRoot, { recursive: true, force: true });
|
|
15593
|
+
mkdirSync8(targetRoot, { recursive: true });
|
|
15205
15594
|
const usedPaths = /* @__PURE__ */ new Set();
|
|
15206
15595
|
const materialized = [];
|
|
15207
15596
|
for (const [index, rawEntry] of manifest.entries.entries()) {
|
|
@@ -15219,7 +15608,7 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
15219
15608
|
throw new Error(`artifact_input_manifest_invalid: entry ${index} contentPath does not match attachmentId`);
|
|
15220
15609
|
}
|
|
15221
15610
|
const body = await runtimeApiBuffer(runtimeAuth, contentPath);
|
|
15222
|
-
const actualSha256 =
|
|
15611
|
+
const actualSha256 = createHash13("sha256").update(body).digest("hex");
|
|
15223
15612
|
if (body.byteLength !== byteSize || actualSha256 !== sha2562) {
|
|
15224
15613
|
throw new Error(
|
|
15225
15614
|
`artifact_input_integrity_mismatch: workProductId=${workProductId} expectedBytes=${byteSize} actualBytes=${body.byteLength} expectedSha256=${sha2562} actualSha256=${actualSha256}`
|
|
@@ -15230,18 +15619,18 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
15230
15619
|
id: attachmentId,
|
|
15231
15620
|
originalFilename: readString(entry.originalFilename)
|
|
15232
15621
|
}, index);
|
|
15233
|
-
let relativePath =
|
|
15622
|
+
let relativePath = join13("input-artifacts", sourceDir, filename).split(/[\\/]+/).join("/");
|
|
15234
15623
|
if (usedPaths.has(relativePath)) {
|
|
15235
15624
|
const ext = extname2(filename);
|
|
15236
15625
|
const stem = ext ? filename.slice(0, -ext.length) : filename;
|
|
15237
15626
|
filename = `${stem}-${index + 1}${ext}`;
|
|
15238
|
-
relativePath =
|
|
15627
|
+
relativePath = join13("input-artifacts", sourceDir, filename).split(/[\\/]+/).join("/");
|
|
15239
15628
|
}
|
|
15240
15629
|
usedPaths.add(relativePath);
|
|
15241
|
-
const targetPath =
|
|
15242
|
-
|
|
15243
|
-
|
|
15244
|
-
|
|
15630
|
+
const targetPath = join13(workspace.cwd, relativePath);
|
|
15631
|
+
mkdirSync8(dirname8(targetPath), { recursive: true });
|
|
15632
|
+
writeFileSync8(targetPath, body);
|
|
15633
|
+
chmodSync5(targetPath, 292);
|
|
15245
15634
|
materialized.push({
|
|
15246
15635
|
id: attachmentId,
|
|
15247
15636
|
workProductId,
|
|
@@ -15260,9 +15649,9 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
15260
15649
|
version: 1,
|
|
15261
15650
|
entries: materialized.map(({ path: _path, relativePath, ...entry }) => ({ ...entry, path: relativePath }))
|
|
15262
15651
|
};
|
|
15263
|
-
const manifestPath =
|
|
15264
|
-
|
|
15265
|
-
|
|
15652
|
+
const manifestPath = join13(targetRoot, "artifact-input-manifest.json");
|
|
15653
|
+
writeFileSync8(manifestPath, JSON.stringify(localManifest, null, 2) + "\n");
|
|
15654
|
+
chmodSync5(manifestPath, 292);
|
|
15266
15655
|
updateWorkspaceManifest(workspaceManifestPath(workspace), { artifactInputManifest: localManifest });
|
|
15267
15656
|
await ingestLog(config, command, "system", "info", `Materialized ${materialized.length} required artifact input(s) into the execution workspace`, {
|
|
15268
15657
|
artifactInputCount: materialized.length,
|
|
@@ -15271,12 +15660,12 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
|
|
|
15271
15660
|
return materialized;
|
|
15272
15661
|
}
|
|
15273
15662
|
function issueCheckpointDir(workspace) {
|
|
15274
|
-
return
|
|
15663
|
+
return join13(dirname8(workspace.runDir), "checkpoint");
|
|
15275
15664
|
}
|
|
15276
15665
|
async function clearIssueCheckpoint(config, command, workspace, reason) {
|
|
15277
15666
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
15278
|
-
if (!
|
|
15279
|
-
|
|
15667
|
+
if (!existsSync12(checkpointDir)) return false;
|
|
15668
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
15280
15669
|
await ingestLog(config, command, "system", "info", "Cleared issue continuation checkpoint", { reason });
|
|
15281
15670
|
return true;
|
|
15282
15671
|
}
|
|
@@ -15289,28 +15678,28 @@ function safeCheckpointRelativePath(rawPath) {
|
|
|
15289
15678
|
return normalized;
|
|
15290
15679
|
}
|
|
15291
15680
|
function hashFileSha256(filePath) {
|
|
15292
|
-
return
|
|
15681
|
+
return createHash13("sha256").update(readFileSync11(filePath)).digest("hex");
|
|
15293
15682
|
}
|
|
15294
15683
|
async function materializeIssueCheckpoint(config, command, workspace) {
|
|
15295
15684
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
15296
|
-
const manifestPath =
|
|
15297
|
-
if (!
|
|
15685
|
+
const manifestPath = join13(checkpointDir, "manifest.json");
|
|
15686
|
+
if (!existsSync12(manifestPath)) return [];
|
|
15298
15687
|
let manifest;
|
|
15299
15688
|
try {
|
|
15300
|
-
manifest = asRecord(JSON.parse(
|
|
15689
|
+
manifest = asRecord(JSON.parse(readFileSync11(manifestPath, "utf8")));
|
|
15301
15690
|
} catch (err) {
|
|
15302
|
-
|
|
15691
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
15303
15692
|
throw new Error(`invalid issue checkpoint manifest: ${err instanceof Error ? err.message : String(err)}`);
|
|
15304
15693
|
}
|
|
15305
15694
|
const expiresAt = Date.parse(readString(manifest.expiresAt) ?? "");
|
|
15306
15695
|
if (!Number.isFinite(expiresAt) || expiresAt <= Date.now() || readString(manifest.issueId) !== commandIssueId(command)) {
|
|
15307
|
-
|
|
15696
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
15308
15697
|
return [];
|
|
15309
15698
|
}
|
|
15310
15699
|
try {
|
|
15311
15700
|
const files = Array.isArray(manifest.files) ? manifest.files : [];
|
|
15312
15701
|
if (files.length > 20) throw new Error("issue checkpoint manifest exceeds the limit of 20 files");
|
|
15313
|
-
const filesRoot = realpathSync5(
|
|
15702
|
+
const filesRoot = realpathSync5(join13(checkpointDir, "files"));
|
|
15314
15703
|
const workspaceRoot = realpathSync5(workspace.cwd);
|
|
15315
15704
|
const validated = [];
|
|
15316
15705
|
let totalBytes = 0;
|
|
@@ -15318,14 +15707,14 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
15318
15707
|
const file = asRecord(rawFile);
|
|
15319
15708
|
const relativePath = safeCheckpointRelativePath(readString(file.path));
|
|
15320
15709
|
if (!relativePath) throw new Error("issue checkpoint manifest contains an invalid file path");
|
|
15321
|
-
const sourceCandidate =
|
|
15322
|
-
const target =
|
|
15710
|
+
const sourceCandidate = resolve10(filesRoot, relativePath);
|
|
15711
|
+
const target = resolve10(workspaceRoot, relativePath);
|
|
15323
15712
|
if (!pathWithin2(sourceCandidate, filesRoot) || !pathWithin2(target, workspaceRoot)) {
|
|
15324
15713
|
throw new Error(`issue checkpoint path escapes its workspace: ${relativePath}`);
|
|
15325
15714
|
}
|
|
15326
|
-
if (!
|
|
15715
|
+
if (!existsSync12(sourceCandidate)) throw new Error(`issue checkpoint file is missing: ${relativePath}`);
|
|
15327
15716
|
const source = realpathSync5(sourceCandidate);
|
|
15328
|
-
if (!pathWithin2(source, filesRoot) || !
|
|
15717
|
+
if (!pathWithin2(source, filesRoot) || !statSync9(source).isFile()) {
|
|
15329
15718
|
throw new Error(`issue checkpoint source escapes its storage root: ${relativePath}`);
|
|
15330
15719
|
}
|
|
15331
15720
|
const expectedSha256 = readString(file.sha256);
|
|
@@ -15333,7 +15722,7 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
15333
15722
|
if (!expectedSha256 || expectedByteSize === null || expectedByteSize <= 0) {
|
|
15334
15723
|
throw new Error(`issue checkpoint evidence is incomplete: ${relativePath}`);
|
|
15335
15724
|
}
|
|
15336
|
-
if (hashFileSha256(source) !== expectedSha256 ||
|
|
15725
|
+
if (hashFileSha256(source) !== expectedSha256 || statSync9(source).size !== expectedByteSize) {
|
|
15337
15726
|
throw new Error(`issue checkpoint integrity mismatch: ${relativePath}`);
|
|
15338
15727
|
}
|
|
15339
15728
|
totalBytes += expectedByteSize;
|
|
@@ -15343,13 +15732,13 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
15343
15732
|
const materialized = [];
|
|
15344
15733
|
for (const { relativePath, source, target } of validated) {
|
|
15345
15734
|
try {
|
|
15346
|
-
|
|
15735
|
+
lstatSync6(target);
|
|
15347
15736
|
continue;
|
|
15348
15737
|
} catch (err) {
|
|
15349
15738
|
if (err?.code !== "ENOENT") throw err;
|
|
15350
15739
|
}
|
|
15351
|
-
|
|
15352
|
-
const targetParent = realpathSync5(
|
|
15740
|
+
mkdirSync8(dirname8(target), { recursive: true });
|
|
15741
|
+
const targetParent = realpathSync5(dirname8(target));
|
|
15353
15742
|
if (!pathWithin2(targetParent, workspaceRoot)) {
|
|
15354
15743
|
throw new Error(`issue checkpoint target escapes its workspace: ${relativePath}`);
|
|
15355
15744
|
}
|
|
@@ -15377,31 +15766,31 @@ async function materializeIssueCheckpoint(config, command, workspace) {
|
|
|
15377
15766
|
}
|
|
15378
15767
|
async function saveIssueCheckpoint(config, command, workspace, candidates) {
|
|
15379
15768
|
const checkpointDir = issueCheckpointDir(workspace);
|
|
15380
|
-
const filesDir =
|
|
15381
|
-
|
|
15382
|
-
|
|
15769
|
+
const filesDir = join13(checkpointDir, "files");
|
|
15770
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
15771
|
+
mkdirSync8(filesDir, { recursive: true });
|
|
15383
15772
|
const files = [];
|
|
15384
15773
|
let totalBytes = 0;
|
|
15385
15774
|
const workspaceRoot = realpathSync5(workspace.cwd);
|
|
15386
15775
|
for (const candidate of candidates.slice(0, 20)) {
|
|
15387
15776
|
const relativePath = safeCheckpointRelativePath(candidate.rawPath);
|
|
15388
15777
|
const source = readString(candidate.filePath);
|
|
15389
|
-
if (!relativePath || !source || !
|
|
15778
|
+
if (!relativePath || !source || !existsSync12(source) || !statSync9(source).isFile()) continue;
|
|
15390
15779
|
const ownedSource = realpathSync5(source);
|
|
15391
15780
|
if (!pathWithin2(ownedSource, workspaceRoot)) {
|
|
15392
15781
|
throw new Error(`issue checkpoint source escapes its execution workspace: ${relativePath}`);
|
|
15393
15782
|
}
|
|
15394
|
-
const byteSize =
|
|
15783
|
+
const byteSize = statSync9(ownedSource).size;
|
|
15395
15784
|
if (byteSize <= 0 || totalBytes + byteSize > MAX_CHECKPOINT_BYTES) continue;
|
|
15396
|
-
const target =
|
|
15785
|
+
const target = resolve10(filesDir, relativePath);
|
|
15397
15786
|
if (!pathWithin2(target, filesDir)) continue;
|
|
15398
|
-
|
|
15787
|
+
mkdirSync8(dirname8(target), { recursive: true });
|
|
15399
15788
|
copyFileSync2(ownedSource, target);
|
|
15400
15789
|
totalBytes += byteSize;
|
|
15401
15790
|
files.push({ path: relativePath, byteSize, sha256: hashFileSha256(ownedSource) });
|
|
15402
15791
|
}
|
|
15403
15792
|
if (files.length === 0) {
|
|
15404
|
-
|
|
15793
|
+
rmSync6(checkpointDir, { recursive: true, force: true });
|
|
15405
15794
|
return null;
|
|
15406
15795
|
}
|
|
15407
15796
|
const manifest = {
|
|
@@ -15413,7 +15802,7 @@ async function saveIssueCheckpoint(config, command, workspace, candidates) {
|
|
|
15413
15802
|
totalBytes,
|
|
15414
15803
|
files
|
|
15415
15804
|
};
|
|
15416
|
-
|
|
15805
|
+
writeFileSync8(join13(checkpointDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
15417
15806
|
`);
|
|
15418
15807
|
await ingestLog(config, command, "system", "warn", `Saved ${files.length} required deliverable(s) for continuation recovery`, manifest);
|
|
15419
15808
|
return manifest;
|
|
@@ -15507,7 +15896,7 @@ async function executeRunCommand(config, command) {
|
|
|
15507
15896
|
});
|
|
15508
15897
|
}
|
|
15509
15898
|
await ingestWorkspaceStatus(config, command, cwd);
|
|
15510
|
-
const sourceAcquisition = sourceAcquisitionRuntimeProfile(config, command);
|
|
15899
|
+
const sourceAcquisition = await sourceAcquisitionRuntimeProfile(config, command);
|
|
15511
15900
|
const promptCompilation = buildCommandPrompt(command, workspace, materializedAttachments, {
|
|
15512
15901
|
runnerKind: config.runnerKind,
|
|
15513
15902
|
executorKind: executor.kind,
|
|
@@ -15584,7 +15973,7 @@ async function executeRunCommand(config, command) {
|
|
|
15584
15973
|
executorCommand: invocation.command,
|
|
15585
15974
|
executorHome: workspace.executorHome,
|
|
15586
15975
|
runDir: workspace.runDir,
|
|
15587
|
-
runtimeCacheRoot:
|
|
15976
|
+
runtimeCacheRoot: join13(dirname8(config.daemonStateFile), "cache"),
|
|
15588
15977
|
cwd,
|
|
15589
15978
|
runtimeAuth: commandRuntimeAuth(command),
|
|
15590
15979
|
nativeSession: asRecord(asRecord(command.payload).nativeSession),
|
|
@@ -15644,7 +16033,7 @@ async function executeRunCommand(config, command) {
|
|
|
15644
16033
|
if (executor.kind === "pi" && piResolvedProviderConfig) {
|
|
15645
16034
|
const sharedPiHome = readString(process.env.PI_CODING_AGENT_DIR) ?? readString(process.env.PI_AGENT_HOME) ?? null;
|
|
15646
16035
|
let agentDir = managedMcpProfile ? readString(managedMcpProfile.env.PI_CODING_AGENT_DIR) ?? readString(managedMcpProfile.env.PI_AGENT_HOME) ?? null : desktopDelegatedRunnerEnabled(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;
|
|
15647
|
-
if (agentDir && sharedPiHome &&
|
|
16036
|
+
if (agentDir && sharedPiHome && resolve10(agentDir) === resolve10(sharedPiHome)) {
|
|
15648
16037
|
agentDir = null;
|
|
15649
16038
|
}
|
|
15650
16039
|
try {
|
|
@@ -15926,7 +16315,7 @@ async function executeRunCommand(config, command) {
|
|
|
15926
16315
|
workspace,
|
|
15927
16316
|
workspaceStatus.artifacts.map((artifact) => ({
|
|
15928
16317
|
rawPath: artifact.relativePath,
|
|
15929
|
-
filePath:
|
|
16318
|
+
filePath: resolve10(cwd, artifact.relativePath)
|
|
15930
16319
|
}))
|
|
15931
16320
|
);
|
|
15932
16321
|
nativeSessionRollout = {
|
|
@@ -16237,6 +16626,7 @@ async function executeRunCommand(config, command) {
|
|
|
16237
16626
|
}
|
|
16238
16627
|
return { resultDelivered: Boolean(completion) };
|
|
16239
16628
|
} finally {
|
|
16629
|
+
sourceAcquisition?.releaseBrowserLease?.();
|
|
16240
16630
|
if (managedMcpProfile && !managedMcpCleanup && !completionOwnsManagedMcpProfile) {
|
|
16241
16631
|
managedMcpCleanup = cleanupManagedMcpProfile(managedMcpProfile, {
|
|
16242
16632
|
commandId: command.commandId,
|
|
@@ -16267,7 +16657,9 @@ async function processCommand(config, command) {
|
|
|
16267
16657
|
}
|
|
16268
16658
|
if (command.commandType === "browser_session") {
|
|
16269
16659
|
await ackCommand(config, command, "spawned");
|
|
16270
|
-
const result3 = await executeBrowserSessionCommand(command, {
|
|
16660
|
+
const result3 = await executeBrowserSessionCommand(command, {
|
|
16661
|
+
broker: browserSessionBrokerFor(config)
|
|
16662
|
+
});
|
|
16271
16663
|
const failed = result3.outcome === "failed";
|
|
16272
16664
|
await completeCommand(
|
|
16273
16665
|
config,
|
|
@@ -16472,7 +16864,7 @@ async function runLoop(config) {
|
|
|
16472
16864
|
${message}
|
|
16473
16865
|
`);
|
|
16474
16866
|
}
|
|
16475
|
-
await new Promise((
|
|
16867
|
+
await new Promise((resolve11) => setTimeout(resolve11, config.pollIntervalSeconds * 1e3));
|
|
16476
16868
|
}
|
|
16477
16869
|
}
|
|
16478
16870
|
function help() {
|
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.69";
|
|
10
10
|
|
|
11
11
|
const CAPABILITIES = [
|
|
12
12
|
"remote_registration",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amaster.ai/employee-runtime-connector",
|
|
3
|
-
"version": "0.1.1-beta.
|
|
3
|
+
"version": "0.1.1-beta.69",
|
|
4
4
|
"description": "MirrorX runtime connector CLI and daemon",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -31,5 +31,7 @@
|
|
|
31
31
|
"esbuild": "^0.27.3",
|
|
32
32
|
"smol-toml": "1.7.0"
|
|
33
33
|
},
|
|
34
|
-
"dependencies": {
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"playwright-core": "^1.58.2"
|
|
36
|
+
}
|
|
35
37
|
}
|