@openclaw/acpx 2026.7.2-beta.7 → 2026.7.33

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,20 +1,18 @@
1
- import { _ as splitCommandParts, a as hashAcpxProcessCommand, l as readAcpxProcessLeaseIdentity, r as createAcpxProcessLeaseId, u as withAcpxLeaseEnvironment } from "./process-lease-DSLDgiNl.js";
2
- import { AcpRuntimeError } from "./runtime-api.js";
3
- import { c as CODEX_ACP_PACKAGE, n as isOpenClawLeaseAwareAcpxProcessCommand, t as cleanupOpenClawOwnedAcpxProcessTree, u as OPENCLAW_CODEX_CONFIG_ARG } from "./process-reaper-DFwbcdPa.js";
4
- import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
5
- import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
6
- import { sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
1
+ import { i as createAcpxProcessLeaseId, o as hashAcpxProcessCommand, u as withAcpxLeaseEnvironment } from "./process-lease-DiKkFj6F.mjs";
2
+ import { AcpRuntimeError } from "../runtime-api.js";
3
+ import { i as splitCommandParts, n as cleanupOpenClawOwnedAcpxProcessTree, r as isOpenClawLeaseAwareAcpxProcessCommand } from "./service-CE4bgxXH.mjs";
7
4
  import fs from "node:fs/promises";
8
5
  import path, { resolve } from "node:path";
6
+ import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
9
7
  import { AsyncLocalStorage } from "node:async_hooks";
10
8
  import { ACPX_BACKEND_ID, AcpxRuntime as AcpxRuntime$1, createAcpRuntime, createAgentRegistry, createFileSessionStore, decodeAcpxRuntimeHandleState, encodeAcpxRuntimeHandleState, isRequestedModelUnsupportedError } from "acpx/runtime";
9
+ import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
11
10
  import { redactSensitiveText } from "openclaw/plugin-sdk/security-runtime";
12
11
  //#region extensions/acpx/src/runtime.ts
13
12
  /**
14
13
  * OpenClaw ACPX runtime adapter. It wraps the upstream acpx runtime with
15
14
  * OpenClaw session metadata, lease tracking, model scoping, and cleanup policy.
16
15
  */
17
- const ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME = "openclaw-plugin-tools";
18
16
  const ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME = "openclaw-tools";
19
17
  const OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV = "OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY";
20
18
  function withOpenClawManagedTurnTimeout(input) {
@@ -50,7 +48,8 @@ function isGenericInternalAcpError(error) {
50
48
  async function readCodexWrapperStderrTail(params) {
51
49
  if (!params.wrapperRoot || !params.leaseId) return "";
52
50
  try {
53
- return compactDiagnosticText(redactSensitiveText(sliceUtf16Safe(await fs.readFile(path.join(params.wrapperRoot, codexWrapperStderrLogFileName(params.leaseId)), "utf8"), -6e3)));
51
+ const text = await fs.readFile(path.join(params.wrapperRoot, codexWrapperStderrLogFileName(params.leaseId)), "utf8");
52
+ return compactDiagnosticText(redactSensitiveText(text.slice(-6e3)));
54
53
  } catch {
55
54
  return "";
56
55
  }
@@ -128,42 +127,29 @@ function createResetAwareSessionStore(baseStore, params) {
128
127
  let recordToSave = record;
129
128
  const launch = params?.launchScope?.getStore();
130
129
  const sessionName = readSessionRecordName(record);
130
+ const rootPid = readRecordAgentPid(record);
131
131
  const agentCommand = readRecordAgentCommand(record);
132
- const leasedCommand = launch?.leasedCommand ?? agentCommand;
133
- const leaseIdentity = launch ?? readAcpxProcessLeaseIdentity(leasedCommand);
134
- if (params?.leaseStore && params.gatewayInstanceId && params.wrapperRoot && (!launch || sessionName === launch.sessionKey) && leasedCommand && leaseIdentity?.gatewayInstanceId === params.gatewayInstanceId && isOpenClawLeaseAwareAcpxProcessCommand({
135
- command: leasedCommand,
136
- wrapperRoot: params.wrapperRoot
137
- })) {
138
- const existing = await params.leaseStore.load(leaseIdentity.leaseId);
139
- if (!existing || existing.gatewayInstanceId === leaseIdentity.gatewayInstanceId && existing.sessionKey === sessionName && existing.wrapperRoot === params.wrapperRoot) {
140
- const lifecycleRecord = Boolean(launch && launch.resolvedCommand !== launch.leasedCommand) ? {
141
- ...record,
142
- pid: void 0,
143
- processId: void 0,
144
- agentStartedAt: void 0
145
- } : record;
146
- const rootPid = readRecordAgentPid(lifecycleRecord);
147
- if (rootPid) await params.leaseStore.save({
148
- leaseId: leaseIdentity.leaseId,
149
- gatewayInstanceId: leaseIdentity.gatewayInstanceId,
150
- sessionKey: sessionName,
151
- wrapperRoot: params.wrapperRoot,
152
- wrapperPath: extractGeneratedWrapperPath(leasedCommand),
153
- rootPid,
154
- ...existing?.rootPid === rootPid && existing.processGroupId ? { processGroupId: existing.processGroupId } : {},
155
- commandHash: hashAcpxProcessCommand(leasedCommand),
156
- startedAt: existing?.rootPid === rootPid ? existing.startedAt : Date.now(),
157
- state: "open"
158
- });
159
- recordToSave = withOpenClawLeaseSessionMetadata({
160
- ...lifecycleRecord,
161
- agentCommand: leasedCommand
162
- }, {
163
- openclawLeaseId: leaseIdentity.leaseId,
164
- openclawGatewayInstanceId: leaseIdentity.gatewayInstanceId
165
- });
166
- }
132
+ const stableAgentCommand = launch?.stableCommand ?? agentCommand;
133
+ if (launch && params?.leaseStore && sessionName === launch.sessionKey && rootPid && stableAgentCommand) {
134
+ const lease = {
135
+ leaseId: launch.leaseId,
136
+ gatewayInstanceId: launch.gatewayInstanceId,
137
+ sessionKey: launch.sessionKey,
138
+ wrapperRoot: launch.wrapperRoot,
139
+ wrapperPath: extractGeneratedWrapperPath(stableAgentCommand),
140
+ rootPid,
141
+ commandHash: hashAcpxProcessCommand(stableAgentCommand),
142
+ startedAt: Date.now(),
143
+ state: "open"
144
+ };
145
+ await params.leaseStore.save(lease);
146
+ recordToSave = withOpenClawLeaseSessionMetadata({
147
+ ...record,
148
+ agentCommand: stableAgentCommand
149
+ }, {
150
+ openclawLeaseId: launch.leaseId,
151
+ openclawGatewayInstanceId: launch.gatewayInstanceId
152
+ });
167
153
  }
168
154
  await baseStore.save(recordToSave);
169
155
  if (sessionName) freshSessionKeys.delete(sessionName);
@@ -179,6 +165,12 @@ const OPENCLAW_BRIDGE_SUBCOMMAND = "acp";
179
165
  const CODEX_ACP_AGENT_ID = "codex";
180
166
  const CODEX_ACP_OPENCLAW_PREFIX = "openai/";
181
167
  const CLAUDE_ACP_OPENCLAW_PREFIX = "anthropic/";
168
+ const CODEX_ACP_REASONING_EFFORTS = /* @__PURE__ */ new Set([
169
+ "low",
170
+ "medium",
171
+ "high",
172
+ "xhigh"
173
+ ]);
182
174
  const CODEX_ACP_THINKING_ALIASES = /* @__PURE__ */ new Map([
183
175
  ["off", void 0],
184
176
  ["minimal", "low"],
@@ -222,14 +214,9 @@ function isEnvAssignment(value) {
222
214
  return /^[A-Za-z_][A-Za-z0-9_]*=/.test(value);
223
215
  }
224
216
  function unwrapEnvCommand(parts) {
225
- const command = parts.at(0);
226
- if (!command || basename(command) !== "env") return parts;
217
+ if (!parts.length || basename(parts[0]) !== "env") return parts;
227
218
  let index = 1;
228
- while (true) {
229
- const part = parts.at(index);
230
- if (!part || !isEnvAssignment(part)) break;
231
- index += 1;
232
- }
219
+ while (index < parts.length && isEnvAssignment(parts[index])) index += 1;
233
220
  return parts.slice(index);
234
221
  }
235
222
  function matchesExecutableName(value, executableName) {
@@ -264,7 +251,7 @@ function isOpenClawBridgeCommand(command) {
264
251
  }
265
252
  function isCodexAcpCommand(command) {
266
253
  return isAcpCommand(command, {
267
- packageName: CODEX_ACP_PACKAGE,
254
+ packageName: "@zed-industries/codex-acp",
268
255
  executableName: "codex-acp"
269
256
  });
270
257
  }
@@ -293,50 +280,27 @@ function normalizeCodexAcpReasoningEffort(rawThinking) {
293
280
  if (!CODEX_ACP_THINKING_ALIASES.has(normalized)) failUnsupportedCodexAcpThinking(rawThinking ?? "");
294
281
  return CODEX_ACP_THINKING_ALIASES.get(normalized);
295
282
  }
296
- function isCodexAcpReasoningEffortAlias(value) {
297
- const normalized = value?.trim().toLowerCase();
298
- return Boolean(normalized && CODEX_ACP_THINKING_ALIASES.has(normalized));
299
- }
300
- function classifyCodexAcpModelRequest(rawModel, rawThinking) {
283
+ function normalizeCodexAcpModelOverride(rawModel, rawThinking) {
301
284
  const raw = rawModel?.trim();
302
285
  const thinkingReasoningEffort = normalizeCodexAcpReasoningEffort(rawThinking);
303
- const thinkingOnlyOverride = thinkingReasoningEffort ? { reasoningEffort: thinkingReasoningEffort } : void 0;
304
- if (!raw) return {
305
- kind: "override",
306
- override: thinkingOnlyOverride ?? {}
307
- };
286
+ if (!raw) return thinkingReasoningEffort ? { reasoningEffort: thinkingReasoningEffort } : void 0;
308
287
  let value = raw;
309
- let hadOpenAiQualifier = false;
310
- if (value.toLowerCase().startsWith(CODEX_ACP_OPENCLAW_PREFIX)) {
311
- value = value.slice(7);
312
- hadOpenAiQualifier = true;
313
- }
314
- let model = value.trim();
315
- let modelReasoningEffort;
316
- const slashIndex = value.lastIndexOf("/");
317
- if (slashIndex >= 0 && isCodexAcpReasoningEffortAlias(value.slice(slashIndex + 1))) {
318
- modelReasoningEffort = normalizeCodexAcpReasoningEffort(value.slice(slashIndex + 1));
319
- model = value.slice(0, slashIndex).trim();
320
- }
321
- if (hadOpenAiQualifier && (!model || model.includes("/"))) failUnsupportedCodexAcpModel(raw, `Codex ACP model "${raw}" is not supported. Use openai/<model> or <model>/<reasoning-effort>.`);
322
- if (!model || model.includes("/")) return thinkingOnlyOverride ? {
323
- kind: "unsupported",
324
- thinkingOverride: thinkingOnlyOverride
325
- } : { kind: "unsupported" };
288
+ if (value.toLowerCase().startsWith(CODEX_ACP_OPENCLAW_PREFIX)) value = value.slice(7);
289
+ const parts = value.split("/");
290
+ if (parts.length > 2) failUnsupportedCodexAcpModel(raw, `Codex ACP model "${raw}" is not supported. Use openai/<model> or <model>/<reasoning-effort>.`);
291
+ const model = (parts[0] ?? "").trim();
292
+ const modelReasoningEffort = normalizeCodexAcpReasoningEffort(parts[1]);
293
+ if (!model) failUnsupportedCodexAcpModel(raw, `Codex ACP model "${raw}" is not supported. Use openai/<model> or <model>/<reasoning-effort>.`);
326
294
  const reasoningEffort = thinkingReasoningEffort ?? modelReasoningEffort;
295
+ if (reasoningEffort && !CODEX_ACP_REASONING_EFFORTS.has(reasoningEffort)) failUnsupportedCodexAcpThinking(reasoningEffort);
327
296
  return {
328
- kind: "override",
329
- override: {
330
- model,
331
- ...reasoningEffort ? { reasoningEffort } : {}
332
- }
297
+ model,
298
+ ...reasoningEffort ? { reasoningEffort } : {}
333
299
  };
334
300
  }
335
- function withCodexSessionModel(input, override) {
336
- const next = { ...input };
337
- if (override?.model) next.model = override.model;
338
- else delete next.model;
339
- return next;
301
+ function codexAcpSessionModelId(override) {
302
+ if (!override.model) return "";
303
+ return override.reasoningEffort ? `${override.model}/${override.reasoningEffort}` : override.model;
340
304
  }
341
305
  function normalizeClaudeAcpModelOverride(rawModel) {
342
306
  const raw = rawModel?.trim();
@@ -351,9 +315,8 @@ function withAcpxSessionOptions(input) {
351
315
  ...existingOptions,
352
316
  model
353
317
  } : existingOptions;
354
- const { modelExplicit: _modelExplicit, ...rest } = input;
355
318
  return {
356
- ...rest,
319
+ ...input,
357
320
  ...sessionOptions ? { sessionOptions } : {}
358
321
  };
359
322
  }
@@ -375,21 +338,16 @@ function quoteShellArg(value) {
375
338
  if (/^[A-Za-z0-9_./:=@+-]+$/.test(value)) return value;
376
339
  return `'${value.replace(/'/g, "'\\''")}'`;
377
340
  }
378
- function normalizeAgentCommand(command) {
379
- return (Array.isArray(command) ? command.map((part) => quoteShellArg(part)).join(" ") : command).trim() || void 0;
380
- }
381
341
  function appendCodexAcpConfigOverrides(command, override) {
382
- const config = {
383
- ...override.model ? { model: override.model } : {},
384
- ...override.reasoningEffort ? { model_reasoning_effort: override.reasoningEffort } : {}
385
- };
386
- if (Object.keys(config).length === 0) return command;
387
- return `${command} ${OPENCLAW_CODEX_CONFIG_ARG} ${quoteShellArg(JSON.stringify(config))}`;
342
+ const configArgs = override.model ? [`model=${override.model}`] : [];
343
+ if (override.reasoningEffort) configArgs.push(`model_reasoning_effort=${override.reasoningEffort}`);
344
+ if (configArgs.length === 0) return command;
345
+ return `${command} ${configArgs.map((arg) => `-c ${quoteShellArg(arg)}`).join(" ")}`;
388
346
  }
389
347
  function createModelScopedAgentRegistry(params) {
390
348
  return {
391
349
  resolve(agentName) {
392
- const command = normalizeAgentCommand(params.agentRegistry.resolve(agentName)) ?? "";
350
+ const command = params.agentRegistry.resolve(agentName);
393
351
  const override = params.scope.getStore();
394
352
  if (!override || normalizeAgentName(agentName) !== CODEX_ACP_AGENT_ID || !isCodexAcpCommand(command)) return params.leaseCommand(command);
395
353
  return params.leaseCommand(appendCodexAcpConfigOverrides(command, override));
@@ -402,7 +360,15 @@ function createModelScopedAgentRegistry(params) {
402
360
  function resolveAgentCommand(params) {
403
361
  const normalizedAgentName = normalizeAgentName(params.agentName);
404
362
  if (!normalizedAgentName) return;
405
- return normalizeAgentCommand(params.agentRegistry.resolve(normalizedAgentName));
363
+ const resolvedCommand = params.agentRegistry.resolve(normalizedAgentName);
364
+ return typeof resolvedCommand === "string" ? resolvedCommand.trim() || void 0 : void 0;
365
+ }
366
+ function resolveProbeAgentName(options) {
367
+ const { probeAgent } = options;
368
+ return normalizeAgentName(typeof probeAgent === "string" ? probeAgent : void 0) ?? "codex";
369
+ }
370
+ function resolveAgentCommandForName(params) {
371
+ return resolveAgentCommand(params);
406
372
  }
407
373
  function shouldUseBridgeSafeDelegateForCommand(command) {
408
374
  return isOpenClawBridgeCommand(command);
@@ -411,14 +377,12 @@ function shouldUseDistinctBridgeDelegate(options) {
411
377
  const { mcpServers } = options;
412
378
  return Array.isArray(mcpServers) && mcpServers.length > 0;
413
379
  }
414
- function withManagedToolsMcpSessionEnv(params) {
380
+ function withOpenClawToolsMcpSessionEnv(params) {
415
381
  const sessionKey = params.sessionKey.trim();
416
- if (!params.pluginToolsEnabled && !params.openclawToolsEnabled || !sessionKey || !params.mcpServers?.length) return params.mcpServers;
382
+ if (!params.enabled || !sessionKey || !params.mcpServers?.length) return params.mcpServers;
417
383
  let changed = false;
418
384
  const nextServers = params.mcpServers.map((server) => {
419
- const isManagedPluginTools = params.pluginToolsEnabled && server.name === ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME;
420
- const isManagedOpenClawTools = params.openclawToolsEnabled && server.name === ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME;
421
- if (!isManagedPluginTools && !isManagedOpenClawTools || !("command" in server)) return server;
385
+ if (server.name !== ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME || !("command" in server)) return server;
422
386
  changed = true;
423
387
  const env = [...server.env.filter((entry) => entry.name !== OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV), {
424
388
  name: OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV,
@@ -435,25 +399,19 @@ function withManagedToolsMcpSessionEnv(params) {
435
399
  var AcpxRuntime = class {
436
400
  constructor(options, testOptions) {
437
401
  this.codexAcpModelOverrideScope = new AsyncLocalStorage();
438
- this.managedToolsSessionDelegates = /* @__PURE__ */ new Map();
402
+ this.openclawToolsSessionDelegates = /* @__PURE__ */ new Map();
439
403
  this.launchLeaseScope = new AsyncLocalStorage();
440
- this.ensureSessionTails = /* @__PURE__ */ new Map();
441
- this.processLeaseTransitionTails = /* @__PURE__ */ new Map();
442
- this.processLeaseOperationCounts = /* @__PURE__ */ new Map();
443
404
  const { openclawProcessCleanup, ...delegateTestOptions } = testOptions ?? {};
444
405
  this.processCleanupDeps = openclawProcessCleanup;
445
406
  this.wrapperRoot = options.openclawWrapperRoot;
446
407
  this.gatewayInstanceId = options.openclawGatewayInstanceId;
447
408
  this.processLeaseStore = options.openclawProcessLeaseStore;
448
- this.pluginToolsMcpBridgeEnabled = options.pluginToolsMcpBridgeEnabled === true;
449
409
  this.openclawToolsMcpBridgeEnabled = options.openclawToolsMcpBridgeEnabled === true;
450
- this.managedToolsMcpBridgeEnabled = this.pluginToolsMcpBridgeEnabled || this.openclawToolsMcpBridgeEnabled;
451
410
  this.cwd = options.cwd;
452
411
  this.sessionStore = createResetAwareSessionStore(options.sessionStore, {
453
412
  gatewayInstanceId: this.gatewayInstanceId,
454
413
  leaseStore: this.processLeaseStore,
455
- launchScope: this.launchLeaseScope,
456
- wrapperRoot: this.wrapperRoot
414
+ launchScope: this.launchLeaseScope
457
415
  });
458
416
  this.agentRegistry = options.agentRegistry;
459
417
  this.scopedAgentRegistry = createModelScopedAgentRegistry({
@@ -473,40 +431,44 @@ var AcpxRuntime = class {
473
431
  ...sharedOptions,
474
432
  mcpServers: []
475
433
  }, this.delegateTestOptions) : this.delegate;
476
- const probeCommand = resolveAgentCommand({
477
- agentName: normalizeAgentName(options.probeAgent) ?? "codex",
434
+ this.probeDelegate = this.openclawToolsMcpBridgeEnabled ? this.bridgeSafeDelegate : this.resolveDelegateForAgent(resolveProbeAgentName(options));
435
+ }
436
+ resolveDelegateForAgent(agentName) {
437
+ const command = resolveAgentCommandForName({
438
+ agentName,
478
439
  agentRegistry: this.agentRegistry
479
440
  });
480
- const useBridgeSafeProbe = this.managedToolsMcpBridgeEnabled || shouldUseBridgeSafeDelegateForCommand(probeCommand);
481
- this.probeDelegate = useBridgeSafeProbe ? this.bridgeSafeDelegate : this.delegate;
441
+ return this.resolveDelegateForCommand(command);
442
+ }
443
+ resolveDelegateForCommand(command) {
444
+ return shouldUseBridgeSafeDelegateForCommand(command) ? this.bridgeSafeDelegate : this.delegate;
482
445
  }
483
446
  resolveDelegateForSession(params) {
484
447
  if (shouldUseBridgeSafeDelegateForCommand(params.command)) return this.bridgeSafeDelegate;
485
- return this.resolveManagedToolsDelegateForSession(params.sessionKey);
448
+ return this.resolveOpenClawToolsDelegateForSession(params.sessionKey);
486
449
  }
487
- resolveManagedToolsDelegateForSession(sessionKey) {
488
- if (!this.managedToolsMcpBridgeEnabled) return this.delegate;
450
+ resolveOpenClawToolsDelegateForSession(sessionKey) {
451
+ if (!this.openclawToolsMcpBridgeEnabled) return this.delegate;
489
452
  const normalizedSessionKey = sessionKey.trim();
490
453
  if (!normalizedSessionKey) return this.delegate;
491
- const cached = this.managedToolsSessionDelegates.get(normalizedSessionKey);
454
+ const cached = this.openclawToolsSessionDelegates.get(normalizedSessionKey);
492
455
  if (cached) return cached;
493
456
  const delegate = new AcpxRuntime$1({
494
457
  ...this.delegateOptions,
495
- mcpServers: withManagedToolsMcpSessionEnv({
496
- pluginToolsEnabled: this.pluginToolsMcpBridgeEnabled,
497
- openclawToolsEnabled: this.openclawToolsMcpBridgeEnabled,
458
+ mcpServers: withOpenClawToolsMcpSessionEnv({
459
+ enabled: this.openclawToolsMcpBridgeEnabled,
498
460
  mcpServers: this.delegateOptions.mcpServers,
499
461
  sessionKey: normalizedSessionKey
500
462
  })
501
463
  }, this.delegateTestOptions);
502
- this.managedToolsSessionDelegates.set(normalizedSessionKey, delegate);
464
+ this.openclawToolsSessionDelegates.set(normalizedSessionKey, delegate);
503
465
  return delegate;
504
466
  }
505
- releaseManagedToolsDelegateForSession(sessionKey) {
506
- if (!this.managedToolsMcpBridgeEnabled) return;
467
+ releaseOpenClawToolsDelegateForSession(sessionKey) {
468
+ if (!this.openclawToolsMcpBridgeEnabled) return;
507
469
  const normalizedSessionKey = sessionKey.trim();
508
470
  if (!normalizedSessionKey) return;
509
- this.managedToolsSessionDelegates.delete(normalizedSessionKey);
471
+ this.openclawToolsSessionDelegates.delete(normalizedSessionKey);
510
472
  }
511
473
  async resolveDelegateForHandle(handle) {
512
474
  const record = await this.sessionStore.load(handle.acpxRecordId ?? handle.sessionKey);
@@ -518,7 +480,7 @@ var AcpxRuntime = class {
518
480
  command: recordCommand,
519
481
  sessionKey: handle.sessionKey
520
482
  });
521
- const command = resolveAgentCommand({
483
+ const command = resolveAgentCommandForName({
522
484
  agentName: readAgentFromHandle(handle),
523
485
  agentRegistry: this.agentRegistry
524
486
  });
@@ -530,7 +492,7 @@ var AcpxRuntime = class {
530
492
  async resolveCommandForHandle(handle) {
531
493
  const recordCommand = readAgentCommandFromRecord(await this.sessionStore.load(handle.acpxRecordId ?? handle.sessionKey));
532
494
  if (recordCommand) return recordCommand;
533
- return resolveAgentCommand({
495
+ return resolveAgentCommandForName({
534
496
  agentName: readAgentFromHandle(handle),
535
497
  agentRegistry: this.agentRegistry
536
498
  });
@@ -538,206 +500,47 @@ var AcpxRuntime = class {
538
500
  commandWithLaunchLease(command) {
539
501
  const launch = this.launchLeaseScope.getStore();
540
502
  if (!launch) return command;
541
- if (command === launch.stableCommand) return launch.resolvedCommand;
503
+ launch.stableCommand = command;
542
504
  return withAcpxLeaseEnvironment({
543
505
  command,
544
506
  leaseId: launch.leaseId,
545
507
  gatewayInstanceId: launch.gatewayInstanceId
546
508
  });
547
509
  }
548
- async readReusablePersistentSessionCommand(params) {
549
- if (params.mode !== "persistent" || !params.command) return;
510
+ async canReuseStablePersistentSession(params) {
511
+ if (params.mode !== "persistent" || !params.command) return false;
550
512
  const existing = await this.sessionStore.load(params.sessionKey);
551
- if (!existing || readRecordResetOnNextEnsure(existing)) return;
513
+ if (!existing || readRecordResetOnNextEnsure(existing)) return false;
552
514
  const recordCwd = readRecordCwd(existing);
553
- if (!recordCwd || resolve(recordCwd) !== resolve(params.cwd?.trim() || this.cwd)) return;
554
- const recordCommand = readRecordAgentCommand(existing);
555
- if (!recordCommand) return;
556
- const leaseIdentity = readAcpxProcessLeaseIdentity(recordCommand);
557
- if (leaseIdentity && leaseIdentity.gatewayInstanceId !== this.gatewayInstanceId) return;
558
- if (recordCommand !== (leaseIdentity ? withAcpxLeaseEnvironment({
559
- command: params.command,
560
- leaseId: leaseIdentity.leaseId,
561
- gatewayInstanceId: leaseIdentity.gatewayInstanceId
562
- }) : params.command)) return;
515
+ if (!recordCwd || resolve(recordCwd) !== resolve(params.cwd?.trim() || this.cwd)) return false;
516
+ if (readRecordAgentCommand(existing) !== params.command) return false;
563
517
  const existingSessionId = typeof existing === "object" && existing !== null ? existing.acpSessionId : void 0;
564
- return !params.resumeSessionId || existingSessionId === params.resumeSessionId ? recordCommand : void 0;
518
+ return !params.resumeSessionId || existingSessionId === params.resumeSessionId;
565
519
  }
566
520
  async runWithLaunchLease(params) {
567
- if (!params.command || !this.wrapperRoot || !this.gatewayInstanceId || !this.processLeaseStore || !isOpenClawLeaseAwareAcpxProcessCommand({
521
+ if (params.enabled === false || !params.command || !this.wrapperRoot || !this.gatewayInstanceId || !this.processLeaseStore || !isOpenClawLeaseAwareAcpxProcessCommand({
568
522
  command: params.command,
569
523
  wrapperRoot: this.wrapperRoot
570
524
  })) return await params.run();
571
- const processLeaseStore = this.processLeaseStore;
572
- const reusableIdentity = readAcpxProcessLeaseIdentity(params.reusableCommand);
573
- const canReuseLeaseIdentity = reusableIdentity?.gatewayInstanceId === this.gatewayInstanceId;
574
- const leaseId = canReuseLeaseIdentity ? reusableIdentity.leaseId : createAcpxProcessLeaseId();
575
- const leasedCommand = withAcpxLeaseEnvironment({
576
- command: params.command,
577
- leaseId,
578
- gatewayInstanceId: this.gatewayInstanceId
579
- });
580
525
  const launch = {
581
- leaseId,
526
+ leaseId: createAcpxProcessLeaseId(),
582
527
  gatewayInstanceId: this.gatewayInstanceId,
583
528
  sessionKey: params.sessionKey,
584
529
  wrapperRoot: this.wrapperRoot,
585
- stableCommand: params.command,
586
- resolvedCommand: params.reusableCommand ?? leasedCommand,
587
- leasedCommand
530
+ stableCommand: params.command
588
531
  };
589
- await this.retainProcessLeaseOperation(launch, async () => {
590
- const reusableLease = canReuseLeaseIdentity ? await processLeaseStore.load(launch.leaseId) : void 0;
591
- if (reusableLease && (reusableLease.gatewayInstanceId !== launch.gatewayInstanceId || reusableLease.sessionKey !== launch.sessionKey || reusableLease.wrapperRoot !== launch.wrapperRoot)) throw new AcpRuntimeError("ACP_SESSION_INIT_FAILED", `ACPX process lease ${launch.leaseId} belongs to another session`);
592
- if (!(!reusableLease && (!params.reusableCommand || params.reusableCommand === leasedCommand))) return;
593
- await processLeaseStore.save({
594
- leaseId: launch.leaseId,
595
- gatewayInstanceId: launch.gatewayInstanceId,
596
- sessionKey: launch.sessionKey,
597
- wrapperRoot: launch.wrapperRoot,
598
- wrapperPath: extractGeneratedWrapperPath(leasedCommand),
599
- rootPid: 0,
600
- commandHash: hashAcpxProcessCommand(leasedCommand),
601
- startedAt: Date.now(),
602
- state: "open"
603
- });
604
- });
605
- try {
606
- const result = await this.launchLeaseScope.run(launch, params.run);
607
- await this.finalizeProcessLeaseForSession(params.sessionKey, launch);
608
- return result;
609
- } catch (error) {
610
- await this.retirePendingProcessLease(launch);
611
- throw error;
612
- }
613
- }
614
- async prepareProcessLeaseForOperation(handle) {
615
- if (!this.processLeaseStore || !this.gatewayInstanceId || !this.wrapperRoot) return;
616
- const processLeaseStore = this.processLeaseStore;
617
- const wrapperRoot = this.wrapperRoot;
618
- const record = await this.sessionStore.load(handle.acpxRecordId ?? handle.sessionKey);
619
- const recordPid = readRecordAgentPid(record);
620
- const command = readAgentCommandFromRecord(record);
621
- const identity = readAcpxProcessLeaseIdentity(command);
622
- if (!command || !isOpenClawLeaseAwareAcpxProcessCommand({
623
- command,
624
- wrapperRoot
625
- })) return;
626
- if (!identity) return;
627
- if (identity.gatewayInstanceId !== this.gatewayInstanceId) throw new AcpRuntimeError("ACP_TURN_FAILED", `ACPX process lease ${identity.leaseId} belongs to another gateway`);
628
- await this.retainProcessLeaseOperation(identity, async () => {
629
- const existing = await processLeaseStore.load(identity.leaseId);
630
- if (!existing) {
631
- await processLeaseStore.save({
632
- leaseId: identity.leaseId,
633
- gatewayInstanceId: identity.gatewayInstanceId,
634
- sessionKey: handle.sessionKey,
635
- wrapperRoot,
636
- wrapperPath: extractGeneratedWrapperPath(command),
637
- rootPid: recordPid ?? 0,
638
- commandHash: hashAcpxProcessCommand(command),
639
- startedAt: Date.now(),
640
- state: "open"
641
- });
642
- return;
643
- }
644
- if (existing.gatewayInstanceId !== identity.gatewayInstanceId || existing.sessionKey !== handle.sessionKey || existing.wrapperRoot !== wrapperRoot) throw new AcpRuntimeError("ACP_TURN_FAILED", `ACPX process lease ${identity.leaseId} belongs to another session`);
645
- });
646
- return identity;
647
- }
648
- async runSerializedProcessLeaseTransition(leaseId, run) {
649
- const previous = this.processLeaseTransitionTails.get(leaseId) ?? Promise.resolve();
650
- let release;
651
- const current = new Promise((resolve) => {
652
- release = resolve;
653
- });
654
- const tail = previous.then(() => current);
655
- this.processLeaseTransitionTails.set(leaseId, tail);
656
- await previous;
657
- try {
658
- return await run();
659
- } finally {
660
- release();
661
- if (this.processLeaseTransitionTails.get(leaseId) === tail) this.processLeaseTransitionTails.delete(leaseId);
662
- }
663
- }
664
- async retainProcessLeaseOperation(identity, prepare) {
665
- await this.runSerializedProcessLeaseTransition(identity.leaseId, async () => {
666
- await prepare();
667
- this.processLeaseOperationCounts.set(identity.leaseId, (this.processLeaseOperationCounts.get(identity.leaseId) ?? 0) + 1);
668
- });
669
- }
670
- async releaseProcessLeaseOperation(identity, finalize) {
671
- if (!identity) return;
672
- await this.runSerializedProcessLeaseTransition(identity.leaseId, async () => {
673
- const count = this.processLeaseOperationCounts.get(identity.leaseId) ?? 0;
674
- if (count > 1) {
675
- this.processLeaseOperationCounts.set(identity.leaseId, count - 1);
676
- return;
677
- }
678
- if (count === 0) return;
679
- this.processLeaseOperationCounts.delete(identity.leaseId);
680
- await finalize();
681
- });
682
- }
683
- async finalizeProcessLeaseForOperation(handle, identity) {
684
- await this.finalizeProcessLeaseForSession(handle.acpxRecordId ?? handle.sessionKey, identity);
685
- }
686
- async finalizeProcessLeaseForSession(sessionId, identity) {
687
- if (!identity || !this.processLeaseStore) return;
688
- const processLeaseStore = this.processLeaseStore;
689
- await this.releaseProcessLeaseOperation(identity, async () => {
690
- const lease = await processLeaseStore.load(identity.leaseId);
691
- if (!lease || lease.gatewayInstanceId !== identity.gatewayInstanceId) return;
692
- if (lease.rootPid <= 0) {
693
- await processLeaseStore.markState(identity.leaseId, "lost");
694
- return;
695
- }
696
- try {
697
- const recordIdentity = readAcpxProcessLeaseIdentity(readAgentCommandFromRecord(await this.sessionStore.load(sessionId)));
698
- if (recordIdentity?.leaseId !== identity.leaseId || recordIdentity.gatewayInstanceId !== identity.gatewayInstanceId) await processLeaseStore.markState(identity.leaseId, "lost");
699
- } catch {}
700
- });
701
- }
702
- async retirePendingProcessLease(identity) {
703
- if (!identity || !this.processLeaseStore) return;
704
- const processLeaseStore = this.processLeaseStore;
705
- await this.releaseProcessLeaseOperation(identity, async () => {
706
- const lease = await processLeaseStore.load(identity.leaseId);
707
- if (lease?.gatewayInstanceId === identity.gatewayInstanceId && lease.rootPid <= 0) await processLeaseStore.markState(identity.leaseId, "lost");
708
- });
709
- }
710
- async runWithProcessLeaseForHandle(handle, run) {
711
- const identity = await this.prepareProcessLeaseForOperation(handle);
712
- try {
713
- return await run();
714
- } finally {
715
- await this.finalizeProcessLeaseForOperation(handle, identity);
716
- }
717
- }
718
- async finalizeProcessLeaseAfter(handle, identityPromise, resultPromise) {
719
- try {
720
- return await resultPromise;
721
- } finally {
722
- await this.finalizeProcessLeaseForOperation(handle, await identityPromise);
723
- }
724
- }
725
- async runSerializedSessionEnsure(sessionKey, run) {
726
- const key = sessionKey.trim() || sessionKey;
727
- const previous = this.ensureSessionTails.get(key) ?? Promise.resolve();
728
- let release;
729
- const current = new Promise((resolve) => {
730
- release = resolve;
532
+ await this.processLeaseStore.save({
533
+ leaseId: launch.leaseId,
534
+ gatewayInstanceId: launch.gatewayInstanceId,
535
+ sessionKey: launch.sessionKey,
536
+ wrapperRoot: launch.wrapperRoot,
537
+ wrapperPath: extractGeneratedWrapperPath(params.command),
538
+ rootPid: 0,
539
+ commandHash: hashAcpxProcessCommand(params.command),
540
+ startedAt: Date.now(),
541
+ state: "open"
731
542
  });
732
- const tail = previous.then(() => current);
733
- this.ensureSessionTails.set(key, tail);
734
- await previous;
735
- try {
736
- return await run();
737
- } finally {
738
- release();
739
- if (this.ensureSessionTails.get(key) === tail) this.ensureSessionTails.delete(key);
740
- }
543
+ return await this.launchLeaseScope.run(launch, params.run);
741
544
  }
742
545
  async withCodexWrapperDiagnostics(params) {
743
546
  try {
@@ -780,10 +583,10 @@ var AcpxRuntime = class {
780
583
  wrapperRoot: lease.wrapperRoot,
781
584
  deps: this.processCleanupDeps
782
585
  });
783
- await this.processLeaseStore?.markState(lease.leaseId, result.skippedReason === "process-list-unavailable" ? "open" : result.terminatedPids.length > 0 || result.skippedReason === "missing-root" ? "closed" : "lost");
586
+ await this.processLeaseStore?.markState(lease.leaseId, result.terminatedPids.length > 0 || result.skippedReason === "missing-root" ? "closed" : "lost");
784
587
  return;
785
588
  }
786
- const rootCommand = readAgentCommandFromRecord(record) ?? resolveAgentCommand({
589
+ const rootCommand = readAgentCommandFromRecord(record) ?? resolveAgentCommandForName({
787
590
  agentName: readAgentFromHandle(handle),
788
591
  agentRegistry: this.agentRegistry
789
592
  });
@@ -808,11 +611,8 @@ var AcpxRuntime = class {
808
611
  return this.probeDelegate.doctor();
809
612
  }
810
613
  async ensureSession(input) {
811
- return await this.runSerializedSessionEnsure(input.sessionKey, () => this.ensureSessionUnlocked(input));
812
- }
813
- async ensureSessionUnlocked(input) {
814
614
  assertSupportedRuntimeSessionMode(input.mode);
815
- const command = resolveAgentCommand({
615
+ const command = resolveAgentCommandForName({
816
616
  agentName: input.agent,
817
617
  agentRegistry: this.agentRegistry
818
618
  });
@@ -820,59 +620,49 @@ var AcpxRuntime = class {
820
620
  command,
821
621
  sessionKey: input.sessionKey
822
622
  });
823
- const isCodexAcp = normalizeAgentName(input.agent) === CODEX_ACP_AGENT_ID && isCodexAcpCommand(command);
824
623
  const claudeModelOverride = isClaudeAcpCommand(command) ? normalizeClaudeAcpModelOverride(input.model) : void 0;
825
- const codexClassification = isCodexAcp ? classifyCodexAcpModelRequest(input.model, input.thinking) : void 0;
826
- if (codexClassification?.kind === "unsupported" && input.modelExplicit) failUnsupportedCodexAcpModel(input.model ?? "");
827
- const classifiedCodexOverride = codexClassification?.kind === "override" ? codexClassification.override : codexClassification?.thinkingOverride;
828
- const codexModelOverride = classifiedCodexOverride && Object.keys(classifiedCodexOverride).length > 0 ? classifiedCodexOverride : void 0;
829
- const requestedModel = input.model?.trim();
830
- const appliedModel = isCodexAcp && requestedModel ? codexModelOverride?.model ? {
831
- kind: "applied",
832
- model: requestedModel
833
- } : { kind: "dropped" } : void 0;
834
- const ensureInput = isCodexAcp ? withCodexSessionModel(input, codexModelOverride) : claudeModelOverride ? {
624
+ const codexModelOverride = normalizeAgentName(input.agent) === CODEX_ACP_AGENT_ID && isCodexAcpCommand(command) ? normalizeCodexAcpModelOverride(input.model, input.thinking) : void 0;
625
+ const ensureInput = claudeModelOverride ? {
835
626
  ...input,
836
627
  model: claudeModelOverride
837
628
  } : input;
838
629
  const stableLaunchCommand = codexModelOverride && command ? appendCodexAcpConfigOverrides(command, codexModelOverride) : command;
839
- const reusableCommand = await this.readReusablePersistentSessionCommand({
630
+ const shouldStartWithLease = !await this.canReuseStablePersistentSession({
840
631
  sessionKey: input.sessionKey,
841
632
  mode: input.mode,
842
633
  cwd: input.cwd,
843
634
  command: stableLaunchCommand,
844
635
  resumeSessionId: input.resumeSessionId
845
636
  });
846
- const handle = !codexModelOverride ? await this.runWithLaunchLease({
637
+ if (!codexModelOverride) return await this.runWithLaunchLease({
847
638
  sessionKey: ensureInput.sessionKey,
848
639
  command: stableLaunchCommand,
849
- reusableCommand,
640
+ enabled: shouldStartWithLease,
850
641
  run: () => this.withCodexWrapperDiagnostics({
851
642
  command: stableLaunchCommand,
852
643
  fallbackCode: "ACP_SESSION_INIT_FAILED",
853
644
  run: () => ensureDelegateSessionWithModelFallback(delegate, ensureInput)
854
645
  })
855
- }) : await this.runWithLaunchLease({
646
+ });
647
+ const normalizedInput = {
648
+ ...ensureInput,
649
+ ...codexAcpSessionModelId(codexModelOverride) ? { model: codexAcpSessionModelId(codexModelOverride) } : {}
650
+ };
651
+ return await this.runWithLaunchLease({
856
652
  sessionKey: input.sessionKey,
857
653
  command: stableLaunchCommand,
858
- reusableCommand,
654
+ enabled: shouldStartWithLease,
859
655
  run: () => this.codexAcpModelOverrideScope.run(codexModelOverride, () => this.withCodexWrapperDiagnostics({
860
656
  command: stableLaunchCommand,
861
657
  fallbackCode: "ACP_SESSION_INIT_FAILED",
862
- run: () => delegate.ensureSession(withAcpxSessionOptions(ensureInput))
658
+ run: () => delegate.ensureSession(withAcpxSessionOptions(normalizedInput))
863
659
  }))
864
660
  });
865
- return appliedModel ? {
866
- ...handle,
867
- appliedModel
868
- } : handle;
869
661
  }
870
662
  async *runTurn(input) {
871
- const turnLease = await this.prepareProcessLeaseForOperation(input.handle);
872
- let command;
663
+ const command = await this.resolveCommandForHandle(input.handle);
664
+ const delegate = await this.resolveDelegateForHandle(input.handle);
873
665
  try {
874
- command = await this.resolveCommandForHandle(input.handle);
875
- const delegate = await this.resolveDelegateForHandle(input.handle);
876
666
  for await (const event of delegate.runTurn(withOpenClawManagedTurnTimeout(input))) {
877
667
  if (event.type !== "error" || !isCodexAcpCommand(command) || !isGenericInternalAcpErrorMessage(event.message)) {
878
668
  yield event;
@@ -894,18 +684,11 @@ var AcpxRuntime = class {
894
684
  const stderrTail = await this.readCodexTurnFailureStderr({ handle: input.handle });
895
685
  if (!stderrTail) throw error;
896
686
  throw new AcpRuntimeError("ACP_TURN_FAILED", `Internal error: ${stderrTail}`, { cause: error });
897
- } finally {
898
- await this.finalizeProcessLeaseForOperation(input.handle, turnLease);
899
687
  }
900
688
  }
901
689
  startTurn(input) {
902
690
  const readCodexTurnFailureStderr = () => this.readCodexTurnFailureStderr({ handle: input.handle });
903
- const turnLeasePromise = this.prepareProcessLeaseForOperation(input.handle);
904
- const turnPromise = Promise.all([
905
- turnLeasePromise,
906
- this.resolveCommandForHandle(input.handle),
907
- this.resolveDelegateForHandle(input.handle)
908
- ]).then(async ([, command, delegate]) => {
691
+ const turnPromise = Promise.all([this.resolveCommandForHandle(input.handle), this.resolveDelegateForHandle(input.handle)]).then(async ([command, delegate]) => {
909
692
  try {
910
693
  return {
911
694
  command,
@@ -946,7 +729,7 @@ var AcpxRuntime = class {
946
729
  throw new AcpRuntimeError("ACP_TURN_FAILED", `Internal error: ${stderrTail}`, { cause: error });
947
730
  }
948
731
  } },
949
- result: this.finalizeProcessLeaseAfter(input.handle, turnLeasePromise, turnPromise.then(async ({ command, turn }) => {
732
+ result: turnPromise.then(async ({ command, turn }) => {
950
733
  try {
951
734
  const result = await turn.result;
952
735
  if (result.status !== "failed" || !isCodexAcpCommand(command) || !isGenericInternalAcpErrorMessage(result.error.message)) return result;
@@ -966,7 +749,7 @@ var AcpxRuntime = class {
966
749
  if (!stderrTail) throw error;
967
750
  throw new AcpRuntimeError("ACP_TURN_FAILED", `Internal error: ${stderrTail}`, { cause: error });
968
751
  }
969
- })),
752
+ }),
970
753
  cancel(inputArgs) {
971
754
  return turnPromise.then(({ turn }) => turn.cancel(inputArgs));
972
755
  },
@@ -975,52 +758,38 @@ var AcpxRuntime = class {
975
758
  }
976
759
  };
977
760
  }
978
- getCapabilities(input) {
979
- return this.delegate.getCapabilities(input);
761
+ getCapabilities() {
762
+ return this.delegate.getCapabilities();
980
763
  }
981
764
  async getStatus(input) {
982
765
  return (await this.resolveDelegateForHandle(input.handle)).getStatus(input);
983
766
  }
984
767
  async setMode(input) {
985
- const delegate = await this.resolveDelegateForHandle(input.handle);
986
- await this.runWithProcessLeaseForHandle(input.handle, () => delegate.setMode(input));
768
+ await (await this.resolveDelegateForHandle(input.handle)).setMode(input);
987
769
  }
988
770
  async setConfigOption(input) {
989
- await this.runWithProcessLeaseForHandle(input.handle, () => this.setConfigOptionUnlocked(input));
990
- }
991
- async setConfigOptionUnlocked(input) {
992
771
  const delegate = await this.resolveDelegateForHandle(input.handle);
993
772
  const command = await this.resolveCommandForHandle(input.handle);
994
773
  const key = input.key.trim().toLowerCase();
995
774
  const isCodexAcp = isCodexAcpCommand(command);
996
775
  if (WIRE_TIMEOUT_CONFIG_KEYS.has(key) && (isCodexAcp || isClaudeAcpCommand(command))) return;
997
776
  if (isCodexAcp) {
998
- if (key === "model") {
999
- const classification = classifyCodexAcpModelRequest(input.value);
1000
- if (classification.kind === "unsupported") failUnsupportedCodexAcpModel(input.value);
1001
- const { override } = classification;
1002
- if (override.model) await delegate.setConfigOption({
1003
- ...input,
1004
- key: "model",
1005
- value: override.model
1006
- });
1007
- if (override.reasoningEffort) await delegate.setConfigOption({
1008
- ...input,
1009
- key: "reasoning_effort",
1010
- value: override.reasoningEffort
1011
- });
1012
- return;
1013
- }
1014
- if (key === "thinking" || key === "thought_level" || key === "reasoning_effort") {
1015
- const classification = classifyCodexAcpModelRequest(void 0, input.value);
1016
- const reasoningEffort = classification.kind === "override" ? classification.override.reasoningEffort : void 0;
1017
- if (!reasoningEffort) return;
1018
- await delegate.setConfigOption({
1019
- ...input,
1020
- key: "reasoning_effort",
1021
- value: reasoningEffort
1022
- });
1023
- return;
777
+ if (key === "model" || key === "thinking" || key === "thought_level" || key === "reasoning_effort") {
778
+ const override = key === "model" ? normalizeCodexAcpModelOverride(input.value) : normalizeCodexAcpModelOverride(void 0, input.value);
779
+ if (!override && key !== "model") return;
780
+ if (override) {
781
+ if (override.model) await delegate.setConfigOption({
782
+ ...input,
783
+ key: "model",
784
+ value: override.model
785
+ });
786
+ if (override.reasoningEffort) await delegate.setConfigOption({
787
+ ...input,
788
+ key: "reasoning_effort",
789
+ value: override.reasoningEffort
790
+ });
791
+ return;
792
+ }
1024
793
  }
1025
794
  }
1026
795
  if (isClaudeAcpCommand(command) && key === "model") {
@@ -1040,40 +809,32 @@ var AcpxRuntime = class {
1040
809
  this.sessionStore.markFresh(input.sessionKey);
1041
810
  }
1042
811
  async close(input) {
1043
- const closeLease = await this.prepareProcessLeaseForOperation(input.handle);
1044
- let cleanupSucceeded = false;
812
+ const record = await this.sessionStore.load(input.handle.acpxRecordId ?? input.handle.sessionKey);
813
+ let closeSucceeded;
814
+ const delegate = this.resolveDelegateForLoadedRecord(input.handle, record);
1045
815
  try {
1046
- const record = await this.sessionStore.load(input.handle.acpxRecordId ?? input.handle.sessionKey);
1047
- let closeSucceeded;
1048
- const delegate = this.resolveDelegateForLoadedRecord(input.handle, record);
1049
- try {
1050
- await delegate.close({
1051
- handle: input.handle,
1052
- reason: input.reason,
1053
- discardPersistentState: input.discardPersistentState
1054
- });
1055
- closeSucceeded = true;
1056
- } finally {
1057
- await this.cleanupProcessTreeForRecord(input.handle, record);
1058
- cleanupSucceeded = true;
1059
- }
1060
- if (closeSucceeded) this.releaseManagedToolsDelegateForSession(input.handle.sessionKey);
1061
- if (closeSucceeded && input.discardPersistentState) this.sessionStore.markFresh(input.handle.sessionKey);
816
+ await delegate.close({
817
+ handle: input.handle,
818
+ reason: input.reason,
819
+ discardPersistentState: input.discardPersistentState
820
+ });
821
+ closeSucceeded = true;
1062
822
  } finally {
1063
- if (cleanupSucceeded) await this.finalizeProcessLeaseForOperation(input.handle, closeLease);
1064
- else await this.retirePendingProcessLease(closeLease);
823
+ await this.cleanupProcessTreeForRecord(input.handle, record);
1065
824
  }
825
+ if (closeSucceeded) this.releaseOpenClawToolsDelegateForSession(input.handle.sessionKey);
826
+ if (closeSucceeded && input.discardPersistentState) this.sessionStore.markFresh(input.handle.sessionKey);
1066
827
  }
1067
828
  };
1068
829
  /** Test-only hooks for ACPX runtime behavior that is otherwise private. */
1069
830
  const testing = {
1070
831
  appendCodexAcpConfigOverrides,
1071
832
  assertSupportedRuntimeSessionMode,
1072
- classifyCodexAcpModelRequest,
833
+ codexAcpSessionModelId,
1073
834
  isClaudeAcpCommand,
1074
835
  isCodexAcpCommand,
1075
- normalizeAgentCommand,
1076
- normalizeClaudeAcpModelOverride
836
+ normalizeClaudeAcpModelOverride,
837
+ normalizeCodexAcpModelOverride
1077
838
  };
1078
839
  //#endregion
1079
840
  export { ACPX_BACKEND_ID, AcpxRuntime, testing as __testing, testing, createAcpRuntime, createAgentRegistry, createFileSessionStore, decodeAcpxRuntimeHandleState, encodeAcpxRuntimeHandleState };