diff --git a/src/link-understanding/runner.test.ts b/src/link-understanding/runner.test.ts index 007303c4fb50..bd1fc970b0d5 100644 --- a/src/link-understanding/runner.test.ts +++ b/src/link-understanding/runner.test.ts @@ -72,6 +72,39 @@ describe("runLinkUnderstanding", () => { mocks.runCommandWithTimeout.mockReset(); }); + it("applies shared media scope rules to link message context", async () => { + const result = await runLinkUnderstanding({ + cfg: { + tools: { + links: { + enabled: true, + scope: { + default: "allow", + rules: [ + { + action: "deny", + match: { channel: "slack", chatType: "channel", keyPrefix: "agent:main:" }, + }, + ], + }, + models: [{ type: "cli", command: "summarize" }], + }, + }, + } as OpenClawConfig, + ctx: { + Body: "see https://example.com/page", + ChatType: "channel", + Provider: "discord", + SessionKey: "agent:main:slack:channel:C123", + Surface: "slack", + } as MsgContext, + }); + + expect(result).toEqual({ urls: [], outputs: [] }); + expect(fetchWithSsrFGuard).not.toHaveBeenCalled(); + expect(runCommandWithTimeout).not.toHaveBeenCalled(); + }); + it("fetches links through the SSRF guard before passing content to CLI stdin", async () => { const release = mockGuardedFetch("page body", "https://example.com/final"); mockCommand("summarized page"); diff --git a/src/link-understanding/runner.ts b/src/link-understanding/runner.ts index fec777029dc6..fd994fdd3269 100644 --- a/src/link-understanding/runner.ts +++ b/src/link-understanding/runner.ts @@ -7,11 +7,7 @@ import { logVerbose, shouldLogVerbose } from "../globals.js"; import { cancelUnreadResponseBody, readResponseWithLimit } from "../infra/http-body.js"; import { fetchWithSsrFGuard, GUARDED_FETCH_MODE } from "../infra/net/fetch-guard.js"; import { CLI_OUTPUT_MAX_BUFFER } from "../media-understanding/defaults.js"; -import { resolveTimeoutMs } from "../media-understanding/resolve.js"; -import { - normalizeMediaUnderstandingChatType, - resolveMediaUnderstandingScope, -} from "../media-understanding/scope.js"; +import { resolveScopeDecision, resolveTimeoutMs } from "../media-understanding/resolve.js"; import { runCommandWithTimeout } from "../process/exec.js"; import { DEFAULT_LINK_TIMEOUT_SECONDS } from "./defaults.js"; import { extractLinksFromMessage } from "./detect.js"; @@ -21,18 +17,6 @@ type LinkUnderstandingResult = { outputs: string[]; }; -function resolveScopeDecision(params: { - config?: LinkToolsConfig; - ctx: MsgContext; -}): "allow" | "deny" { - return resolveMediaUnderstandingScope({ - scope: params.config?.scope, - sessionKey: params.ctx.SessionKey, - channel: params.ctx.Surface ?? params.ctx.Provider, - chatType: normalizeMediaUnderstandingChatType(params.ctx.ChatType), - }); -} - function resolveTimeoutMsFromConfig(params: { config?: LinkToolsConfig; entry: LinkModelConfig; @@ -217,7 +201,7 @@ export async function runLinkUnderstanding(params: { return { urls: [], outputs: [] }; } - const scopeDecision = resolveScopeDecision({ config, ctx: params.ctx }); + const scopeDecision = resolveScopeDecision({ scope: config.scope, ctx: params.ctx }); if (scopeDecision === "deny") { if (shouldLogVerbose()) { logVerbose("Link understanding disabled by scope policy.");