feat: 重构为 Monorepo 架构并实现 HTTP Server
架构变更: - 采用 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 - 配置管理
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
import type { AgentInfo, AgentConfigFile, AgentMode } from './types.js';
|
||||
import { presetAgents } from './presets/index.js';
|
||||
import { loadAgentConfig } from './config-loader.js';
|
||||
import { mergePermissions, SYSTEM_DEFAULT_PERMISSION } from './permission-merger.js';
|
||||
|
||||
/**
|
||||
* Agent 注册表
|
||||
* 管理所有 Agent 的注册、查询和配置合并
|
||||
*/
|
||||
export class AgentRegistry {
|
||||
private agents: Map<string, AgentInfo> = new Map();
|
||||
private globalConfig: AgentConfigFile['defaults'] | null = null;
|
||||
private userConfig: AgentConfigFile | null = null;
|
||||
private initialized = false;
|
||||
|
||||
/**
|
||||
* 初始化 - 加载预设和用户配置
|
||||
*/
|
||||
async init(workdir: string): Promise<void> {
|
||||
if (this.initialized) return;
|
||||
|
||||
// 1. 注册预设 Agent
|
||||
for (const [name, agentConfig] of Object.entries(presetAgents)) {
|
||||
this.agents.set(name, { ...agentConfig, name });
|
||||
}
|
||||
|
||||
// 2. 加载用户配置
|
||||
this.userConfig = await loadAgentConfig(workdir);
|
||||
if (this.userConfig) {
|
||||
this.globalConfig = this.userConfig.defaults ?? null;
|
||||
|
||||
// 注册用户自定义 Agent
|
||||
if (this.userConfig.agents) {
|
||||
for (const [name, config] of Object.entries(this.userConfig.agents)) {
|
||||
this.agents.set(name, { ...config, name });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Agent(应用权限合并)
|
||||
*/
|
||||
get(name: string): AgentInfo | undefined {
|
||||
const agent = this.agents.get(name);
|
||||
if (!agent) return undefined;
|
||||
|
||||
return this.applyGlobalConfig(agent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出所有 Agent
|
||||
*/
|
||||
list(mode?: AgentMode): AgentInfo[] {
|
||||
return [...this.agents.values()]
|
||||
.filter((a) => !mode || a.mode === mode || a.mode === 'all')
|
||||
.map((a) => this.applyGlobalConfig(a));
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出可作为子 Agent 的 Agent(供 Task 工具使用)
|
||||
*/
|
||||
listSubagents(): AgentInfo[] {
|
||||
return this.list().filter((a) => a.mode !== 'primary');
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出可作为主交互 Agent 的 Agent(供 /agent 命令使用)
|
||||
*/
|
||||
listPrimaryAgents(): AgentInfo[] {
|
||||
return this.list().filter((a) => a.mode !== 'subagent');
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态注册 Agent(运行时)
|
||||
*/
|
||||
register(agent: AgentInfo): void {
|
||||
this.agents.set(agent.name, agent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除 Agent
|
||||
*/
|
||||
remove(name: string): boolean {
|
||||
return this.agents.delete(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 Agent 是否存在
|
||||
*/
|
||||
has(name: string): boolean {
|
||||
return this.agents.has(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Agent 数量
|
||||
*/
|
||||
get size(): number {
|
||||
return this.agents.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有 Agent 名称
|
||||
*/
|
||||
getNames(): string[] {
|
||||
return [...this.agents.keys()];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全局配置
|
||||
*/
|
||||
getGlobalConfig(): AgentConfigFile['defaults'] | null {
|
||||
return this.globalConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用全局配置到 Agent
|
||||
*/
|
||||
private applyGlobalConfig(agent: AgentInfo): AgentInfo {
|
||||
// 合并 maxSteps
|
||||
const maxSteps = agent.maxSteps ?? this.globalConfig?.maxSteps ?? 10;
|
||||
|
||||
// 合并模型配置
|
||||
const model = {
|
||||
...this.globalConfig?.model,
|
||||
...agent.model,
|
||||
};
|
||||
|
||||
// 合并权限配置
|
||||
const permission = mergePermissions(
|
||||
SYSTEM_DEFAULT_PERMISSION,
|
||||
this.globalConfig?.permission,
|
||||
agent.permission
|
||||
);
|
||||
|
||||
return {
|
||||
...agent,
|
||||
maxSteps,
|
||||
model: Object.keys(model).length > 0 ? model : undefined,
|
||||
permission,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 Task 工具的 Agent 描述(用于工具 description)
|
||||
*/
|
||||
generateSubagentDescription(): string {
|
||||
const subagents = this.listSubagents();
|
||||
if (subagents.length === 0) {
|
||||
return '当前没有可用的子 Agent';
|
||||
}
|
||||
|
||||
const descriptions = subagents.map((a) => `- ${a.name}: ${a.description}`);
|
||||
return `可用的 Agent:\n${descriptions.join('\n')}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 导出单例
|
||||
export const agentRegistry = new AgentRegistry();
|
||||
Reference in New Issue
Block a user