@openclaw/acpx 2026.7.2-beta.1 → 2026.7.2-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +33 -17
- package/dist/{process-reaper-B29BzBk4.js → process-reaper-CoGRyMJ_.js} +26 -4
- package/dist/{register.runtime-DBqbPx5P.js → register.runtime-BrVpU-xc.js} +1 -1
- package/dist/register.runtime.js +1 -1
- package/dist/{runtime-D_fW1HnP.js → runtime-CMARmJuS.js} +118 -75
- package/dist/{service-Dm8hpy-C.js → service-D6LQXIcJ.js} +173 -21
- package/npm-shrinkwrap.json +299 -58
- package/package.json +6 -5
- package/skills/acp-router/SKILL.md +1 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { t as createAcpxRuntimeService } from "./register.runtime-
|
|
1
|
+
import { t as createAcpxRuntimeService } from "./register.runtime-BrVpU-xc.js";
|
|
2
2
|
import "./config-schema-lrk5nlcV.js";
|
|
3
3
|
import { tryDispatchAcpReplyHook } from "openclaw/plugin-sdk/acp-runtime-backend";
|
|
4
4
|
import { finiteSecondsToTimerSafeMilliseconds } from "openclaw/plugin-sdk/number-runtime";
|
|
5
5
|
import process$1 from "node:process";
|
|
6
|
-
import { decodeNodePtyResumeParams,
|
|
6
|
+
import { decodeNodePtyResumeParams, resolveNodeHostExecutable, runNodePtyCommand } from "openclaw/plugin-sdk/node-host";
|
|
7
7
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
8
|
+
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
8
9
|
import { createReadStream, readFileSync, statSync } from "node:fs";
|
|
9
10
|
import fs$1 from "node:fs/promises";
|
|
10
11
|
import path from "node:path";
|
|
@@ -389,7 +390,7 @@ async function readPiSessionById(threadId, env) {
|
|
|
389
390
|
const LOCAL_HOST_ID$1 = "gateway";
|
|
390
391
|
const DEFAULT_PAGE_LIMIT = 20;
|
|
391
392
|
const MAX_PAGE_LIMIT$1 = 100;
|
|
392
|
-
const MAX_SEARCH_LENGTH
|
|
393
|
+
const MAX_SEARCH_LENGTH = 500;
|
|
393
394
|
const MAX_CURSOR_LENGTH$1 = 128;
|
|
394
395
|
const MAX_TRANSCRIPT_ITEM_BYTES = 512 * 1024;
|
|
395
396
|
const MAX_TRANSCRIPT_PAGE_BYTES = 20 * 1024 * 1024;
|
|
@@ -483,7 +484,7 @@ function parseListParams(value) {
|
|
|
483
484
|
"cursor"
|
|
484
485
|
].includes(key));
|
|
485
486
|
if (unknown) throw new Error(`unknown Pi session list parameter: ${unknown}`);
|
|
486
|
-
const searchTerm = optionalPiString(value.searchTerm, MAX_SEARCH_LENGTH
|
|
487
|
+
const searchTerm = optionalPiString(value.searchTerm, MAX_SEARCH_LENGTH);
|
|
487
488
|
if (value.searchTerm !== void 0 && !searchTerm) throw new Error("searchTerm is invalid");
|
|
488
489
|
const cursor = optionalPiString(value.cursor, MAX_CURSOR_LENGTH$1);
|
|
489
490
|
if (value.cursor !== void 0 && !cursor) throw new Error("cursor is invalid");
|
|
@@ -534,7 +535,7 @@ function isoTimestamp(message, entry) {
|
|
|
534
535
|
function jsonText(value, maxLength = 2e4) {
|
|
535
536
|
try {
|
|
536
537
|
const text = JSON.stringify(value);
|
|
537
|
-
return text.length > maxLength ? `${text
|
|
538
|
+
return text.length > maxLength ? `${truncateUtf16Safe(text, maxLength)}…` : text;
|
|
538
539
|
} catch {
|
|
539
540
|
return;
|
|
540
541
|
}
|
|
@@ -693,7 +694,6 @@ const LOCAL_HOST_ID = "gateway";
|
|
|
693
694
|
const MAX_PAGE_LIMIT = 100;
|
|
694
695
|
const MAX_HOSTS = 100;
|
|
695
696
|
const MAX_CURSOR_LENGTH = 128;
|
|
696
|
-
const MAX_SEARCH_LENGTH = 500;
|
|
697
697
|
const NODE_TIMEOUT_MS = 2e4;
|
|
698
698
|
const SESSION_ID_PATTERN = /^(?!-)[A-Za-z0-9._:-]{1,256}$/u;
|
|
699
699
|
const TRANSCRIPT_ITEM_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -762,15 +762,23 @@ function createPiSessionNodeHostCommands() {
|
|
|
762
762
|
isAvailable: ({ config, env }) => storeAvailable({
|
|
763
763
|
config,
|
|
764
764
|
env
|
|
765
|
-
}) && Boolean(
|
|
765
|
+
}) && Boolean(resolveNodeHostExecutable("pi", {
|
|
766
|
+
env,
|
|
767
|
+
pathEnv: env.PATH ?? env.Path ?? "",
|
|
768
|
+
strategy: "direct"
|
|
769
|
+
})),
|
|
766
770
|
handle: async (paramsJSON, io) => {
|
|
767
771
|
if (!io) throw new Error("Pi terminal command requires duplex transport");
|
|
768
772
|
const params = decodeNodePtyResumeParams(paramsJSON, validatePiThreadId);
|
|
769
773
|
const record = await requireLocalPiSession(params.threadId);
|
|
770
|
-
const
|
|
771
|
-
|
|
774
|
+
const resolution = resolveNodeHostExecutable("pi", {
|
|
775
|
+
env: process$1.env,
|
|
776
|
+
pathEnv: process$1.env.PATH ?? process$1.env.Path ?? "",
|
|
777
|
+
strategy: "direct"
|
|
778
|
+
});
|
|
779
|
+
if (!resolution) throw new Error("Pi CLI is unavailable");
|
|
772
780
|
return JSON.stringify(await runNodePtyCommand({
|
|
773
|
-
file,
|
|
781
|
+
file: resolution.executable,
|
|
774
782
|
args: ["--session", params.threadId],
|
|
775
783
|
cwd: record.cwd,
|
|
776
784
|
cols: params.cols,
|
|
@@ -828,7 +836,7 @@ async function listPiNodeHost(runtime, query, node) {
|
|
|
828
836
|
command: PI_SESSIONS_LIST_COMMAND,
|
|
829
837
|
params: {
|
|
830
838
|
...query.limitPerHost ? { limit: query.limitPerHost } : {},
|
|
831
|
-
...query.search
|
|
839
|
+
...query.search ? { searchTerm: query.search } : {},
|
|
832
840
|
...query.cursors?.[hostId] ? { cursor: query.cursors[hostId] } : {}
|
|
833
841
|
},
|
|
834
842
|
timeoutMs: NODE_TIMEOUT_MS,
|
|
@@ -874,7 +882,6 @@ function parseNodeTranscriptPage(value, threadId) {
|
|
|
874
882
|
}
|
|
875
883
|
async function listPiHosts(runtime, query) {
|
|
876
884
|
const requested = query.hostIds ? new Set(query.hostIds) : void 0;
|
|
877
|
-
const searchTerm = query.search?.trim().slice(0, MAX_SEARCH_LENGTH) || void 0;
|
|
878
885
|
const hosts = [];
|
|
879
886
|
if ((!requested || requested.has(LOCAL_HOST_ID)) && piSessionStoreAvailable(process$1.env)) try {
|
|
880
887
|
hosts.push({
|
|
@@ -884,9 +891,13 @@ async function listPiHosts(runtime, query) {
|
|
|
884
891
|
connected: true,
|
|
885
892
|
...await listLocalPiSessionPage({
|
|
886
893
|
limit: query.limitPerHost,
|
|
887
|
-
...
|
|
894
|
+
...query.search ? { searchTerm: query.search } : {},
|
|
888
895
|
cursor: query.cursors?.[LOCAL_HOST_ID]
|
|
889
|
-
}).then((page) => setTerminalCapability(page,
|
|
896
|
+
}).then((page) => setTerminalCapability(page, resolveNodeHostExecutable("pi", {
|
|
897
|
+
env: process$1.env,
|
|
898
|
+
pathEnv: process$1.env.PATH ?? "",
|
|
899
|
+
strategy: "fallback"
|
|
900
|
+
}) !== void 0))
|
|
890
901
|
});
|
|
891
902
|
} catch {
|
|
892
903
|
hosts.push({
|
|
@@ -937,16 +948,21 @@ async function openPiTerminal(params) {
|
|
|
937
948
|
const title = `pi --session ${params.threadId.slice(0, 12)}…`;
|
|
938
949
|
if (params.hostId === LOCAL_HOST_ID) {
|
|
939
950
|
const record = await requireLocalPiSession(params.threadId);
|
|
940
|
-
const
|
|
941
|
-
|
|
951
|
+
const resolution = resolveNodeHostExecutable("pi", {
|
|
952
|
+
env: process$1.env,
|
|
953
|
+
pathEnv: process$1.env.PATH ?? "",
|
|
954
|
+
strategy: "fallback"
|
|
955
|
+
});
|
|
956
|
+
if (!resolution) throw new Error("Pi CLI is unavailable");
|
|
942
957
|
return {
|
|
943
958
|
kind: "local",
|
|
944
959
|
argv: [
|
|
945
|
-
executable,
|
|
960
|
+
resolution.executable,
|
|
946
961
|
"--session",
|
|
947
962
|
params.threadId
|
|
948
963
|
],
|
|
949
964
|
...record.cwd ? { cwd: record.cwd } : {},
|
|
965
|
+
...resolution.pathEnv ? { pathEnv: resolution.pathEnv } : {},
|
|
950
966
|
title
|
|
951
967
|
};
|
|
952
968
|
}
|
|
@@ -7,6 +7,12 @@ import fs from "node:fs";
|
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import { runExec } from "openclaw/plugin-sdk/process-runtime";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
|
+
//#region extensions/acpx/src/codex-adapter.ts
|
|
11
|
+
const CODEX_ACP_PACKAGE = "@agentclientprotocol/codex-acp";
|
|
12
|
+
const CODEX_ACP_BIN = "codex-acp";
|
|
13
|
+
const LEGACY_CODEX_ACP_PACKAGE = "@zed-industries/codex-acp";
|
|
14
|
+
const OPENCLAW_CODEX_CONFIG_ARG = "--openclaw-codex-config";
|
|
15
|
+
//#endregion
|
|
10
16
|
//#region extensions/acpx/src/command-line.ts
|
|
11
17
|
/**
|
|
12
18
|
* Small shell-command helpers for ACPX-launched processes. Splitting supports
|
|
@@ -248,8 +254,10 @@ function resolveAcpxPluginConfig(params) {
|
|
|
248
254
|
const requireFromHere = createRequire(import.meta.url);
|
|
249
255
|
const GENERATED_WRAPPER_BASENAMES = /* @__PURE__ */ new Set(["codex-acp-wrapper.mjs", "claude-agent-acp-wrapper.mjs"]);
|
|
250
256
|
const OPENCLAW_PLUGIN_DEPS_MARKER = "/plugin-runtime-deps/";
|
|
257
|
+
const ACPX_PROCESS_LIST_TIMEOUT_MS = 2e3;
|
|
251
258
|
const OWNED_ACP_PACKAGE_NAMES = [
|
|
252
|
-
|
|
259
|
+
CODEX_ACP_PACKAGE,
|
|
260
|
+
LEGACY_CODEX_ACP_PACKAGE,
|
|
253
261
|
"@zed-industries/codex-acp-darwin-arm64",
|
|
254
262
|
"@zed-industries/codex-acp-darwin-x64",
|
|
255
263
|
"@zed-industries/codex-acp-linux-arm64",
|
|
@@ -259,7 +267,20 @@ const OWNED_ACP_PACKAGE_NAMES = [
|
|
|
259
267
|
"@agentclientprotocol/claude-agent-acp",
|
|
260
268
|
"acpx"
|
|
261
269
|
];
|
|
262
|
-
const
|
|
270
|
+
const PLUGIN_DEPS_CODEX_PACKAGE_NAMES = [
|
|
271
|
+
"@openai/codex",
|
|
272
|
+
"@openai/codex-darwin-arm64",
|
|
273
|
+
"@openai/codex-darwin-x64",
|
|
274
|
+
"@openai/codex-linux-arm64",
|
|
275
|
+
"@openai/codex-linux-x64",
|
|
276
|
+
"@openai/codex-win32-arm64",
|
|
277
|
+
"@openai/codex-win32-x64"
|
|
278
|
+
];
|
|
279
|
+
const ACP_PACKAGE_MARKERS = [
|
|
280
|
+
...OWNED_ACP_PACKAGE_NAMES.map((packageName) => `/node_modules/${packageName}/`),
|
|
281
|
+
...PLUGIN_DEPS_CODEX_PACKAGE_NAMES.map((packageName) => `/node_modules/${packageName}/`),
|
|
282
|
+
"/acpx/dist/"
|
|
283
|
+
];
|
|
263
284
|
function normalizePathLike(value) {
|
|
264
285
|
return value.replaceAll("\\", "/");
|
|
265
286
|
}
|
|
@@ -354,7 +375,8 @@ async function listPlatformProcesses() {
|
|
|
354
375
|
if (process.platform === "win32") return [];
|
|
355
376
|
const { stdout } = await runExec("ps", ["-axo", "pid=,ppid=,command="], {
|
|
356
377
|
logOutput: false,
|
|
357
|
-
maxBuffer: 8 * 1024 * 1024
|
|
378
|
+
maxBuffer: 8 * 1024 * 1024,
|
|
379
|
+
timeoutMs: ACPX_PROCESS_LIST_TIMEOUT_MS
|
|
358
380
|
});
|
|
359
381
|
return parseProcessList(stdout);
|
|
360
382
|
}
|
|
@@ -488,4 +510,4 @@ async function reapStaleOpenClawOwnedAcpxOrphans(params) {
|
|
|
488
510
|
};
|
|
489
511
|
}
|
|
490
512
|
//#endregion
|
|
491
|
-
export { resolveAcpxPluginRoot as a, splitCommandParts as c, resolveAcpxPluginConfig as i, isOpenClawLeaseAwareAcpxProcessCommand as n, toAcpMcpServers as o, reapStaleOpenClawOwnedAcpxOrphans as r, quoteCommandPart as s, cleanupOpenClawOwnedAcpxProcessTree as t };
|
|
513
|
+
export { resolveAcpxPluginRoot as a, splitCommandParts as c, LEGACY_CODEX_ACP_PACKAGE as d, OPENCLAW_CODEX_CONFIG_ARG as f, resolveAcpxPluginConfig as i, CODEX_ACP_BIN as l, isOpenClawLeaseAwareAcpxProcessCommand as n, toAcpMcpServers as o, reapStaleOpenClawOwnedAcpxOrphans as r, quoteCommandPart as s, cleanupOpenClawOwnedAcpxProcessTree as t, CODEX_ACP_PACKAGE as u };
|
|
@@ -200,7 +200,7 @@ function createLazyAcpRuntimeProxy(resolveRuntime) {
|
|
|
200
200
|
* immediately, then imports the heavier service only when a session needs it.
|
|
201
201
|
*/
|
|
202
202
|
const ACPX_BACKEND_ID = "acpx";
|
|
203
|
-
const loadServiceModule = createLazyRuntimeModule(() => import("./service-
|
|
203
|
+
const loadServiceModule = createLazyRuntimeModule(() => import("./service-D6LQXIcJ.js"));
|
|
204
204
|
async function startRealService(state) {
|
|
205
205
|
if (state.realRuntime) return state.realRuntime;
|
|
206
206
|
if (!state.ctx) throw new Error("ACPX runtime service is not started");
|
package/dist/register.runtime.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createAcpxRuntimeService } from "./register.runtime-
|
|
1
|
+
import { t as createAcpxRuntimeService } from "./register.runtime-BrVpU-xc.js";
|
|
2
2
|
export { createAcpxRuntimeService };
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { i as createAcpxProcessLeaseId, o as hashAcpxProcessCommand, u as withAcpxLeaseEnvironment } from "./process-lease-DiKkFj6F.js";
|
|
2
2
|
import { AcpRuntimeError } from "./runtime-api.js";
|
|
3
|
-
import { c as splitCommandParts, n as isOpenClawLeaseAwareAcpxProcessCommand, t as cleanupOpenClawOwnedAcpxProcessTree } from "./process-reaper-
|
|
3
|
+
import { c as splitCommandParts, f as OPENCLAW_CODEX_CONFIG_ARG, n as isOpenClawLeaseAwareAcpxProcessCommand, t as cleanupOpenClawOwnedAcpxProcessTree, u as CODEX_ACP_PACKAGE } from "./process-reaper-CoGRyMJ_.js";
|
|
4
4
|
import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
5
5
|
import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
|
+
import { sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
6
7
|
import fs from "node:fs/promises";
|
|
7
8
|
import path, { resolve } from "node:path";
|
|
8
9
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
9
10
|
import { ACPX_BACKEND_ID, AcpxRuntime as AcpxRuntime$1, createAcpRuntime, createAgentRegistry, createFileSessionStore, decodeAcpxRuntimeHandleState, encodeAcpxRuntimeHandleState, isRequestedModelUnsupportedError } from "acpx/runtime";
|
|
10
11
|
import { redactSensitiveText } from "openclaw/plugin-sdk/security-runtime";
|
|
11
|
-
import { sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
12
12
|
//#region extensions/acpx/src/runtime.ts
|
|
13
13
|
/**
|
|
14
14
|
* OpenClaw ACPX runtime adapter. It wraps the upstream acpx runtime with
|
|
15
15
|
* OpenClaw session metadata, lease tracking, model scoping, and cleanup policy.
|
|
16
16
|
*/
|
|
17
|
+
const ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME = "openclaw-plugin-tools";
|
|
17
18
|
const ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME = "openclaw-tools";
|
|
18
19
|
const OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV = "OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY";
|
|
19
20
|
function withOpenClawManagedTurnTimeout(input) {
|
|
@@ -165,12 +166,6 @@ const OPENCLAW_BRIDGE_SUBCOMMAND = "acp";
|
|
|
165
166
|
const CODEX_ACP_AGENT_ID = "codex";
|
|
166
167
|
const CODEX_ACP_OPENCLAW_PREFIX = "openai/";
|
|
167
168
|
const CLAUDE_ACP_OPENCLAW_PREFIX = "anthropic/";
|
|
168
|
-
const CODEX_ACP_REASONING_EFFORTS = /* @__PURE__ */ new Set([
|
|
169
|
-
"low",
|
|
170
|
-
"medium",
|
|
171
|
-
"high",
|
|
172
|
-
"xhigh"
|
|
173
|
-
]);
|
|
174
169
|
const CODEX_ACP_THINKING_ALIASES = /* @__PURE__ */ new Map([
|
|
175
170
|
["off", void 0],
|
|
176
171
|
["minimal", "low"],
|
|
@@ -256,7 +251,7 @@ function isOpenClawBridgeCommand(command) {
|
|
|
256
251
|
}
|
|
257
252
|
function isCodexAcpCommand(command) {
|
|
258
253
|
return isAcpCommand(command, {
|
|
259
|
-
packageName:
|
|
254
|
+
packageName: CODEX_ACP_PACKAGE,
|
|
260
255
|
executableName: "codex-acp"
|
|
261
256
|
});
|
|
262
257
|
}
|
|
@@ -285,27 +280,50 @@ function normalizeCodexAcpReasoningEffort(rawThinking) {
|
|
|
285
280
|
if (!CODEX_ACP_THINKING_ALIASES.has(normalized)) failUnsupportedCodexAcpThinking(rawThinking ?? "");
|
|
286
281
|
return CODEX_ACP_THINKING_ALIASES.get(normalized);
|
|
287
282
|
}
|
|
288
|
-
function
|
|
283
|
+
function isCodexAcpReasoningEffortAlias(value) {
|
|
284
|
+
const normalized = value?.trim().toLowerCase();
|
|
285
|
+
return Boolean(normalized && CODEX_ACP_THINKING_ALIASES.has(normalized));
|
|
286
|
+
}
|
|
287
|
+
function classifyCodexAcpModelRequest(rawModel, rawThinking) {
|
|
289
288
|
const raw = rawModel?.trim();
|
|
290
289
|
const thinkingReasoningEffort = normalizeCodexAcpReasoningEffort(rawThinking);
|
|
291
|
-
|
|
290
|
+
const thinkingOnlyOverride = thinkingReasoningEffort ? { reasoningEffort: thinkingReasoningEffort } : void 0;
|
|
291
|
+
if (!raw) return {
|
|
292
|
+
kind: "override",
|
|
293
|
+
override: thinkingOnlyOverride ?? {}
|
|
294
|
+
};
|
|
292
295
|
let value = raw;
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
296
|
+
let hadOpenAiQualifier = false;
|
|
297
|
+
if (value.toLowerCase().startsWith(CODEX_ACP_OPENCLAW_PREFIX)) {
|
|
298
|
+
value = value.slice(7);
|
|
299
|
+
hadOpenAiQualifier = true;
|
|
300
|
+
}
|
|
301
|
+
let model = value.trim();
|
|
302
|
+
let modelReasoningEffort;
|
|
303
|
+
const slashIndex = value.lastIndexOf("/");
|
|
304
|
+
if (slashIndex >= 0 && isCodexAcpReasoningEffortAlias(value.slice(slashIndex + 1))) {
|
|
305
|
+
modelReasoningEffort = normalizeCodexAcpReasoningEffort(value.slice(slashIndex + 1));
|
|
306
|
+
model = value.slice(0, slashIndex).trim();
|
|
307
|
+
}
|
|
308
|
+
if (hadOpenAiQualifier && (!model || model.includes("/"))) failUnsupportedCodexAcpModel(raw, `Codex ACP model "${raw}" is not supported. Use openai/<model> or <model>/<reasoning-effort>.`);
|
|
309
|
+
if (!model || model.includes("/")) return thinkingOnlyOverride ? {
|
|
310
|
+
kind: "unsupported",
|
|
311
|
+
thinkingOverride: thinkingOnlyOverride
|
|
312
|
+
} : { kind: "unsupported" };
|
|
299
313
|
const reasoningEffort = thinkingReasoningEffort ?? modelReasoningEffort;
|
|
300
|
-
if (reasoningEffort && !CODEX_ACP_REASONING_EFFORTS.has(reasoningEffort)) failUnsupportedCodexAcpThinking(reasoningEffort);
|
|
301
314
|
return {
|
|
302
|
-
|
|
303
|
-
|
|
315
|
+
kind: "override",
|
|
316
|
+
override: {
|
|
317
|
+
model,
|
|
318
|
+
...reasoningEffort ? { reasoningEffort } : {}
|
|
319
|
+
}
|
|
304
320
|
};
|
|
305
321
|
}
|
|
306
|
-
function
|
|
307
|
-
|
|
308
|
-
|
|
322
|
+
function withCodexSessionModel(input, override) {
|
|
323
|
+
const next = { ...input };
|
|
324
|
+
if (override?.model) next.model = override.model;
|
|
325
|
+
else delete next.model;
|
|
326
|
+
return next;
|
|
309
327
|
}
|
|
310
328
|
function normalizeClaudeAcpModelOverride(rawModel) {
|
|
311
329
|
const raw = rawModel?.trim();
|
|
@@ -320,8 +338,9 @@ function withAcpxSessionOptions(input) {
|
|
|
320
338
|
...existingOptions,
|
|
321
339
|
model
|
|
322
340
|
} : existingOptions;
|
|
341
|
+
const { modelExplicit: _modelExplicit, ...rest } = input;
|
|
323
342
|
return {
|
|
324
|
-
...
|
|
343
|
+
...rest,
|
|
325
344
|
...sessionOptions ? { sessionOptions } : {}
|
|
326
345
|
};
|
|
327
346
|
}
|
|
@@ -344,10 +363,12 @@ function quoteShellArg(value) {
|
|
|
344
363
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
345
364
|
}
|
|
346
365
|
function appendCodexAcpConfigOverrides(command, override) {
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
366
|
+
const config = {
|
|
367
|
+
...override.model ? { model: override.model } : {},
|
|
368
|
+
...override.reasoningEffort ? { model_reasoning_effort: override.reasoningEffort } : {}
|
|
369
|
+
};
|
|
370
|
+
if (Object.keys(config).length === 0) return command;
|
|
371
|
+
return `${command} ${OPENCLAW_CODEX_CONFIG_ARG} ${quoteShellArg(JSON.stringify(config))}`;
|
|
351
372
|
}
|
|
352
373
|
function createModelScopedAgentRegistry(params) {
|
|
353
374
|
return {
|
|
@@ -375,12 +396,14 @@ function shouldUseDistinctBridgeDelegate(options) {
|
|
|
375
396
|
const { mcpServers } = options;
|
|
376
397
|
return Array.isArray(mcpServers) && mcpServers.length > 0;
|
|
377
398
|
}
|
|
378
|
-
function
|
|
399
|
+
function withManagedToolsMcpSessionEnv(params) {
|
|
379
400
|
const sessionKey = params.sessionKey.trim();
|
|
380
|
-
if (!params.
|
|
401
|
+
if (!params.pluginToolsEnabled && !params.openclawToolsEnabled || !sessionKey || !params.mcpServers?.length) return params.mcpServers;
|
|
381
402
|
let changed = false;
|
|
382
403
|
const nextServers = params.mcpServers.map((server) => {
|
|
383
|
-
|
|
404
|
+
const isManagedPluginTools = params.pluginToolsEnabled && server.name === ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME;
|
|
405
|
+
const isManagedOpenClawTools = params.openclawToolsEnabled && server.name === ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME;
|
|
406
|
+
if (!isManagedPluginTools && !isManagedOpenClawTools || !("command" in server)) return server;
|
|
384
407
|
changed = true;
|
|
385
408
|
const env = [...server.env.filter((entry) => entry.name !== OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV), {
|
|
386
409
|
name: OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV,
|
|
@@ -397,14 +420,16 @@ function withOpenClawToolsMcpSessionEnv(params) {
|
|
|
397
420
|
var AcpxRuntime = class {
|
|
398
421
|
constructor(options, testOptions) {
|
|
399
422
|
this.codexAcpModelOverrideScope = new AsyncLocalStorage();
|
|
400
|
-
this.
|
|
423
|
+
this.managedToolsSessionDelegates = /* @__PURE__ */ new Map();
|
|
401
424
|
this.launchLeaseScope = new AsyncLocalStorage();
|
|
402
425
|
const { openclawProcessCleanup, ...delegateTestOptions } = testOptions ?? {};
|
|
403
426
|
this.processCleanupDeps = openclawProcessCleanup;
|
|
404
427
|
this.wrapperRoot = options.openclawWrapperRoot;
|
|
405
428
|
this.gatewayInstanceId = options.openclawGatewayInstanceId;
|
|
406
429
|
this.processLeaseStore = options.openclawProcessLeaseStore;
|
|
430
|
+
this.pluginToolsMcpBridgeEnabled = options.pluginToolsMcpBridgeEnabled === true;
|
|
407
431
|
this.openclawToolsMcpBridgeEnabled = options.openclawToolsMcpBridgeEnabled === true;
|
|
432
|
+
this.managedToolsMcpBridgeEnabled = this.pluginToolsMcpBridgeEnabled || this.openclawToolsMcpBridgeEnabled;
|
|
408
433
|
this.cwd = options.cwd;
|
|
409
434
|
this.sessionStore = createResetAwareSessionStore(options.sessionStore, {
|
|
410
435
|
gatewayInstanceId: this.gatewayInstanceId,
|
|
@@ -433,35 +458,36 @@ var AcpxRuntime = class {
|
|
|
433
458
|
agentName: normalizeAgentName(options.probeAgent) ?? "codex",
|
|
434
459
|
agentRegistry: this.agentRegistry
|
|
435
460
|
});
|
|
436
|
-
const useBridgeSafeProbe = this.
|
|
461
|
+
const useBridgeSafeProbe = this.managedToolsMcpBridgeEnabled || shouldUseBridgeSafeDelegateForCommand(probeCommand);
|
|
437
462
|
this.probeDelegate = useBridgeSafeProbe ? this.bridgeSafeDelegate : this.delegate;
|
|
438
463
|
}
|
|
439
464
|
resolveDelegateForSession(params) {
|
|
440
465
|
if (shouldUseBridgeSafeDelegateForCommand(params.command)) return this.bridgeSafeDelegate;
|
|
441
|
-
return this.
|
|
466
|
+
return this.resolveManagedToolsDelegateForSession(params.sessionKey);
|
|
442
467
|
}
|
|
443
|
-
|
|
444
|
-
if (!this.
|
|
468
|
+
resolveManagedToolsDelegateForSession(sessionKey) {
|
|
469
|
+
if (!this.managedToolsMcpBridgeEnabled) return this.delegate;
|
|
445
470
|
const normalizedSessionKey = sessionKey.trim();
|
|
446
471
|
if (!normalizedSessionKey) return this.delegate;
|
|
447
|
-
const cached = this.
|
|
472
|
+
const cached = this.managedToolsSessionDelegates.get(normalizedSessionKey);
|
|
448
473
|
if (cached) return cached;
|
|
449
474
|
const delegate = new AcpxRuntime$1({
|
|
450
475
|
...this.delegateOptions,
|
|
451
|
-
mcpServers:
|
|
452
|
-
|
|
476
|
+
mcpServers: withManagedToolsMcpSessionEnv({
|
|
477
|
+
pluginToolsEnabled: this.pluginToolsMcpBridgeEnabled,
|
|
478
|
+
openclawToolsEnabled: this.openclawToolsMcpBridgeEnabled,
|
|
453
479
|
mcpServers: this.delegateOptions.mcpServers,
|
|
454
480
|
sessionKey: normalizedSessionKey
|
|
455
481
|
})
|
|
456
482
|
}, this.delegateTestOptions);
|
|
457
|
-
this.
|
|
483
|
+
this.managedToolsSessionDelegates.set(normalizedSessionKey, delegate);
|
|
458
484
|
return delegate;
|
|
459
485
|
}
|
|
460
|
-
|
|
461
|
-
if (!this.
|
|
486
|
+
releaseManagedToolsDelegateForSession(sessionKey) {
|
|
487
|
+
if (!this.managedToolsMcpBridgeEnabled) return;
|
|
462
488
|
const normalizedSessionKey = sessionKey.trim();
|
|
463
489
|
if (!normalizedSessionKey) return;
|
|
464
|
-
this.
|
|
490
|
+
this.managedToolsSessionDelegates.delete(normalizedSessionKey);
|
|
465
491
|
}
|
|
466
492
|
async resolveDelegateForHandle(handle) {
|
|
467
493
|
const record = await this.sessionStore.load(handle.acpxRecordId ?? handle.sessionKey);
|
|
@@ -613,9 +639,18 @@ var AcpxRuntime = class {
|
|
|
613
639
|
command,
|
|
614
640
|
sessionKey: input.sessionKey
|
|
615
641
|
});
|
|
642
|
+
const isCodexAcp = normalizeAgentName(input.agent) === CODEX_ACP_AGENT_ID && isCodexAcpCommand(command);
|
|
616
643
|
const claudeModelOverride = isClaudeAcpCommand(command) ? normalizeClaudeAcpModelOverride(input.model) : void 0;
|
|
617
|
-
const
|
|
618
|
-
|
|
644
|
+
const codexClassification = isCodexAcp ? classifyCodexAcpModelRequest(input.model, input.thinking) : void 0;
|
|
645
|
+
if (codexClassification?.kind === "unsupported" && input.modelExplicit) failUnsupportedCodexAcpModel(input.model ?? "");
|
|
646
|
+
const classifiedCodexOverride = codexClassification?.kind === "override" ? codexClassification.override : codexClassification?.thinkingOverride;
|
|
647
|
+
const codexModelOverride = classifiedCodexOverride && Object.keys(classifiedCodexOverride).length > 0 ? classifiedCodexOverride : void 0;
|
|
648
|
+
const requestedModel = input.model?.trim();
|
|
649
|
+
const appliedModel = isCodexAcp && requestedModel ? codexModelOverride?.model ? {
|
|
650
|
+
kind: "applied",
|
|
651
|
+
model: requestedModel
|
|
652
|
+
} : { kind: "dropped" } : void 0;
|
|
653
|
+
const ensureInput = isCodexAcp ? withCodexSessionModel(input, codexModelOverride) : claudeModelOverride ? {
|
|
619
654
|
...input,
|
|
620
655
|
model: claudeModelOverride
|
|
621
656
|
} : input;
|
|
@@ -627,7 +662,7 @@ var AcpxRuntime = class {
|
|
|
627
662
|
command: stableLaunchCommand,
|
|
628
663
|
resumeSessionId: input.resumeSessionId
|
|
629
664
|
});
|
|
630
|
-
|
|
665
|
+
const handle = !codexModelOverride ? await this.runWithLaunchLease({
|
|
631
666
|
sessionKey: ensureInput.sessionKey,
|
|
632
667
|
command: stableLaunchCommand,
|
|
633
668
|
enabled: shouldStartWithLease,
|
|
@@ -636,21 +671,20 @@ var AcpxRuntime = class {
|
|
|
636
671
|
fallbackCode: "ACP_SESSION_INIT_FAILED",
|
|
637
672
|
run: () => ensureDelegateSessionWithModelFallback(delegate, ensureInput)
|
|
638
673
|
})
|
|
639
|
-
})
|
|
640
|
-
const normalizedInput = {
|
|
641
|
-
...ensureInput,
|
|
642
|
-
...codexAcpSessionModelId(codexModelOverride) ? { model: codexAcpSessionModelId(codexModelOverride) } : {}
|
|
643
|
-
};
|
|
644
|
-
return await this.runWithLaunchLease({
|
|
674
|
+
}) : await this.runWithLaunchLease({
|
|
645
675
|
sessionKey: input.sessionKey,
|
|
646
676
|
command: stableLaunchCommand,
|
|
647
677
|
enabled: shouldStartWithLease,
|
|
648
678
|
run: () => this.codexAcpModelOverrideScope.run(codexModelOverride, () => this.withCodexWrapperDiagnostics({
|
|
649
679
|
command: stableLaunchCommand,
|
|
650
680
|
fallbackCode: "ACP_SESSION_INIT_FAILED",
|
|
651
|
-
run: () => delegate.ensureSession(withAcpxSessionOptions(
|
|
681
|
+
run: () => delegate.ensureSession(withAcpxSessionOptions(ensureInput))
|
|
652
682
|
}))
|
|
653
683
|
});
|
|
684
|
+
return appliedModel ? {
|
|
685
|
+
...handle,
|
|
686
|
+
appliedModel
|
|
687
|
+
} : handle;
|
|
654
688
|
}
|
|
655
689
|
async *runTurn(input) {
|
|
656
690
|
const command = await this.resolveCommandForHandle(input.handle);
|
|
@@ -751,8 +785,8 @@ var AcpxRuntime = class {
|
|
|
751
785
|
}
|
|
752
786
|
};
|
|
753
787
|
}
|
|
754
|
-
getCapabilities() {
|
|
755
|
-
return this.delegate.getCapabilities();
|
|
788
|
+
getCapabilities(input) {
|
|
789
|
+
return this.delegate.getCapabilities(input);
|
|
756
790
|
}
|
|
757
791
|
async getStatus(input) {
|
|
758
792
|
return (await this.resolveDelegateForHandle(input.handle)).getStatus(input);
|
|
@@ -767,22 +801,32 @@ var AcpxRuntime = class {
|
|
|
767
801
|
const isCodexAcp = isCodexAcpCommand(command);
|
|
768
802
|
if (WIRE_TIMEOUT_CONFIG_KEYS.has(key) && (isCodexAcp || isClaudeAcpCommand(command))) return;
|
|
769
803
|
if (isCodexAcp) {
|
|
770
|
-
if (key === "model"
|
|
771
|
-
const
|
|
772
|
-
if (
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
804
|
+
if (key === "model") {
|
|
805
|
+
const classification = classifyCodexAcpModelRequest(input.value);
|
|
806
|
+
if (classification.kind === "unsupported") failUnsupportedCodexAcpModel(input.value);
|
|
807
|
+
const { override } = classification;
|
|
808
|
+
if (override.model) await delegate.setConfigOption({
|
|
809
|
+
...input,
|
|
810
|
+
key: "model",
|
|
811
|
+
value: override.model
|
|
812
|
+
});
|
|
813
|
+
if (override.reasoningEffort) await delegate.setConfigOption({
|
|
814
|
+
...input,
|
|
815
|
+
key: "reasoning_effort",
|
|
816
|
+
value: override.reasoningEffort
|
|
817
|
+
});
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
if (key === "thinking" || key === "thought_level" || key === "reasoning_effort") {
|
|
821
|
+
const classification = classifyCodexAcpModelRequest(void 0, input.value);
|
|
822
|
+
const reasoningEffort = classification.kind === "override" ? classification.override.reasoningEffort : void 0;
|
|
823
|
+
if (!reasoningEffort) return;
|
|
824
|
+
await delegate.setConfigOption({
|
|
825
|
+
...input,
|
|
826
|
+
key: "reasoning_effort",
|
|
827
|
+
value: reasoningEffort
|
|
828
|
+
});
|
|
829
|
+
return;
|
|
786
830
|
}
|
|
787
831
|
}
|
|
788
832
|
if (isClaudeAcpCommand(command) && key === "model") {
|
|
@@ -815,7 +859,7 @@ var AcpxRuntime = class {
|
|
|
815
859
|
} finally {
|
|
816
860
|
await this.cleanupProcessTreeForRecord(input.handle, record);
|
|
817
861
|
}
|
|
818
|
-
if (closeSucceeded) this.
|
|
862
|
+
if (closeSucceeded) this.releaseManagedToolsDelegateForSession(input.handle.sessionKey);
|
|
819
863
|
if (closeSucceeded && input.discardPersistentState) this.sessionStore.markFresh(input.handle.sessionKey);
|
|
820
864
|
}
|
|
821
865
|
};
|
|
@@ -823,11 +867,10 @@ var AcpxRuntime = class {
|
|
|
823
867
|
const testing = {
|
|
824
868
|
appendCodexAcpConfigOverrides,
|
|
825
869
|
assertSupportedRuntimeSessionMode,
|
|
826
|
-
|
|
870
|
+
classifyCodexAcpModelRequest,
|
|
827
871
|
isClaudeAcpCommand,
|
|
828
872
|
isCodexAcpCommand,
|
|
829
|
-
normalizeClaudeAcpModelOverride
|
|
830
|
-
normalizeCodexAcpModelOverride
|
|
873
|
+
normalizeClaudeAcpModelOverride
|
|
831
874
|
};
|
|
832
875
|
//#endregion
|
|
833
876
|
export { ACPX_BACKEND_ID, AcpxRuntime, testing as __testing, testing, createAcpRuntime, createAgentRegistry, createFileSessionStore, decodeAcpxRuntimeHandleState, encodeAcpxRuntimeHandleState };
|