@amaster.ai/employee-runtime-connector 0.1.1-beta.103 → 0.1.1-beta.104

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.
@@ -3490,7 +3490,7 @@ function createManagedPiMcpProfileApi(options = {}) {
3490
3490
  const PI_ATTESTATION_RECENT_LIVE_TTL_MS = Number.isFinite(options.recentLiveTtlMs) && options.recentLiveTtlMs > 0 ? options.recentLiveTtlMs : 30 * 60 * 1e3;
3491
3491
  const recentLivePiVersionProbes = /* @__PURE__ */ new Map();
3492
3492
  const effectiveToolsProbeCircuits = /* @__PURE__ */ new Map();
3493
- function record6(value) {
3493
+ function record7(value) {
3494
3494
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
3495
3495
  }
3496
3496
  function readJsonObjectFile(filePath) {
@@ -3552,7 +3552,7 @@ function createManagedPiMcpProfileApi(options = {}) {
3552
3552
  return matches[0];
3553
3553
  }
3554
3554
  function restoreManagedPiSessionRollout(input, sessionsRoot, runDir, executorHome, authority) {
3555
- const session = record6(input.nativeSession);
3555
+ const session = record7(input.nativeSession);
3556
3556
  if (session.mode !== "governed_action_approval" || session.required !== true) return null;
3557
3557
  const sessionId = nonEmpty2(session.sessionId, "nativeSession.sessionId");
3558
3558
  const sourceRunId = nonEmpty2(session.sourceRunId, "nativeSession.sourceRunId");
@@ -3838,11 +3838,11 @@ function createManagedPiMcpProfileApi(options = {}) {
3838
3838
  return sha2563(stablePiJson(identity2));
3839
3839
  }
3840
3840
  function validateDirectCatalog(gateway, mcpToolMode) {
3841
- const catalog = record6(gateway.toolCatalog);
3841
+ const catalog = record7(gateway.toolCatalog);
3842
3842
  if (catalog.schemaVersion !== DIRECT_CATALOG_SCHEMA_VERSION) {
3843
3843
  throw new Error("pi_managed_mcp_invalid: direct tool catalog schema mismatch");
3844
3844
  }
3845
- const tools = Array.isArray(catalog.tools) ? catalog.tools.map(record6) : [];
3845
+ const tools = Array.isArray(catalog.tools) ? catalog.tools.map(record7) : [];
3846
3846
  const declaredToolNames = new Set(tools.map((tool) => tool.name).filter((name) => typeof name === "string"));
3847
3847
  const covers = (set) => [...set].every((name) => declaredToolNames.has(name));
3848
3848
  const countIn = (set) => tools.filter((tool) => set.has(tool.name)).length;
@@ -3873,7 +3873,7 @@ function createManagedPiMcpProfileApi(options = {}) {
3873
3873
  throw new Error(`pi_managed_mcp_invalid: direct tool exposed name collision for ${exposedName}`);
3874
3874
  }
3875
3875
  exposedNames.add(exposedName);
3876
- const inputSchema = record6(tool.inputSchema);
3876
+ const inputSchema = record7(tool.inputSchema);
3877
3877
  if (inputSchema.type !== "object" || inputSchema.additionalProperties !== false) {
3878
3878
  throw new Error(`pi_managed_mcp_invalid: direct tool schema is not strict for ${name}`);
3879
3879
  }
@@ -3960,8 +3960,8 @@ function createManagedPiMcpProfileApi(options = {}) {
3960
3960
  }
3961
3961
  }
3962
3962
  function validateAuthority2(input) {
3963
- const runtimeAuth = record6(input.runtimeAuth);
3964
- const gateway = record6(runtimeAuth.governedMcp);
3963
+ const runtimeAuth = record7(input.runtimeAuth);
3964
+ const gateway = record7(runtimeAuth.governedMcp);
3965
3965
  const runId = nonEmpty2(input.runId, "runId");
3966
3966
  if (runtimeAuth.runId !== runId) throw new Error("pi_managed_mcp_owner_mismatch: command runId does not match runtime authority");
3967
3967
  if (gateway.schemaVersion !== SUPPORTED_SCHEMA_VERSION2) throw new Error("pi_managed_mcp_invalid: unsupported schema version");
@@ -3977,7 +3977,7 @@ function createManagedPiMcpProfileApi(options = {}) {
3977
3977
  if (!Number.isFinite(expiresAt) || expiresAt <= Date.now() + 3e4) {
3978
3978
  throw new Error("pi_managed_mcp_session_expired: Gateway session must remain valid through spawn preflight");
3979
3979
  }
3980
- const headers = record6(gateway.headers);
3980
+ const headers = record7(gateway.headers);
3981
3981
  for (const name of REQUIRED_AUTHORITY_HEADERS2) nonEmpty2(headers[name], `headers.${name}`);
3982
3982
  const allowedHeaderNames = /* @__PURE__ */ new Set([...REQUIRED_AUTHORITY_HEADERS2, ...runtimeAuth.issueId ? ["x-amaster-issue-id"] : []]);
3983
3983
  if (Object.keys(headers).some((name) => !allowedHeaderNames.has(name)) || Object.keys(headers).length !== allowedHeaderNames.size) {
@@ -4039,7 +4039,7 @@ function createManagedPiMcpProfileApi(options = {}) {
4039
4039
  return env;
4040
4040
  }
4041
4041
  function assertInvocationIsolation2(input) {
4042
- for (const name of Object.keys(record6(input.commandEnv))) {
4042
+ for (const name of Object.keys(record7(input.commandEnv))) {
4043
4043
  if (FORBIDDEN_COMMAND_ENV2.has(name)) throw new Error(`pi_managed_mcp_env_override_blocked: ${name}`);
4044
4044
  if (!ALLOWED_COMMAND_ENV2.has(name)) throw new Error(`pi_managed_mcp_env_injection_blocked: ${name}`);
4045
4045
  }
@@ -4071,7 +4071,7 @@ function createManagedPiMcpProfileApi(options = {}) {
4071
4071
  const value = safeProxyValue2(baseEnv?.[name], name);
4072
4072
  if (value) env[name] = value;
4073
4073
  }
4074
- return { ...env, ...record6(commandEnv) };
4074
+ return { ...env, ...record7(commandEnv) };
4075
4075
  }
4076
4076
  function sourceAcquisitionBrowserEnvironment(sourceAcquisition, baseEnv) {
4077
4077
  const env = {
@@ -4116,8 +4116,8 @@ function createManagedPiMcpProfileApi(options = {}) {
4116
4116
  } catch {
4117
4117
  return true;
4118
4118
  }
4119
- const config = record6(parsed);
4120
- return Object.keys(record6(config.mcpServers)).length > 0 || Object.keys(record6(config.servers)).length > 0 || Array.isArray(config.imports) && config.imports.length > 0;
4119
+ const config = record7(parsed);
4120
+ return Object.keys(record7(config.mcpServers)).length > 0 || Object.keys(record7(config.servers)).length > 0 || Array.isArray(config.imports) && config.imports.length > 0;
4121
4121
  }
4122
4122
  function walkProjectMcpConfigs(cwd, runDir, visit) {
4123
4123
  const start = resolve3(cwd);
@@ -4191,7 +4191,7 @@ function createManagedPiMcpProfileApi(options = {}) {
4191
4191
  let settings = {};
4192
4192
  if (existsSync4(settingsPath)) {
4193
4193
  try {
4194
- settings = record6(JSON.parse(readFileSync4(settingsPath, "utf8")));
4194
+ settings = record7(JSON.parse(readFileSync4(settingsPath, "utf8")));
4195
4195
  } catch {
4196
4196
  throw new Error("pi_managed_mcp_attestation_failed: source Pi settings are invalid");
4197
4197
  }
@@ -4582,7 +4582,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
4582
4582
  workspaceMcpConfigPath
4583
4583
  })}
4584
4584
  `);
4585
- const runtimeAuth = record6(input.runtimeAuth);
4585
+ const runtimeAuth = record7(input.runtimeAuth);
4586
4586
  const authority = Object.freeze({
4587
4587
  companyId: nonEmpty2(runtimeAuth.companyId, "runtimeAuth.companyId"),
4588
4588
  agentId: nonEmpty2(runtimeAuth.agentId, "runtimeAuth.agentId"),
@@ -4924,11 +4924,11 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
4924
4924
  }
4925
4925
  function restoreManagedPiRunExitClosureBaseline2(input, expectedOwner2) {
4926
4926
  if (!input) return { status: "not_required" };
4927
- const baseline = record6(input);
4927
+ const baseline = record7(input);
4928
4928
  if (!["amaster.pi-run-exit-closure-baseline.v1", "amaster.pi-run-exit-closure-baseline.v2"].includes(baseline.schemaVersion)) {
4929
4929
  throw new Error("pi_run_exit_closure_baseline_invalid: unsupported schema version");
4930
4930
  }
4931
- const owner = record6(baseline.owner);
4931
+ const owner = record7(baseline.owner);
4932
4932
  if (owner.commandId !== expectedOwner2?.commandId || owner.runId !== expectedOwner2?.runId) {
4933
4933
  throw new Error("pi_run_exit_closure_baseline_owner_mismatch");
4934
4934
  }
@@ -4957,12 +4957,12 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
4957
4957
  if (sha2563(cacheContents) !== cacheSha256) {
4958
4958
  throw new Error("pi_run_exit_closure_baseline_cache_digest_mismatch");
4959
4959
  }
4960
- const baselineCacheOwnership = record6(baseline.cacheOwnership);
4960
+ const baselineCacheOwnership = record7(baseline.cacheOwnership);
4961
4961
  const cacheOwnership = Number.isSafeInteger(baselineCacheOwnership.uid) && baselineCacheOwnership.uid >= 0 && Number.isSafeInteger(baselineCacheOwnership.gid) && baselineCacheOwnership.gid >= 0 ? { uid: baselineCacheOwnership.uid, gid: baselineCacheOwnership.gid } : existsSync4(cachePath) ? ownershipStatSyncImpl(cachePath) : null;
4962
4962
  if (!cacheOwnership) {
4963
4963
  throw new Error("pi_run_exit_closure_baseline_cache_owner_missing");
4964
4964
  }
4965
- const closureProfile = baseline.schemaVersion === "amaster.pi-run-exit-closure-baseline.v2" ? record6(baseline.closureProfile) : null;
4965
+ const closureProfile = baseline.schemaVersion === "amaster.pi-run-exit-closure-baseline.v2" ? record7(baseline.closureProfile) : null;
4966
4966
  const closureToolAllowlist = closureProfile ? Array.isArray(closureProfile.toolAllowlist) ? closureProfile.toolAllowlist.filter((name) => typeof name === "string") : [] : null;
4967
4967
  if (closureToolAllowlist && (closureToolAllowlist.length !== RUN_EXIT_CLOSURE_DIRECT_TYPED_TOOL_NAMES.size || new Set(closureToolAllowlist).size !== RUN_EXIT_CLOSURE_DIRECT_TYPED_TOOL_NAMES.size || closureToolAllowlist.some((name) => !PROVIDER_SAFE_TOOL_NAME.test(name)))) {
4968
4968
  throw new Error("pi_run_exit_closure_baseline_tool_allowlist_invalid");
@@ -4988,7 +4988,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
4988
4988
  path: configPath,
4989
4989
  bytes: Buffer.from(nonEmpty2(closureProfile.configContentsBase64, "closureProfile.configContentsBase64"), "base64"),
4990
4990
  expectedSha256: nonEmpty2(closureProfile.configSha256, "closureProfile.configSha256"),
4991
- ownership: record6(closureProfile.configOwnership),
4991
+ ownership: record7(closureProfile.configOwnership),
4992
4992
  label: "config"
4993
4993
  },
4994
4994
  {
@@ -5002,7 +5002,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
5002
5002
  path: manifestPath,
5003
5003
  bytes: Buffer.from(nonEmpty2(closureProfile.manifestContentsBase64, "closureProfile.manifestContentsBase64"), "base64"),
5004
5004
  expectedSha256: nonEmpty2(closureProfile.manifestSha256, "closureProfile.manifestSha256"),
5005
- ownership: record6(closureProfile.manifestOwnership),
5005
+ ownership: record7(closureProfile.manifestOwnership),
5006
5006
  label: "manifest"
5007
5007
  }
5008
5008
  ] : [{
@@ -5039,8 +5039,8 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
5039
5039
  }
5040
5040
  function inspectManagedPiRunExitClosureAttestation2(input, expectedOwner2) {
5041
5041
  if (!input) return { status: "not_required" };
5042
- const baseline = record6(input);
5043
- const owner = record6(baseline.owner);
5042
+ const baseline = record7(input);
5043
+ const owner = record7(baseline.owner);
5044
5044
  if (owner.commandId !== expectedOwner2?.commandId || owner.runId !== expectedOwner2?.runId) {
5045
5045
  throw new Error("pi_run_exit_closure_baseline_owner_mismatch");
5046
5046
  }
@@ -5053,7 +5053,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
5053
5053
  throw new Error(`pi_run_exit_closure_baseline_unsafe: ${receiptPath}`);
5054
5054
  }
5055
5055
  try {
5056
- const receipt = record6(JSON.parse(readFileSync4(receiptPath, "utf8")));
5056
+ const receipt = record7(JSON.parse(readFileSync4(receiptPath, "utf8")));
5057
5057
  return {
5058
5058
  status: nonEmpty2(receipt.status, "effectiveToolsReceipt.status"),
5059
5059
  ...typeof receipt.mode === "string" ? { mode: receipt.mode } : {},
@@ -5087,7 +5087,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
5087
5087
  const owner = Object.freeze({ commandId: input.commandId, runId });
5088
5088
  writePrivateFile2(markerPath, `${JSON.stringify({ version: 1, ...owner, profileRoot, piCodingAgentDir })}
5089
5089
  `);
5090
- const runtimeAuth = record6(input.runtimeAuth);
5090
+ const runtimeAuth = record7(input.runtimeAuth);
5091
5091
  const authority = Object.freeze({
5092
5092
  companyId: nonEmpty2(runtimeAuth.companyId, "runtimeAuth.companyId"),
5093
5093
  agentId: nonEmpty2(runtimeAuth.agentId, "runtimeAuth.agentId"),
@@ -5114,11 +5114,11 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
5114
5114
  const config = {
5115
5115
  ...sourceMcp,
5116
5116
  settings: {
5117
- ...record6(sourceMcp.settings),
5117
+ ...record7(sourceMcp.settings),
5118
5118
  ...mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE ? { disableProxyTool: true } : {}
5119
5119
  },
5120
5120
  mcpServers: {
5121
- ...record6(sourceMcp.mcpServers),
5121
+ ...record7(sourceMcp.mcpServers),
5122
5122
  [SUPPORTED_SERVER_NAME2]: serverConfig
5123
5123
  }
5124
5124
  };
@@ -5141,7 +5141,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
5141
5141
  }
5142
5142
  const env = {
5143
5143
  ...input.baseEnv,
5144
- ...record6(input.commandEnv),
5144
+ ...record7(input.commandEnv),
5145
5145
  PI_AGENT_HOME: sourcePiHome,
5146
5146
  PI_CODING_AGENT_DIR: piCodingAgentDir,
5147
5147
  "AMASTER-CLI_CODING_AGENT_DIR": piCodingAgentDir,
@@ -5497,8 +5497,8 @@ function resultOutboxFileName(commandId, now = Date.now()) {
5497
5497
  return `${now}-${safeCommandId}.json`;
5498
5498
  }
5499
5499
  function isValidResultOutboxEntry(entry) {
5500
- const record6 = asRecord(entry);
5501
- return record6.version === 1 && Boolean(readString(record6.path)) && Object.keys(asRecord(record6.payload)).length > 0;
5500
+ const record7 = asRecord(entry);
5501
+ return record7.version === 1 && Boolean(readString(record7.path)) && Object.keys(asRecord(record7.payload)).length > 0;
5502
5502
  }
5503
5503
  function resultOutboxEntryAgeMs(entry, nowMs) {
5504
5504
  const createdAt = Date.parse(readString(entry.createdAt) ?? "");
@@ -5805,6 +5805,60 @@ function retainedSourceExecutorEntry(entry, executorKind) {
5805
5805
  };
5806
5806
  }
5807
5807
 
5808
+ // src/amaster-runtime-daemon/source-acquisition-profile.mjs
5809
+ var HEADLESS_ADAPTER = "pi_browser_use_headless_v1";
5810
+ var DESKTOP_ADAPTER = "browser_skill_desktop_v1";
5811
+ function invalid() {
5812
+ return Object.assign(new Error("source_acquisition_profile_invalid"), {
5813
+ code: "source_acquisition_profile_invalid"
5814
+ });
5815
+ }
5816
+ function exactSourceLocator(value) {
5817
+ if (typeof value !== "string" || value.length === 0) throw invalid();
5818
+ let url;
5819
+ try {
5820
+ url = new URL(value);
5821
+ } catch {
5822
+ throw invalid();
5823
+ }
5824
+ if (!["http:", "https:"].includes(url.protocol) || url.username || url.password) throw invalid();
5825
+ return url;
5826
+ }
5827
+ function exactAuthenticationOrigin(value) {
5828
+ const url = exactSourceLocator(value);
5829
+ if (url.protocol !== "https:" || value !== url.origin) throw invalid();
5830
+ return url.origin;
5831
+ }
5832
+ function exactSourceOrigin(value) {
5833
+ const url = exactSourceLocator(value);
5834
+ if (value !== url.origin) throw invalid();
5835
+ return url.origin;
5836
+ }
5837
+ function inspectSourceAcquisitionProfile(profile, expectedRunId) {
5838
+ const access = profile?.access;
5839
+ const transport = profile?.transport;
5840
+ const tools = profile?.tools;
5841
+ const connectorAdmission = profile?.connectorAdmission;
5842
+ if (!profile || typeof profile !== "object" || profile.retention !== "source_summary_only_v1" || profile.runId !== expectedRunId || !Array.isArray(tools?.exactAllowlist) || tools.exactAllowlist.length === 0 || !["public", "authenticated"].includes(access?.mode) || !["isolated", "existing"].includes(transport?.browserMode) || ![HEADLESS_ADAPTER, DESKTOP_ADAPTER].includes(transport?.adapter) || connectorAdmission?.adapter !== transport?.adapter) throw invalid();
5843
+ if (access.mode === "public" && (transport.browserMode !== "isolated" || transport.adapter !== HEADLESS_ADAPTER) || access.mode === "authenticated" && (transport.browserMode !== "existing" || transport.adapter !== DESKTOP_ADAPTER)) throw invalid();
5844
+ if (profile.purpose === "source_acquisition_v1") {
5845
+ if (connectorAdmission.capability !== "source_acquisition_v1" || connectorAdmission.profileVersion !== "source_acquisition_v1") throw invalid();
5846
+ const locators = [access.exactLocator, ...Array.isArray(access.declaredPageLocators) ? access.declaredPageLocators : []];
5847
+ const sourceOrigins2 = [...new Set(locators.map((locator) => exactSourceLocator(locator).origin))];
5848
+ return { version: profile.purpose, mode: access.mode, sourceOrigins: sourceOrigins2 };
5849
+ }
5850
+ if (profile.purpose !== "source_acquisition_v2" || connectorAdmission.capability !== "source_authentication_origin_discovery_v1" || connectorAdmission.profileVersion !== "source_acquisition_v2" || !Array.isArray(access.exactSourceLocators) || access.exactSourceLocators.length === 0 || !Array.isArray(access.sourceOrigins) || access.sourceOrigins.length === 0 || !Array.isArray(access.authorizedAuthenticationOrigins) || access.authenticationOriginDiscovery?.enabled !== true) throw invalid();
5851
+ const derivedSourceOrigins = [...new Set(
5852
+ access.exactSourceLocators.map((locator) => exactSourceLocator(locator).origin)
5853
+ )];
5854
+ const sourceOrigins = access.sourceOrigins.map(exactSourceOrigin);
5855
+ const sourceOriginSet = new Set(sourceOrigins);
5856
+ if (sourceOriginSet.size !== sourceOrigins.length || derivedSourceOrigins.length !== sourceOrigins.length || derivedSourceOrigins.some((origin) => !sourceOriginSet.has(origin))) throw invalid();
5857
+ const authenticationOrigins = access.authorizedAuthenticationOrigins.map(exactAuthenticationOrigin);
5858
+ if (authenticationOrigins.some((origin) => sourceOriginSet.has(origin))) throw invalid();
5859
+ return { version: profile.purpose, mode: access.mode, sourceOrigins };
5860
+ }
5861
+
5808
5862
  // src/amaster-runtime-daemon/prompt-compiler.mjs
5809
5863
  import { createHash as createHash6 } from "node:crypto";
5810
5864
 
@@ -6046,7 +6100,18 @@ function sourceAcquisitionPiInvocationArgs(profile) {
6046
6100
  }
6047
6101
  function serializeSourceAcquisitionProfile(profile) {
6048
6102
  if (!profile || typeof profile !== "object" || Array.isArray(profile)) return null;
6049
- const input = Buffer.from(JSON.stringify(profile), "utf8");
6103
+ const canonicalize = (value) => {
6104
+ if (value === null || typeof value === "boolean" || typeof value === "string") {
6105
+ return JSON.stringify(value);
6106
+ }
6107
+ if (typeof value === "number" && Number.isFinite(value)) return JSON.stringify(value);
6108
+ if (Array.isArray(value)) return `[${value.map(canonicalize).join(",")}]`;
6109
+ if (value && typeof value === "object") {
6110
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalize(value[key])}`).join(",")}}`;
6111
+ }
6112
+ throw new Error("source_acquisition_profile_canonicalization_failed");
6113
+ };
6114
+ const input = Buffer.from(canonicalize(profile), "utf8");
6050
6115
  return {
6051
6116
  input,
6052
6117
  sha256: createHash5("sha256").update(input).digest("hex")
@@ -6137,19 +6202,19 @@ function promptContextMode(input) {
6137
6202
  }
6138
6203
  function filterDuplicatedTaskComments(context, mode) {
6139
6204
  if (mode !== "cold") return context;
6140
- const record6 = asRecord(context);
6205
+ const record7 = asRecord(context);
6141
6206
  const included = new Set(
6142
- (Array.isArray(record6.paperclipTaskMarkdownCommentIds) ? record6.paperclipTaskMarkdownCommentIds : []).map((entry) => readString(entry)).filter(Boolean)
6207
+ (Array.isArray(record7.paperclipTaskMarkdownCommentIds) ? record7.paperclipTaskMarkdownCommentIds : []).map((entry) => readString(entry)).filter(Boolean)
6143
6208
  );
6144
6209
  if (included.size === 0) return context;
6145
- const wake = asRecord(record6.paperclipWake);
6210
+ const wake = asRecord(record7.paperclipWake);
6146
6211
  const comments = Array.isArray(wake.comments) ? wake.comments : [];
6147
6212
  const kept = comments.filter((entry) => {
6148
6213
  const id = readString(asRecord(entry).id);
6149
6214
  return !id || !included.has(id);
6150
6215
  });
6151
6216
  if (kept.length === comments.length) return context;
6152
- return { ...record6, paperclipWake: { ...wake, comments: kept } };
6217
+ return { ...record7, paperclipWake: { ...wake, comments: kept } };
6153
6218
  }
6154
6219
  function commentRefs(context) {
6155
6220
  const comments = Array.isArray(asRecord(context.paperclipWake).comments) ? asRecord(context.paperclipWake).comments : [];
@@ -6283,8 +6348,8 @@ function governedReadSection(context) {
6283
6348
  const reads = Array.isArray(context.governedReadResults) ? context.governedReadResults : [];
6284
6349
  if (reads.length === 0) return { content: "", provenance: [] };
6285
6350
  const normalized = reads.map((entry, index) => {
6286
- const record6 = asRecord(entry);
6287
- const receipt = asRecord(record6.receipt);
6351
+ const record7 = asRecord(entry);
6352
+ const receipt = asRecord(record7.receipt);
6288
6353
  const provider = readString(receipt.provider) ?? readString(receipt.transport);
6289
6354
  const operation = readString(receipt.operation);
6290
6355
  const observedAt = readString(receipt.retrievedAt) ?? readString(receipt.observedAt);
@@ -6294,7 +6359,7 @@ function governedReadSection(context) {
6294
6359
  throw new Error(`governed_read_context_provenance_invalid: entry ${index} requires provider, operation, observedAt, and source`);
6295
6360
  }
6296
6361
  return {
6297
- content: record6.content,
6362
+ content: record7.content,
6298
6363
  receipt: {
6299
6364
  provider,
6300
6365
  operation,
@@ -6340,11 +6405,11 @@ function governedBusinessDetailRead(input, issueId) {
6340
6405
  return { mode: "canonical", tool: canonicalTool, arguments: argumentsValue };
6341
6406
  }
6342
6407
  function governedBusinessDecisionProjection(state, detailRead) {
6343
- const record6 = asRecord(state);
6344
- const snapshot = asRecord(record6.governed_state_snapshot);
6345
- const authoritativeObjectRefs = Array.isArray(record6.authoritative_object_refs) ? record6.authoritative_object_refs : [];
6346
- const capabilities = Array.isArray(record6.capabilities) ? record6.capabilities : [];
6347
- const availability = asRecord(record6.availability);
6408
+ const record7 = asRecord(state);
6409
+ const snapshot = asRecord(record7.governed_state_snapshot);
6410
+ const authoritativeObjectRefs = Array.isArray(record7.authoritative_object_refs) ? record7.authoritative_object_refs : [];
6411
+ const capabilities = Array.isArray(record7.capabilities) ? record7.capabilities : [];
6412
+ const availability = asRecord(record7.availability);
6348
6413
  const projection = {
6349
6414
  status: readString(availability.status) ?? null,
6350
6415
  objects: authoritativeObjectRefs.map((entry) => {
@@ -6359,7 +6424,7 @@ function governedBusinessDecisionProjection(state, detailRead) {
6359
6424
  }
6360
6425
  return compact;
6361
6426
  }),
6362
- missing: (Array.isArray(record6.missing_objects) ? record6.missing_objects : []).map((entry) => {
6427
+ missing: (Array.isArray(record7.missing_objects) ? record7.missing_objects : []).map((entry) => {
6363
6428
  const missing = asRecord(entry);
6364
6429
  return {
6365
6430
  kind: readString(missing.object_kind) ?? null,
@@ -6379,22 +6444,22 @@ function governedBusinessDecisionProjection(state, detailRead) {
6379
6444
  if (unavailableReads.length > 0) {
6380
6445
  projection.unavailable_reads = unavailableReads;
6381
6446
  }
6382
- const continuationId = readString(record6.continuation_id);
6447
+ const continuationId = readString(record7.continuation_id);
6383
6448
  if (continuationId) projection.continuation_id = continuationId;
6384
- if (Number.isInteger(record6.outcome_revision)) projection.outcome_revision = record6.outcome_revision;
6385
- const freeTextReason = readString(record6.free_text_reason);
6449
+ if (Number.isInteger(record7.outcome_revision)) projection.outcome_revision = record7.outcome_revision;
6450
+ const freeTextReason = readString(record7.free_text_reason);
6386
6451
  if (freeTextReason) projection.free_text_reason = freeTextReason;
6387
6452
  return projection;
6388
6453
  }
6389
6454
  function governedBusinessModelView(state, input) {
6390
- const record6 = asRecord(state);
6391
- const snapshot = asRecord(record6.governed_state_snapshot);
6455
+ const record7 = asRecord(state);
6456
+ const snapshot = asRecord(record7.governed_state_snapshot);
6392
6457
  const detailRead = governedBusinessDetailRead(
6393
6458
  input,
6394
6459
  readString(snapshot.issue_id) ?? readString(input.issueId)
6395
6460
  );
6396
6461
  if (detailRead.mode === "unavailable") {
6397
- const { task_acceptance_contract: _TaskAcceptanceContract, ...stateWithoutAcceptanceContract } = record6;
6462
+ const { task_acceptance_contract: _TaskAcceptanceContract, ...stateWithoutAcceptanceContract } = record7;
6398
6463
  return {
6399
6464
  mode: "full_snapshot",
6400
6465
  content: stateWithoutAcceptanceContract,
@@ -6403,7 +6468,7 @@ function governedBusinessModelView(state, input) {
6403
6468
  }
6404
6469
  return {
6405
6470
  mode: "decision_projection",
6406
- content: governedBusinessDecisionProjection(record6, detailRead),
6471
+ content: governedBusinessDecisionProjection(record7, detailRead),
6407
6472
  unavailableReason: null
6408
6473
  };
6409
6474
  }
@@ -6469,10 +6534,10 @@ ${bodies}`,
6469
6534
  }
6470
6535
  function canonicalJsonValue(value) {
6471
6536
  if (Array.isArray(value)) return value.map(canonicalJsonValue);
6472
- const record6 = asRecord(value);
6473
- if (Object.keys(record6).length === 0) return value;
6537
+ const record7 = asRecord(value);
6538
+ if (Object.keys(record7).length === 0) return value;
6474
6539
  return Object.fromEntries(
6475
- Object.keys(record6).sort().map((key) => [key, canonicalJsonValue(record6[key])])
6540
+ Object.keys(record7).sort().map((key) => [key, canonicalJsonValue(record7[key])])
6476
6541
  );
6477
6542
  }
6478
6543
  function resolvedDependencySections(context, input, contextScope, snapshotFreshness) {
@@ -8543,10 +8608,10 @@ function compactExecutorJsonlForTranscript(event) {
8543
8608
  const text = JSON.stringify(compactExecutorJsonValue(event, stringMaxChars));
8544
8609
  if (text.length <= 15e3) return text;
8545
8610
  }
8546
- const record6 = tcAsRecord(event);
8547
- const item = tcAsRecord(record6.item);
8611
+ const record7 = tcAsRecord(event);
8612
+ const item = tcAsRecord(record7.item);
8548
8613
  return JSON.stringify({
8549
- type: tcReadString(record6.type) ?? "executor.event",
8614
+ type: tcReadString(record7.type) ?? "executor.event",
8550
8615
  item: item.type ? {
8551
8616
  id: tcReadString(item.id),
8552
8617
  type: tcReadString(item.type),
@@ -8559,10 +8624,10 @@ function compactExecutorJsonlForTranscript(event) {
8559
8624
  });
8560
8625
  }
8561
8626
  function summarizeTokenUsage(usage) {
8562
- const record6 = tcAsRecord(usage);
8563
- const inputTokens = tcReadNumber(record6.input_tokens ?? record6.inputTokens, 0);
8564
- const cachedInputTokens = tcReadNumber(record6.cached_input_tokens ?? record6.cachedInputTokens, 0);
8565
- const outputTokens = tcReadNumber(record6.output_tokens ?? record6.outputTokens, 0);
8627
+ const record7 = tcAsRecord(usage);
8628
+ const inputTokens = tcReadNumber(record7.input_tokens ?? record7.inputTokens, 0);
8629
+ const cachedInputTokens = tcReadNumber(record7.cached_input_tokens ?? record7.cachedInputTokens, 0);
8630
+ const outputTokens = tcReadNumber(record7.output_tokens ?? record7.outputTokens, 0);
8566
8631
  const parts = [];
8567
8632
  if (inputTokens > 0) parts.push(`\u8F93\u5165 ${inputTokens}`);
8568
8633
  if (cachedInputTokens > 0) parts.push(`\u7F13\u5B58 ${cachedInputTokens}`);
@@ -8817,8 +8882,8 @@ function summarizeClaudeEvent(event) {
8817
8882
  return null;
8818
8883
  }
8819
8884
  function tcPiMessageText(message) {
8820
- const record6 = tcAsRecord(message);
8821
- const content = record6.content;
8885
+ const record7 = tcAsRecord(message);
8886
+ const content = record7.content;
8822
8887
  if (typeof content === "string" && content.trim().length > 0) return content.trim();
8823
8888
  if (!Array.isArray(content)) return "";
8824
8889
  return content.map((entry) => {
@@ -8832,14 +8897,14 @@ function tcPiAssistantMessageEventText(assistantMessageEvent) {
8832
8897
  return tcReadString(event.content) ?? "";
8833
8898
  }
8834
8899
  function tcPiMessageStopReason(message) {
8835
- const record6 = tcAsRecord(message);
8836
- return tcReadString(record6.stopReason ?? record6.stop_reason);
8900
+ const record7 = tcAsRecord(message);
8901
+ return tcReadString(record7.stopReason ?? record7.stop_reason);
8837
8902
  }
8838
8903
  function tcPiMessageErrorText(message) {
8839
- const record6 = tcAsRecord(message);
8840
- const explicitError = tcReadString(record6.errorMessage ?? record6.error_message)?.trim();
8904
+ const record7 = tcAsRecord(message);
8905
+ const explicitError = tcReadString(record7.errorMessage ?? record7.error_message)?.trim();
8841
8906
  if (explicitError) return explicitError;
8842
- const stopReason = tcPiMessageStopReason(record6);
8907
+ const stopReason = tcPiMessageStopReason(record7);
8843
8908
  if (stopReason === "error" || stopReason === "failed" || stopReason === "exception") {
8844
8909
  return `Pi Agent message ended with stopReason=${stopReason}`;
8845
8910
  }
@@ -9494,13 +9559,13 @@ function parseClaudeStreamJson(stdout) {
9494
9559
  }
9495
9560
  function openCodeErrorText(value) {
9496
9561
  if (typeof value === "string") return value;
9497
- const record6 = asRecord(value);
9498
- const message = readString(record6.message);
9562
+ const record7 = asRecord(value);
9563
+ const message = readString(record7.message);
9499
9564
  if (message) return message;
9500
- const data = asRecord(record6.data);
9565
+ const data = asRecord(record7.data);
9501
9566
  const nestedMessage = readString(data.message);
9502
9567
  if (nestedMessage) return nestedMessage;
9503
- return readString(record6.name) ?? readString(record6.code) ?? "";
9568
+ return readString(record7.name) ?? readString(record7.code) ?? "";
9504
9569
  }
9505
9570
  function parseOpenCodeJsonl(stdout) {
9506
9571
  let sessionId = null;
@@ -9538,8 +9603,8 @@ function parseOpenCodeJsonl(stdout) {
9538
9603
  return { sessionId, summary, usage, errorMessage };
9539
9604
  }
9540
9605
  function piMessageText(message) {
9541
- const record6 = asRecord(message);
9542
- const content = record6.content;
9606
+ const record7 = asRecord(message);
9607
+ const content = record7.content;
9543
9608
  if (typeof content === "string") return content.trim();
9544
9609
  if (!Array.isArray(content)) return "";
9545
9610
  return content.map((entry) => {
@@ -9548,10 +9613,10 @@ function piMessageText(message) {
9548
9613
  }).filter(Boolean).join("\n").trim();
9549
9614
  }
9550
9615
  function piAgentEndHasFinalAssistantText(event) {
9551
- const record6 = asRecord(event);
9552
- if (record6.type !== "agent_end") return false;
9553
- const messages = Array.isArray(record6.messages) ? [...record6.messages] : [];
9554
- if (Object.keys(asRecord(record6.message)).length > 0) messages.push(record6.message);
9616
+ const record7 = asRecord(event);
9617
+ if (record7.type !== "agent_end") return false;
9618
+ const messages = Array.isArray(record7.messages) ? [...record7.messages] : [];
9619
+ if (Object.keys(asRecord(record7.message)).length > 0) messages.push(record7.message);
9555
9620
  for (let index = messages.length - 1; index >= 0; index -= 1) {
9556
9621
  const message = asRecord(messages[index]);
9557
9622
  if (message.role !== "assistant") continue;
@@ -9584,10 +9649,10 @@ function piTextValue(value) {
9584
9649
  return typeof value === "string" && value.length > 0 ? value : "";
9585
9650
  }
9586
9651
  function piAssistantEventText(assistantEvent) {
9587
- const record6 = asRecord(assistantEvent);
9588
- const type = readString(record6.type);
9589
- if (type === "text_delta") return piTextValue(record6.delta);
9590
- if (type === "text_end") return piTextValue(record6.content);
9652
+ const record7 = asRecord(assistantEvent);
9653
+ const type = readString(record7.type);
9654
+ if (type === "text_delta") return piTextValue(record7.delta);
9655
+ if (type === "text_end") return piTextValue(record7.content);
9591
9656
  return "";
9592
9657
  }
9593
9658
  function piMessageUsage(message) {
@@ -9608,14 +9673,14 @@ function assignPiUsage(target, source) {
9608
9673
  if (source.costUsd > 0) target.costUsd = source.costUsd;
9609
9674
  }
9610
9675
  function piMessageStopReason(message) {
9611
- const record6 = asRecord(message);
9612
- return readString(record6.stopReason ?? record6.stop_reason);
9676
+ const record7 = asRecord(message);
9677
+ return readString(record7.stopReason ?? record7.stop_reason);
9613
9678
  }
9614
9679
  function piMessageErrorText(message) {
9615
- const record6 = asRecord(message);
9616
- const explicitError = readString(record6.errorMessage ?? record6.error_message)?.trim();
9680
+ const record7 = asRecord(message);
9681
+ const explicitError = readString(record7.errorMessage ?? record7.error_message)?.trim();
9617
9682
  if (explicitError) return explicitError;
9618
- const stopReason = piMessageStopReason(record6);
9683
+ const stopReason = piMessageStopReason(record7);
9619
9684
  if (stopReason === "error" || stopReason === "failed" || stopReason === "exception") {
9620
9685
  return `Pi Agent message ended with stopReason=${stopReason}`;
9621
9686
  }
@@ -9779,6 +9844,79 @@ function piSourceObservationReceipts(event) {
9779
9844
  }
9780
9845
  return receipts;
9781
9846
  }
9847
+ function hasExactKeys(value, expected) {
9848
+ const keys = Object.keys(asRecord(value)).sort();
9849
+ return keys.length === expected.length && expected.slice().sort().every((key, index) => key === keys[index]);
9850
+ }
9851
+ function canonicalOrigin(value, protocol) {
9852
+ const raw = readString(value);
9853
+ if (!raw) return null;
9854
+ try {
9855
+ const url = new URL(raw);
9856
+ if ((protocol ? url.protocol !== protocol : !["http:", "https:"].includes(url.protocol)) || url.username || url.password || url.pathname !== "/" || url.search || url.hash || url.origin !== raw || url.hostname === "localhost" || url.hostname.endsWith(".localhost") || /^\[.*\]$|^\d{1,3}(?:\.\d{1,3}){3}$/.test(url.hostname)) return null;
9857
+ return url.origin;
9858
+ } catch {
9859
+ return null;
9860
+ }
9861
+ }
9862
+ function piSourceAuthenticationOriginDiscoveries(event) {
9863
+ if (readString(event?.type) !== "amaster_source_authentication_discovery" || readString(event?.version) !== "authentication_origin_discovery_v1" || !hasExactKeys(event, ["type", "version", "authenticationOriginDiscovery"])) return [];
9864
+ const discovery = asRecord(event.authenticationOriginDiscovery);
9865
+ const context = asRecord(discovery.context);
9866
+ const receipt = asRecord(discovery.receipt);
9867
+ const uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
9868
+ if (!hasExactKeys(discovery, ["context", "receipt", "receiptDigest"]) || !hasExactKeys(context, [
9869
+ "companyId",
9870
+ "sourceId",
9871
+ "sourceRevisionId",
9872
+ "attemptId",
9873
+ "epoch",
9874
+ "connectorId",
9875
+ "connectionEpoch"
9876
+ ]) || !hasExactKeys(receipt, [
9877
+ "version",
9878
+ "discoveryId",
9879
+ "runId",
9880
+ "sourceOrigin",
9881
+ "targetOrigin",
9882
+ "navigationKind",
9883
+ "redirectStatus",
9884
+ "capturedAt",
9885
+ "profileDigest"
9886
+ ]) || ![
9887
+ context.companyId,
9888
+ context.sourceId,
9889
+ context.sourceRevisionId,
9890
+ context.attemptId,
9891
+ context.connectorId,
9892
+ context.connectionEpoch,
9893
+ receipt.discoveryId,
9894
+ receipt.runId
9895
+ ].every((value) => uuid.test(readString(value) ?? "")) || !Number.isSafeInteger(context.epoch) || context.epoch < 1 || receipt.version !== "authentication_origin_discovery_v1" || !canonicalOrigin(receipt.sourceOrigin) || !canonicalOrigin(receipt.targetOrigin, "https:") || receipt.sourceOrigin === receipt.targetOrigin || !["http_redirect", "top_frame_navigation"].includes(receipt.navigationKind) || (receipt.navigationKind === "http_redirect" ? !Number.isInteger(receipt.redirectStatus) || receipt.redirectStatus < 300 || receipt.redirectStatus > 399 : receipt.redirectStatus !== null) || !Number.isFinite(Date.parse(readString(receipt.capturedAt) ?? "")) || !/^sha256:[a-f0-9]{64}$/.test(readString(receipt.profileDigest) ?? "") || !/^sha256:[a-f0-9]{64}$/.test(readString(discovery.receiptDigest) ?? "")) return [];
9896
+ return [{
9897
+ context: {
9898
+ companyId: context.companyId,
9899
+ sourceId: context.sourceId,
9900
+ sourceRevisionId: context.sourceRevisionId,
9901
+ attemptId: context.attemptId,
9902
+ epoch: context.epoch,
9903
+ connectorId: context.connectorId,
9904
+ connectionEpoch: context.connectionEpoch
9905
+ },
9906
+ receipt: {
9907
+ version: receipt.version,
9908
+ discoveryId: receipt.discoveryId,
9909
+ runId: receipt.runId,
9910
+ sourceOrigin: receipt.sourceOrigin,
9911
+ targetOrigin: receipt.targetOrigin,
9912
+ navigationKind: receipt.navigationKind,
9913
+ redirectStatus: receipt.redirectStatus,
9914
+ capturedAt: receipt.capturedAt,
9915
+ profileDigest: receipt.profileDigest
9916
+ },
9917
+ receiptDigest: discovery.receiptDigest
9918
+ }];
9919
+ }
9782
9920
  function parsePiJsonl(stdout) {
9783
9921
  let sessionId = null;
9784
9922
  let errorMessage = null;
@@ -11581,7 +11719,8 @@ async function executeBrowserSessionCommand(command, dependencies = {}) {
11581
11719
  }
11582
11720
 
11583
11721
  // src/amaster-runtime-daemon/browser-session-broker.mjs
11584
- import { createHash as createHash13 } from "node:crypto";
11722
+ import { createHash as createHash13, randomUUID } from "node:crypto";
11723
+ import { lookup as dnsLookup } from "node:dns/promises";
11585
11724
  import {
11586
11725
  chmodSync as chmodSync6,
11587
11726
  existsSync as existsSync13,
@@ -11592,12 +11731,213 @@ import {
11592
11731
  statSync as statSync8,
11593
11732
  writeFileSync as writeFileSync9
11594
11733
  } from "node:fs";
11734
+ import { createServer as createHttpServer } from "node:http";
11735
+ import { connect as connectTcp, isIP } from "node:net";
11595
11736
  import { dirname as dirname9, join as join14, relative as relative6, resolve as resolve10 } from "node:path";
11596
11737
  var MARKER_NAME = ".amaster-browser-session.json";
11738
+ var HUMAN_LEASE_INACTIVITY_MS = 30 * 60 * 1e3;
11597
11739
  var HUMAN_LEASE_HARD_CAP_MS = 2 * 60 * 60 * 1e3;
11740
+ var TERMINATED_LEASE_HISTORY_LIMIT = 100;
11598
11741
  function brokerError(code) {
11599
11742
  return Object.assign(new Error(code), { code });
11600
11743
  }
11744
+ function parseIpv4(value) {
11745
+ const parts = value.split(".").map(Number);
11746
+ if (parts.length !== 4 || parts.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) {
11747
+ return null;
11748
+ }
11749
+ return parts;
11750
+ }
11751
+ function parseIpv6(value) {
11752
+ const withoutZone = value.split("%")[0].toLowerCase();
11753
+ const halves = withoutZone.split("::");
11754
+ if (halves.length > 2) return null;
11755
+ const parseSide = (side) => {
11756
+ if (!side) return [];
11757
+ const groups2 = [];
11758
+ for (const part of side.split(":")) {
11759
+ if (part.includes(".")) {
11760
+ const ipv4 = parseIpv4(part);
11761
+ if (!ipv4) return null;
11762
+ groups2.push(ipv4[0] << 8 | ipv4[1], ipv4[2] << 8 | ipv4[3]);
11763
+ } else {
11764
+ if (!/^[a-f0-9]{1,4}$/.test(part)) return null;
11765
+ groups2.push(Number.parseInt(part, 16));
11766
+ }
11767
+ }
11768
+ return groups2;
11769
+ };
11770
+ const left = parseSide(halves[0]);
11771
+ const right = parseSide(halves[1] ?? "");
11772
+ if (!left || !right) return null;
11773
+ const missing = 8 - left.length - right.length;
11774
+ if (halves.length === 1 && missing !== 0 || halves.length === 2 && missing < 1) return null;
11775
+ const groups = [...left, ...Array(Math.max(0, missing)).fill(0), ...right];
11776
+ if (groups.length !== 8) return null;
11777
+ return groups.flatMap((group) => [group >> 8, group & 255]);
11778
+ }
11779
+ function prefixMatches(bytes, prefix, bits) {
11780
+ const whole = Math.floor(bits / 8);
11781
+ const rest = bits % 8;
11782
+ for (let index = 0; index < whole; index += 1) {
11783
+ if (bytes[index] !== prefix[index]) return false;
11784
+ }
11785
+ if (!rest) return true;
11786
+ const mask = 255 << 8 - rest;
11787
+ return (bytes[whole] & mask) === (prefix[whole] & mask);
11788
+ }
11789
+ function ipv4IsPublic(address) {
11790
+ const bytes = parseIpv4(address);
11791
+ if (!bytes) return false;
11792
+ const [a, b, c] = bytes;
11793
+ if (a === 0 || a === 10 || a === 127 || a >= 224) return false;
11794
+ if (a === 100 && b >= 64 && b <= 127) return false;
11795
+ if (a === 169 && b === 254) return false;
11796
+ if (a === 172 && b >= 16 && b <= 31) return false;
11797
+ if (a === 192 && (b === 0 || b === 168)) return false;
11798
+ if (a === 192 && b === 88 && c === 99) return false;
11799
+ if (a === 198 && (b === 18 || b === 19 || b === 51 && c === 100)) return false;
11800
+ if (a === 203 && b === 0 && c === 113) return false;
11801
+ return true;
11802
+ }
11803
+ function ipv6IsPublic(address) {
11804
+ const bytes = parseIpv6(address);
11805
+ if (!bytes) return false;
11806
+ const allZero = bytes.every((byte) => byte === 0);
11807
+ if (allZero || bytes.slice(0, 15).every((byte) => byte === 0) && bytes[15] === 1) return false;
11808
+ if ((bytes[0] & 254) === 252 || bytes[0] === 254 && (bytes[1] & 192) === 128 || bytes[0] === 255) {
11809
+ return false;
11810
+ }
11811
+ if (bytes.slice(0, 12).every((byte) => byte === 0)) return false;
11812
+ if (prefixMatches(bytes, [32, 1, 0, 0], 32)) return false;
11813
+ if (prefixMatches(bytes, [32, 1, 0, 2, 0, 0], 48)) return false;
11814
+ if (prefixMatches(bytes, [32, 1, 13, 184], 32)) return false;
11815
+ if (prefixMatches(bytes, [32, 1, 0, 16], 28)) return false;
11816
+ if (prefixMatches(bytes, [0, 100, 255, 155, 0, 1], 48)) return false;
11817
+ if (prefixMatches(bytes, Array(10).fill(0).concat([255, 255]), 96)) {
11818
+ return ipv4IsPublic(bytes.slice(12).join("."));
11819
+ }
11820
+ if (prefixMatches(bytes, [0, 100, 255, 155].concat(Array(8).fill(0)), 96)) {
11821
+ return ipv4IsPublic(bytes.slice(12).join("."));
11822
+ }
11823
+ if (prefixMatches(bytes, [32, 2], 16)) {
11824
+ return ipv4IsPublic(bytes.slice(2, 6).join("."));
11825
+ }
11826
+ return true;
11827
+ }
11828
+ function isPublicNetworkAddress(address) {
11829
+ const family = isIP(address);
11830
+ return family === 4 ? ipv4IsPublic(address) : family === 6 ? ipv6IsPublic(address) : false;
11831
+ }
11832
+ async function defaultResolveAddresses(hostname3) {
11833
+ const family = isIP(hostname3);
11834
+ if (family) return [{ address: hostname3, family }];
11835
+ return dnsLookup(hostname3, { all: true, verbatim: true });
11836
+ }
11837
+ function parseProxyAuthority(authority) {
11838
+ let target;
11839
+ try {
11840
+ target = new URL(`http://${authority}`);
11841
+ } catch {
11842
+ throw brokerError("browser_session_proxy_target_invalid");
11843
+ }
11844
+ const port = Number(target.port || 443);
11845
+ if (!target.hostname || target.username || target.password || !Number.isInteger(port) || port < 1 || port > 65535) {
11846
+ throw brokerError("browser_session_proxy_target_invalid");
11847
+ }
11848
+ return { hostname: target.hostname, port };
11849
+ }
11850
+ async function resolvePublicAddress(hostname3, resolveAddresses) {
11851
+ if (isIP(hostname3) && !isPublicNetworkAddress(hostname3)) {
11852
+ throw brokerError("browser_session_private_network_request_blocked");
11853
+ }
11854
+ let answers;
11855
+ try {
11856
+ answers = await resolveAddresses(hostname3);
11857
+ } catch {
11858
+ throw brokerError("browser_session_dns_failed");
11859
+ }
11860
+ if (!Array.isArray(answers) || answers.length === 0 || answers.some((answer) => !isPublicNetworkAddress(answer?.address))) {
11861
+ throw brokerError("browser_session_private_network_request_blocked");
11862
+ }
11863
+ return answers[0];
11864
+ }
11865
+ async function startPublicNetworkProxy(resolveAddresses) {
11866
+ const sockets = /* @__PURE__ */ new Set();
11867
+ const trackSocket = (socket) => {
11868
+ sockets.add(socket);
11869
+ socket.once("close", () => sockets.delete(socket));
11870
+ socket.on("error", () => socket.destroy());
11871
+ };
11872
+ const server = createHttpServer((_request, response) => {
11873
+ response.writeHead(403, { "content-type": "text/plain" });
11874
+ response.end("browser_session_non_https_request_blocked");
11875
+ });
11876
+ server.on("connection", trackSocket);
11877
+ server.on("connect", async (request, clientSocket, head) => {
11878
+ try {
11879
+ const target = parseProxyAuthority(request.url ?? "");
11880
+ const resolved = await resolvePublicAddress(target.hostname, resolveAddresses);
11881
+ const upstream = connectTcp({
11882
+ host: resolved.address,
11883
+ family: resolved.family,
11884
+ port: target.port
11885
+ });
11886
+ trackSocket(upstream);
11887
+ upstream.once("connect", () => {
11888
+ clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
11889
+ if (head.length) upstream.write(head);
11890
+ upstream.pipe(clientSocket);
11891
+ clientSocket.pipe(upstream);
11892
+ });
11893
+ upstream.once("error", () => clientSocket.destroy());
11894
+ } catch {
11895
+ clientSocket.end("HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n");
11896
+ }
11897
+ });
11898
+ await new Promise((resolveListen, reject) => {
11899
+ server.once("error", reject);
11900
+ server.listen(0, "127.0.0.1", () => {
11901
+ server.off("error", reject);
11902
+ resolveListen();
11903
+ });
11904
+ });
11905
+ const address = server.address();
11906
+ if (!address || typeof address === "string") {
11907
+ server.close();
11908
+ throw brokerError("browser_session_proxy_start_failed");
11909
+ }
11910
+ return {
11911
+ url: `http://127.0.0.1:${address.port}`,
11912
+ close: () => new Promise((resolveClose) => {
11913
+ for (const socket of sockets) socket.destroy();
11914
+ server.close(() => resolveClose());
11915
+ })
11916
+ };
11917
+ }
11918
+ async function installPublicHttpsPolicy(context, resolveAddresses) {
11919
+ if (typeof context.route !== "function") {
11920
+ throw brokerError("browser_session_public_https_policy_unavailable");
11921
+ }
11922
+ await context.route("**/*", async (route) => {
11923
+ try {
11924
+ const requestUrl = new URL(route.request().url());
11925
+ if (requestUrl.protocol !== "https:" || requestUrl.username || requestUrl.password) {
11926
+ throw brokerError("browser_session_non_https_request_blocked");
11927
+ }
11928
+ if (isIP(requestUrl.hostname) && !isPublicNetworkAddress(requestUrl.hostname)) {
11929
+ throw brokerError("browser_session_private_network_request_blocked");
11930
+ }
11931
+ const addresses = await resolveAddresses(requestUrl.hostname);
11932
+ if (!Array.isArray(addresses) || addresses.length === 0 || addresses.some((answer) => !isPublicNetworkAddress(answer?.address))) {
11933
+ throw brokerError("browser_session_private_network_request_blocked");
11934
+ }
11935
+ await route.continue();
11936
+ } catch {
11937
+ await route.abort("blockedbyclient");
11938
+ }
11939
+ });
11940
+ }
11601
11941
  function pathWithin3(candidate, root) {
11602
11942
  const value = relative6(root, candidate);
11603
11943
  return value === "" || !value.startsWith("..") && !value.startsWith("/");
@@ -11739,10 +12079,57 @@ function createBrowserSessionBroker({
11739
12079
  stateRoot,
11740
12080
  browserExecutable,
11741
12081
  chromium,
12082
+ resolveAddresses = defaultResolveAddresses,
12083
+ startNetworkProxy = () => startPublicNetworkProxy(resolveAddresses),
12084
+ scheduleTimeout = setTimeout,
12085
+ cancelTimeout = clearTimeout,
11742
12086
  now = () => /* @__PURE__ */ new Date()
11743
12087
  }) {
11744
12088
  const active = /* @__PURE__ */ new Map();
11745
12089
  const readers = /* @__PURE__ */ new Map();
12090
+ const terminated = [];
12091
+ function rememberTermination(lease, reason) {
12092
+ terminated.push({
12093
+ companyId: lease.owner.companyId,
12094
+ bindingId: lease.owner.bindingId,
12095
+ leaseId: lease.leaseId,
12096
+ reason,
12097
+ terminatedAt: now().toISOString()
12098
+ });
12099
+ if (terminated.length > TERMINATED_LEASE_HISTORY_LIMIT) terminated.shift();
12100
+ }
12101
+ async function closeHumanLease(localOpaqueRef, lease, reason = null) {
12102
+ if (lease.closePromise) return lease.closePromise;
12103
+ lease.closePromise = (async () => {
12104
+ if (lease.inactivityTimer) cancelTimeout(lease.inactivityTimer);
12105
+ if (lease.hardCapTimer) cancelTimeout(lease.hardCapTimer);
12106
+ if (active.get(localOpaqueRef) === lease) active.delete(localOpaqueRef);
12107
+ if (reason) rememberTermination(lease, reason);
12108
+ await Promise.allSettled([
12109
+ lease.context.close(),
12110
+ lease.networkProxy.close()
12111
+ ]);
12112
+ })();
12113
+ return lease.closePromise;
12114
+ }
12115
+ function scheduleLeaseTimer(localOpaqueRef, lease, kind, delay, reason) {
12116
+ if (lease[kind]) cancelTimeout(lease[kind]);
12117
+ lease[kind] = scheduleTimeout(() => {
12118
+ if (active.get(localOpaqueRef) !== lease) return;
12119
+ void closeHumanLease(localOpaqueRef, lease, reason);
12120
+ }, Math.max(0, delay));
12121
+ lease[kind]?.unref?.();
12122
+ }
12123
+ function scheduleInactivity(localOpaqueRef, lease) {
12124
+ const lastActivityMs = Date.parse(lease.lastActivityAt);
12125
+ scheduleLeaseTimer(
12126
+ localOpaqueRef,
12127
+ lease,
12128
+ "inactivityTimer",
12129
+ lastActivityMs + HUMAN_LEASE_INACTIVITY_MS - now().getTime(),
12130
+ "browser_auth_human_lease_inactive"
12131
+ );
12132
+ }
11746
12133
  async function open(payload, { replace = false } = {}) {
11747
12134
  validateHttpsLocator(payload);
11748
12135
  validateHumanLease(payload, now);
@@ -11762,38 +12149,97 @@ function createBrowserSessionBroker({
11762
12149
  state: "human_ready"
11763
12150
  };
11764
12151
  }
11765
- await existing.context.close();
11766
- active.delete(payload.localOpaqueRef);
12152
+ await closeHumanLease(payload.localOpaqueRef, existing);
11767
12153
  }
11768
12154
  if (!chromium || typeof chromium.launchPersistentContext !== "function") {
11769
12155
  throw brokerError("browser_session_runtime_unavailable");
11770
12156
  }
11771
- const context = await chromium.launchPersistentContext(profilePath, {
11772
- executablePath: browserExecutable,
11773
- headless: false,
11774
- acceptDownloads: false
11775
- });
12157
+ const networkProxy = await startNetworkProxy();
12158
+ let context;
12159
+ try {
12160
+ context = await chromium.launchPersistentContext(profilePath, {
12161
+ executablePath: browserExecutable,
12162
+ headless: false,
12163
+ acceptDownloads: false,
12164
+ proxy: { server: networkProxy.url }
12165
+ });
12166
+ } catch (error) {
12167
+ await networkProxy.close();
12168
+ throw error;
12169
+ }
12170
+ try {
12171
+ await installPublicHttpsPolicy(context, resolveAddresses);
12172
+ } catch (error) {
12173
+ await context.close();
12174
+ await networkProxy.close();
12175
+ throw error;
12176
+ }
11776
12177
  const leaseState = {
11777
12178
  context,
12179
+ networkProxy,
11778
12180
  leaseId: payload.leaseId,
11779
12181
  owner: expectedOwner(payload),
11780
- lastActivityAt: now().toISOString()
12182
+ startedAt: now().toISOString(),
12183
+ lastActivityAt: now().toISOString(),
12184
+ activityToken: randomUUID(),
12185
+ inactivityTimer: null,
12186
+ hardCapTimer: null,
12187
+ closePromise: null
11781
12188
  };
11782
- if (typeof context.exposeBinding === "function" && typeof context.addInitScript === "function") {
11783
- await context.exposeBinding("__mirrorxBrowserAuthActivity", () => {
11784
- leaseState.lastActivityAt = now().toISOString();
11785
- });
11786
- await context.addInitScript(() => {
11787
- const report = () => globalThis.__mirrorxBrowserAuthActivity?.().catch?.(() => {
12189
+ try {
12190
+ if (typeof context.exposeBinding === "function" && typeof context.addInitScript === "function") {
12191
+ await context.exposeBinding("__mirrorxBrowserAuthActivity", (_source, activityToken) => {
12192
+ if (activityToken !== leaseState.activityToken) return;
12193
+ leaseState.lastActivityAt = now().toISOString();
12194
+ scheduleInactivity(payload.localOpaqueRef, leaseState);
11788
12195
  });
11789
- globalThis.addEventListener("pointerdown", report, { capture: true, passive: true });
11790
- globalThis.addEventListener("keydown", report, { capture: true, passive: true });
11791
- globalThis.addEventListener("touchstart", report, { capture: true, passive: true });
12196
+ await context.addInitScript(({ activityToken }) => {
12197
+ const reportActivity = globalThis.__mirrorxBrowserAuthActivity;
12198
+ try {
12199
+ delete globalThis.__mirrorxBrowserAuthActivity;
12200
+ } catch {
12201
+ }
12202
+ const report = (event) => {
12203
+ if (event.isTrusted !== true) return;
12204
+ reportActivity?.(activityToken).catch?.(() => {
12205
+ });
12206
+ };
12207
+ globalThis.addEventListener("pointerdown", report, { capture: true, passive: true });
12208
+ globalThis.addEventListener("keydown", report, { capture: true, passive: true });
12209
+ globalThis.addEventListener("touchstart", report, { capture: true, passive: true });
12210
+ }, { activityToken: leaseState.activityToken });
12211
+ }
12212
+ const page = context.pages()[0] ?? await context.newPage();
12213
+ if (typeof context.on !== "function" || typeof page.on !== "function") {
12214
+ throw brokerError("browser_session_lifecycle_monitor_unavailable");
12215
+ }
12216
+ const terminateFromBrowser = (reason) => {
12217
+ if (active.get(payload.localOpaqueRef) !== leaseState) return;
12218
+ void closeHumanLease(payload.localOpaqueRef, leaseState, reason);
12219
+ };
12220
+ context.on("close", () => terminateFromBrowser("browser_auth_human_session_closed"));
12221
+ context.on("page", (openedPage) => {
12222
+ if (openedPage !== page) void openedPage.close();
11792
12223
  });
12224
+ page.on("close", () => terminateFromBrowser("browser_auth_human_session_closed"));
12225
+ page.on("crash", () => terminateFromBrowser("browser_auth_human_session_crashed"));
12226
+ page.on("download", (download) => {
12227
+ void download.cancel();
12228
+ });
12229
+ active.set(payload.localOpaqueRef, leaseState);
12230
+ await page.goto(payload.locator);
12231
+ } catch (error) {
12232
+ await closeHumanLease(payload.localOpaqueRef, leaseState);
12233
+ throw error;
11793
12234
  }
11794
- const page = context.pages()[0] ?? await context.newPage();
11795
- await page.goto(payload.locator);
11796
- active.set(payload.localOpaqueRef, leaseState);
12235
+ scheduleInactivity(payload.localOpaqueRef, leaseState);
12236
+ scheduleLeaseTimer(
12237
+ payload.localOpaqueRef,
12238
+ leaseState,
12239
+ "hardCapTimer",
12240
+ Date.parse(leaseState.startedAt) + HUMAN_LEASE_HARD_CAP_MS - now().getTime(),
12241
+ "browser_auth_human_lease_hard_expired"
12242
+ );
11797
12243
  return {
11798
12244
  bindingId: payload.bindingId,
11799
12245
  localOpaqueRef: payload.localOpaqueRef,
@@ -11809,8 +12255,7 @@ function createBrowserSessionBroker({
11809
12255
  }
11810
12256
  const profilePath = exactProfile(stateRoot, payload);
11811
12257
  if (existing) {
11812
- await existing.context.close();
11813
- active.delete(payload.localOpaqueRef);
12258
+ await closeHumanLease(payload.localOpaqueRef, existing);
11814
12259
  }
11815
12260
  rmSync7(profilePath, { recursive: true, force: false });
11816
12261
  return {
@@ -11854,8 +12299,7 @@ function createBrowserSessionBroker({
11854
12299
  if (human.owner.companyId !== payload.companyId || human.owner.bindingId !== payload.bindingId) {
11855
12300
  throw brokerError("browser_session_profile_owner_mismatch");
11856
12301
  }
11857
- await human.context.close();
11858
- active.delete(payload.localOpaqueRef);
12302
+ await closeHumanLease(payload.localOpaqueRef, human);
11859
12303
  }
11860
12304
  readers.set(payload.localOpaqueRef, payload.leaseId);
11861
12305
  return () => {
@@ -11870,15 +12314,154 @@ function createBrowserSessionBroker({
11870
12314
  bindingId: entry.owner.bindingId,
11871
12315
  leaseId: entry.leaseId,
11872
12316
  lastActivityAt: entry.lastActivityAt
11873
- }))
12317
+ })),
12318
+ terminatedHumanLeases: terminated.map((entry) => ({ ...entry }))
11874
12319
  })
11875
12320
  };
11876
12321
  }
11877
12322
 
12323
+ // src/amaster-runtime-daemon/source-authentication-origin-discovery-ingest.mjs
12324
+ function asRecord2(value) {
12325
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
12326
+ }
12327
+ function readString2(value) {
12328
+ return typeof value === "string" && value.length > 0 ? value : null;
12329
+ }
12330
+ async function submitSourceAuthenticationOriginDiscovery({
12331
+ config,
12332
+ command,
12333
+ connectorId,
12334
+ profile,
12335
+ discoveries,
12336
+ postJsonWithRetry: postJsonWithRetry2,
12337
+ ingestLog: ingestLog2
12338
+ }) {
12339
+ if (profile.purpose !== "source_acquisition_v2" || discoveries.length !== 1) {
12340
+ throw new Error("source_authentication_origin_discovery_profile_inactive");
12341
+ }
12342
+ const discovery = asRecord2(discoveries[0]);
12343
+ const context = asRecord2(discovery.context);
12344
+ const receipt = asRecord2(discovery.receipt);
12345
+ if (context.companyId !== profile.companyId || context.sourceId !== profile.sourceId || context.sourceRevisionId !== profile.sourceRevisionId || context.attemptId !== profile.attemptId || context.epoch !== profile.epoch || context.connectorId !== connectorId || context.connectionEpoch !== profile.connectorAdmission.connectionEpoch || receipt.runId !== profile.runId) {
12346
+ throw new Error("source_authentication_origin_discovery_authority_invalid");
12347
+ }
12348
+ const accepted = asRecord2(await postJsonWithRetry2(
12349
+ config,
12350
+ `/api/amaster/runtime-connectors/${connectorId}/commands/${command.commandId}/source-acquisition/authentication-origin-discoveries`,
12351
+ {
12352
+ profileVersion: profile.purpose,
12353
+ attemptId: profile.attemptId,
12354
+ epoch: profile.epoch,
12355
+ receipt,
12356
+ receiptDigest: discovery.receiptDigest
12357
+ },
12358
+ { maxAttempts: 3, timeoutMs: 5e3, delayMs: 100 }
12359
+ ));
12360
+ if (accepted.status !== "auth_required" || accepted.attemptId !== profile.attemptId || !readString2(accepted.interactionId)) {
12361
+ throw new Error("source_authentication_origin_discovery_ingest_rejected");
12362
+ }
12363
+ await ingestLog2(
12364
+ config,
12365
+ command,
12366
+ "system",
12367
+ "info",
12368
+ "Source Authentication origin discovery recorded",
12369
+ {
12370
+ presentationKind: "source_authentication_origin_discovery",
12371
+ attemptId: profile.attemptId,
12372
+ interactionId: accepted.interactionId,
12373
+ discoveryId: receipt.discoveryId,
12374
+ sourceOrigin: receipt.sourceOrigin,
12375
+ targetOrigin: receipt.targetOrigin,
12376
+ replayed: accepted.replayed === true
12377
+ }
12378
+ );
12379
+ }
12380
+
12381
+ // src/amaster-runtime-daemon/source-completion-policy.mjs
12382
+ var SOURCE_COMPLETION_REPAIR_HARD_CAP_MS = 12e4;
12383
+ function record6(value) {
12384
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
12385
+ }
12386
+ function sourceCompletionActionAccepted(results) {
12387
+ return (Array.isArray(results) ? results : []).some((value) => {
12388
+ const result3 = record6(value);
12389
+ const runtimeAction = record6(result3.runtimeAction);
12390
+ return result3.status === "succeeded" && result3.providerStatus === "accepted" && runtimeAction.toolName === "runtime_action.submit" && typeof runtimeAction.callId === "string" && runtimeAction.callId.length > 0 && runtimeAction.resultStatus === "succeeded";
12391
+ });
12392
+ }
12393
+ function sourceCompletionTerminalFailure(stderr, profile) {
12394
+ if (!profile || profile.purpose !== "source_acquisition_v2") return null;
12395
+ for (const line of String(stderr ?? "").split(/\r?\n/u)) {
12396
+ const trimmed = line.trim();
12397
+ if (!trimmed.startsWith("{")) continue;
12398
+ try {
12399
+ const event = record6(JSON.parse(trimmed));
12400
+ if (event.type === "amaster_source_acquisition_terminal" && event.code === "source_acquisition_terminal_action_missing" && event.companyId === profile.companyId && event.sourceId === profile.sourceId && event.sourceRevisionId === profile.sourceRevisionId && event.attemptId === profile.attemptId && event.epoch === profile.epoch && event.runId === profile.runId) {
12401
+ return "source_acquisition_terminal_action_missing";
12402
+ }
12403
+ } catch {
12404
+ }
12405
+ }
12406
+ return null;
12407
+ }
12408
+ function createSourceCompletionStopPolicy({
12409
+ enabled,
12410
+ onStop,
12411
+ scheduleTimeout = setTimeout,
12412
+ cancelTimeout = clearTimeout,
12413
+ hardCapMs = SOURCE_COMPLETION_REPAIR_HARD_CAP_MS
12414
+ }) {
12415
+ let timer = null;
12416
+ let hardCapExceeded = false;
12417
+ let settled = false;
12418
+ function clear() {
12419
+ if (timer) cancelTimeout(timer);
12420
+ timer = null;
12421
+ }
12422
+ return {
12423
+ observe(eventType) {
12424
+ if (!enabled || settled) return { handled: false };
12425
+ if (eventType === "agent_end") {
12426
+ if (!timer) {
12427
+ timer = scheduleTimeout(() => {
12428
+ if (settled) return;
12429
+ hardCapExceeded = true;
12430
+ onStop("source_completion_hard_cap");
12431
+ }, hardCapMs);
12432
+ timer?.unref?.();
12433
+ }
12434
+ return { handled: true, completionOutputType: null };
12435
+ }
12436
+ if (eventType === "agent_settled") {
12437
+ settled = true;
12438
+ clear();
12439
+ onStop("completion_output");
12440
+ return { handled: true, completionOutputType: "agent_settled" };
12441
+ }
12442
+ return { handled: false };
12443
+ },
12444
+ close: clear,
12445
+ get hardCapExceeded() {
12446
+ return hardCapExceeded;
12447
+ }
12448
+ };
12449
+ }
12450
+
11878
12451
  // ../shared/src/source-acquisition-compatibility.json
11879
12452
  var source_acquisition_compatibility_default = {
11880
12453
  schemaVersion: "mirrorx.source-acquisition-compatibility.v1",
11881
12454
  profileVersion: "source_acquisition_v1",
12455
+ supportedProfileVersions: [
12456
+ "source_acquisition_v1",
12457
+ "source_acquisition_v2"
12458
+ ],
12459
+ v2Activation: {
12460
+ profileVersion: "source_acquisition_v2",
12461
+ capability: "source_authentication_origin_discovery_v1",
12462
+ piCodingAgentVersion: "0.80.10",
12463
+ completionGuard: "source_completion_same_session_v1"
12464
+ },
11882
12465
  retentionVersion: "source_summary_only_v1",
11883
12466
  actionVersion: "complete_source_acquisition_v1",
11884
12467
  policyVersion: "browser_read_policy_v1",
@@ -11891,7 +12474,7 @@ var source_acquisition_compatibility_default = {
11891
12474
  };
11892
12475
 
11893
12476
  // src/amaster-runtime-daemon.mjs
11894
- var CONNECTOR_VERSION = "0.1.1-beta.103";
12477
+ var CONNECTOR_VERSION = "0.1.1-beta.104";
11895
12478
  var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
11896
12479
  var SOURCE_ACQUISITION_CAPABILITY = source_acquisition_compatibility_default.profileVersion;
11897
12480
  var daemonRequire = createRequire(import.meta.url);
@@ -11901,6 +12484,10 @@ var SOURCE_ACQUISITION_ACTION_VERSION = source_acquisition_compatibility_default
11901
12484
  var SOURCE_ACQUISITION_BROWSER_POLICY_VERSION = source_acquisition_compatibility_default.policyVersion;
11902
12485
  var SOURCE_ACQUISITION_HEADLESS_ADAPTER = source_acquisition_compatibility_default.adapters[0];
11903
12486
  var SOURCE_ACQUISITION_DESKTOP_ADAPTER = "browser_skill_desktop_v1";
12487
+ var SOURCE_ACQUISITION_PROFILE_VERSION_V2 = source_acquisition_compatibility_default.v2Activation.profileVersion;
12488
+ var SOURCE_AUTHENTICATION_ORIGIN_DISCOVERY_CAPABILITY = source_acquisition_compatibility_default.v2Activation.capability;
12489
+ var SOURCE_ACQUISITION_V2_PI_VERSION = source_acquisition_compatibility_default.v2Activation.piCodingAgentVersion;
12490
+ var SOURCE_ACQUISITION_V2_COMPLETION_GUARD = source_acquisition_compatibility_default.v2Activation.completionGuard;
11904
12491
  var SOURCE_ACQUISITION_PACKAGE_VERSIONS = Object.freeze(
11905
12492
  source_acquisition_compatibility_default.requiredPackages
11906
12493
  );
@@ -12370,6 +12957,70 @@ function sourceAcquisitionBrowserExecutableReady() {
12370
12957
  return false;
12371
12958
  }
12372
12959
  }
12960
+ function sourceAcquisitionV2Cohort(extensionDigest) {
12961
+ const names = [
12962
+ "AMASTER_SOURCE_ACQUISITION_SUPPORTED_PROFILE_VERSIONS",
12963
+ "AMASTER_SOURCE_ACQUISITION_AUTHENTICATION_ORIGIN_DISCOVERY_CAPABILITY",
12964
+ "AMASTER_SOURCE_ACQUISITION_COMPLETION_GUARD",
12965
+ "AMASTER_SOURCE_ACQUISITION_CAPABILITY_DIGEST",
12966
+ "AMASTER_SOURCE_ACQUISITION_RUNTIME_BUILD_COMMIT",
12967
+ "AMASTER_SOURCE_ACQUISITION_SOURCE_EXTENSION_DIGEST",
12968
+ "AMASTER_SOURCE_ACQUISITION_PI_CODING_AGENT_VERSION",
12969
+ "AMASTER_SOURCE_ACQUISITION_PI_CODING_AGENT_DIGEST"
12970
+ ];
12971
+ if (names.every((name) => !readString(process.env[name]))) return null;
12972
+ const incompatible = (reason) => ({ state: "incompatible", reason });
12973
+ const piMetadata = sourceAcquisitionPackageMetadata("@earendil-works/pi-coding-agent");
12974
+ const piVersion = readString(process.env.AMASTER_SOURCE_ACQUISITION_PI_CODING_AGENT_VERSION);
12975
+ const piDigest = readString(process.env.AMASTER_SOURCE_ACQUISITION_PI_CODING_AGENT_DIGEST);
12976
+ const sourceExtensionDigest = readString(process.env.AMASTER_SOURCE_ACQUISITION_SOURCE_EXTENSION_DIGEST);
12977
+ const runtimeBuildCommit = readString(process.env.AMASTER_SOURCE_ACQUISITION_RUNTIME_BUILD_COMMIT);
12978
+ const deploymentImageDigest = readString(process.env.AMASTER_DEPLOYMENT_IMAGE_DIGEST);
12979
+ const capabilityDigest = readString(process.env.AMASTER_SOURCE_ACQUISITION_CAPABILITY_DIGEST);
12980
+ if (readString(process.env.AMASTER_SOURCE_ACQUISITION_SUPPORTED_PROFILE_VERSIONS) !== source_acquisition_compatibility_default.supportedProfileVersions.join(",") || readString(process.env.AMASTER_SOURCE_ACQUISITION_AUTHENTICATION_ORIGIN_DISCOVERY_CAPABILITY) !== SOURCE_AUTHENTICATION_ORIGIN_DISCOVERY_CAPABILITY || readString(process.env.AMASTER_SOURCE_ACQUISITION_COMPLETION_GUARD) !== SOURCE_ACQUISITION_V2_COMPLETION_GUARD) return incompatible("source_acquisition_v2_capability_mismatch");
12981
+ if (piVersion !== SOURCE_ACQUISITION_V2_PI_VERSION || readString(piMetadata?.version) !== piVersion) {
12982
+ return incompatible("source_acquisition_v2_pi_version_mismatch");
12983
+ }
12984
+ if (!piDigest || !/^[a-f0-9]{64}$/u.test(piDigest)) {
12985
+ return incompatible("source_acquisition_v2_pi_digest_invalid");
12986
+ }
12987
+ if (sourceExtensionDigest !== `sha256:${extensionDigest}`) {
12988
+ return incompatible("source_acquisition_v2_extension_digest_mismatch");
12989
+ }
12990
+ if (!runtimeBuildCommit || !/^[a-f0-9]{40}$/u.test(runtimeBuildCommit)) {
12991
+ return incompatible("source_acquisition_v2_build_commit_invalid");
12992
+ }
12993
+ if (!deploymentImageDigest || !/^sha256:[a-f0-9]{64}$/u.test(deploymentImageDigest)) {
12994
+ return incompatible("source_acquisition_v2_image_digest_invalid");
12995
+ }
12996
+ const runtimeIdentity = {
12997
+ sourceProfileVersion: SOURCE_ACQUISITION_PROFILE_VERSION_V2,
12998
+ piCodingAgentVersion: SOURCE_ACQUISITION_V2_PI_VERSION,
12999
+ supportsAgentSettled: true,
13000
+ supportsSameSessionFollowUp: true,
13001
+ completionRepairHardCapSeconds: 120,
13002
+ sourceExtensionDigest,
13003
+ runtimeBuildCommit
13004
+ };
13005
+ const expectedCapabilityDigest = `sha256:${serializeSourceAcquisitionProfile(runtimeIdentity).sha256}`;
13006
+ if (capabilityDigest !== expectedCapabilityDigest) {
13007
+ return incompatible("source_acquisition_v2_capability_digest_mismatch");
13008
+ }
13009
+ return {
13010
+ state: "ready",
13011
+ proof: {
13012
+ supportedProfileVersions: [...source_acquisition_compatibility_default.supportedProfileVersions],
13013
+ profileVersion: SOURCE_ACQUISITION_PROFILE_VERSION_V2,
13014
+ capability: SOURCE_AUTHENTICATION_ORIGIN_DISCOVERY_CAPABILITY,
13015
+ piCodingAgent: { version: piVersion, digest: piDigest },
13016
+ sourceExtensionDigest,
13017
+ runtimeBuildCommit,
13018
+ deploymentImageDigest,
13019
+ completionGuard: SOURCE_ACQUISITION_V2_COMPLETION_GUARD,
13020
+ capabilityDigest
13021
+ }
13022
+ };
13023
+ }
12373
13024
  function sourceAcquisitionRuntimeReadiness(config) {
12374
13025
  const unavailable = (reason) => ({ ready: false, reason });
12375
13026
  const piExecutor = config.executors.find((executor) => executor.kind === "pi");
@@ -12392,13 +13043,22 @@ function sourceAcquisitionRuntimeReadiness(config) {
12392
13043
  }
12393
13044
  let browserSkill;
12394
13045
  if (adapters.includes(SOURCE_ACQUISITION_DESKTOP_ADAPTER)) {
13046
+ const authenticationOriginDiscoveryCapability = readString(
13047
+ process.env.AMASTER_SOURCE_ACQUISITION_BROWSER_SKILL_AUTHENTICATION_ORIGIN_DISCOVERY_CAPABILITY
13048
+ );
13049
+ if (authenticationOriginDiscoveryCapability && authenticationOriginDiscoveryCapability !== SOURCE_AUTHENTICATION_ORIGIN_DISCOVERY_CAPABILITY) {
13050
+ return unavailable("source_acquisition_browser_skill_discovery_attestation_invalid");
13051
+ }
12395
13052
  browserSkill = {
12396
13053
  runtimeVersion: readString(process.env.AMASTER_SOURCE_ACQUISITION_BROWSER_SKILL_RUNTIME_VERSION),
12397
13054
  runtimeDigest: readString(process.env.AMASTER_SOURCE_ACQUISITION_BROWSER_SKILL_RUNTIME_DIGEST),
12398
13055
  assetVersion: readString(process.env.AMASTER_SOURCE_ACQUISITION_BROWSER_SKILL_ASSET_VERSION),
12399
13056
  assetDigest: readString(process.env.AMASTER_SOURCE_ACQUISITION_BROWSER_SKILL_ASSET_DIGEST),
12400
13057
  policyVersion: SOURCE_ACQUISITION_BROWSER_POLICY_VERSION,
12401
- policyDigest: readString(process.env.AMASTER_SOURCE_ACQUISITION_BROWSER_SKILL_POLICY_DIGEST)
13058
+ policyDigest: readString(process.env.AMASTER_SOURCE_ACQUISITION_BROWSER_SKILL_POLICY_DIGEST),
13059
+ ...authenticationOriginDiscoveryCapability ? {
13060
+ authenticationOriginDiscoveryCapability
13061
+ } : {}
12402
13062
  };
12403
13063
  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 ?? "")) {
12404
13064
  return unavailable("source_acquisition_browser_skill_attestation_invalid");
@@ -12423,6 +13083,7 @@ function sourceAcquisitionRuntimeReadiness(config) {
12423
13083
  }
12424
13084
  packages.push({ name, version, digest });
12425
13085
  }
13086
+ const v2Cohort = sourceAcquisitionV2Cohort(extensionDigest);
12426
13087
  return {
12427
13088
  ready: true,
12428
13089
  profileVersion: SOURCE_ACQUISITION_PROFILE_VERSION,
@@ -12435,7 +13096,8 @@ function sourceAcquisitionRuntimeReadiness(config) {
12435
13096
  version: CONNECTOR_VERSION,
12436
13097
  digest: connectorDigest
12437
13098
  },
12438
- packages
13099
+ packages,
13100
+ ...v2Cohort ? { v2Cohort } : {}
12439
13101
  };
12440
13102
  }
12441
13103
  function browserSessionRuntimeReadiness(config) {
@@ -13142,41 +13804,14 @@ function commandTrustedPiRuntimeAssertion(command) {
13142
13804
  function commandSourceAcquisitionProfile(command) {
13143
13805
  return asRecord(asRecord(asRecord(command.payload).sourceAcquisition).profile);
13144
13806
  }
13145
- function sourceAcquisitionExactOrigin(value) {
13146
- const locator = readString(value);
13147
- let url;
13148
- try {
13149
- url = new URL(locator ?? "");
13150
- } catch {
13151
- throw Object.assign(new Error("source_acquisition_profile_invalid"), {
13152
- code: "source_acquisition_profile_invalid"
13153
- });
13154
- }
13155
- if (url.protocol !== "https:" || url.username || url.password) {
13156
- throw Object.assign(new Error("source_acquisition_profile_invalid"), {
13157
- code: "source_acquisition_profile_invalid"
13158
- });
13159
- }
13160
- return url.origin;
13161
- }
13162
13807
  async function sourceAcquisitionRuntimeProfile(config, command) {
13163
13808
  const profile = commandSourceAcquisitionProfile(command);
13164
13809
  if (Object.keys(profile).length === 0) return null;
13165
13810
  const access = asRecord(profile.access);
13166
- const transport = asRecord(profile.transport);
13167
- const tools = asRecord(profile.tools);
13168
- 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)) {
13169
- throw new Error("source_acquisition_profile_invalid");
13170
- }
13811
+ const inspection = inspectSourceAcquisitionProfile(profile, commandRunId(command));
13171
13812
  if (access.mode === "public") {
13172
- if (transport.browserMode !== "isolated" || transport.adapter !== SOURCE_ACQUISITION_HEADLESS_ADAPTER) {
13173
- throw new Error("source_acquisition_profile_invalid");
13174
- }
13175
13813
  return { profile };
13176
13814
  }
13177
- if (transport.browserMode !== "existing" || transport.adapter !== SOURCE_ACQUISITION_DESKTOP_ADAPTER) {
13178
- throw new Error("source_acquisition_profile_invalid");
13179
- }
13180
13815
  const companyId = readString(profile.companyId);
13181
13816
  const bindingId = readString(access.browserBindingId);
13182
13817
  const localOpaqueRef = readString(access.localOpaqueRef);
@@ -13185,7 +13820,6 @@ async function sourceAcquisitionRuntimeProfile(config, command) {
13185
13820
  if (!companyId || !bindingId || !/^profile_[a-z0-9]{16,64}$/i.test(localOpaqueRef ?? "") || !browserLeaseId || !browserLeaseExpiresAt || Date.parse(browserLeaseExpiresAt) <= Date.now()) {
13186
13821
  throw new Error("source_acquisition_profile_invalid");
13187
13822
  }
13188
- const exactOrigin = sourceAcquisitionExactOrigin(access.exactLocator);
13189
13823
  const profileName2 = createHash14("sha256").update(`${companyId}\0${bindingId}\0${localOpaqueRef}`).digest("hex");
13190
13824
  const stateRoot = resolve11(config.browserSessionStateRoot);
13191
13825
  const userDataDir = resolve11(stateRoot, profileName2);
@@ -13193,7 +13827,7 @@ async function sourceAcquisitionRuntimeProfile(config, command) {
13193
13827
  const markerPath = join15(userDataDir, ".amaster-browser-session.json");
13194
13828
  if (!existsSync14(userDataDir) || lstatSync7(userDataDir).isSymbolicLink() || !lstatSync7(userDataDir).isDirectory() || !existsSync14(markerPath) || lstatSync7(markerPath).isSymbolicLink()) throw new Error("source_acquisition_browser_profile_invalid");
13195
13829
  const marker = readJsonFile2(markerPath);
13196
- if (marker.version !== 1 || marker.companyId !== companyId || marker.bindingId !== bindingId || marker.localOpaqueRef !== localOpaqueRef || !readString(marker.provider) || marker.origin !== exactOrigin || Object.keys(marker).length !== 6) {
13830
+ if (marker.version !== 1 || marker.companyId !== companyId || marker.bindingId !== bindingId || marker.localOpaqueRef !== localOpaqueRef || !readString(marker.provider) || !inspection.sourceOrigins.includes(marker.origin) || Object.keys(marker).length !== 6) {
13197
13831
  throw new Error("source_acquisition_browser_profile_invalid");
13198
13832
  }
13199
13833
  const releaseBrowserLease = await browserSessionBrokerFor(config).acquireAgentRead({
@@ -13822,9 +14456,11 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
13822
14456
  const liveMcpToolResults = [];
13823
14457
  const sourceRetention = options.sourceRetention === true;
13824
14458
  const onSourceObservations = typeof options.onSourceObservations === "function" ? options.onSourceObservations : null;
14459
+ const onSourceAuthenticationOriginDiscoveries = typeof options.onSourceAuthenticationOriginDiscoveries === "function" ? options.onSourceAuthenticationOriginDiscoveries : null;
13825
14460
  let queue = Promise.resolve();
13826
14461
  let observationQueue = Promise.resolve();
13827
14462
  let observationError = null;
14463
+ let authenticationDiscoverySeen = false;
13828
14464
  const piToolArgumentTracker = executorKind === "pi" ? createPiToolArgumentAmplificationTracker(options.piToolArgumentGuard) : null;
13829
14465
  const maxEntriesPerStream = parsePositiveInteger(process.env.AMASTER_RUNTIME_LIVE_LOG_MAX_ENTRIES_PER_STREAM, 200);
13830
14466
  const countEventType = (event) => {
@@ -13906,6 +14542,7 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
13906
14542
  const text = redactProtectedText(line, protectedValues).trim();
13907
14543
  if (!text) return;
13908
14544
  const event = stream === "stdout" ? parseJsonLine(text) : null;
14545
+ const sourceControlEvent = parseJsonLine(text);
13909
14546
  const argumentAmplificationStop = stream === "stdout" ? piToolArgumentTracker?.record(event) ?? null : null;
13910
14547
  const eventType = readString(asRecord(event).type);
13911
14548
  if (executorKind === "pi" && eventType === "session") {
@@ -13939,6 +14576,24 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
13939
14576
  });
13940
14577
  }
13941
14578
  }
14579
+ if (sourceRetention && executorKind === "pi" && sourceControlEvent && onSourceAuthenticationOriginDiscoveries) {
14580
+ const discoveries = piSourceAuthenticationOriginDiscoveries(sourceControlEvent);
14581
+ if (discoveries.length > 0) {
14582
+ if (authenticationDiscoverySeen) {
14583
+ observationError ??= new Error("source_authentication_origin_discovery_duplicate");
14584
+ } else {
14585
+ authenticationDiscoverySeen = true;
14586
+ observationQueue = observationQueue.then(async () => {
14587
+ if (observationError) return;
14588
+ try {
14589
+ await onSourceAuthenticationOriginDiscoveries(discoveries);
14590
+ } catch (error) {
14591
+ observationError = error;
14592
+ }
14593
+ });
14594
+ }
14595
+ }
14596
+ }
13942
14597
  let entry = null;
13943
14598
  if (event && shouldPreserveExecutorJsonlForTranscript(executorKind, event)) {
13944
14599
  entry = {
@@ -14414,6 +15069,7 @@ function runExecutor(command, args, options) {
14414
15069
  if (quiescenceTimer) clearTimeout(quiescenceTimer);
14415
15070
  if (stoppedResidentTimer) clearTimeout(stoppedResidentTimer);
14416
15071
  if (completionOutputDrainTimer) clearTimeout(completionOutputDrainTimer);
15072
+ sourceCompletionStopPolicy.close();
14417
15073
  options.signal?.removeEventListener?.("abort", abort);
14418
15074
  resolveRun({
14419
15075
  stdout,
@@ -14426,6 +15082,7 @@ function runExecutor(command, args, options) {
14426
15082
  memoryLimit,
14427
15083
  completionOutputType,
14428
15084
  completionOutputHasFinalAssistantText,
15085
+ sourceCompletionHardCapExceeded: sourceCompletionStopPolicy.hardCapExceeded,
14429
15086
  killedWorkspaceResidents,
14430
15087
  ...outputDrainForcedClosed ? { outputDrainForcedClosed: true } : {},
14431
15088
  ...result3
@@ -14441,6 +15098,10 @@ function runExecutor(command, args, options) {
14441
15098
  signalExecutorProcess(child, "SIGTERM", processGroupId);
14442
15099
  scheduleStopKill();
14443
15100
  };
15101
+ const sourceCompletionStopPolicy = createSourceCompletionStopPolicy({
15102
+ enabled: options.sourceCompletionGuard === true,
15103
+ onStop: requestStop
15104
+ });
14444
15105
  deliverSourceAcquisitionManagedInputs(child, managedInputs, (code, error) => {
14445
15106
  spawnError = `${code}_delivery_failed: ${error.message}`;
14446
15107
  requestStop(`${code}_delivery_failed`);
@@ -14522,6 +15183,15 @@ function runExecutor(command, args, options) {
14522
15183
  if (!trimmed.startsWith("{")) continue;
14523
15184
  try {
14524
15185
  const event = JSON.parse(trimmed);
15186
+ const eventType = readString(asRecord(event).type);
15187
+ const sourceStop = sourceCompletionStopPolicy.observe(eventType);
15188
+ if (sourceStop.handled) {
15189
+ if (sourceStop.completionOutputType) {
15190
+ completionOutputType = sourceStop.completionOutputType;
15191
+ return;
15192
+ }
15193
+ continue;
15194
+ }
14525
15195
  const stopType = piCompletionOutputType(event);
14526
15196
  if (stopType) {
14527
15197
  completionOutputType = stopType;
@@ -14705,6 +15375,17 @@ async function ingestSourceAcquisitionObservations(config, command, profile, rec
14705
15375
  );
14706
15376
  }
14707
15377
  }
15378
+ async function ingestSourceAuthenticationOriginDiscoveries(config, command, profile, discoveries) {
15379
+ await submitSourceAuthenticationOriginDiscovery({
15380
+ config,
15381
+ command,
15382
+ connectorId: requireConnectorId(config),
15383
+ profile,
15384
+ discoveries,
15385
+ postJsonWithRetry,
15386
+ ingestLog
15387
+ });
15388
+ }
14708
15389
  function parsedUsageCostCents(usage) {
14709
15390
  const costUsd = readNumber(asRecord(usage).costUsd, 0);
14710
15391
  if (!Number.isFinite(costUsd) || costUsd <= 0) return 0;
@@ -16836,6 +17517,7 @@ async function executeRunCommand(config, command) {
16836
17517
  const protectedExecutorValues = managedMcpProfile?.protectedValues ?? providerProtectedValues;
16837
17518
  const runtimeArtifacts = [];
16838
17519
  const runtimeDocuments = [];
17520
+ let sourceAuthenticationDiscoveryAccepted = false;
16839
17521
  const runtimeArtifactIngest = createRuntimeArtifactIngestQueue({
16840
17522
  ingest: (results) => ingestRuntimeArtifacts(config, command, cwd, results)
16841
17523
  });
@@ -16860,7 +17542,15 @@ async function executeRunCommand(config, command) {
16860
17542
  command,
16861
17543
  sourceAcquisition.profile,
16862
17544
  receipts
16863
- )
17545
+ ),
17546
+ onSourceAuthenticationOriginDiscoveries: (discoveries) => ingestSourceAuthenticationOriginDiscoveries(
17547
+ config,
17548
+ command,
17549
+ sourceAcquisition.profile,
17550
+ discoveries
17551
+ ).then(() => {
17552
+ sourceAuthenticationDiscoveryAccepted = true;
17553
+ })
16864
17554
  } : {}
16865
17555
  }
16866
17556
  );
@@ -16875,6 +17565,7 @@ async function executeRunCommand(config, command) {
16875
17565
  maxRssMb: config.executorMaxRssMb,
16876
17566
  signal: abortController.signal,
16877
17567
  executorKind: executor.kind,
17568
+ sourceCompletionGuard: executor.kind === "pi" && sourceAcquisition?.profile?.purpose === SOURCE_ACQUISITION_PROFILE_VERSION_V2,
16878
17569
  ...piExecutorIdentity ? { spawnIdentity: piExecutorIdentity } : {},
16879
17570
  ...sourceProfile ? { sourceProfileInput: sourceProfile.input } : {},
16880
17571
  onOutput: (stream, chunk, rawBytes) => {
@@ -17100,11 +17791,14 @@ async function executeRunCommand(config, command) {
17100
17791
  }
17101
17792
  }
17102
17793
  const cancelled = execution.cancelled === true;
17794
+ const sourceCompletionGuard = executor.kind === "pi" && sourceAcquisition?.profile?.purpose === SOURCE_ACQUISITION_PROFILE_VERSION_V2;
17795
+ const sourceCompletionOutputStopped = sourceCompletionGuard && execution.completionOutputType === "agent_settled" && piCompletionCleanupStopped(execution);
17796
+ const sourceCompletionFailure = sourceCompletionGuard && !sourceAuthenticationDiscoveryAccepted && (execution.sourceCompletionHardCapExceeded === true || sourceCompletionTerminalFailure(execution.stderr, sourceAcquisition.profile) || !sourceCompletionActionAccepted(mcpToolResults)) ? "source_acquisition_terminal_action_missing" : null;
17103
17797
  const outputFloodError = hasOutputFlood ? `${executor.kind === "pi" ? "Pi Agent" : "Executor"} output flood: ${outputFlood.stream} exceeded ${readNumber(outputFlood.limitBytes, 0)} bytes` : null;
17104
17798
  const argumentAmplificationError = hasArgumentAmplification ? `Pi Agent tool argument stream amplification stopped before execution: ${readNumber(argumentAmplification.transportArgumentBytes, 0)} transported byte(s), ${readNumber(argumentAmplification.materializedArgumentBytes, 0)} materialized byte(s)` : null;
17105
17799
  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;
17106
17800
  const piUsageDiagnostic = executor.kind === "pi" && !hasOutputFlood && !hasArgumentAmplification && piOutputUsageMetadataMissing(parsed) ? "Pi Agent exited without usage metadata" : null;
17107
- const completionOutputStopped = executor.kind === "pi" && piCompletionOutputStopped(execution);
17801
+ const completionOutputStopped = executor.kind === "pi" && (piCompletionOutputStopped(execution) || sourceCompletionOutputStopped);
17108
17802
  const cleanupDisposition = executor.kind === "pi" && !cancelled && !hasOutputFlood && !hasArgumentAmplification && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError && execution.signal === null ? classifyPiTerminalCleanupDisposition(
17109
17803
  { ...parsed, mcpToolResults },
17110
17804
  runtimeArtifacts
@@ -17126,13 +17820,13 @@ async function executeRunCommand(config, command) {
17126
17820
  const piTurnLimitFailure = executor.kind === "pi" && !cancelled && !hasOutputFlood && !hasArgumentAmplification && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError ? classifyPiTurnLimitResult(parsedForValidation) : null;
17127
17821
  const piInvalidOutputError = executor.kind === "pi" ? piOutputValidationError(parsedForValidation, {
17128
17822
  allowMissingTurnEnd: completionOutputStopped,
17129
- allowMissingAssistantOutput: execution.completionOutputType === "approval_required",
17823
+ allowMissingAssistantOutput: execution.completionOutputType === "approval_required" || sourceCompletionGuard,
17130
17824
  completionOutputType: execution.completionOutputType,
17131
17825
  completionOutputHasFinalAssistantText: terminalTextRepair?.succeeded === true ? true : execution.completionOutputHasFinalAssistantText
17132
17826
  }) : null;
17133
17827
  const piOutputFailure = executor.kind === "pi" && !cancelled && !hasOutputFlood && !hasArgumentAmplification && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError ? classifyPiOutputFailure(parsedForValidation, { invalidOutputError: piInvalidOutputError }) : null;
17134
17828
  const piProviderFailure = piOutputFailure?.errorCode !== "pi_executor_invalid_output" ? piOutputFailure : null;
17135
- const parsedErrorMessage = outputFloodError ?? argumentAmplificationError ?? memoryLimitError ?? piTurnLimitFailure?.message ?? piInvalidOutputError ?? nativeSessionRolloutError ?? nativeSessionRolloutCleanupError ?? parsedForValidation.errorMessage;
17829
+ const parsedErrorMessage = outputFloodError ?? argumentAmplificationError ?? memoryLimitError ?? sourceCompletionFailure ?? piTurnLimitFailure?.message ?? piInvalidOutputError ?? nativeSessionRolloutError ?? nativeSessionRolloutCleanupError ?? parsedForValidation.errorMessage;
17136
17830
  const codexTransientFailure = executor.kind === "codex" && (execution.exitCode ?? 0) !== 0 ? classifyCodexTransientUpstreamError({
17137
17831
  stdout: execution.stdout,
17138
17832
  stderr: execution.stderr,
@@ -17159,15 +17853,15 @@ async function executeRunCommand(config, command) {
17159
17853
  receipt: sourceExecutionReceiptPath ? readSourceAcquisitionExecutionReceipt(sourceExecutionReceiptPath, sourceExecutionIdentity) : null,
17160
17854
  exitCode: execution.exitCode
17161
17855
  }) : null;
17162
- const sourceErrorCode = sourceAcquisition ? execution.timedOut ? "source_acquisition_timeout" : cancelled ? "source_acquisition_cancelled" : hasOutputFlood ? "source_acquisition_output_flood" : hasMemoryLimit ? "source_acquisition_memory_limit" : execution.spawnError ? "source_acquisition_executor_unavailable" : succeeded ? null : sourceExecutionFailure?.failureCode ?? "source_acquisition_executor_failed" : null;
17856
+ const sourceErrorCode = sourceAcquisition ? sourceCompletionFailure ?? (execution.timedOut ? "source_acquisition_timeout" : cancelled ? "source_acquisition_cancelled" : hasOutputFlood ? "source_acquisition_output_flood" : hasMemoryLimit ? "source_acquisition_memory_limit" : execution.spawnError ? "source_acquisition_executor_unavailable" : succeeded ? null : sourceExecutionFailure?.failureCode ?? "source_acquisition_executor_failed") : null;
17163
17857
  const error = sourceAcquisition ? sourceErrorCode : unsafeError;
17164
17858
  const costUsage = parsedCostUsage(parsed.usage);
17165
- const cleanPiTerminalOutputStop = succeeded && (completionOutputStopped || repairedPiTerminalOutputStop) && execution.completionOutputType === "agent_end" && parsed.terminalEventType === "agent_end" && Number.isInteger(parsed.terminalEventIndex);
17859
+ const cleanPiTerminalOutputStop = succeeded && (completionOutputStopped || repairedPiTerminalOutputStop) && (sourceCompletionOutputStopped || execution.completionOutputType === "agent_end" && parsed.terminalEventType === "agent_end" && Number.isInteger(parsed.terminalEventIndex));
17166
17860
  const executorOutcome = {
17167
17861
  status: cancelled ? "cancelled" : execution.timedOut ? "timed_out" : cleanPiTerminalOutputStop || execution.exitCode === 0 && execution.signal === null ? "completed" : "failed",
17168
17862
  exitCode: cleanPiTerminalOutputStop ? 0 : execution.exitCode,
17169
17863
  signal: cleanPiTerminalOutputStop ? null : execution.signal,
17170
- terminalEvent: ["agent_end", "turn_end"].includes(readString(parsed.terminalEventType) ?? "") ? readString(parsed.terminalEventType) : null,
17864
+ terminalEvent: sourceCompletionOutputStopped ? "agent_settled" : ["agent_end", "turn_end"].includes(readString(parsed.terminalEventType) ?? "") ? readString(parsed.terminalEventType) : null,
17171
17865
  terminalEventIndex: Number.isInteger(parsed.terminalEventIndex) ? parsed.terminalEventIndex : null
17172
17866
  };
17173
17867
  let result3 = {