import type { AgentPermission, AgentFilePermission, AgentBashPermission, AgentGitPermission, PermissionAction, PermissionRule, } from './types.js'; /** * 系统默认权限配置 */ export const SYSTEM_DEFAULT_PERMISSION: AgentPermission = { file: { read: 'allow', write: 'ask', edit: 'ask', delete: 'ask', }, bash: { enabled: true, default: 'ask', rules: [ // 安全命令 { pattern: 'ls *', action: 'allow' }, { pattern: 'pwd', action: 'allow' }, { pattern: 'cat *', action: 'allow' }, { pattern: 'head *', action: 'allow' }, { pattern: 'tail *', action: 'allow' }, { pattern: 'wc *', action: 'allow' }, { pattern: 'echo *', action: 'allow' }, { pattern: 'which *', action: 'allow' }, { pattern: 'type *', action: 'allow' }, // 危险命令 { pattern: 'rm -rf *', action: 'deny' }, { pattern: 'rm -fr *', action: 'deny' }, { pattern: 'sudo *', action: 'deny' }, { pattern: 'chmod 777 *', action: 'deny' }, ], }, web: 'ask', git: { read: 'allow', write: 'ask', dangerous: 'deny', }, }; /** * 合并单个权限值 * 优先级: agent > global > system */ function mergeAction( system: PermissionAction | undefined, global: PermissionAction | undefined, agent: PermissionAction | undefined ): PermissionAction { return agent ?? global ?? system ?? 'ask'; } /** * 合并规则数组 * Agent 规则优先,然后是 global,最后是 system */ function mergeRules( system: PermissionRule[] | undefined, global: PermissionRule[] | undefined, agent: PermissionRule[] | undefined ): PermissionRule[] { return [ ...(agent ?? []), ...(global ?? []), ...(system ?? []), ]; } /** * 合并文件权限配置 */ function mergeFilePermission( system: AgentFilePermission | undefined, global: AgentFilePermission | undefined, agent: AgentFilePermission | undefined ): AgentFilePermission { return { read: mergeAction(system?.read, global?.read, agent?.read), write: mergeAction(system?.write, global?.write, agent?.write), edit: mergeAction(system?.edit, global?.edit, agent?.edit), delete: mergeAction(system?.delete, global?.delete, agent?.delete), sensitivePaths: mergeRules( system?.sensitivePaths, global?.sensitivePaths, agent?.sensitivePaths ), }; } /** * 合并 Bash 权限配置 */ function mergeBashPermission( system: AgentBashPermission | undefined, global: AgentBashPermission | undefined, agent: AgentBashPermission | undefined ): AgentBashPermission { // 如果 agent 显式禁用,直接返回 if (agent?.enabled === false) { return { enabled: false }; } // 如果 global 禁用且 agent 没有覆盖 if (global?.enabled === false && agent?.enabled === undefined) { return { enabled: false }; } return { enabled: agent?.enabled ?? global?.enabled ?? system?.enabled ?? true, rules: mergeRules(system?.rules, global?.rules, agent?.rules), default: mergeAction(system?.default, global?.default, agent?.default), }; } /** * 合并 Git 权限配置 */ function mergeGitPermission( system: AgentGitPermission | undefined, global: AgentGitPermission | undefined, agent: AgentGitPermission | undefined ): AgentGitPermission { return { read: mergeAction(system?.read, global?.read, agent?.read), write: mergeAction(system?.write, global?.write, agent?.write), dangerous: mergeAction(system?.dangerous, global?.dangerous, agent?.dangerous), }; } /** * 合并完整的权限配置 * 优先级: Agent 配置 > 全局默认 > 系统默认 */ export function mergePermissions( systemDefault: AgentPermission, globalConfig: AgentPermission | undefined, agentConfig: AgentPermission | undefined ): AgentPermission { return { file: mergeFilePermission( systemDefault.file, globalConfig?.file, agentConfig?.file ), bash: mergeBashPermission( systemDefault.bash, globalConfig?.bash, agentConfig?.bash ), web: mergeAction(systemDefault.web, globalConfig?.web, agentConfig?.web), git: mergeGitPermission( systemDefault.git, globalConfig?.git, agentConfig?.git ), }; } /** * 检查命令是否匹配规则 * 支持通配符 * 匹配任意字符 */ export function matchRule(command: string, pattern: string): boolean { // 将通配符模式转换为正则表达式 const regexPattern = pattern .replace(/[.+^${}()|[\]\\]/g, '\\$&') // 转义特殊字符 .replace(/\*/g, '.*') // * 转换为 .* .replace(/\?/g, '.'); // ? 转换为 . const regex = new RegExp(`^${regexPattern}$`, 'i'); return regex.test(command); } /** * 根据规则列表检查命令权限 */ export function checkBashPermission( command: string, permission: AgentBashPermission ): PermissionAction { // 如果禁用,直接拒绝 if (permission.enabled === false) { return 'deny'; } // 按顺序检查规则 for (const rule of permission.rules ?? []) { if (matchRule(command, rule.pattern)) { return rule.action; } } // 返回默认策略 return permission.default ?? 'ask'; } /** * 根据规则列表检查文件路径权限 */ export function checkFilePathPermission( filePath: string, sensitivePaths: PermissionRule[] | undefined ): PermissionAction | null { if (!sensitivePaths) return null; for (const rule of sensitivePaths) { if (matchRule(filePath, rule.pattern)) { return rule.action; } } return null; }