


























@@ -349,73 +349,72 @@ function unwrapEnvCommand(parts: string[]): string[] {
349349return parts.slice(index);
350350}
351351352-function isOpenClawBridgeCommand(command: string | undefined): boolean {
353-if (!command) {
354-return false;
355-}
356-const parts = unwrapEnvCommand(splitCommandParts(command.trim()));
357-if (basename(parts[0] ?? "") === OPENCLAW_BRIDGE_EXECUTABLE) {
358-return parts[1] === OPENCLAW_BRIDGE_SUBCOMMAND;
359-}
360-if (basename(parts[0] ?? "") !== "node") {
361-return false;
362-}
363-const scriptName = basename(parts[1] ?? "");
364-return /^openclaw(?:\.[cm]?js)?$/i.test(scriptName) && parts[2] === OPENCLAW_BRIDGE_SUBCOMMAND;
352+function matchesExecutableName(value: string, executableName: string): boolean {
353+const normalized = basename(value).toLowerCase();
354+return normalized === executableName || normalized === `${executableName}.exe`;
365355}
366356367-function isCodexAcpPackageSpec(value: string): boolean {
368-return /^@zed-industries\/codex-acp(?:@.+)?$/i.test(value.trim());
357+function matchesPackageSpec(value: string, packageName: string): boolean {
358+const normalized = value.trim().toLowerCase();
359+return normalized === packageName || normalized.startsWith(`${packageName}@`);
369360}
370361371-function isCodexAcpCommand(command: string | undefined): boolean {
362+function stripModuleExtension(value: string): string {
363+return value.replace(/\.[cm]?js$/i, "").toLowerCase();
364+}
365+366+function isAcpCommand(
367+command: string | undefined,
368+params: { packageName: string; executableName: string },
369+): boolean {
372370if (!command) {
373371return false;
374372}
375373const parts = unwrapEnvCommand(splitCommandParts(command.trim()));
376374if (!parts.length) {
377375return false;
378376}
379-if (parts.some(isCodexAcpPackageSpec)) {
377+if (parts.some((part) => matchesPackageSpec(part, params.packageName))) {
380378return true;
381379}
382380const commandName = basename(parts[0] ?? "");
383-if (/^codex-acp(?:\.exe)?$/i.test(commandName)) {
381+if (matchesExecutableName(commandName, params.executableName)) {
384382return true;
385383}
386-if (commandName !== "node") {
384+if (!matchesExecutableName(commandName, "node")) {
387385return false;
388386}
389-const scriptName = basename(parts[1] ?? "");
390-return /^codex-acp(?:-wrapper)?(?:\.[cm]?js)?$/i.test(scriptName);
387+const scriptName = stripModuleExtension(basename(parts[1] ?? ""));
388+return scriptName === params.executableName || scriptName === `${params.executableName}-wrapper`;
391389}
392390393-function isClaudeAcpPackageSpec(value: string): boolean {
394-return /^@agentclientprotocol\/claude-agent-acp(?:@.+)?$/i.test(value.trim());
395-}
396-397-function isClaudeAcpCommand(command: string | undefined): boolean {
391+function isOpenClawBridgeCommand(command: string | undefined): boolean {
398392if (!command) {
399393return false;
400394}
401395const parts = unwrapEnvCommand(splitCommandParts(command.trim()));
402-if (!parts.length) {
403-return false;
404-}
405-if (parts.some(isClaudeAcpPackageSpec)) {
406-return true;
407-}
408-const commandName = basename(parts[0] ?? "");
409-if (/^claude-agent-acp(?:\.exe)?$/i.test(commandName)) {
410-return true;
396+if (basename(parts[0] ?? "") === OPENCLAW_BRIDGE_EXECUTABLE) {
397+return parts[1] === OPENCLAW_BRIDGE_SUBCOMMAND;
411398}
412-// Generated wrappers are launched via `process.execPath`, which is
413-// `node.exe` on Windows.
414-if (!/^node(?:\.exe)?$/i.test(commandName)) {
399+if (basename(parts[0] ?? "") !== "node") {
415400return false;
416401}
417402const scriptName = basename(parts[1] ?? "");
418-return /^claude-agent-acp(?:-wrapper)?(?:\.[cm]?js)?$/i.test(scriptName);
403+return /^openclaw(?:\.[cm]?js)?$/i.test(scriptName) && parts[2] === OPENCLAW_BRIDGE_SUBCOMMAND;
404+}
405+406+function isCodexAcpCommand(command: string | undefined): boolean {
407+return isAcpCommand(command, {
408+packageName: "@zed-industries/codex-acp",
409+executableName: "codex-acp",
410+});
411+}
412+413+function isClaudeAcpCommand(command: string | undefined): boolean {
414+return isAcpCommand(command, {
415+packageName: "@agentclientprotocol/claude-agent-acp",
416+executableName: "claude-agent-acp",
417+});
419418}
420419421420function failUnsupportedCodexAcpModel(rawModel: string, detail?: string): never {
@@ -431,6 +430,7 @@ function failUnsupportedCodexAcpModel(rawModel: string, detail?: string): never
431430// `SessionResumeRequiredError` on agent restart. Fail fast at this boundary instead.
432431// See openclaw/openclaw#73071.
433432const SUPPORTED_RUNTIME_SESSION_MODES = new Set(["persistent", "oneshot"] as const);
433+const WIRE_TIMEOUT_CONFIG_KEYS = new Set(["timeout", "timeout_seconds"]);
434434435435function assertSupportedRuntimeSessionMode(
436436mode: unknown,
@@ -917,17 +917,11 @@ export class AcpxRuntime implements AcpRuntime {
917917const delegate = await this.resolveDelegateForHandle(input.handle);
918918const command = await this.resolveCommandForHandle(input.handle);
919919const key = input.key.trim().toLowerCase();
920-// Neither @zed-industries/codex-acp nor @agentclientprotocol/claude-agent-acp
921-// advertises a `timeout` config option; forwarding one triggers a JSON-RPC
922-// rejection that surfaces as ACP_TURN_FAILED. OpenClaw still enforces the
923-// per-turn timeout in-process via runTimeoutSeconds.
924-if (
925-(key === "timeout" || key === "timeout_seconds") &&
926-(isCodexAcpCommand(command) || isClaudeAcpCommand(command))
927-) {
920+const isCodexAcp = isCodexAcpCommand(command);
921+if (WIRE_TIMEOUT_CONFIG_KEYS.has(key) && (isCodexAcp || isClaudeAcpCommand(command))) {
928922return;
929923}
930-if (isCodexAcpCommand(command)) {
924+if (isCodexAcp) {
931925if (
932926key === "model" ||
933927key === "thinking" ||
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。