

























@@ -3,11 +3,7 @@
33 * sessions. Keeps runtime tool filtering tied to canonical config, session
44 * provenance, and inherited sub-agent capabilities.
55 */
6-import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id";
7-import {
8-normalizeLowercaseStringOrEmpty,
9-normalizeOptionalLowercaseString,
10-} from "@openclaw/normalization-core/string-coerce";
6+import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
117import {
128normalizeUniqueSingleOrTrimmedStringList,
139uniqueStrings,
@@ -26,6 +22,7 @@ import {
2622import { normalizeMessageChannel } from "../utils/message-channel.js";
2723import { resolveAgentConfig, resolveAgentIdFromSessionKey } from "./agent-scope.js";
2824import type { AnyAgentTool } from "./agent-tools.types.js";
25+import { resolveProviderToolPolicy } from "./provider-tool-policy.js";
2926import { pickSandboxToolPolicy } from "./sandbox-tool-policy.js";
3027import type { SandboxToolPolicy } from "./sandbox.js";
3128import {
@@ -43,6 +40,8 @@ import {
4340resolveToolProfilePolicy,
4441} from "./tool-policy.js";
454243+export { resolveProviderToolPolicy };
44+4645/**
4746 * Tools always denied for sub-agents regardless of depth.
4847 * These are system-level or interactive tools that sub-agents should never use.
@@ -145,59 +144,6 @@ export function filterToolsByPolicy(tools: AnyAgentTool[], policy?: SandboxToolP
145144return tools.filter((tool) => isToolAllowedByPolicyName(tool.name, policy));
146145}
147146148-type ToolPolicyConfig = {
149-allow?: string[];
150-alsoAllow?: string[];
151-deny?: string[];
152-profile?: string;
153-};
154-155-function normalizeProviderKey(value: string): string {
156-const normalized = normalizeLowercaseStringOrEmpty(value);
157-const slashIndex = normalized.indexOf("/");
158-if (slashIndex <= 0) {
159-return normalizeProviderId(normalized);
160-}
161-const provider = normalizeProviderId(normalized.slice(0, slashIndex));
162-const modelId = normalized.slice(slashIndex + 1);
163-return modelId ? `${provider}/${modelId}` : provider;
164-}
165-166-function isCanonicalProviderKey(value: string): boolean {
167-return normalizeLowercaseStringOrEmpty(value) === normalizeProviderKey(value);
168-}
169-170-function buildProviderToolPolicyLookup(
171-entries: Array<[string, ToolPolicyConfig]>,
172-): Map<string, ToolPolicyConfig> {
173-const lookup = new Map<
174-string,
175-{
176-canonical: boolean;
177-value: ToolPolicyConfig;
178-}
179->();
180-for (const [key, value] of entries) {
181-const normalized = normalizeProviderKey(key);
182-if (!normalized) {
183-continue;
184-}
185-const canonical = isCanonicalProviderKey(key);
186-const existing = lookup.get(normalized);
187-// Alias and canonical keys can normalize to the same provider. Prefer the
188-// canonical entry so mixed legacy/canonical configs do not depend on
189-// Object.entries insertion order.
190-if (!existing || (canonical && !existing.canonical)) {
191-lookup.set(normalized, { canonical, value });
192-}
193-}
194-const resolved = new Map<string, ToolPolicyConfig>();
195-for (const [key, entry] of lookup) {
196-resolved.set(key, entry.value);
197-}
198-return resolved;
199-}
200-201147function collectUniqueStrings(values: Array<string | null | undefined>): string[] {
202148return normalizeUniqueSingleOrTrimmedStringList(values);
203149}
@@ -322,42 +268,6 @@ export function resolveTrustedGroupId(params: {
322268});
323269}
324270325-/** Resolve model/provider-scoped tool policy from canonical provider keys. */
326-export function resolveProviderToolPolicy(params: {
327-byProvider?: Record<string, ToolPolicyConfig>;
328-modelProvider?: string;
329-modelId?: string;
330-}): ToolPolicyConfig | undefined {
331-const provider = params.modelProvider?.trim();
332-if (!provider || !params.byProvider) {
333-return undefined;
334-}
335-336-const entries = Object.entries(params.byProvider);
337-if (entries.length === 0) {
338-return undefined;
339-}
340-341-const lookup = buildProviderToolPolicyLookup(entries);
342-343-const normalizedProvider = normalizeProviderKey(provider);
344-const rawModelId = normalizeOptionalLowercaseString(params.modelId);
345-// Model IDs can contain provider-like prefixes (for example OpenRouter refs);
346-// keep them inside the selected provider scope instead of treating them as a
347-// byProvider override.
348-const fullModelId = rawModelId ? `${normalizedProvider}/${rawModelId}` : undefined;
349-350-const candidates = [...(fullModelId ? [fullModelId] : []), normalizedProvider];
351-352-for (const key of candidates) {
353-const match = lookup.get(key);
354-if (match) {
355-return match;
356-}
357-}
358-return undefined;
359-}
360-361271function resolveExplicitProfileAlsoAllow(tools?: OpenClawConfig["tools"]): string[] | undefined {
362272return Array.isArray(tools?.alsoAllow) ? tools.alsoAllow : undefined;
363273}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。