5e32375f0e
架构变更: - 采用 pnpm workspaces 实现 Monorepo 结构 - 将现有代码迁移到 packages/core - 新增 packages/server HTTP 服务层 Server 功能: - REST API: 会话管理、工具管理、配置管理 - WebSocket: 实时双向通信支持 - SSE: 服务端事件推送 - Hono + Bun 作为运行时 API 端点: - GET/POST /api/sessions - 会话 CRUD - GET/POST /api/sessions/:id/messages - 消息管理 - GET /api/sessions/:id/events - SSE 事件流 - WS /api/ws/:sessionId - WebSocket 连接 - GET/POST /api/tools - 工具管理 - GET/PUT /api/config - 配置管理
222 lines
5.5 KiB
TypeScript
222 lines
5.5 KiB
TypeScript
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;
|
|
}
|