diff --git a/src/agents/pi-embedded-runner/run/attempt.ts b/src/agents/pi-embedded-runner/run/attempt.ts index 65791fffaf9..228373711da 100644 --- a/src/agents/pi-embedded-runner/run/attempt.ts +++ b/src/agents/pi-embedded-runner/run/attempt.ts @@ -1595,6 +1595,8 @@ export async function runEmbeddedAttempt( // Collect exact raw names of non-plugin OpenClaw tools. Passed to the // subscriber so filterToolResultMediaUrls only trusts MEDIA: paths from // the concrete built-in tool registrations for this run. + // Built from `tools` (not `effectiveTools`) so bundle-injected MCP/LSP + // tools are deliberately excluded and never receive local-path trust. const builtinToolNames = new Set( tools.flatMap((tool) => { const name = tool.name.trim(); @@ -1609,6 +1611,10 @@ export async function runEmbeddedAttempt( existingToolNames: builtinToolNames, }); if (clientToolNameConflicts.length > 0) { + // Dispose runtimes before throwing — the inner try/finally that normally + // handles disposal hasn't been entered yet at this point. + await bundleMcpRuntime?.dispose(); + await bundleLspRuntime?.dispose(); throw createClientToolNameConflictError(clientToolNameConflicts); } await params.onPreflightPassed?.(); diff --git a/src/agents/pi-embedded-subscribe.tools.ts b/src/agents/pi-embedded-subscribe.tools.ts index cd180bb5dcf..b5f4c52a405 100644 --- a/src/agents/pi-embedded-subscribe.tools.ts +++ b/src/agents/pi-embedded-subscribe.tools.ts @@ -183,6 +183,9 @@ export function filterToolResultMediaUrls( // an exact raw-name match. This prevents MCP/client tools from bypassing // the local-path filter via aliases (bash -> exec), case variants, or // other normalized-name collisions with trusted built-ins. + // NOTE: when builtinToolNames is omitted (undefined), the guard is skipped + // and the weaker normalized-name check applies. All production call paths + // (attempt.ts) supply this set; omitting it preserves legacy behavior only. if (builtinToolNames !== undefined) { const registeredName = toolName?.trim(); if (!registeredName || !builtinToolNames.has(registeredName)) {