@openclaw/acpx 2026.11.3 → 2026.11.5-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,13 @@
1
- import { a as isClaudeAcpCommand, c as renderAgentCommand, d as CODEX_ACP_BIN, f as CODEX_ACP_PACKAGE, i as toAcpMcpServers, l as resolveAgentCommand, m as OPENCLAW_CODEX_CONFIG_ARG, n as resolveAcpxPluginRoot, o as isCodexAcpCommand, p as LEGACY_CODEX_ACP_PACKAGE, r as resolveOpenClawRoot, s as isOpenClawBridgeCommand, t as resolveAcpxPluginConfig, u as splitCommandParts } from "./config-D0ATuiVJ.mjs";
1
+ import { a as isClaudeAcpCommand, c as renderAgentCommand, d as CODEX_ACP_BIN, f as CODEX_ACP_PACKAGE, i as toAcpMcpServers, l as resolveAgentCommand, m as OPENCLAW_CODEX_CONFIG_ARG, n as resolveAcpxPluginRoot, o as isCodexAcpCommand, p as LEGACY_CODEX_ACP_PACKAGE, r as resolveOpenClawRoot, s as isOpenClawBridgeCommand, t as resolveAcpxPluginConfig, u as splitCommandParts } from "./config-DZaY96RI.mjs";
2
2
  import { AcpRuntimeError } from "../runtime-api.js";
3
- import { t as resolveAcpxSessionResource } from "./session-resource-DKJsUJPu.mjs";
4
- import { a as hashAcpxProcessCommand, adoptAcpxStateDirectory, c as withAcpxLeaseArgs, d as normalizeAcpxGatewayInstanceRecord, i as createAcpxProcessLeaseStore, l as ACPX_GATEWAY_INSTANCE_KEY, n as OPENCLAW_ACPX_LEASE_ID_ARG, o as openAcpxProcessLeaseStateStore, r as OPENCLAW_GATEWAY_INSTANCE_ID_ARG, s as readAcpxProcessLeaseIdentity, t as ACPX_PROBE_LEASE_SESSION_KEY, u as ACPX_GATEWAY_INSTANCE_NAMESPACE } from "./session-owner-migration-BA3DJKb2.mjs";
3
+ import { t as resolveAcpxSessionResource } from "./session-resource-BI93OF1C.mjs";
4
+ import { a as hashAcpxProcessCommand, adoptAcpxStateDirectory, c as withAcpxLeaseArgs, d as normalizeAcpxGatewayInstanceRecord, i as createAcpxProcessLeaseStore, l as ACPX_GATEWAY_INSTANCE_KEY, n as OPENCLAW_ACPX_LEASE_ID_ARG, o as openAcpxProcessLeaseStateStore, r as OPENCLAW_GATEWAY_INSTANCE_ID_ARG, s as readAcpxProcessLeaseIdentity, t as ACPX_PROBE_LEASE_SESSION_KEY, u as ACPX_GATEWAY_INSTANCE_NAMESPACE } from "./session-owner-migration-BmfOUj9h.mjs";
5
5
  import { createRequire } from "node:module";
6
- import { finiteSecondsToTimerSafeMilliseconds, parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
6
+ import { finiteSecondsToTimerSafeMilliseconds } from "openclaw/plugin-sdk/number-runtime";
7
7
  import fs from "node:fs";
8
8
  import path from "node:path";
9
- import { asOptionalObjectRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
9
+ import { isPidAlive, runExec } from "openclaw/plugin-sdk/process-runtime";
10
+ import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
10
11
  import os, { availableParallelism } from "node:os";
11
12
  import { randomUUID } from "node:crypto";
12
13
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
@@ -17,7 +18,6 @@ import { raceWithTimeout } from "openclaw/plugin-sdk/time-runtime";
17
18
  import { tryReadJson } from "@openclaw/fs-safe/json";
18
19
  import { parse, stringify } from "smol-toml";
19
20
  import { setTimeout } from "node:timers/promises";
20
- import { isPidAlive, runExec } from "openclaw/plugin-sdk/process-runtime";
21
21
  import { AsyncLocalStorage } from "node:async_hooks";
22
22
  import { isDeepStrictEqual } from "node:util";
23
23
  import { redactSensitiveText } from "openclaw/plugin-sdk/security-runtime";
@@ -441,9 +441,7 @@ const parentWatcher =
441
441
  return;
442
442
  }
443
443
  orphanCleanupStarted = true;
444
- if (parentWatcher) {
445
- clearInterval(parentWatcher);
446
- }
444
+ clearInterval(parentWatcher);
447
445
  killChildTree("SIGTERM");
448
446
  // Keep the wrapper alive long enough for stubborn adapters to receive
449
447
  // a forced fallback signal after SIGTERM.
@@ -479,9 +477,7 @@ child.on("exit", (code, signal) => {
479
477
 
480
478
  child.on("close", () => {
481
479
  finishStderrLog();
482
- if (parentWatcher) {
483
- clearInterval(parentWatcher);
484
- }
480
+ clearInterval(parentWatcher);
485
481
  childClosed = true;
486
482
  finishWrapper();
487
483
  });
@@ -491,121 +487,6 @@ main();
491
487
  }
492
488
  //#endregion
493
489
  //#region extensions/acpx/src/codex-trust-config.ts
494
- function stripTomlComment(line) {
495
- let quote = null;
496
- let escaping = false;
497
- for (let index = 0; index < line.length; index += 1) {
498
- const ch = line[index];
499
- if (escaping) {
500
- escaping = false;
501
- continue;
502
- }
503
- if (quote === "\"" && ch === "\\") {
504
- escaping = true;
505
- continue;
506
- }
507
- if (quote) {
508
- if (ch === quote) quote = null;
509
- continue;
510
- }
511
- if (ch === "'" || ch === "\"") {
512
- quote = ch;
513
- continue;
514
- }
515
- if (ch === "#") return line.slice(0, index);
516
- }
517
- return line;
518
- }
519
- function parseTomlString(value) {
520
- const trimmed = value.trim();
521
- if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) try {
522
- return JSON.parse(trimmed);
523
- } catch {
524
- return;
525
- }
526
- if (trimmed.startsWith("'") && trimmed.endsWith("'")) return trimmed.slice(1, -1);
527
- }
528
- function parseTomlDottedKey(value) {
529
- const parts = [];
530
- let current = "";
531
- let quote = null;
532
- let escaping = false;
533
- for (const ch of value.trim()) {
534
- if (escaping) {
535
- current += ch;
536
- escaping = false;
537
- continue;
538
- }
539
- if (quote === "\"" && ch === "\\") {
540
- current += ch;
541
- escaping = true;
542
- continue;
543
- }
544
- if (quote) {
545
- current += ch;
546
- if (ch === quote) quote = null;
547
- continue;
548
- }
549
- if (ch === "'" || ch === "\"") {
550
- quote = ch;
551
- current += ch;
552
- continue;
553
- }
554
- if (ch === ".") {
555
- parts.push(current.trim());
556
- current = "";
557
- continue;
558
- }
559
- current += ch;
560
- }
561
- if (current.trim()) parts.push(current.trim());
562
- return parts.map((part) => parseTomlString(part) ?? part);
563
- }
564
- function parseProjectHeader(line) {
565
- const parts = parseTableHeader(line);
566
- return parts?.length === 2 && parts[0] === "projects" ? parts[1] : void 0;
567
- }
568
- function parseTrustedInlineProjectEntries(value) {
569
- const trusted = [];
570
- for (const match of value.matchAll(/(?<key>"(?:\\.|[^"\\])*"|'[^']*'|[A-Za-z0-9_\-/.~:]+)\s*=\s*\{(?<body>[^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g)) {
571
- const key = match.groups?.key;
572
- const body = match.groups?.body;
573
- if (!key || !body || !/\btrust_level\s*=\s*["']trusted["']/.test(body)) continue;
574
- const projectPath = parseTomlString(key) ?? key.trim();
575
- if (projectPath) trusted.push(projectPath);
576
- }
577
- return trusted;
578
- }
579
- function extractTrustedCodexProjectPaths(configToml) {
580
- const trusted = /* @__PURE__ */ new Set();
581
- let currentProjectPath;
582
- let inProjectsTable = false;
583
- for (const rawLine of configToml.split(/\r?\n/)) {
584
- const line = stripTomlComment(rawLine).trim();
585
- if (!line) continue;
586
- if (line.startsWith("[")) {
587
- currentProjectPath = parseProjectHeader(line);
588
- inProjectsTable = line === "[projects]";
589
- continue;
590
- }
591
- if (currentProjectPath && /^trust_level\s*=\s*["']trusted["']\s*$/.test(line)) {
592
- trusted.add(currentProjectPath);
593
- continue;
594
- }
595
- const assignment = /^(?<key>"(?:\\.|[^"\\])*"|'[^']*'|[A-Za-z0-9_\-/.~:]+)\s*=\s*(?<value>.+)$/.exec(line);
596
- const rawKey = assignment?.groups?.key;
597
- const rawValue = assignment?.groups?.value;
598
- if (!rawKey || rawValue === void 0) continue;
599
- const key = parseTomlString(rawKey) ?? rawKey;
600
- const value = rawValue.trim();
601
- if (inProjectsTable && /^\{.*\}$/.test(value)) {
602
- if (/\btrust_level\s*=\s*["']trusted["']/.test(value) && key) trusted.add(key);
603
- continue;
604
- }
605
- if (key === "projects" || inProjectsTable) for (const projectPath of parseTrustedInlineProjectEntries(value)) trusted.add(projectPath);
606
- }
607
- return Array.from(trusted);
608
- }
609
490
  const INHERITED_TOP_LEVEL_CODEX_CONFIG_KEYS = /* @__PURE__ */ new Set([
610
491
  "model",
611
492
  "model_provider",
@@ -623,61 +504,30 @@ const INHERITED_MODEL_PROVIDER_CONFIG_KEYS = /* @__PURE__ */ new Set([
623
504
  "stream_max_retries",
624
505
  "stream_idle_timeout_ms"
625
506
  ]);
626
- function parseTableHeader(line) {
627
- const trimmed = line.trim();
628
- if (!trimmed.startsWith("[") || !trimmed.endsWith("]") || trimmed.startsWith("[[")) return;
629
- return parseTomlDottedKey(trimmed.slice(1, -1));
630
- }
631
- function isInheritedModelProviderTable(parts) {
632
- return parts?.[0] === "model_providers" && parts.length === 2;
633
- }
634
- function parseTopLevelAssignmentKey(line) {
635
- return /^(?<key>[A-Za-z0-9_-]+)\s*=\s*(?<value>.+)$/.exec(line)?.groups?.key;
636
- }
637
- function extractInheritedCodexRuntimeConfig(configToml) {
638
- const inheritedLines = [];
639
- let inAnyTable = false;
640
- let inInheritedTable = false;
641
- let pendingInheritedTableHeader = "";
642
- function flushInheritedTableHeader() {
643
- if (!pendingInheritedTableHeader) return;
644
- if (inheritedLines.length > 0 && inheritedLines[inheritedLines.length - 1] !== "") inheritedLines.push("");
645
- inheritedLines.push(pendingInheritedTableHeader);
646
- pendingInheritedTableHeader = "";
647
- }
648
- for (const rawLine of configToml.split(/\r?\n/)) {
649
- const trimmedLine = rawLine.trim();
650
- const semanticLine = stripTomlComment(rawLine).trim();
651
- if (trimmedLine.startsWith("[")) {
652
- const tableParts = parseTableHeader(trimmedLine);
653
- inAnyTable = true;
654
- inInheritedTable = isInheritedModelProviderTable(tableParts);
655
- if (inInheritedTable) pendingInheritedTableHeader = rawLine.trimEnd();
656
- else pendingInheritedTableHeader = "";
657
- continue;
658
- }
659
- if (inInheritedTable) {
660
- if (!semanticLine) continue;
661
- const key = parseTopLevelAssignmentKey(semanticLine);
662
- if (!key || !INHERITED_MODEL_PROVIDER_CONFIG_KEYS.has(key)) continue;
663
- flushInheritedTableHeader();
664
- inheritedLines.push(rawLine.trimEnd());
665
- continue;
666
- }
667
- if (inAnyTable) continue;
668
- const key = parseTopLevelAssignmentKey(semanticLine);
669
- if (!key) continue;
670
- if (!INHERITED_TOP_LEVEL_CODEX_CONFIG_KEYS.has(key)) continue;
671
- inheritedLines.push(rawLine.trimEnd());
672
- }
673
- return inheritedLines.join("\n");
674
- }
675
507
  function renderIsolatedCodexConfig(params) {
676
- const normalized = Array.from(new Set(params.projectPaths.map((projectPath) => projectPath.trim()).filter(Boolean).map((projectPath) => path.resolve(projectPath)))).toSorted((left, right) => left.localeCompare(right));
508
+ let source = {};
509
+ if (params.sourceConfigToml) try {
510
+ source = parse(params.sourceConfigToml, { integersAsBigInt: true });
511
+ } catch {
512
+ throw new Error("Codex config.toml must be valid TOML before starting an ACP session.");
513
+ }
514
+ const providers = /* @__PURE__ */ new Map();
515
+ if (isRecord(source.model_providers)) for (const [name, provider] of Object.entries(source.model_providers)) {
516
+ if (!isRecord(provider)) continue;
517
+ const config = Object.fromEntries(Object.entries(provider).filter(([key]) => INHERITED_MODEL_PROVIDER_CONFIG_KEYS.has(key)));
518
+ if (Object.keys(config).length) providers.set(name, config);
519
+ }
520
+ const inherited = {
521
+ ...Object.fromEntries(Object.entries(source).filter(([key]) => INHERITED_TOP_LEVEL_CODEX_CONFIG_KEYS.has(key))),
522
+ ...providers.size ? { model_providers: Object.fromEntries(providers) } : {},
523
+ ...params.mcpServers ? { mcp_servers: params.mcpServers } : {}
524
+ };
525
+ const trustedProjects = isRecord(source.projects) ? Object.entries(source.projects).filter(([, project]) => isRecord(project) && project.trust_level === "trusted").map(([projectPath]) => projectPath) : [];
526
+ const projectPaths = Array.from(new Set([...params.projectPaths, ...trustedProjects].map((projectPath) => projectPath.trim()).filter(Boolean).map((projectPath) => path.resolve(projectPath)))).toSorted((left, right) => left.localeCompare(right));
677
527
  return [
678
528
  "# Generated by OpenClaw for Codex ACP sessions.",
679
- params.sourceConfigToml ? extractInheritedCodexRuntimeConfig(params.sourceConfigToml) : "",
680
- ...normalized.flatMap((projectPath) => [
529
+ stringify(inherited, { numbersAsFloat: true }).trimEnd(),
530
+ ...projectPaths.flatMap((projectPath) => [
681
531
  "",
682
532
  `[projects.${JSON.stringify(projectPath)}]`,
683
533
  "trust_level = \"trusted\""
@@ -846,17 +696,15 @@ async function readSourceCodexConfig(codexHome) {
846
696
  }
847
697
  async function prepareIsolatedCodexHome(params) {
848
698
  const sourceConfig = await readSourceCodexConfig(process.env.CODEX_HOME || path.join(os.homedir(), ".codex"));
849
- const trustedProjectPaths = [...sourceConfig ? extractTrustedCodexProjectPaths(sourceConfig) : [], params.workspaceDir];
850
699
  const codexHome = path.join(params.baseDir, "codex-home");
851
700
  await fs$1.mkdir(codexHome, { recursive: true });
852
701
  await fs$1.writeFile(path.join(codexHome, "config.toml"), renderIsolatedCodexConfig({
853
702
  sourceConfigToml: sourceConfig,
854
- projectPaths: trustedProjectPaths
703
+ projectPaths: [params.workspaceDir],
704
+ mcpServers: isRecord(params.migratedConfig?.mcp_servers) ? params.migratedConfig.mcp_servers : void 0
855
705
  }), "utf8");
856
- return codexHome;
857
706
  }
858
707
  async function writeAdapterWrapper(baseDir, fileName, script) {
859
- await fs$1.mkdir(baseDir, { recursive: true });
860
708
  const wrapperPath = path.join(baseDir, fileName);
861
709
  await fs$1.writeFile(wrapperPath, script, { encoding: "utf8" });
862
710
  try {
@@ -968,13 +816,6 @@ function resolveCodexAdapterLaunch(configuredCommand) {
968
816
  if (!maintainedAdapterArgs) return;
969
817
  return { args: maintainedAdapterArgs };
970
818
  }
971
- async function persistMigratedCodexMcpConfig(params) {
972
- const mcpServers = params.migratedConfig?.mcp_servers;
973
- if (!isRecord(mcpServers)) return;
974
- const configPath = path.join(params.codexHome, "config.toml");
975
- const merged = mergeConfigRecords(parse(await fs$1.readFile(configPath, "utf8")), { mcp_servers: mcpServers });
976
- await fs$1.writeFile(configPath, stringify(merged), "utf8");
977
- }
978
819
  function buildClaudeAcpWrapperCommand(wrapperPath, configuredCommand) {
979
820
  const configuredAdapterArgs = extractConfiguredAdapterArgs({
980
821
  configuredCommand,
@@ -990,17 +831,15 @@ async function prepareAcpxCodexAuthConfig(params) {
990
831
  const configuredCodexCommand = params.pluginConfig.agents.codex;
991
832
  const configuredClaudeCommand = params.pluginConfig.agents.claude;
992
833
  const codexLaunch = resolveCodexAdapterLaunch(configuredCodexCommand);
993
- await persistMigratedCodexMcpConfig({
994
- codexHome: await prepareIsolatedCodexHome({
995
- baseDir: codexBaseDir,
996
- workspaceDir: params.pluginConfig.cwd
997
- }),
834
+ await prepareIsolatedCodexHome({
835
+ baseDir: codexBaseDir,
836
+ workspaceDir: params.pluginConfig.cwd,
998
837
  migratedConfig: codexLaunch?.migratedConfig
999
838
  });
1000
- const installedCodexBinPath = await (params.resolveInstalledCodexAcpBinPath ? params.resolveInstalledCodexAcpBinPath() : resolveInstalledAcpPackageBinPath(CODEX_ACP_PACKAGE, CODEX_ACP_BIN));
1001
- const installedClaudeBinPath = await (params.resolveInstalledClaudeAcpBinPath ? params.resolveInstalledClaudeAcpBinPath() : resolveInstalledAcpPackageBinPath(CLAUDE_ACP_PACKAGE, CLAUDE_ACP_BIN));
1002
- const wrapperPath = await writeAdapterWrapper(codexBaseDir, "codex-acp-wrapper.mjs", buildCodexAcpWrapperScript(installedCodexBinPath));
1003
- const claudeWrapperPath = await writeAdapterWrapper(codexBaseDir, "claude-agent-acp-wrapper.mjs", buildClaudeAcpWrapperScript(installedClaudeBinPath));
839
+ const codexBinPath = await resolveInstalledAcpPackageBinPath(CODEX_ACP_PACKAGE, CODEX_ACP_BIN);
840
+ const claudeBinPath = await resolveInstalledAcpPackageBinPath(CLAUDE_ACP_PACKAGE, CLAUDE_ACP_BIN);
841
+ const wrapperPath = await writeAdapterWrapper(codexBaseDir, "codex-acp-wrapper.mjs", buildCodexAcpWrapperScript(codexBinPath));
842
+ const claudeWrapperPath = await writeAdapterWrapper(codexBaseDir, "claude-agent-acp-wrapper.mjs", buildClaudeAcpWrapperScript(claudeBinPath));
1004
843
  return {
1005
844
  ...params.pluginConfig,
1006
845
  agents: {
@@ -1127,12 +966,16 @@ function parseProcessList(stdout) {
1127
966
  }
1128
967
  async function listPlatformProcesses() {
1129
968
  if (process.platform === "win32") return [];
1130
- const { stdout } = await runExec("ps", ["-axo", "pid=,ppid=,command="], {
1131
- logOutput: false,
1132
- maxBuffer: 8388608,
1133
- timeoutMs: ACPX_PROCESS_LIST_TIMEOUT_MS
1134
- });
1135
- return parseProcessList(stdout);
969
+ try {
970
+ const { stdout } = await runExec("ps", ["-axo", "pid=,ppid=,command="], {
971
+ logOutput: false,
972
+ maxBuffer: 8388608,
973
+ timeoutMs: ACPX_PROCESS_LIST_TIMEOUT_MS
974
+ });
975
+ return parseProcessList(stdout);
976
+ } catch {
977
+ return;
978
+ }
1136
979
  }
1137
980
  function collectProcessTree(processes, rootPid) {
1138
981
  const childrenByParent = /* @__PURE__ */ new Map();
@@ -1141,7 +984,7 @@ function collectProcessTree(processes, rootPid) {
1141
984
  children.push(processInfo);
1142
985
  childrenByParent.set(processInfo.ppid, children);
1143
986
  }
1144
- const root = new Map(processes.map((processInfo) => [processInfo.pid, processInfo])).get(rootPid);
987
+ const root = processes.find((processInfo) => processInfo.pid === rootPid);
1145
988
  const collected = [];
1146
989
  if (root) collected.push(root);
1147
990
  const queue = [...childrenByParent.get(rootPid) ?? []];
@@ -1179,28 +1022,20 @@ async function terminatePids(pids, assertCurrent) {
1179
1022
  async function cleanupOpenClawOwnedAcpxProcessTree(params) {
1180
1023
  const rootPid = params.rootPid;
1181
1024
  if (!rootPid || rootPid <= 0 || rootPid === process.pid) return {
1182
- inspectedPids: [],
1183
1025
  terminatedPids: [],
1184
1026
  skippedReason: "missing-root"
1185
1027
  };
1186
1028
  if (process.platform === "win32") return {
1187
- inspectedPids: [],
1188
1029
  terminatedPids: [],
1189
1030
  skippedReason: "unsupported-platform"
1190
1031
  };
1191
- let processes;
1192
- try {
1193
- processes = await listPlatformProcesses();
1194
- } catch {
1195
- return {
1196
- inspectedPids: [],
1197
- terminatedPids: [],
1198
- skippedReason: "process-list-unavailable"
1199
- };
1200
- }
1032
+ const processes = await listPlatformProcesses();
1033
+ if (!processes) return {
1034
+ terminatedPids: [],
1035
+ skippedReason: "process-list-unavailable"
1036
+ };
1201
1037
  const listedTree = collectProcessTree(processes, rootPid);
1202
1038
  if (listedTree.length === 0) return {
1203
- inspectedPids: [],
1204
1039
  terminatedPids: [],
1205
1040
  skippedReason: "unverified-root"
1206
1041
  };
@@ -1215,85 +1050,56 @@ async function cleanupOpenClawOwnedAcpxProcessTree(params) {
1215
1050
  expectedLeaseId: params.expectedLeaseId,
1216
1051
  expectedGatewayInstanceId: params.expectedGatewayInstanceId
1217
1052
  })) return {
1218
- inspectedPids: listedTree.map((processInfo) => processInfo.pid),
1219
1053
  terminatedPids: [],
1220
1054
  skippedReason: "not-openclaw-owned"
1221
1055
  };
1222
- const pids = uniquePids(listedTree.toReversed());
1223
- return {
1224
- inspectedPids: uniquePids(listedTree),
1225
- terminatedPids: await terminatePids(pids, params.assertCurrent)
1226
- };
1056
+ return { terminatedPids: await terminatePids(uniquePids(listedTree.toReversed()), params.assertCurrent) };
1227
1057
  }
1228
1058
  /** Recover a pending lease by matching its exact live wrapper identity. */
1229
1059
  async function cleanupOpenClawOwnedAcpxPendingLease(params) {
1230
1060
  if (process.platform === "win32") return {
1231
- inspectedPids: [],
1232
1061
  terminatedPids: [],
1233
1062
  skippedReason: "unsupported-platform"
1234
1063
  };
1235
1064
  if (!params.wrapperPath || !wrapperPathBelongsToRoot(params.wrapperPath, params.wrapperRoot)) return {
1236
- inspectedPids: [],
1237
1065
  terminatedPids: [],
1238
1066
  skippedReason: "unverified-root"
1239
1067
  };
1240
- let processes;
1241
- try {
1242
- processes = await listPlatformProcesses();
1243
- } catch {
1244
- return {
1245
- inspectedPids: [],
1246
- terminatedPids: [],
1247
- skippedReason: "process-list-unavailable"
1248
- };
1249
- }
1068
+ const processes = await listPlatformProcesses();
1069
+ if (!processes) return {
1070
+ terminatedPids: [],
1071
+ skippedReason: "process-list-unavailable"
1072
+ };
1250
1073
  const matchingRoots = processes.filter((processInfo) => commandContainsExactWrapperPath(processInfo.command, params.wrapperPath) && liveCommandMatchesLeaseIdentity({
1251
1074
  command: processInfo.command,
1252
1075
  expectedLeaseId: params.leaseId,
1253
1076
  expectedGatewayInstanceId: params.gatewayInstanceId
1254
1077
  }));
1255
1078
  if (matchingRoots.length === 0) return {
1256
- inspectedPids: [],
1257
1079
  terminatedPids: [],
1258
1080
  skippedReason: "missing-root"
1259
1081
  };
1260
1082
  if (matchingRoots.length > 1) return {
1261
- inspectedPids: uniquePids(matchingRoots),
1262
1083
  terminatedPids: [],
1263
1084
  skippedReason: "ambiguous-root"
1264
1085
  };
1265
- const listedTree = collectProcessTree(processes, matchingRoots[0].pid);
1266
- const pids = uniquePids(listedTree.toReversed());
1267
- return {
1268
- inspectedPids: uniquePids(listedTree),
1269
- terminatedPids: await terminatePids(pids, params.assertCurrent)
1270
- };
1086
+ return { terminatedPids: await terminatePids(uniquePids(collectProcessTree(processes, matchingRoots[0].pid).toReversed()), params.assertCurrent) };
1271
1087
  }
1272
1088
  /** Reap orphaned OpenClaw-owned ACPX wrapper trees during runtime startup. */
1273
1089
  async function reapStaleOpenClawOwnedAcpxOrphans(params) {
1274
1090
  if (process.platform === "win32") return {
1275
- inspectedPids: [],
1276
1091
  terminatedPids: [],
1277
1092
  skippedReason: "unsupported-platform"
1278
1093
  };
1279
- let processes;
1280
- try {
1281
- processes = await listPlatformProcesses();
1282
- } catch {
1283
- return {
1284
- inspectedPids: [],
1285
- terminatedPids: [],
1286
- skippedReason: "process-list-unavailable"
1287
- };
1288
- }
1289
- const orphanTrees = processes.filter((processInfo) => processInfo.ppid === 1 && !readAcpxProcessLeaseIdentity(processInfo.command) && isOpenClawOwnedAcpxProcessCommand({
1094
+ const processes = await listPlatformProcesses();
1095
+ if (!processes) return {
1096
+ terminatedPids: [],
1097
+ skippedReason: "process-list-unavailable"
1098
+ };
1099
+ return { terminatedPids: await terminatePids(uniquePids(processes.filter((processInfo) => processInfo.ppid === 1 && !readAcpxProcessLeaseIdentity(processInfo.command) && isOpenClawOwnedAcpxProcessCommand({
1290
1100
  command: processInfo.command,
1291
1101
  wrapperRoot: params.wrapperRoot
1292
- })).map((orphan) => collectProcessTree(processes, orphan.pid));
1293
- return {
1294
- inspectedPids: uniquePids(orphanTrees.flat()),
1295
- terminatedPids: await terminatePids(uniquePids(orphanTrees.flatMap((tree) => tree.toReversed())), params.assertCurrent)
1296
- };
1102
+ })).map((orphan) => collectProcessTree(processes, orphan.pid)).flatMap((tree) => tree.toReversed())), params.assertCurrent) };
1297
1103
  }
1298
1104
  //#endregion
1299
1105
  //#region extensions/acpx/src/model-ref.ts
@@ -1511,30 +1317,9 @@ function captureGenerationRecord(generation, record) {
1511
1317
  }
1512
1318
  const acpxGenerationKey = Symbol("openclaw.acpxGeneration");
1513
1319
  const acpxOperationScope = new AsyncLocalStorage();
1514
- function readSessionRecordName(record) {
1515
- return normalizeOptionalString(asOptionalObjectRecord(record)?.name) ?? "";
1516
- }
1517
1320
  function readRecordAgentCommand(record) {
1518
1321
  return record?.agentArgv ?? record?.agentCommand;
1519
1322
  }
1520
- function readRecordCwd(record) {
1521
- return normalizeOptionalString(asOptionalObjectRecord(record)?.cwd);
1522
- }
1523
- function readRecordResetOnNextEnsure(record) {
1524
- return asOptionalObjectRecord(asOptionalObjectRecord(record)?.acpx)?.reset_on_next_ensure === true;
1525
- }
1526
- function readRecordAgentPid(record) {
1527
- const { pid, processId } = asOptionalObjectRecord(record) ?? {};
1528
- const rawPid = pid ?? processId;
1529
- const numericPid = typeof rawPid === "number" ? rawPid : typeof rawPid === "string" ? parseStrictPositiveInteger(rawPid) : void 0;
1530
- return numericPid && Number.isInteger(numericPid) && numericPid > 0 ? numericPid : void 0;
1531
- }
1532
- function readOpenClawLeaseIdFromRecord(record) {
1533
- return normalizeOptionalString(asOptionalObjectRecord(record)?.openclawLeaseId);
1534
- }
1535
- function readOpenClawGatewayInstanceIdFromRecord(record) {
1536
- return normalizeOptionalString(asOptionalObjectRecord(record)?.openclawGatewayInstanceId);
1537
- }
1538
1323
  function extractGeneratedWrapperPath(command) {
1539
1324
  return splitCommandParts(command ?? "").find((part) => (part.split(/[\\/]/).pop() ?? "") === "codex-acp-wrapper.mjs" || (part.split(/[\\/]/).pop() ?? "") === "claude-agent-acp-wrapper.mjs") ?? "";
1540
1325
  }
@@ -1563,11 +1348,11 @@ function createResetAwareSessionStore(baseStore, params) {
1563
1348
  const record = await baseStore.load(sessionId);
1564
1349
  if (scope && record) captureGenerationRecord(scope.generation, record);
1565
1350
  if (!record || !params?.leaseStore || !params.gatewayInstanceId) return record;
1566
- const sessionName = readSessionRecordName(record) || normalized;
1351
+ const sessionName = record.name || normalized;
1567
1352
  const lease = selectCurrentSessionLease({
1568
1353
  leases: await params.leaseStore.listOpen(params.gatewayInstanceId),
1569
1354
  sessionKeys: [sessionName, normalized],
1570
- rootPid: readRecordAgentPid(record)
1355
+ rootPid: record.pid
1571
1356
  });
1572
1357
  if (!lease) return record;
1573
1358
  const leasedRecord = withOpenClawLeaseSessionMetadata(record, lease);
@@ -1589,7 +1374,7 @@ function createResetAwareSessionStore(baseStore, params) {
1589
1374
  }
1590
1375
  let recordToSave = record;
1591
1376
  const launch = params?.launchScope?.getStore();
1592
- const sessionName = readSessionRecordName(record);
1377
+ const sessionName = record.name;
1593
1378
  const agentCommand = readRecordAgentCommand(record);
1594
1379
  const leasedCommand = launch?.leasedCommand ?? agentCommand;
1595
1380
  const leaseIdentity = launch ?? readAcpxProcessLeaseIdentity(leasedCommand);
@@ -1643,12 +1428,12 @@ function createResetAwareSessionStore(baseStore, params) {
1643
1428
  /** Capture OpenClaw wrapper cleanup ownership before a backend close can yield. */
1644
1429
  async function prepareAcpxProcessCleanup(params) {
1645
1430
  const { leaseStore, gatewayInstanceId, wrapperRoot } = params;
1646
- const rootPid = readRecordAgentPid(params.record);
1431
+ const rootPid = params.record?.pid;
1647
1432
  const rootCommand = params.command ? renderAgentCommand(params.command) : void 0;
1648
1433
  const identity = readAcpxProcessLeaseIdentity(params.command);
1649
- const leaseId = readOpenClawLeaseIdFromRecord(params.record) ?? identity?.leaseId;
1650
- const expectedGatewayInstanceId = readOpenClawGatewayInstanceIdFromRecord(params.record) ?? identity?.gatewayInstanceId;
1651
- const sessionKeys = [params.sessionKey, readSessionRecordName(params.record)];
1434
+ const leaseId = params.record?.openclawLeaseId ?? identity?.leaseId;
1435
+ const expectedGatewayInstanceId = params.record?.openclawGatewayInstanceId ?? identity?.gatewayInstanceId;
1436
+ const sessionKeys = [params.sessionKey, params.record?.name ?? ""];
1652
1437
  const openLeases = rootPid && gatewayInstanceId && leaseStore ? await leaseStore.listOpen(gatewayInstanceId) : [];
1653
1438
  const selectedLease = rootPid ? selectCurrentSessionLease({
1654
1439
  leases: openLeases,
@@ -1656,8 +1441,7 @@ async function prepareAcpxProcessCleanup(params) {
1656
1441
  rootPid
1657
1442
  }) : void 0;
1658
1443
  const loadedLease = leaseId ? await leaseStore?.load(leaseId) : void 0;
1659
- const ownedLease = selectedLease ?? (loadedLease && loadedLease.gatewayInstanceId === gatewayInstanceId && (!rootPid || loadedLease.rootPid === rootPid) && sessionKeys.includes(loadedLease.sessionKey) ? loadedLease : void 0);
1660
- const lease = ownedLease ? { ...ownedLease } : void 0;
1444
+ const lease = selectedLease ?? (loadedLease && loadedLease.gatewayInstanceId === gatewayInstanceId && (!rootPid || loadedLease.rootPid === rootPid) && sessionKeys.includes(loadedLease.sessionKey) ? loadedLease : void 0);
1661
1445
  return async () => {
1662
1446
  if (lease && lease.gatewayInstanceId === gatewayInstanceId) {
1663
1447
  await leaseStore?.markState(lease.leaseId, "closing");
@@ -1857,35 +1641,9 @@ function appendCodexAcpConfigOverrides(command, override) {
1857
1641
  JSON.stringify(config)
1858
1642
  ];
1859
1643
  }
1860
- function withManagedToolsMcpSessionEnv(params) {
1861
- const sessionKey = params.sessionKey.trim();
1862
- if (!params.pluginToolsEnabled && !params.openclawToolsEnabled || !sessionKey || !params.mcpServers?.length) return params.mcpServers;
1863
- let changed = false;
1864
- const nextServers = params.mcpServers.map((server) => {
1865
- const isManagedPluginTools = params.pluginToolsEnabled && server.name === ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME;
1866
- const isManagedOpenClawTools = params.openclawToolsEnabled && server.name === ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME;
1867
- if (!isManagedPluginTools && !isManagedOpenClawTools || !("command" in server)) return server;
1868
- changed = true;
1869
- const env = [...server.env.filter((entry) => entry.name !== OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV), {
1870
- name: OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV,
1871
- value: sessionKey
1872
- }];
1873
- return {
1874
- ...server,
1875
- env,
1876
- args: params.agentId ? [
1877
- ...server.args,
1878
- "--openclaw-agent-id",
1879
- params.agentId
1880
- ] : server.args
1881
- };
1882
- });
1883
- return changed ? nextServers : params.mcpServers;
1884
- }
1885
1644
  function resolveBridgeSession(handle) {
1886
1645
  return handle.bridgeSession === void 0 ? handle : handle.bridgeSession;
1887
1646
  }
1888
- /** OpenClaw-managed ACP runtime implementation backed by the upstream acpx runtime. */
1889
1647
  var AcpxRuntime$1 = class {
1890
1648
  constructor(options, testOptions) {
1891
1649
  this.ownerAwareSessions = 1;
@@ -1935,12 +1693,29 @@ var AcpxRuntime$1 = class {
1935
1693
  if (target === null) return [];
1936
1694
  if (!this.managedToolsMcpBridgeEnabled) return servers;
1937
1695
  if (!target) throw new AcpRuntimeError("ACP_SESSION_INIT_FAILED", "ACP tool bridge has no session owner");
1938
- return withManagedToolsMcpSessionEnv({
1939
- pluginToolsEnabled: this.pluginToolsMcpBridgeEnabled,
1940
- openclawToolsEnabled: this.openclawToolsMcpBridgeEnabled,
1941
- mcpServers: servers,
1942
- ...target
1696
+ const sessionKey = target.sessionKey.trim();
1697
+ if (!this.pluginToolsMcpBridgeEnabled && !this.openclawToolsMcpBridgeEnabled || !sessionKey || !servers?.length) return servers;
1698
+ let changed = false;
1699
+ const nextServers = servers.map((server) => {
1700
+ const isManagedPluginTools = this.pluginToolsMcpBridgeEnabled && server.name === ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME;
1701
+ const isManagedOpenClawTools = this.openclawToolsMcpBridgeEnabled && server.name === ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME;
1702
+ if (!isManagedPluginTools && !isManagedOpenClawTools || !("command" in server)) return server;
1703
+ changed = true;
1704
+ const env = [...server.env.filter((entry) => entry.name !== OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV), {
1705
+ name: OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV,
1706
+ value: sessionKey
1707
+ }];
1708
+ return {
1709
+ ...server,
1710
+ env,
1711
+ args: target.agentId ? [
1712
+ ...server.args,
1713
+ "--openclaw-agent-id",
1714
+ target.agentId
1715
+ ] : server.args
1716
+ };
1943
1717
  });
1718
+ return changed ? nextServers : servers;
1944
1719
  },
1945
1720
  processLifecycle: {
1946
1721
  onBeforeSpawn: async (launch) => {
@@ -2033,9 +1808,9 @@ var AcpxRuntime$1 = class {
2033
1808
  const recordId = oneShot ? persistedHandle?.acpxRecordId : sessionKey;
2034
1809
  if (!recordId) return;
2035
1810
  const record = await this.sessionStore.load(recordId);
2036
- if (!record || readRecordResetOnNextEnsure(record)) return;
2037
- if (oneShot && (record.acpxRecordId !== recordId || readSessionRecordName(record) !== sessionKey || record.acpSessionId !== (persistedHandle?.backendSessionId ?? decoded?.backendSessionId) || !record.agentCapabilities?.loadSession && !record.agentCapabilities?.sessionCapabilities?.resume || record.lastPromptAt !== void 0 || record.messages.some((message) => typeof message !== "string" && "User" in message))) return;
2038
- const recordCwd = readRecordCwd(record);
1811
+ if (!record || record.acpx?.reset_on_next_ensure === true) return;
1812
+ if (oneShot && (record.acpxRecordId !== recordId || record.name !== sessionKey || record.acpSessionId !== (persistedHandle?.backendSessionId ?? decoded?.backendSessionId) || !record.agentCapabilities?.loadSession && !record.agentCapabilities?.sessionCapabilities?.resume || record.lastPromptAt !== void 0 || record.messages.some((message) => typeof message !== "string" && "User" in message))) return;
1813
+ const recordCwd = record.cwd?.trim();
2039
1814
  const recordCommand = readRecordAgentCommand(record);
2040
1815
  if (!recordCwd || !recordCommand || path.resolve(recordCwd) !== path.resolve(input.cwd?.trim() || this.cwd) || !oneShot && resumeSessionId && record.acpSessionId !== resumeSessionId) return;
2041
1816
  const lease = readAcpxProcessLeaseIdentity(recordCommand);
@@ -2126,7 +1901,7 @@ var AcpxRuntime$1 = class {
2126
1901
  const record = await this.sessionStore.load(params.handle.acpxRecordId ?? resolveAcpxSessionResource(params.handle));
2127
1902
  return readCodexWrapperStderrTail({
2128
1903
  wrapperRoot: this.wrapperRoot,
2129
- leaseId: readOpenClawLeaseIdFromRecord(record)
1904
+ leaseId: record?.openclawLeaseId
2130
1905
  });
2131
1906
  }
2132
1907
  async findSession(input) {
@@ -2467,36 +2242,6 @@ function resolveAgentProcessEnv() {
2467
2242
  if (process.env.TOKIO_WORKER_THREADS?.trim()) return;
2468
2243
  return { TOKIO_WORKER_THREADS: String(Math.min(availableParallelism(), MAX_ACPX_TOKIO_WORKER_THREADS)) };
2469
2244
  }
2470
- async function createDefaultRuntime(params) {
2471
- const names = await fs$1.readdir(path.join(params.pluginConfig.stateDir, "sessions")).catch((error) => {
2472
- if (error instanceof Error && "code" in error && error.code === "ENOENT") return [];
2473
- throw error;
2474
- });
2475
- const legacyBareSessionKeys = /* @__PURE__ */ new Set();
2476
- for (const name of names) {
2477
- if (!name.endsWith(".json")) continue;
2478
- const recordId = decodeURIComponent(name.slice(0, -5));
2479
- if (!recordId.startsWith("agent:") && !recordId.startsWith(".openclaw-owner-") && !recordId.includes(":oneshot:")) legacyBareSessionKeys.add(recordId.toLowerCase());
2480
- }
2481
- return new AcpxRuntime$1({
2482
- cwd: params.pluginConfig.cwd,
2483
- agentProcessEnv: resolveAgentProcessEnv(),
2484
- openclawLegacyBareSessionKeys: legacyBareSessionKeys,
2485
- openclawGatewayInstanceId: params.gatewayInstanceId,
2486
- openclawProcessLeaseStore: params.processLeaseStore,
2487
- openclawWrapperRoot: params.wrapperRoot,
2488
- sessionStore: createFileSessionStore({ stateDir: params.pluginConfig.stateDir }),
2489
- agentRegistry: createAgentRegistry({ overrides: params.pluginConfig.agents }),
2490
- getProbeAgent: params.getProbeAgent,
2491
- mcpServers: toAcpMcpServers(params.pluginConfig.mcpServers),
2492
- pluginToolsMcpBridgeEnabled: params.pluginConfig.pluginToolsMcpBridge,
2493
- openclawToolsMcpBridgeEnabled: params.pluginConfig.openClawToolsMcpBridge,
2494
- permissionMode: params.pluginConfig.permissionMode,
2495
- nonInteractivePermissions: params.pluginConfig.nonInteractivePermissions,
2496
- elicitationModes: ["form", "url"],
2497
- timeoutMs: resolveAcpxTimerTimeoutMs(params.pluginConfig.timeoutSeconds)
2498
- });
2499
- }
2500
2245
  function formatDoctorFailureMessage(report) {
2501
2246
  const detailText = report.details?.map((detail) => detail.trim()).filter(Boolean).join("; ");
2502
2247
  return detailText ? `${report.message} (${detailText})` : report.message;
@@ -2524,7 +2269,6 @@ async function resolveGatewayInstanceId(openKeyedStore) {
2524
2269
  async function reapOpenAcpxProcessLeases(params) {
2525
2270
  const { assertCurrent } = params;
2526
2271
  const leases = await params.leaseStore.listOpen(params.gatewayInstanceId);
2527
- const inspectedPids = [];
2528
2272
  const terminatedPids = [];
2529
2273
  const legacyWrapperRoots = /* @__PURE__ */ new Set();
2530
2274
  for (const lease of leases) {
@@ -2544,7 +2288,6 @@ async function reapOpenAcpxProcessLeases(params) {
2544
2288
  wrapperRoot: lease.wrapperRoot,
2545
2289
  assertCurrent
2546
2290
  });
2547
- inspectedPids.push(...result.inspectedPids);
2548
2291
  terminatedPids.push(...result.terminatedPids);
2549
2292
  const retryableEvidenceFailure = result.skippedReason === "process-list-unavailable" || result.skippedReason === "unsupported-platform" || pending && (result.skippedReason === "ambiguous-root" || result.skippedReason === "unverified-root" || lease.sessionKey === "openclaw:acpx:probe" && result.skippedReason === "missing-root");
2550
2293
  await params.leaseStore.markState(lease.leaseId, retryableEvidenceFailure ? "open" : result.terminatedPids.length > 0 ? "closed" : "lost");
@@ -2554,13 +2297,9 @@ async function reapOpenAcpxProcessLeases(params) {
2554
2297
  wrapperRoot,
2555
2298
  assertCurrent
2556
2299
  });
2557
- inspectedPids.push(...legacyResult.inspectedPids);
2558
2300
  terminatedPids.push(...legacyResult.terminatedPids);
2559
2301
  }
2560
- return {
2561
- inspectedPids,
2562
- terminatedPids
2563
- };
2302
+ return { terminatedPids };
2564
2303
  }
2565
2304
  function createAcpxRuntimeService(params) {
2566
2305
  let runtime = null;
@@ -2591,7 +2330,6 @@ function createAcpxRuntimeService(params) {
2591
2330
  return;
2592
2331
  }
2593
2332
  const openKeyedStore = params.openKeyedStore;
2594
- if (!openKeyedStore) throw new Error("ACPX runtime service requires plugin keyed state");
2595
2333
  const basePluginConfig = await measureAcpxStartup(ctx, "config.resolve", () => resolveAcpxPluginConfig({
2596
2334
  rawConfig: params.pluginConfig,
2597
2335
  workspaceDir: ctx.workspaceDir,
@@ -2626,14 +2364,38 @@ function createAcpxRuntimeService(params) {
2626
2364
  if (params.startupPurpose !== "inspection") await promote(ctx);
2627
2365
  const getAllowedAgents = params.getAllowedAgents ?? (() => ctx.config.acp?.allowedAgents);
2628
2366
  const getProbeAgent = () => pluginConfig.probeAgent ?? getAllowedAgents()?.map(normalizeLowercaseStringOrEmpty).find(Boolean);
2629
- const startedRuntime = await measureAcpxStartup(ctx, "runtime.create", () => (params.runtimeFactory ?? createDefaultRuntime)({
2630
- pluginConfig,
2631
- getProbeAgent,
2632
- gatewayInstanceId,
2633
- processLeaseStore,
2634
- wrapperRoot,
2635
- logger: ctx.logger
2636
- }));
2367
+ const startedRuntime = await measureAcpxStartup(ctx, "runtime.create", async () => {
2368
+ const names = await fs$1.readdir(path.join(pluginConfig.stateDir, "sessions")).catch((error) => {
2369
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") return [];
2370
+ throw error;
2371
+ });
2372
+ const legacyBareSessionKeys = /* @__PURE__ */ new Set();
2373
+ for (const name of names) {
2374
+ if (!name.endsWith(".json")) continue;
2375
+ const recordId = decodeURIComponent(name.slice(0, -5));
2376
+ if (!recordId.startsWith("agent:") && !recordId.startsWith(".openclaw-owner-") && !recordId.includes(":oneshot:")) legacyBareSessionKeys.add(recordId.toLowerCase());
2377
+ }
2378
+ return new AcpxRuntime$1({
2379
+ cwd: pluginConfig.cwd,
2380
+ agentProcessEnv: resolveAgentProcessEnv(),
2381
+ agentProcessEnvAllow: pluginConfig.agentProcessEnvAllow,
2382
+ agentProcessEnvBlock: pluginConfig.agentProcessEnvBlock,
2383
+ openclawLegacyBareSessionKeys: legacyBareSessionKeys,
2384
+ openclawGatewayInstanceId: gatewayInstanceId,
2385
+ openclawProcessLeaseStore: processLeaseStore,
2386
+ openclawWrapperRoot: wrapperRoot,
2387
+ sessionStore: createFileSessionStore({ stateDir: pluginConfig.stateDir }),
2388
+ agentRegistry: createAgentRegistry({ overrides: pluginConfig.agents }),
2389
+ getProbeAgent,
2390
+ mcpServers: toAcpMcpServers(pluginConfig.mcpServers),
2391
+ pluginToolsMcpBridgeEnabled: pluginConfig.pluginToolsMcpBridge,
2392
+ openclawToolsMcpBridgeEnabled: pluginConfig.openClawToolsMcpBridge,
2393
+ permissionMode: pluginConfig.permissionMode,
2394
+ nonInteractivePermissions: pluginConfig.nonInteractivePermissions,
2395
+ elicitationModes: ["form", "url"],
2396
+ timeoutMs: resolveAcpxTimerTimeoutMs(pluginConfig.timeoutSeconds)
2397
+ });
2398
+ });
2637
2399
  runtime = startedRuntime;
2638
2400
  const shouldProbeRuntime = params.probeAtStartup !== false && shouldProbeRuntimeAtStartup();
2639
2401
  ctx.startupTrace?.detail?.("probe-policy", [["startupProbeEnabledCount", shouldProbeRuntime ? 1 : 0], ["probeAgent", getProbeAgent() ?? "default"]]);