























@@ -94,40 +94,59 @@ export function resolveSandboxSessionToolsVisibility(cfg: OpenClawConfig): "spaw
9494return cfg.agents?.defaults?.sandbox?.sessionToolsVisibility ?? "spawned";
9595}
969697+type CompiledAgentAllowPattern =
98+| { kind: "all" }
99+| { kind: "exact"; value: string }
100+| {
101+kind: "wildcard";
102+first: string;
103+last: string;
104+interior: string[];
105+};
106+107+function compileAgentAllowPattern(pattern: string): CompiledAgentAllowPattern | null {
108+const raw = normalizeOptionalString(pattern) ?? "";
109+if (!raw) {
110+return null;
111+}
112+if (raw === "*") {
113+return { kind: "all" };
114+}
115+if (!raw.includes("*")) {
116+return { kind: "exact", value: raw };
117+}
118+const parts = raw.toLowerCase().split("*");
119+return {
120+kind: "wildcard",
121+first: parts[0] ?? "",
122+last: parts[parts.length - 1] ?? "",
123+interior: parts.slice(1, -1).filter(Boolean),
124+};
125+}
126+97127/**
98- * Linear-time case-insensitive glob matcher. Splits the pattern on `*` and
99- * checks that all segments appear in order inside `value` with the first
100- * anchored to the start and the last anchored to the end. O(n·k) where
101- * n = value length and k = segment count, avoiding the polynomial
102- * backtracking that `new RegExp("^.*a.*b.*$")` causes with multiple wildcards.
128+ * Linear-time case-insensitive glob matcher for precompiled `*` patterns.
129+ * Checks prefix, suffix, then ordered interior segments without entering the
130+ * regex engine, avoiding polynomial backtracking on repeated wildcards.
103131 */
104-function matchesWildcardCaseInsensitive(pattern: string, value: string): boolean {
105-const parts = pattern.toLowerCase().split("*");
106-const lower = value.toLowerCase();
107-108-// First part must be a prefix.
109-const first = parts[0];
132+function matchesCompiledWildcard(
133+pattern: Extract<CompiledAgentAllowPattern, { kind: "wildcard" }>,
134+lower: string,
135+): boolean {
110136let pos = 0;
111-if (first) {
112-if (!lower.startsWith(first)) {
137+if (pattern.first) {
138+if (!lower.startsWith(pattern.first)) {
113139return false;
114140}
115-pos = first.length;
141+pos = pattern.first.length;
116142}
117143118-// Last part must be a suffix.
119-const last = parts[parts.length - 1];
120-const endBound = last ? lower.length - last.length : lower.length;
121-if (last && (!lower.endsWith(last) || endBound < pos)) {
144+const endBound = pattern.last ? lower.length - pattern.last.length : lower.length;
145+if (pattern.last && (!lower.endsWith(pattern.last) || endBound < pos)) {
122146return false;
123147}
124148125-// Interior parts must appear in order between prefix end and suffix start.
126-for (let i = 1; i < parts.length - 1; i++) {
127-const part = parts[i];
128-if (!part) {
129-continue;
130-}
149+for (const part of pattern.interior) {
131150const idx = lower.indexOf(part, pos);
132151if (idx === -1 || idx + part.length > endBound) {
133152return false;
@@ -141,25 +160,24 @@ function matchesWildcardCaseInsensitive(pattern: string, value: string): boolean
141160export function createAgentToAgentPolicy(cfg: OpenClawConfig): AgentToAgentPolicy {
142161const routingA2A = cfg.tools?.agentToAgent;
143162const enabled = routingA2A?.enabled === true;
144-const allowPatterns = Array.isArray(routingA2A?.allow) ? routingA2A.allow : [];
163+const rawAllowPatterns = Array.isArray(routingA2A?.allow) ? routingA2A.allow : [];
164+const allowPatterns = rawAllowPatterns
165+.map((pattern) => compileAgentAllowPattern(pattern))
166+.filter((pattern): pattern is CompiledAgentAllowPattern => pattern !== null);
167+const hasWildcardPatterns = allowPatterns.some((pattern) => pattern.kind === "wildcard");
145168const matchesAllow = (agentId: string) => {
146169if (allowPatterns.length === 0) {
147170return true;
148171}
172+const lowerAgentId = hasWildcardPatterns ? agentId.toLowerCase() : "";
149173return allowPatterns.some((pattern) => {
150-const raw =
151-normalizeOptionalString(typeof pattern === "string" ? pattern : String(pattern ?? "")) ??
152-"";
153-if (!raw) {
154-return false;
155-}
156-if (raw === "*") {
174+if (pattern.kind === "all") {
157175return true;
158176}
159-if (!raw.includes("*")) {
160-return raw === agentId;
177+if (pattern.kind === "exact") {
178+return pattern.value === agentId;
161179}
162-return matchesWildcardCaseInsensitive(raw, agentId);
180+return matchesCompiledWildcard(pattern, lowerAgentId);
163181});
164182};
165183const isAllowed = (requesterAgentId: string, targetAgentId: string) => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。