mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
refactor(core): dedupe tool policy and IPv4 matcher logic
This commit is contained in:
@@ -7,6 +7,7 @@ import { resolveThreadParentSessionKey } from "../sessions/session-key-utils.js"
|
||||
import { normalizeMessageChannel } from "../utils/message-channel.js";
|
||||
import { resolveAgentConfig, resolveAgentIdFromSessionKey } from "./agent-scope.js";
|
||||
import { compileGlobPatterns, matchesAnyGlobPattern } from "./glob-pattern.js";
|
||||
import { pickSandboxToolPolicy } from "./sandbox-tool-policy.js";
|
||||
import { expandToolGroups, normalizeToolName } from "./tool-policy.js";
|
||||
|
||||
function makeToolPolicyMatcher(policy: SandboxToolPolicy) {
|
||||
@@ -112,34 +113,6 @@ type ToolPolicyConfig = {
|
||||
profile?: string;
|
||||
};
|
||||
|
||||
function unionAllow(base?: string[], extra?: string[]) {
|
||||
if (!Array.isArray(extra) || extra.length === 0) {
|
||||
return base;
|
||||
}
|
||||
// If the user is using alsoAllow without an allowlist, treat it as additive on top of
|
||||
// an implicit allow-all policy.
|
||||
if (!Array.isArray(base) || base.length === 0) {
|
||||
return Array.from(new Set(["*", ...extra]));
|
||||
}
|
||||
return Array.from(new Set([...base, ...extra]));
|
||||
}
|
||||
|
||||
function pickToolPolicy(config?: ToolPolicyConfig): SandboxToolPolicy | undefined {
|
||||
if (!config) {
|
||||
return undefined;
|
||||
}
|
||||
const allow = Array.isArray(config.allow)
|
||||
? unionAllow(config.allow, config.alsoAllow)
|
||||
: Array.isArray(config.alsoAllow) && config.alsoAllow.length > 0
|
||||
? unionAllow(undefined, config.alsoAllow)
|
||||
: undefined;
|
||||
const deny = Array.isArray(config.deny) ? config.deny : undefined;
|
||||
if (!allow && !deny) {
|
||||
return undefined;
|
||||
}
|
||||
return { allow, deny };
|
||||
}
|
||||
|
||||
function normalizeProviderKey(value: string): string {
|
||||
return value.trim().toLowerCase();
|
||||
}
|
||||
@@ -237,10 +210,10 @@ export function resolveEffectiveToolPolicy(params: {
|
||||
});
|
||||
return {
|
||||
agentId,
|
||||
globalPolicy: pickToolPolicy(globalTools),
|
||||
globalProviderPolicy: pickToolPolicy(providerPolicy),
|
||||
agentPolicy: pickToolPolicy(agentTools),
|
||||
agentProviderPolicy: pickToolPolicy(agentProviderPolicy),
|
||||
globalPolicy: pickSandboxToolPolicy(globalTools),
|
||||
globalProviderPolicy: pickSandboxToolPolicy(providerPolicy),
|
||||
agentPolicy: pickSandboxToolPolicy(agentTools),
|
||||
agentProviderPolicy: pickSandboxToolPolicy(agentProviderPolicy),
|
||||
profile,
|
||||
providerProfile: agentProviderPolicy?.profile ?? providerPolicy?.profile,
|
||||
// alsoAllow is applied at the profile stage (to avoid being filtered out early).
|
||||
@@ -313,7 +286,7 @@ export function resolveGroupToolPolicy(params: {
|
||||
senderUsername: params.senderUsername,
|
||||
senderE164: params.senderE164,
|
||||
});
|
||||
return pickToolPolicy(toolsConfig);
|
||||
return pickSandboxToolPolicy(toolsConfig);
|
||||
}
|
||||
|
||||
export function isToolAllowedByPolicies(
|
||||
|
||||
37
src/agents/sandbox-tool-policy.ts
Normal file
37
src/agents/sandbox-tool-policy.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import type { SandboxToolPolicy } from "./sandbox/types.js";
|
||||
|
||||
type SandboxToolPolicyConfig = {
|
||||
allow?: string[];
|
||||
alsoAllow?: string[];
|
||||
deny?: string[];
|
||||
};
|
||||
|
||||
function unionAllow(base?: string[], extra?: string[]): string[] | undefined {
|
||||
if (!Array.isArray(extra) || extra.length === 0) {
|
||||
return base;
|
||||
}
|
||||
// If the user is using alsoAllow without an allowlist, treat it as additive on top of
|
||||
// an implicit allow-all policy.
|
||||
if (!Array.isArray(base) || base.length === 0) {
|
||||
return Array.from(new Set(["*", ...extra]));
|
||||
}
|
||||
return Array.from(new Set([...base, ...extra]));
|
||||
}
|
||||
|
||||
export function pickSandboxToolPolicy(
|
||||
config?: SandboxToolPolicyConfig,
|
||||
): SandboxToolPolicy | undefined {
|
||||
if (!config) {
|
||||
return undefined;
|
||||
}
|
||||
const allow = Array.isArray(config.allow)
|
||||
? unionAllow(config.allow, config.alsoAllow)
|
||||
: Array.isArray(config.alsoAllow) && config.alsoAllow.length > 0
|
||||
? unionAllow(undefined, config.alsoAllow)
|
||||
: undefined;
|
||||
const deny = Array.isArray(config.deny) ? config.deny : undefined;
|
||||
if (!allow && !deny) {
|
||||
return undefined;
|
||||
}
|
||||
return { allow, deny };
|
||||
}
|
||||
@@ -152,8 +152,9 @@ function isTailnetIPv4(address: string): boolean {
|
||||
return a === 100 && b >= 64 && b <= 127;
|
||||
}
|
||||
|
||||
function pickLanIPv4(
|
||||
function pickIPv4Matching(
|
||||
networkInterfaces: () => ReturnType<typeof os.networkInterfaces>,
|
||||
matches: (address: string) => boolean,
|
||||
): string | null {
|
||||
const nets = networkInterfaces();
|
||||
for (const entries of Object.values(nets)) {
|
||||
@@ -170,7 +171,7 @@ function pickLanIPv4(
|
||||
if (!address) {
|
||||
continue;
|
||||
}
|
||||
if (isPrivateIPv4(address)) {
|
||||
if (matches(address)) {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
@@ -178,30 +179,16 @@ function pickLanIPv4(
|
||||
return null;
|
||||
}
|
||||
|
||||
function pickLanIPv4(
|
||||
networkInterfaces: () => ReturnType<typeof os.networkInterfaces>,
|
||||
): string | null {
|
||||
return pickIPv4Matching(networkInterfaces, isPrivateIPv4);
|
||||
}
|
||||
|
||||
function pickTailnetIPv4(
|
||||
networkInterfaces: () => ReturnType<typeof os.networkInterfaces>,
|
||||
): string | null {
|
||||
const nets = networkInterfaces();
|
||||
for (const entries of Object.values(nets)) {
|
||||
if (!entries) {
|
||||
continue;
|
||||
}
|
||||
for (const entry of entries) {
|
||||
const family = entry?.family;
|
||||
const isIpv4 = family === "IPv4";
|
||||
if (!entry || entry.internal || !isIpv4) {
|
||||
continue;
|
||||
}
|
||||
const address = entry.address?.trim() ?? "";
|
||||
if (!address) {
|
||||
continue;
|
||||
}
|
||||
if (isTailnetIPv4(address)) {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return pickIPv4Matching(networkInterfaces, isTailnetIPv4);
|
||||
}
|
||||
|
||||
function parsePossiblyNoisyJsonObject(raw: string): Record<string, unknown> {
|
||||
|
||||
@@ -1,31 +1 @@
|
||||
import type { SandboxToolPolicy } from "../agents/sandbox/types.js";
|
||||
|
||||
function unionAllow(base?: string[], extra?: string[]): string[] | undefined {
|
||||
if (!Array.isArray(extra) || extra.length === 0) {
|
||||
return base;
|
||||
}
|
||||
if (!Array.isArray(base) || base.length === 0) {
|
||||
return Array.from(new Set(["*", ...extra]));
|
||||
}
|
||||
return Array.from(new Set([...base, ...extra]));
|
||||
}
|
||||
|
||||
export function pickSandboxToolPolicy(config?: {
|
||||
allow?: string[];
|
||||
alsoAllow?: string[];
|
||||
deny?: string[];
|
||||
}): SandboxToolPolicy | undefined {
|
||||
if (!config) {
|
||||
return undefined;
|
||||
}
|
||||
const allow = Array.isArray(config.allow)
|
||||
? unionAllow(config.allow, config.alsoAllow)
|
||||
: Array.isArray(config.alsoAllow) && config.alsoAllow.length > 0
|
||||
? unionAllow(undefined, config.alsoAllow)
|
||||
: undefined;
|
||||
const deny = Array.isArray(config.deny) ? config.deny : undefined;
|
||||
if (!allow && !deny) {
|
||||
return undefined;
|
||||
}
|
||||
return { allow, deny };
|
||||
}
|
||||
export { pickSandboxToolPolicy } from "../agents/sandbox-tool-policy.js";
|
||||
|
||||
Reference in New Issue
Block a user