









@@ -48,7 +48,11 @@ import {
4848type NativeHookRelayEvent,
4949type NativeHookRelayRegistrationHandle,
5050} from "openclaw/plugin-sdk/agent-harness-runtime";
51-import { markAuthProfileBlockedUntil, resolveAgentDir } from "openclaw/plugin-sdk/agent-runtime";
51+import {
52+markAuthProfileBlockedUntil,
53+resolveAgentConfig,
54+resolveAgentDir,
55+} from "openclaw/plugin-sdk/agent-runtime";
5256import {
5357emitTrustedDiagnosticEvent,
5458hasPendingInternalDiagnosticEvent,
@@ -956,6 +960,7 @@ export async function runCodexAppServerAttempt(
956960});
957961const sandboxExecServerEnabled = isCodexSandboxExecServerEnabled(pluginConfig);
958962const nativeToolSurfaceEnabled = shouldEnableCodexAppServerNativeToolSurface(params, sandbox, {
963+agentId: sessionAgentId,
959964 sandboxExecServerEnabled,
960965});
961966for (const diagnostic of bundleMcpThreadConfig.diagnostics) {
@@ -3666,10 +3671,14 @@ async function buildDynamicTools(input: DynamicToolBuildParams) {
36663671input.runAbortController.abort("sessions_yield");
36673672},
36683673});
3669-const codexFilteredTools = addSandboxShellDynamicToolsIfAvailable(
3670-isCodexMemoryFlushRun(params)
3671- ? filterCodexMemoryFlushDynamicTools(allTools)
3672- : filterCodexDynamicTools(allTools, input.pluginConfig),
3674+const codexFilteredTools = addNodeShellDynamicToolsIfNeeded(
3675+addSandboxShellDynamicToolsIfAvailable(
3676+isCodexMemoryFlushRun(params)
3677+ ? filterCodexMemoryFlushDynamicTools(allTools)
3678+ : filterCodexDynamicTools(allTools, input.pluginConfig),
3679+allTools,
3680+input,
3681+),
36733682allTools,
36743683input,
36753684);
@@ -3713,11 +3722,14 @@ function includeForcedMessageToolAllow(
37133722function shouldEnableCodexAppServerNativeToolSurface(
37143723params: EmbeddedRunAttemptParams,
37153724sandbox?: OpenClawSandboxContext,
3716-options: { sandboxExecServerEnabled?: boolean } = {},
3725+options: { agentId?: string; sandboxExecServerEnabled?: boolean } = {},
37173726): boolean {
37183727if (isCodexMemoryFlushRun(params)) {
37193728return false;
37203729}
3730+if (isEffectiveExecHostNode(params, options.agentId)) {
3731+return false;
3732+}
37213733const toolsAllow = includeForcedMessageToolAllow(params.toolsAllow, params);
37223734if (toolsAllow === undefined) {
37233735return canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox, options);
@@ -3731,6 +3743,14 @@ function shouldEnableCodexAppServerNativeToolSurface(
37313743);
37323744}
373337453746+function isEffectiveExecHostNode(params: EmbeddedRunAttemptParams, agentId?: string): boolean {
3747+const agentExec =
3748+params.config && agentId ? resolveAgentConfig(params.config, agentId)?.tools?.exec : undefined;
3749+return (
3750+(params.execOverrides?.host ?? agentExec?.host ?? params.config?.tools?.exec?.host) === "node"
3751+);
3752+}
3753+37343754function canCodexAppServerNativeToolSurfaceHonorSandbox(
37353755sandbox: OpenClawSandboxContext | undefined,
37363756options: { sandboxExecServerEnabled?: boolean } = {},
@@ -3882,22 +3902,58 @@ function shouldExposeSandboxExecDynamicTool(input: DynamicToolBuildParams): bool
38823902if (isCodexMemoryFlushRun(input.params)) {
38833903return false;
38843904}
3905+if (isEffectiveExecHostNode(input.params, input.sessionAgentId)) {
3906+return false;
3907+}
38853908const backendId = input.sandbox?.enabled ? input.sandbox.backendId.trim().toLowerCase() : "";
38863909return Boolean(backendId && input.nativeToolSurfaceEnabled === false);
38873910}
388839113889-function isSandboxShellDynamicToolExcluded(config: CodexPluginConfig): boolean {
3912+function isCodexDynamicToolExcluded(config: CodexPluginConfig, names: string[]): boolean {
3913+const normalizedNames = new Set(names.map((name) => normalizeCodexDynamicToolName(name)));
38903914return (config.codexDynamicToolsExclude ?? []).some((name) => {
38913915const normalized = normalizeCodexDynamicToolName(name);
3892-return (
3893-normalized === "exec" ||
3894-normalized === "sandbox_exec" ||
3895-normalized === "process" ||
3896-normalized === "sandbox_process"
3897-);
3916+return normalizedNames.has(normalized);
38983917});
38993918}
390039193920+function isSandboxShellDynamicToolExcluded(config: CodexPluginConfig): boolean {
3921+return isCodexDynamicToolExcluded(config, ["exec", "sandbox_exec", "process", "sandbox_process"]);
3922+}
3923+3924+function addNodeShellDynamicToolsIfNeeded(
3925+filteredTools: OpenClawDynamicTool[],
3926+allTools: OpenClawDynamicTool[],
3927+input: DynamicToolBuildParams,
3928+): OpenClawDynamicTool[] {
3929+if (
3930+isCodexMemoryFlushRun(input.params) ||
3931+!isEffectiveExecHostNode(input.params, input.sessionAgentId)
3932+) {
3933+return filteredTools;
3934+}
3935+let next = filteredTools;
3936+for (const toolName of ["exec", "process"]) {
3937+if (isCodexDynamicToolExcluded(input.pluginConfig, [toolName])) {
3938+continue;
3939+}
3940+if (next.some((tool) => normalizeCodexDynamicToolName(tool.name) === toolName)) {
3941+continue;
3942+}
3943+const tool = allTools.find(
3944+(candidate) => normalizeCodexDynamicToolName(candidate.name) === toolName,
3945+);
3946+if (!tool) {
3947+continue;
3948+}
3949+if (next === filteredTools) {
3950+next = [...filteredTools];
3951+}
3952+next.push(tool);
3953+}
3954+return next;
3955+}
3956+39013957function filterCodexDynamicToolsForAllowlist<T extends { name: string }>(
39023958tools: T[],
39033959toolsAllow?: string[],
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。