openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
298 lines (297 loc) • 10.8 kB
JavaScript
import { a as normalizeLowercaseStringOrEmpty, s as normalizeOptionalLowercaseString } from "./string-coerce-mnp54Vah.js";
import { p as normalizeUniqueStringEntries } from "./string-normalization-WNUDCpXX.js";
import { i as NODE_SYSTEM_RUN_COMMANDS, r as NODE_SYSTEM_NOTIFY_COMMAND, t as NODE_BROWSER_PROXY_COMMAND } from "./node-commands-SnI8Vs7F.js";
import { t as getActiveRuntimePluginRegistry } from "./active-runtime-registry-PnN7H8vW.js";
//#region src/gateway/device-metadata-normalization.ts
function normalizeTrimmedMetadata(value) {
if (typeof value !== "string") return "";
const trimmed = value.trim();
return trimmed ? trimmed : "";
}
/** Normalize device metadata for policy classification. */
function normalizeDeviceMetadataForPolicy(value) {
const trimmed = normalizeTrimmedMetadata(value);
if (!trimmed) return "";
return normalizeLowercaseStringOrEmpty(trimmed.normalize("NFKD").replace(/\p{M}/gu, ""));
}
//#endregion
//#region src/gateway/node-command-policy.ts
const CAMERA_COMMANDS = ["camera.list"];
const CAMERA_DANGEROUS_COMMANDS = ["camera.snap", "camera.clip"];
const SCREEN_COMMANDS = ["screen.snapshot"];
const SCREEN_DANGEROUS_COMMANDS = ["screen.record"];
const LOCATION_COMMANDS = ["location.get"];
const ANDROID_NOTIFICATION_COMMANDS = [...["notifications.list"], "notifications.actions"];
const DEVICE_COMMANDS = ["device.info", "device.status"];
const ANDROID_DEVICE_COMMANDS = [
...DEVICE_COMMANDS,
"device.permissions",
"device.health",
"device.apps"
];
const CONTACTS_COMMANDS = ["contacts.search"];
const CONTACTS_DANGEROUS_COMMANDS = ["contacts.add"];
const CALENDAR_COMMANDS = ["calendar.events"];
const CALENDAR_DANGEROUS_COMMANDS = ["calendar.add"];
const CALL_LOG_COMMANDS = ["callLog.search"];
const REMINDERS_COMMANDS = ["reminders.list"];
const REMINDERS_DANGEROUS_COMMANDS = ["reminders.add"];
const PHOTOS_COMMANDS = ["photos.latest"];
const MOTION_COMMANDS = ["motion.activity", "motion.pedometer"];
const SMS_DANGEROUS_COMMANDS = ["sms.send", "sms.search"];
const TALK_PTT_COMMANDS = [
"talk.ptt.start",
"talk.ptt.stop",
"talk.ptt.cancel",
"talk.ptt.once"
];
const IOS_SYSTEM_COMMANDS = [NODE_SYSTEM_NOTIFY_COMMAND];
const SYSTEM_COMMANDS = [
...NODE_SYSTEM_RUN_COMMANDS,
NODE_SYSTEM_NOTIFY_COMMAND,
NODE_BROWSER_PROXY_COMMAND
];
const DESKTOP_HOST_COMMANDS = new Set([
...NODE_SYSTEM_RUN_COMMANDS,
NODE_BROWSER_PROXY_COMMAND,
...SCREEN_COMMANDS
]);
const UNKNOWN_PLATFORM_COMMANDS = [
...CAMERA_COMMANDS,
...LOCATION_COMMANDS,
NODE_SYSTEM_NOTIFY_COMMAND
];
const DEFAULT_DANGEROUS_NODE_COMMANDS = [
...CAMERA_DANGEROUS_COMMANDS,
...SCREEN_DANGEROUS_COMMANDS,
...CONTACTS_DANGEROUS_COMMANDS,
...CALENDAR_DANGEROUS_COMMANDS,
...REMINDERS_DANGEROUS_COMMANDS,
...SMS_DANGEROUS_COMMANDS
];
const PLATFORM_DEFAULTS = {
ios: [
...CAMERA_COMMANDS,
...LOCATION_COMMANDS,
...DEVICE_COMMANDS,
...CONTACTS_COMMANDS,
...CALENDAR_COMMANDS,
...REMINDERS_COMMANDS,
...PHOTOS_COMMANDS,
...MOTION_COMMANDS,
...IOS_SYSTEM_COMMANDS
],
android: [
...CAMERA_COMMANDS,
...LOCATION_COMMANDS,
...ANDROID_NOTIFICATION_COMMANDS,
NODE_SYSTEM_NOTIFY_COMMAND,
...ANDROID_DEVICE_COMMANDS,
...CONTACTS_COMMANDS,
...CALENDAR_COMMANDS,
...CALL_LOG_COMMANDS,
...REMINDERS_COMMANDS,
...PHOTOS_COMMANDS,
...MOTION_COMMANDS
],
macos: [
...CAMERA_COMMANDS,
...LOCATION_COMMANDS,
...DEVICE_COMMANDS,
...CONTACTS_COMMANDS,
...CALENDAR_COMMANDS,
...REMINDERS_COMMANDS,
...PHOTOS_COMMANDS,
...MOTION_COMMANDS,
...SYSTEM_COMMANDS,
...SCREEN_COMMANDS
],
linux: [...SYSTEM_COMMANDS],
windows: [
...CAMERA_COMMANDS,
...LOCATION_COMMANDS,
...DEVICE_COMMANDS,
...SYSTEM_COMMANDS,
...SCREEN_COMMANDS
],
unknown: [...UNKNOWN_PLATFORM_COMMANDS]
};
const CANONICAL_PLATFORM_IDS = new Set([
"ios",
"android",
"macos",
"windows",
"linux"
]);
const DEVICE_FAMILY_TOKEN_RULES = [
{
id: "ios",
tokens: [
"iphone",
"ipad",
"ios"
]
},
{
id: "android",
tokens: ["android"]
},
{
id: "macos",
tokens: ["mac"]
},
{
id: "windows",
tokens: ["windows"]
},
{
id: "linux",
tokens: ["linux"]
}
];
function resolvePlatformIdByExactMatch(value) {
if (CANONICAL_PLATFORM_IDS.has(value)) return value;
}
function platformMatchesDeviceFamily(platformId, family) {
switch (platformId) {
case "ios": return family === "" || /^(?:iphone|ipad|ios)$/.test(family);
case "android": return family === "" || family === "android";
case "macos": return family === "mac";
case "windows": return family === "windows";
case "linux": return family === "linux";
}
return false;
}
function resolvePlatformIdByNativeLabel(platform, deviceFamily) {
if (/^(?:ios|ipados) \d+(?:\.\d+){0,2}$/.test(platform)) return /^(?:iphone|ipad|ios)$/.test(deviceFamily) ? "ios" : void 0;
if (/^macos \d+(?:\.\d+){0,2}$/.test(platform)) return deviceFamily === "mac" ? "macos" : void 0;
if (/^android \d+(?: \(sdk \d+\))?$/.test(platform)) return deviceFamily === "android" ? "android" : void 0;
}
function resolvePlatformIdByDeviceFamily(value) {
for (const rule of DEVICE_FAMILY_TOKEN_RULES) if (rule.tokens.some((token) => value.includes(token))) return rule.id;
}
function normalizePlatformId(platform, deviceFamily) {
const raw = normalizeDeviceMetadataForPolicy(platform);
const family = normalizeDeviceMetadataForPolicy(deviceFamily);
const byPlatform = resolvePlatformIdByExactMatch(raw);
if (byPlatform) return platformMatchesDeviceFamily(byPlatform, family) ? byPlatform : "unknown";
const byNativeLabel = resolvePlatformIdByNativeLabel(raw, family);
if (byNativeLabel) return byNativeLabel;
if (raw) return "unknown";
return resolvePlatformIdByDeviceFamily(family) ?? "unknown";
}
function listDangerousPluginNodeCommands() {
const registry = getActiveRuntimePluginRegistry();
if (!registry) return [];
return normalizeUniqueStringEntries([...(registry.nodeHostCommands ?? []).filter((entry) => entry.command.dangerous === true).map((entry) => entry.command.command), ...(registry.nodeInvokePolicies ?? []).filter((entry) => entry.policy.dangerous === true).flatMap((entry) => entry.policy.commands)]);
}
function listDefaultPluginNodeCommands(platformId) {
const registry = getActiveRuntimePluginRegistry();
if (!registry) return [];
return normalizeUniqueStringEntries((registry.nodeInvokePolicies ?? []).flatMap((entry) => {
if (entry.policy.dangerous === true) return [];
return (entry.policy.defaultPlatforms ?? []).includes(platformId) ? entry.policy.commands : [];
}));
}
function isForegroundRestrictedPluginNodeCommand(command) {
const registry = getActiveRuntimePluginRegistry();
if (!registry) return false;
const normalized = command.trim();
if (!normalized) return false;
return (registry.nodeInvokePolicies ?? []).some((entry) => entry.policy.foregroundRestrictedOnIos === true && entry.policy.commands.some((policyCommand) => policyCommand.trim() === normalized));
}
function isDesktopPlatformId(platformId) {
return platformId === "macos" || platformId === "windows" || platformId === "linux";
}
function filterDesktopHostCommandDefaults(params) {
if (params.includeDesktopHostCommands === true || !isDesktopPlatformId(params.platformId)) return [...params.commands];
return params.commands.filter((command) => !DESKTOP_HOST_COMMANDS.has(command));
}
function filterApprovedRuntimeCommands(params) {
if (!isDesktopPlatformId(params.platformId)) return [];
return params.commands.filter((command) => DESKTOP_HOST_COMMANDS.has(command.trim()));
}
function isLiveNodeSession(node) {
return typeof node?.nodeId === "string" && node.nodeId.trim() !== "" && typeof node.connId === "string" && node.connId.trim() !== "";
}
function hasTalkSurface(node) {
if (!node) return false;
return (node.caps ?? []).some((capability) => normalizeOptionalLowercaseString(capability) === "talk") || (node.commands ?? []).some((command) => normalizeOptionalLowercaseString(command)?.startsWith("talk."));
}
function resolveNodeCommandAllowlistInternal(cfg, node, options) {
const platformId = normalizePlatformId(node?.platform, node?.deviceFamily);
const base = filterDesktopHostCommandDefaults({
platformId,
commands: PLATFORM_DEFAULTS[platformId] ?? PLATFORM_DEFAULTS.unknown,
includeDesktopHostCommands: options?.includeDesktopHostCommands
});
const talkCommands = hasTalkSurface(node) ? TALK_PTT_COMMANDS : [];
const pluginDefaults = listDefaultPluginNodeCommands(platformId);
const approved = filterApprovedRuntimeCommands({
platformId,
commands: node?.approvedCommands ?? (isLiveNodeSession(node) ? node?.commands ?? [] : [])
});
const extra = cfg.gateway?.nodes?.allowCommands ?? [];
const deny = new Set(cfg.gateway?.nodes?.denyCommands ?? []);
const dangerousPluginCommands = new Set(listDangerousPluginNodeCommands());
const allow = new Set([
...base,
...talkCommands,
...pluginDefaults,
...approved,
...extra
].map((cmd) => cmd.trim()).filter((cmd) => cmd && !dangerousPluginCommands.has(cmd)));
for (const cmd of extra) {
const trimmed = cmd.trim();
if (trimmed) allow.add(trimmed);
}
for (const blocked of deny) {
const trimmed = blocked.trim();
if (trimmed) allow.delete(trimmed);
}
return allow;
}
function resolveNodeCommandAllowlist(cfg, node) {
return resolveNodeCommandAllowlistInternal(cfg, node);
}
function resolveNodePairingCommandAllowlist(cfg, node) {
return resolveNodeCommandAllowlistInternal(cfg, node, { includeDesktopHostCommands: true });
}
function normalizeDeclaredCommands(commands) {
if (!Array.isArray(commands)) return [];
const seen = /* @__PURE__ */ new Set();
const normalized = [];
for (const value of commands) {
const trimmed = value.trim();
if (!trimmed || seen.has(trimmed)) continue;
seen.add(trimmed);
normalized.push(trimmed);
}
return normalized;
}
function normalizeDeclaredNodeCommands(params) {
return normalizeDeclaredCommands(params.declaredCommands).filter((command) => params.allowlist.has(command));
}
function isNodeCommandAllowed(params) {
const command = params.command.trim();
if (!command) return {
ok: false,
reason: "command required"
};
if (!params.allowlist.has(command)) return {
ok: false,
reason: "command not allowlisted"
};
if (Array.isArray(params.declaredCommands) && params.declaredCommands.length > 0) {
if (!params.declaredCommands.includes(command)) return {
ok: false,
reason: "command not declared by node"
};
} else return {
ok: false,
reason: "node did not declare commands"
};
return { ok: true };
}
//#endregion
export { normalizeDeclaredNodeCommands as a, listDangerousPluginNodeCommands as i, isForegroundRestrictedPluginNodeCommand as n, resolveNodeCommandAllowlist as o, isNodeCommandAllowed as r, resolveNodePairingCommandAllowlist as s, DEFAULT_DANGEROUS_NODE_COMMANDS as t };