@openclaw/acpx 2026.10.5-beta.4 → 2026.10.10-beta.1

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,18 +1,18 @@
1
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";
2
2
  import { AcpRuntimeError } from "../runtime-api.js";
3
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-DECUY80a.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-duvwZfxk.mjs";
5
5
  import { createRequire } from "node:module";
6
- import { AcpxRuntime, createAgentRegistry, createFileSessionStore, decodeAcpxRuntimeHandleState, isRequestedModelUnsupportedError } from "acpx/runtime";
7
6
  import { finiteSecondsToTimerSafeMilliseconds, parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
8
7
  import fs from "node:fs";
9
- import path, { resolve } from "node:path";
8
+ import path from "node:path";
10
9
  import { asOptionalObjectRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
11
10
  import os, { availableParallelism } from "node:os";
12
11
  import { randomUUID } from "node:crypto";
13
12
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
14
13
  import { escapeRegExp, sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
15
14
  import fs$1 from "node:fs/promises";
15
+ import { AcpxRuntime, createAgentRegistry, createFileSessionStore, decodeAcpxRuntimeHandleState, isRequestedModelUnsupportedError } from "acpx/runtime";
16
16
  import { raceWithTimeout } from "openclaw/plugin-sdk/time-runtime";
17
17
  import { tryReadJson } from "@openclaw/fs-safe/json";
18
18
  import { parse, stringify } from "smol-toml";
@@ -22,244 +22,8 @@ import { AsyncLocalStorage } from "node:async_hooks";
22
22
  import { isDeepStrictEqual } from "node:util";
23
23
  import { redactSensitiveText } from "openclaw/plugin-sdk/security-runtime";
24
24
  import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
25
- //#region extensions/acpx/src/codex-trust-config.ts
26
- function stripTomlComment(line) {
27
- let quote = null;
28
- let escaping = false;
29
- for (let index = 0; index < line.length; index += 1) {
30
- const ch = line[index];
31
- if (escaping) {
32
- escaping = false;
33
- continue;
34
- }
35
- if (quote === "\"" && ch === "\\") {
36
- escaping = true;
37
- continue;
38
- }
39
- if (quote) {
40
- if (ch === quote) quote = null;
41
- continue;
42
- }
43
- if (ch === "'" || ch === "\"") {
44
- quote = ch;
45
- continue;
46
- }
47
- if (ch === "#") return line.slice(0, index);
48
- }
49
- return line;
50
- }
51
- function parseTomlString(value) {
52
- const trimmed = value.trim();
53
- if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) try {
54
- return JSON.parse(trimmed);
55
- } catch {
56
- return;
57
- }
58
- if (trimmed.startsWith("'") && trimmed.endsWith("'")) return trimmed.slice(1, -1);
59
- }
60
- function parseTomlDottedKey(value) {
61
- const parts = [];
62
- let current = "";
63
- let quote = null;
64
- let escaping = false;
65
- for (const ch of value.trim()) {
66
- if (escaping) {
67
- current += ch;
68
- escaping = false;
69
- continue;
70
- }
71
- if (quote === "\"" && ch === "\\") {
72
- current += ch;
73
- escaping = true;
74
- continue;
75
- }
76
- if (quote) {
77
- current += ch;
78
- if (ch === quote) quote = null;
79
- continue;
80
- }
81
- if (ch === "'" || ch === "\"") {
82
- quote = ch;
83
- current += ch;
84
- continue;
85
- }
86
- if (ch === ".") {
87
- parts.push(current.trim());
88
- current = "";
89
- continue;
90
- }
91
- current += ch;
92
- }
93
- if (current.trim()) parts.push(current.trim());
94
- return parts.map((part) => parseTomlString(part) ?? part);
95
- }
96
- function parseProjectHeader(line) {
97
- const parts = parseTableHeader(line);
98
- return parts?.length === 2 && parts[0] === "projects" ? parts[1] : void 0;
99
- }
100
- function parseTrustedInlineProjectEntries(value) {
101
- const trusted = [];
102
- for (const match of value.matchAll(/(?<key>"(?:\\.|[^"\\])*"|'[^']*'|[A-Za-z0-9_\-/.~:]+)\s*=\s*\{(?<body>[^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g)) {
103
- const key = match.groups?.key;
104
- const body = match.groups?.body;
105
- if (!key || !body || !/\btrust_level\s*=\s*["']trusted["']/.test(body)) continue;
106
- const projectPath = parseTomlString(key) ?? key.trim();
107
- if (projectPath) trusted.push(projectPath);
108
- }
109
- return trusted;
110
- }
111
- function extractTrustedCodexProjectPaths(configToml) {
112
- const trusted = /* @__PURE__ */ new Set();
113
- let currentProjectPath;
114
- let inProjectsTable = false;
115
- for (const rawLine of configToml.split(/\r?\n/)) {
116
- const line = stripTomlComment(rawLine).trim();
117
- if (!line) continue;
118
- if (line.startsWith("[")) {
119
- currentProjectPath = parseProjectHeader(line);
120
- inProjectsTable = line === "[projects]";
121
- continue;
122
- }
123
- if (currentProjectPath && /^trust_level\s*=\s*["']trusted["']\s*$/.test(line)) {
124
- trusted.add(currentProjectPath);
125
- continue;
126
- }
127
- const assignment = /^(?<key>"(?:\\.|[^"\\])*"|'[^']*'|[A-Za-z0-9_\-/.~:]+)\s*=\s*(?<value>.+)$/.exec(line);
128
- const rawKey = assignment?.groups?.key;
129
- const rawValue = assignment?.groups?.value;
130
- if (!rawKey || rawValue === void 0) continue;
131
- const key = parseTomlString(rawKey) ?? rawKey;
132
- const value = rawValue.trim();
133
- if (inProjectsTable && /^\{.*\}$/.test(value)) {
134
- if (/\btrust_level\s*=\s*["']trusted["']/.test(value) && key) trusted.add(key);
135
- continue;
136
- }
137
- if (key === "projects" || inProjectsTable) for (const projectPath of parseTrustedInlineProjectEntries(value)) trusted.add(projectPath);
138
- }
139
- return Array.from(trusted);
140
- }
141
- const INHERITED_TOP_LEVEL_CODEX_CONFIG_KEYS = /* @__PURE__ */ new Set([
142
- "model",
143
- "model_provider",
144
- "model_reasoning_effort",
145
- "sandbox_mode"
146
- ]);
147
- const INHERITED_MODEL_PROVIDER_CONFIG_KEYS = /* @__PURE__ */ new Set([
148
- "name",
149
- "base_url",
150
- "wire_api",
151
- "env_key",
152
- "env_key_instructions",
153
- "requires_openai_auth",
154
- "request_max_retries",
155
- "stream_max_retries",
156
- "stream_idle_timeout_ms"
157
- ]);
158
- function parseTableHeader(line) {
159
- const trimmed = line.trim();
160
- if (!trimmed.startsWith("[") || !trimmed.endsWith("]") || trimmed.startsWith("[[")) return;
161
- return parseTomlDottedKey(trimmed.slice(1, -1));
162
- }
163
- function isInheritedModelProviderTable(parts) {
164
- return parts?.[0] === "model_providers" && parts.length === 2;
165
- }
166
- function parseTopLevelAssignmentKey(line) {
167
- return /^(?<key>[A-Za-z0-9_-]+)\s*=\s*(?<value>.+)$/.exec(line)?.groups?.key;
168
- }
169
- function extractInheritedCodexRuntimeConfig(configToml) {
170
- const inheritedLines = [];
171
- let inAnyTable = false;
172
- let inInheritedTable = false;
173
- let pendingInheritedTableHeader = "";
174
- function flushInheritedTableHeader() {
175
- if (!pendingInheritedTableHeader) return;
176
- if (inheritedLines.length > 0 && inheritedLines[inheritedLines.length - 1] !== "") inheritedLines.push("");
177
- inheritedLines.push(pendingInheritedTableHeader);
178
- pendingInheritedTableHeader = "";
179
- }
180
- for (const rawLine of configToml.split(/\r?\n/)) {
181
- const trimmedLine = rawLine.trim();
182
- const semanticLine = stripTomlComment(rawLine).trim();
183
- if (trimmedLine.startsWith("[")) {
184
- const tableParts = parseTableHeader(trimmedLine);
185
- inAnyTable = true;
186
- inInheritedTable = isInheritedModelProviderTable(tableParts);
187
- if (inInheritedTable) pendingInheritedTableHeader = rawLine.trimEnd();
188
- else pendingInheritedTableHeader = "";
189
- continue;
190
- }
191
- if (inInheritedTable) {
192
- if (!semanticLine) continue;
193
- const key = parseTopLevelAssignmentKey(semanticLine);
194
- if (!key || !INHERITED_MODEL_PROVIDER_CONFIG_KEYS.has(key)) continue;
195
- flushInheritedTableHeader();
196
- inheritedLines.push(rawLine.trimEnd());
197
- continue;
198
- }
199
- if (inAnyTable) continue;
200
- const key = parseTopLevelAssignmentKey(semanticLine);
201
- if (!key) continue;
202
- if (!INHERITED_TOP_LEVEL_CODEX_CONFIG_KEYS.has(key)) continue;
203
- inheritedLines.push(rawLine.trimEnd());
204
- }
205
- return inheritedLines.join("\n");
206
- }
207
- function renderIsolatedCodexConfig(params) {
208
- 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));
209
- return [
210
- "# Generated by OpenClaw for Codex ACP sessions.",
211
- params.sourceConfigToml ? extractInheritedCodexRuntimeConfig(params.sourceConfigToml) : "",
212
- ...normalized.flatMap((projectPath) => [
213
- "",
214
- `[projects.${JSON.stringify(projectPath)}]`,
215
- "trust_level = \"trusted\""
216
- ]),
217
- ""
218
- ].filter((line, index, lines) => !(line === "" && lines[index - 1] === "")).join("\n");
219
- }
220
- //#endregion
221
- //#region extensions/acpx/src/codex-auth-bridge.ts
222
- /**
223
- * Prepares isolated Codex and Claude ACP wrapper commands for ACPX. The bridge
224
- * copies safe auth/config state into plugin-owned homes and redacts diagnostics.
225
- */
226
- const CLAUDE_ACP_PACKAGE = "@agentclientprotocol/claude-agent-acp";
227
- const CLAUDE_ACP_BIN = "claude-agent-acp";
25
+ //#region extensions/acpx/src/adapter-wrapper-script.ts
228
26
  const RUN_CONFIGURED_COMMAND_SENTINEL = "--openclaw-run-configured";
229
- const requireFromHere$1 = createRequire(import.meta.url);
230
- function readSelfManifest() {
231
- const manifestPath = path.join(resolveAcpxPluginRoot(import.meta.url), "package.json");
232
- return JSON.parse(fs.readFileSync(manifestPath, "utf8"));
233
- }
234
- function readManifestDependencyVersion(packageName) {
235
- const version = readSelfManifest().dependencies?.[packageName];
236
- if (typeof version !== "string" || version.trim() === "") throw new Error(`Missing ${packageName} dependency version in @openclaw/acpx manifest`);
237
- return version;
238
- }
239
- const CODEX_ACP_PACKAGE_VERSION = readManifestDependencyVersion(CODEX_ACP_PACKAGE);
240
- const CLAUDE_ACP_PACKAGE_VERSION = readManifestDependencyVersion(CLAUDE_ACP_PACKAGE);
241
- function basename(value) {
242
- return value.split(/[\\/]/).pop() ?? value;
243
- }
244
- function resolvePackageBinPath(packageJsonPath, manifest, binName) {
245
- const { bin } = manifest;
246
- const relativeBinPath = typeof bin === "string" ? bin : bin && typeof bin === "object" ? bin[binName] : void 0;
247
- if (typeof relativeBinPath !== "string" || relativeBinPath.trim() === "") return;
248
- return path.resolve(path.dirname(packageJsonPath), relativeBinPath);
249
- }
250
- async function resolveInstalledAcpPackageBinPath(packageName, binName) {
251
- try {
252
- const packageJsonPath = requireFromHere$1.resolve(`${packageName}/package.json`);
253
- const manifest = await tryReadJson(packageJsonPath);
254
- if (manifest?.name !== packageName) return;
255
- const binPath = resolvePackageBinPath(packageJsonPath, manifest, binName);
256
- if (!binPath) return;
257
- await fs$1.access(binPath);
258
- return binPath;
259
- } catch {
260
- return;
261
- }
262
- }
263
27
  const DIAGNOSTIC_REDACTION_RULES = [
264
28
  {
265
29
  source: String.raw`(authorization\s*[:=]\s*bearer\s+)[^\s'"<>]+`,
@@ -375,6 +139,7 @@ import { spawn } from "node:child_process";
375
139
  import { StringDecoder } from "node:string_decoder";
376
140
  import { fileURLToPath } from "node:url";
377
141
 
142
+ function main() {
378
143
  ${params.envSetup}
379
144
  const stderrLogFileNamePrefix = ${params.stderrLogFileNamePrefix ? JSON.stringify(params.stderrLogFileNamePrefix) : "undefined"};
380
145
  const stderrLogMaxChars = 256 * 1024;
@@ -602,7 +367,8 @@ const args =
602
367
 
603
368
  if (!command) {
604
369
  console.error("[openclaw] missing configured ${params.displayName} ACP command");
605
- process.exit(1);
370
+ process.exitCode = 1;
371
+ return;
606
372
  }
607
373
 
608
374
  const child = spawn(command, args, {
@@ -620,6 +386,18 @@ child.stderr?.on("data", (chunk) => {
620
386
  let forceKillTimer;
621
387
  let orphanCleanupStarted = false;
622
388
  let childExitCode = 1;
389
+ let childFailed = false;
390
+ let childClosed = false;
391
+
392
+ function finishWrapper() {
393
+ if (!childClosed || forceKillTimer) {
394
+ return;
395
+ }
396
+ for (const [signal, listener] of signalListeners) {
397
+ process.off(signal, listener);
398
+ }
399
+ process.exitCode = childFailed ? 1 : childExitCode;
400
+ }
623
401
 
624
402
  function killChildTree(signal, options = {}) {
625
403
  if (!child.pid || (!options.force && child.killed)) {
@@ -638,10 +416,11 @@ function killChildTree(signal, options = {}) {
638
416
  child.kill(signal);
639
417
  }
640
418
 
419
+ const signalListeners = new Map();
641
420
  for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
642
- process.once(signal, () => {
643
- killChildTree(signal);
644
- });
421
+ const listener = () => killChildTree(signal);
422
+ signalListeners.set(signal, listener);
423
+ process.on(signal, listener);
645
424
  }
646
425
 
647
426
  const originalParentPid = process.ppid;
@@ -669,27 +448,28 @@ const parentWatcher =
669
448
  // Keep the wrapper alive long enough for stubborn adapters to receive
670
449
  // a forced fallback signal after SIGTERM.
671
450
  forceKillTimer = setTimeout(() => {
672
- killChildTree("SIGKILL", { force: true });
673
- childExitCode = 1;
451
+ try {
452
+ killChildTree("SIGKILL", { force: true });
453
+ } finally {
454
+ forceKillTimer = undefined;
455
+ childExitCode = 1;
456
+ finishWrapper();
457
+ }
674
458
  }, 1_500);
675
459
  }, 1_000);
676
460
  parentWatcher?.unref?.();
677
461
 
678
462
  child.on("error", (error) => {
679
463
  console.error(\`[openclaw] failed to launch ${params.displayName} ACP wrapper: \${error.message}\`);
680
- process.exit(1);
464
+ childFailed = true;
681
465
  });
682
466
 
683
467
  child.on("exit", (code, signal) => {
684
- if (parentWatcher) {
685
- clearInterval(parentWatcher);
686
- }
468
+ // Descendants can retain stdio after the direct child exits. Keep watching
469
+ // the wrapper parent until close, including after this status notification.
687
470
  if (orphanCleanupStarted) {
688
471
  return;
689
472
  }
690
- if (forceKillTimer) {
691
- clearTimeout(forceKillTimer);
692
- }
693
473
  if (code !== null) {
694
474
  childExitCode = code;
695
475
  return;
@@ -699,10 +479,254 @@ child.on("exit", (code, signal) => {
699
479
 
700
480
  child.on("close", () => {
701
481
  finishStderrLog();
702
- process.exit(childExitCode);
482
+ if (parentWatcher) {
483
+ clearInterval(parentWatcher);
484
+ }
485
+ childClosed = true;
486
+ finishWrapper();
703
487
  });
488
+ }
489
+ main();
704
490
  `;
705
491
  }
492
+ //#endregion
493
+ //#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
+ const INHERITED_TOP_LEVEL_CODEX_CONFIG_KEYS = /* @__PURE__ */ new Set([
610
+ "model",
611
+ "model_provider",
612
+ "model_reasoning_effort",
613
+ "sandbox_mode"
614
+ ]);
615
+ const INHERITED_MODEL_PROVIDER_CONFIG_KEYS = /* @__PURE__ */ new Set([
616
+ "name",
617
+ "base_url",
618
+ "wire_api",
619
+ "env_key",
620
+ "env_key_instructions",
621
+ "requires_openai_auth",
622
+ "request_max_retries",
623
+ "stream_max_retries",
624
+ "stream_idle_timeout_ms"
625
+ ]);
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
+ 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));
677
+ return [
678
+ "# Generated by OpenClaw for Codex ACP sessions.",
679
+ params.sourceConfigToml ? extractInheritedCodexRuntimeConfig(params.sourceConfigToml) : "",
680
+ ...normalized.flatMap((projectPath) => [
681
+ "",
682
+ `[projects.${JSON.stringify(projectPath)}]`,
683
+ "trust_level = \"trusted\""
684
+ ]),
685
+ ""
686
+ ].filter((line, index, lines) => !(line === "" && lines[index - 1] === "")).join("\n");
687
+ }
688
+ //#endregion
689
+ //#region extensions/acpx/src/codex-auth-bridge.ts
690
+ /**
691
+ * Prepares isolated Codex and Claude ACP wrapper commands for ACPX. The bridge
692
+ * copies safe auth/config state into plugin-owned homes and redacts diagnostics.
693
+ */
694
+ const CLAUDE_ACP_PACKAGE = "@agentclientprotocol/claude-agent-acp";
695
+ const CLAUDE_ACP_BIN = "claude-agent-acp";
696
+ const requireFromHere$1 = createRequire(import.meta.url);
697
+ function readSelfManifest() {
698
+ const manifestPath = path.join(resolveAcpxPluginRoot(import.meta.url), "package.json");
699
+ return JSON.parse(fs.readFileSync(manifestPath, "utf8"));
700
+ }
701
+ function readManifestDependencyVersion(packageName) {
702
+ const version = readSelfManifest().dependencies?.[packageName];
703
+ if (typeof version !== "string" || version.trim() === "") throw new Error(`Missing ${packageName} dependency version in @openclaw/acpx manifest`);
704
+ return version;
705
+ }
706
+ const CODEX_ACP_PACKAGE_VERSION = readManifestDependencyVersion(CODEX_ACP_PACKAGE);
707
+ const CLAUDE_ACP_PACKAGE_VERSION = readManifestDependencyVersion(CLAUDE_ACP_PACKAGE);
708
+ function basename(value) {
709
+ return value.split(/[\\/]/).pop() ?? value;
710
+ }
711
+ function resolvePackageBinPath(packageJsonPath, manifest, binName) {
712
+ const { bin } = manifest;
713
+ const relativeBinPath = typeof bin === "string" ? bin : bin && typeof bin === "object" ? bin[binName] : void 0;
714
+ if (typeof relativeBinPath !== "string" || relativeBinPath.trim() === "") return;
715
+ return path.resolve(path.dirname(packageJsonPath), relativeBinPath);
716
+ }
717
+ async function resolveInstalledAcpPackageBinPath(packageName, binName) {
718
+ try {
719
+ const packageJsonPath = requireFromHere$1.resolve(`${packageName}/package.json`);
720
+ const manifest = await tryReadJson(packageJsonPath);
721
+ if (manifest?.name !== packageName) return;
722
+ const binPath = resolvePackageBinPath(packageJsonPath, manifest, binName);
723
+ if (!binPath) return;
724
+ await fs$1.access(binPath);
725
+ return binPath;
726
+ } catch {
727
+ return;
728
+ }
729
+ }
706
730
  function buildCodexAcpWrapperScript(installedBinPath) {
707
731
  return buildAdapterWrapperScript({
708
732
  displayName: "Codex",
@@ -776,7 +800,8 @@ if (openClawCodexConfigs.length > 0) {
776
800
  existingCodexConfig = parsedCodexConfig;
777
801
  } catch {
778
802
  console.error("[openclaw] CODEX_CONFIG must be a valid JSON object");
779
- process.exit(1);
803
+ process.exitCode = 1;
804
+ return;
780
805
  }
781
806
  }
782
807
  for (const openClawCodexConfig of openClawCodexConfigs) {
@@ -792,7 +817,8 @@ if (openClawCodexConfigs.length > 0) {
792
817
  existingCodexConfig = mergeCodexConfig(existingCodexConfig, parsedOpenClawCodexConfig);
793
818
  } catch {
794
819
  console.error("[openclaw] invalid generated Codex ACP startup config");
795
- process.exit(1);
820
+ process.exitCode = 1;
821
+ return;
796
822
  }
797
823
  }
798
824
  env.CODEX_CONFIG = JSON.stringify(existingCodexConfig);
@@ -979,7 +1005,7 @@ async function prepareAcpxCodexAuthConfig(params) {
979
1005
  ...params.pluginConfig,
980
1006
  agents: {
981
1007
  ...params.pluginConfig.agents,
982
- codex: buildWrapperCommand(wrapperPath, codexLaunch?.args ?? [RUN_CONFIGURED_COMMAND_SENTINEL, ...splitCommandParts(configuredCodexCommand ?? [])]),
1008
+ codex: buildWrapperCommand(wrapperPath, codexLaunch?.args ?? ["--openclaw-run-configured", ...splitCommandParts(configuredCodexCommand ?? [])]),
983
1009
  claude: buildClaudeAcpWrapperCommand(claudeWrapperPath, configuredClaudeCommand)
984
1010
  }
985
1011
  };
@@ -1452,7 +1478,6 @@ var AcpxRuntimeProbe = class {
1452
1478
  const runtime = this.params.createRuntime(agent);
1453
1479
  try {
1454
1480
  const report = await this.params.runWithLease(agent, () => runtime.doctor());
1455
- this.params.assertRunning();
1456
1481
  this.health = {
1457
1482
  agent,
1458
1483
  ok: report.ok
@@ -1536,7 +1561,6 @@ function createResetAwareSessionStore(baseStore, params) {
1536
1561
  const normalized = sessionId.trim();
1537
1562
  if (normalized && freshSessionKeys.has(normalized)) return;
1538
1563
  const record = await baseStore.load(sessionId);
1539
- if (scope?.generation.retired || freshSessionKeys.has(scope?.generation.resource ?? normalized)) return;
1540
1564
  if (scope && record) captureGenerationRecord(scope.generation, record);
1541
1565
  if (!record || !params?.leaseStore || !params.gatewayInstanceId) return record;
1542
1566
  const sessionName = readSessionRecordName(record) || normalized;
@@ -1546,7 +1570,6 @@ function createResetAwareSessionStore(baseStore, params) {
1546
1570
  rootPid: readRecordAgentPid(record)
1547
1571
  });
1548
1572
  if (!lease) return record;
1549
- if (scope?.generation.retired) return;
1550
1573
  const leasedRecord = withOpenClawLeaseSessionMetadata(record, lease);
1551
1574
  if (scope) captureGenerationRecord(scope.generation, leasedRecord);
1552
1575
  return leasedRecord;
@@ -1575,7 +1598,6 @@ function createResetAwareSessionStore(baseStore, params) {
1575
1598
  wrapperRoot: params.wrapperRoot
1576
1599
  })) {
1577
1600
  const existing = await params.leaseStore.load(leaseIdentity.leaseId);
1578
- if (scope?.generation.retired) return;
1579
1601
  if (!existing || existing.gatewayInstanceId === leaseIdentity.gatewayInstanceId && existing.sessionKey === sessionName && existing.wrapperRoot === params.wrapperRoot) {
1580
1602
  const adoptingLease = Boolean(launch && !isDeepStrictEqual(splitCommandParts(launch.resolvedCommand), splitCommandParts(launch.leasedCommand)));
1581
1603
  const persistedCommand = launch && !adoptingLease ? launch.resolvedCommand : leasedCommand;
@@ -1952,7 +1974,7 @@ var AcpxRuntime$1 = class {
1952
1974
  });
1953
1975
  }
1954
1976
  async runInGeneration(target, scope, run) {
1955
- const release = this.generationRegistry.retainGenerationOperation(scope.generation, scope.recordId ?? target.acpxRecordId ?? scope.generation.resource);
1977
+ const release = this.generationRegistry.retainGenerationOperation(scope.generation, target.acpxRecordId ?? scope.generation.resource);
1956
1978
  try {
1957
1979
  return await this.sessionScope.run(resolveBridgeSession(target), () => acpxOperationScope.run(scope, run));
1958
1980
  } finally {
@@ -1969,13 +1991,9 @@ var AcpxRuntime$1 = class {
1969
1991
  }
1970
1992
  async loadOperationSnapshotForHandle(handle, generation, allowRetired = false) {
1971
1993
  const resource = generation.resource;
1972
- if (!allowRetired) this.generationRegistry.assertCurrentGeneration(generation);
1973
1994
  const ownedRecord = generation.records.get(handle.acpxRecordId ?? resource);
1974
- if (ownedRecord && (handle.acpxRecordId && ownedRecord.acpxRecordId !== handle.acpxRecordId || handle.backendSessionId && ownedRecord.acpSessionId && ownedRecord.acpSessionId !== handle.backendSessionId)) throw new AcpRuntimeError("ACP_TURN_FAILED", "ACP handle no longer owns this runtime generation.");
1975
- let record = allowRetired ? generation.retired ? ownedRecord : await this.sessionStore.loadForClose(handle.acpxRecordId ?? resource) : await acpxOperationScope.run({ generation }, () => this.sessionStore.load(handle.acpxRecordId ?? resource));
1976
- if (allowRetired && generation.retired && ownedRecord) record = ownedRecord;
1995
+ const record = allowRetired ? generation.retired ? ownedRecord : await this.sessionStore.loadForClose(handle.acpxRecordId ?? resource) : await acpxOperationScope.run({ generation }, () => this.sessionStore.load(handle.acpxRecordId ?? resource));
1977
1996
  if (allowRetired && record) captureGenerationRecord(generation, record);
1978
- if (!allowRetired) this.generationRegistry.assertCurrentGeneration(generation);
1979
1997
  if (record && (handle.acpxRecordId && handle.acpxRecordId !== record.acpxRecordId || handle.backendSessionId && record.acpSessionId && handle.backendSessionId !== record.acpSessionId)) throw new AcpRuntimeError("ACP_TURN_FAILED", "ACP handle no longer owns this runtime record.");
1980
1998
  const command = readRecordAgentCommand(record) ?? resolveAgentCommand({
1981
1999
  agentName: readAgentFromHandle(handle),
@@ -1987,7 +2005,6 @@ var AcpxRuntime$1 = class {
1987
2005
  if (identity.gatewayInstanceId !== this.gatewayInstanceId) throw new AcpRuntimeError("ACP_TURN_FAILED", `ACPX process lease ${identity.leaseId} belongs to another gateway`);
1988
2006
  if (lease && (lease.gatewayInstanceId !== identity.gatewayInstanceId || lease.sessionKey !== resolveAcpxSessionResource(handle) || lease.wrapperRoot !== this.wrapperRoot)) throw new AcpRuntimeError("ACP_TURN_FAILED", `ACPX process lease ${identity.leaseId} belongs to another session`);
1989
2007
  }
1990
- if (!allowRetired) this.generationRegistry.assertCurrentGeneration(generation);
1991
2008
  return {
1992
2009
  record,
1993
2010
  command,
@@ -1999,32 +2016,38 @@ var AcpxRuntime$1 = class {
1999
2016
  return await this.runInGeneration(handle, { generation }, async () => {
2000
2017
  const snapshot = await this.loadOperationSnapshotForHandle(handle, generation);
2001
2018
  this.generationRegistry.assertCurrentGeneration(generation);
2002
- return await this.runInGeneration(handle, {
2003
- generation,
2004
- recordId: snapshot.record?.acpxRecordId
2005
- }, () => run(snapshot));
2019
+ return await run(snapshot);
2006
2020
  });
2007
2021
  }
2008
2022
  resolveDelegateForOperationSnapshot(handle, snapshot) {
2009
2023
  return this.generationRegistry.resolveDelegate(snapshot.generation, snapshot.generation.nativeTools ?? resolveBridgeSession(handle)?.native === true);
2010
2024
  }
2011
- async readReusablePersistentSessionCommand(params) {
2012
- if (params.mode !== "persistent" || !params.command) return;
2013
- const existing = await this.sessionStore.load(params.sessionKey);
2014
- if (!existing || readRecordResetOnNextEnsure(existing)) return;
2015
- const recordCwd = readRecordCwd(existing);
2016
- if (!recordCwd || resolve(recordCwd) !== resolve(params.cwd?.trim() || this.cwd)) return;
2017
- const recordCommand = readRecordAgentCommand(existing);
2018
- if (!recordCommand) return;
2019
- const leaseIdentity = readAcpxProcessLeaseIdentity(recordCommand);
2020
- if (leaseIdentity && leaseIdentity.gatewayInstanceId !== this.gatewayInstanceId) return;
2021
- const stableRecordCommand = leaseIdentity ? withAcpxLeaseArgs({
2022
- command: params.command,
2023
- leaseId: leaseIdentity.leaseId,
2024
- gatewayInstanceId: leaseIdentity.gatewayInstanceId
2025
- }) : params.command;
2026
- if (!isDeepStrictEqual(splitCommandParts(recordCommand), splitCommandParts(stableRecordCommand))) return;
2027
- return !params.resumeSessionId || existing.acpSessionId === params.resumeSessionId ? recordCommand : void 0;
2025
+ async readReusableSession(input, command) {
2026
+ const { persistedHandle, sessionKey, resumeSessionId } = input;
2027
+ const oneShot = input.mode === "oneshot";
2028
+ const decoded = persistedHandle && decodeAcpxRuntimeHandleState(persistedHandle.runtimeSessionName);
2029
+ if (!command || oneShot && (resumeSessionId || persistedHandle?.backend !== "acpx" || !persistedHandle.acpxRecordId || decoded?.mode !== "oneshot" || decoded.name !== sessionKey || decoded.acpxRecordId !== persistedHandle.acpxRecordId || decoded.agent !== normalizeOptionalLowercaseString(input.agent))) return;
2030
+ const recordId = oneShot ? persistedHandle?.acpxRecordId : sessionKey;
2031
+ if (!recordId) return;
2032
+ const record = await this.sessionStore.load(recordId);
2033
+ if (!record || readRecordResetOnNextEnsure(record)) return;
2034
+ 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;
2035
+ const recordCwd = readRecordCwd(record);
2036
+ const recordCommand = readRecordAgentCommand(record);
2037
+ if (!recordCwd || !recordCommand || path.resolve(recordCwd) !== path.resolve(input.cwd?.trim() || this.cwd) || !oneShot && resumeSessionId && record.acpSessionId !== resumeSessionId) return;
2038
+ const lease = readAcpxProcessLeaseIdentity(recordCommand);
2039
+ const ownLease = !lease || lease.gatewayInstanceId === this.gatewayInstanceId;
2040
+ if (!oneShot && !ownLease) return;
2041
+ const expectedCommand = lease ? withAcpxLeaseArgs({
2042
+ command,
2043
+ leaseId: lease.leaseId,
2044
+ gatewayInstanceId: lease.gatewayInstanceId
2045
+ }) : command;
2046
+ if (!isDeepStrictEqual(splitCommandParts(recordCommand), splitCommandParts(expectedCommand))) return;
2047
+ return {
2048
+ reusableCommand: ownLease ? recordCommand : void 0,
2049
+ resumeSessionId: oneShot ? record.acpSessionId : void 0
2050
+ };
2028
2051
  }
2029
2052
  async runWithLaunchLease(params) {
2030
2053
  if (!params.command || !this.wrapperRoot || !this.gatewayInstanceId || !this.processLeaseStore || !isOpenClawLeaseAwareAcpxProcessCommand({
@@ -2111,7 +2134,6 @@ var AcpxRuntime$1 = class {
2111
2134
  sessionKey: resource,
2112
2135
  agent: input.agent
2113
2136
  });
2114
- this.generationRegistry.assertCurrentGeneration(generation);
2115
2137
  generation.admitted ||= Boolean(handle);
2116
2138
  return handle ? {
2117
2139
  ...handle,
@@ -2183,26 +2205,28 @@ var AcpxRuntime$1 = class {
2183
2205
  model: claudeModelOverride
2184
2206
  } : effectiveInput;
2185
2207
  const stableLaunchCommand = codexModelOverride && command ? appendCodexAcpConfigOverrides(command, codexModelOverride) : command;
2186
- const reusableCommand = await this.readReusablePersistentSessionCommand({
2187
- sessionKey: input.sessionKey,
2188
- mode: input.mode,
2189
- cwd: input.cwd,
2190
- command: stableLaunchCommand,
2191
- resumeSessionId: input.resumeSessionId
2192
- });
2208
+ const restoration = await this.readReusableSession(input, stableLaunchCommand);
2209
+ this.generationRegistry.assertCurrentGeneration(generation);
2210
+ const restoredInput = restoration?.resumeSessionId ? {
2211
+ ...ensureInput,
2212
+ resumeSessionId: restoration.resumeSessionId
2213
+ } : ensureInput;
2193
2214
  return {
2194
2215
  ...await this.runWithLaunchLease({
2195
- agent: ensureInput.agent,
2216
+ agent: restoredInput.agent,
2196
2217
  sessionKey: ensureInput.sessionKey,
2197
2218
  command: stableLaunchCommand,
2198
- reusableCommand,
2219
+ reusableCommand: restoration?.reusableCommand,
2199
2220
  run: () => this.withCodexWrapperDiagnostics({
2200
2221
  command: stableLaunchCommand,
2201
2222
  fallbackCode: "ACP_SESSION_INIT_FAILED",
2202
- run: () => codexModelOverride ? delegate.ensureSession(withAcpxSessionOptions(ensureInput)) : ensureSessionWithModelRef((request) => {
2223
+ run: () => {
2203
2224
  this.generationRegistry.assertCurrentGeneration(generation);
2204
- return delegate.ensureSession(request);
2205
- }, ensureInput)
2225
+ return codexModelOverride ? delegate.ensureSession(withAcpxSessionOptions(restoredInput)) : ensureSessionWithModelRef((request) => {
2226
+ this.generationRegistry.assertCurrentGeneration(generation);
2227
+ return delegate.ensureSession(request);
2228
+ }, restoredInput);
2229
+ }
2206
2230
  })
2207
2231
  }),
2208
2232
  ...logicalTarget,
@@ -2242,7 +2266,6 @@ var AcpxRuntime$1 = class {
2242
2266
  });
2243
2267
  const turnPromise = this.runWithOperationSnapshot(input.handle, (snapshot) => {
2244
2268
  const { command, generation } = snapshot;
2245
- this.generationRegistry.assertCurrentGeneration(generation);
2246
2269
  const delegate = this.resolveDelegateForOperationSnapshot(input.handle, snapshot);
2247
2270
  return this.sessionScope.run(resolveBridgeSession(input.handle), () => acpxOperationScope.run({ generation }, () => withTurnDiagnostics(command, async () => {
2248
2271
  const release = this.generationRegistry.retainGenerationOperation(generation, snapshot.record?.acpxRecordId ?? input.handle.acpxRecordId ?? generation.resource);
@@ -2504,9 +2527,7 @@ async function reapOpenAcpxProcessLeases(params) {
2504
2527
  for (const lease of leases) {
2505
2528
  const pending = lease.rootPid <= 0;
2506
2529
  if (pending) legacyWrapperRoots.add(lease.wrapperRoot);
2507
- assertCurrent?.();
2508
2530
  await params.leaseStore.markState(lease.leaseId, "closing");
2509
- assertCurrent?.();
2510
2531
  const result = pending ? await cleanupOpenClawOwnedAcpxPendingLease({
2511
2532
  leaseId: lease.leaseId,
2512
2533
  gatewayInstanceId: lease.gatewayInstanceId,
@@ -2523,11 +2544,9 @@ async function reapOpenAcpxProcessLeases(params) {
2523
2544
  inspectedPids.push(...result.inspectedPids);
2524
2545
  terminatedPids.push(...result.terminatedPids);
2525
2546
  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");
2526
- assertCurrent?.();
2527
2547
  await params.leaseStore.markState(lease.leaseId, retryableEvidenceFailure ? "open" : result.terminatedPids.length > 0 ? "closed" : "lost");
2528
2548
  }
2529
2549
  for (const wrapperRoot of legacyWrapperRoots) {
2530
- assertCurrent?.();
2531
2550
  const legacyResult = await reapStaleOpenClawOwnedAcpxOrphans({
2532
2551
  wrapperRoot,
2533
2552
  assertCurrent
@@ -2556,11 +2575,9 @@ function createAcpxRuntimeService(params) {
2556
2575
  assertCurrent();
2557
2576
  recoveryPromise ??= measureAcpxStartup(ctx, "process-leases.reap", async () => {
2558
2577
  const result = await recover(assertCurrent);
2559
- assertCurrent();
2560
2578
  if (result.terminatedPids.length > 0) ctx.logger.info(`reaped ${result.terminatedPids.length} stale OpenClaw-owned ACPX processes`);
2561
2579
  });
2562
2580
  await recoveryPromise;
2563
- assertCurrent();
2564
2581
  };
2565
2582
  return {
2566
2583
  id: "acpx-runtime",
@@ -2626,14 +2643,11 @@ function createAcpxRuntimeService(params) {
2626
2643
  ctx.logger.info(`embedded acpx runtime backend registered (cwd: ${pluginConfig.cwd})`);
2627
2644
  });
2628
2645
  if (!shouldProbeRuntime) return;
2629
- lifecycleRevision += 1;
2630
- const currentRevision = lifecycleRevision;
2631
2646
  try {
2632
2647
  const timeoutSeconds = pluginConfig.timeoutSeconds ?? 120;
2633
2648
  const doctorReport = await measureAcpxStartup(ctx, "probe.availability", () => raceWithTimeout(startedRuntime.doctor(), resolveAcpxTimerTimeoutMs(timeoutSeconds) ?? 1, () => {
2634
2649
  throw new Error(`embedded acpx runtime backend startup check timed out after ${timeoutSeconds}s`);
2635
2650
  }, { ref: false }));
2636
- if (currentRevision !== lifecycleRevision) return;
2637
2651
  if (doctorReport.ok) {
2638
2652
  ctx.startupTrace?.detail?.("probe.result", [["healthyCount", 1]]);
2639
2653
  ctx.logger.info("embedded acpx runtime backend ready");
@@ -2642,7 +2656,6 @@ function createAcpxRuntimeService(params) {
2642
2656
  ctx.startupTrace?.detail?.("probe.result", [["healthyCount", 0]]);
2643
2657
  ctx.logger.warn(`embedded acpx runtime backend check failed: ${formatDoctorFailureMessage(doctorReport)}`);
2644
2658
  } catch (err) {
2645
- if (currentRevision !== lifecycleRevision) return;
2646
2659
  ctx.startupTrace?.detail?.("probe.result", [["healthyCount", 0]]);
2647
2660
  ctx.logger.warn(`embedded acpx runtime setup failed: ${formatErrorMessage(err)}`);
2648
2661
  }