refactor(server): 消除与 Core 的重复类型定义
- 删除 Server 中 60+ 个与 Core 重复的类型定义 - 将动态导入 (await import) 改为静态类型导入 (import type) - 保留必要的运行时静态导入 - 修复测试文件中的 mock 初始化问题 - 净删除约 960 行重复代码 重构文件: - routes/checkpoints.ts: 删除 155 行重复类型 - routes/agents.ts: 删除 93 行重复类型 - routes/commands.ts: 删除 83 行重复类型 - routes/mcp.ts: 修复类型窄化 - routes/hooks.ts: 已使用静态导入 - routes/providers.ts: 删除 63 行重复类型 - session/manager.ts: 删除 41 行重复类型 - routes/sessions.ts: 添加类型导入 - permission/handler.ts: 添加类型导入
This commit is contained in:
@@ -6,83 +6,20 @@
|
||||
|
||||
import { Hono } from 'hono';
|
||||
import { getConfig } from './config.js';
|
||||
|
||||
// Agent 类型定义(与 Core 对应)
|
||||
type AgentMode = 'primary' | 'subagent' | 'all';
|
||||
|
||||
interface AgentModelConfig {
|
||||
provider?: 'anthropic' | 'deepseek' | 'openai';
|
||||
model?: string;
|
||||
temperature?: number;
|
||||
topP?: number;
|
||||
maxTokens?: number;
|
||||
}
|
||||
|
||||
interface AgentToolConfig {
|
||||
disabled?: string[];
|
||||
enabled?: string[];
|
||||
noTask?: boolean;
|
||||
}
|
||||
|
||||
interface PermissionRule {
|
||||
pattern: string;
|
||||
action: 'allow' | 'deny';
|
||||
}
|
||||
|
||||
interface AgentBashPermission {
|
||||
rules?: PermissionRule[];
|
||||
defaultAction?: 'allow' | 'deny';
|
||||
}
|
||||
|
||||
interface AgentFilePermission {
|
||||
read?: { rules?: PermissionRule[]; defaultAction?: 'allow' | 'deny' };
|
||||
write?: { rules?: PermissionRule[]; defaultAction?: 'allow' | 'deny' };
|
||||
}
|
||||
|
||||
interface AgentGitPermission {
|
||||
commands?: string[];
|
||||
allowPush?: boolean;
|
||||
allowForce?: boolean;
|
||||
}
|
||||
|
||||
interface AgentPermission {
|
||||
bash?: AgentBashPermission;
|
||||
file?: AgentFilePermission;
|
||||
git?: AgentGitPermission;
|
||||
}
|
||||
|
||||
interface AgentInfo {
|
||||
name: string;
|
||||
description: string;
|
||||
mode: AgentMode;
|
||||
prompt?: string;
|
||||
model?: AgentModelConfig;
|
||||
tools?: AgentToolConfig;
|
||||
permission?: AgentPermission;
|
||||
maxSteps?: number;
|
||||
}
|
||||
|
||||
interface AgentConfigFile {
|
||||
defaults?: {
|
||||
maxSteps?: number;
|
||||
model?: AgentModelConfig;
|
||||
permission?: AgentPermission;
|
||||
};
|
||||
agents?: Record<string, Omit<AgentInfo, 'name'>>;
|
||||
}
|
||||
|
||||
// Core Agent 模块类型
|
||||
interface AgentModule {
|
||||
agentRegistry: {
|
||||
init: () => Promise<void>;
|
||||
get: (name: string) => AgentInfo | undefined;
|
||||
list: () => AgentInfo[];
|
||||
};
|
||||
loadAgentConfig: (workdir: string) => Promise<AgentConfigFile | null>;
|
||||
saveAgentConfig: (workdir: string, config: AgentConfigFile, format?: 'json' | 'yaml') => Promise<void>;
|
||||
presetAgents: Record<string, Omit<AgentInfo, 'name'>>;
|
||||
isPresetAgent: (name: string) => boolean;
|
||||
}
|
||||
import type {
|
||||
AgentMode,
|
||||
AgentInfo,
|
||||
AgentConfigFile,
|
||||
AgentModelConfig,
|
||||
AgentPermission,
|
||||
} from '@ai-assistant/core';
|
||||
import {
|
||||
agentRegistry,
|
||||
loadAgentConfig,
|
||||
saveAgentConfig,
|
||||
presetAgents,
|
||||
isPresetAgent,
|
||||
} from '@ai-assistant/core';
|
||||
|
||||
// API 响应类型
|
||||
interface AgentListItem {
|
||||
@@ -103,72 +40,30 @@ interface AgentDefaults {
|
||||
|
||||
export const agentsRouter = new Hono();
|
||||
|
||||
// Core 模块缓存
|
||||
let agentModule: AgentModule | null = null;
|
||||
// 初始化状态
|
||||
let initialized = false;
|
||||
|
||||
/**
|
||||
* 初始化 Agent 模块
|
||||
*/
|
||||
async function initAgentModule(): Promise<AgentModule | null> {
|
||||
if (agentModule) return agentModule;
|
||||
|
||||
try {
|
||||
const corePath = '@ai-assistant/core';
|
||||
const core = (await import(corePath)) as Record<string, unknown>;
|
||||
|
||||
if (
|
||||
!core.agentRegistry ||
|
||||
typeof core.loadAgentConfig !== 'function' ||
|
||||
typeof core.saveAgentConfig !== 'function' ||
|
||||
!core.presetAgents ||
|
||||
typeof core.isPresetAgent !== 'function'
|
||||
) {
|
||||
console.warn('[Agents] Core module missing Agent exports');
|
||||
return null;
|
||||
}
|
||||
|
||||
agentModule = {
|
||||
agentRegistry: core.agentRegistry as AgentModule['agentRegistry'],
|
||||
loadAgentConfig: core.loadAgentConfig as AgentModule['loadAgentConfig'],
|
||||
saveAgentConfig: core.saveAgentConfig as AgentModule['saveAgentConfig'],
|
||||
presetAgents: core.presetAgents as AgentModule['presetAgents'],
|
||||
isPresetAgent: core.isPresetAgent as AgentModule['isPresetAgent'],
|
||||
};
|
||||
|
||||
console.log('[Agents] Agent module initialized');
|
||||
return agentModule;
|
||||
} catch (error) {
|
||||
console.warn('[Agents] Failed to load Agent module:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保 AgentRegistry 已初始化
|
||||
*/
|
||||
async function ensureRegistryInitialized(): Promise<boolean> {
|
||||
const module = await initAgentModule();
|
||||
if (!module) return false;
|
||||
|
||||
if (!initialized) {
|
||||
await module.agentRegistry.init();
|
||||
await agentRegistry.init();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 AgentInfo 转换为 AgentListItem
|
||||
*/
|
||||
function toListItem(agent: AgentInfo, module: AgentModule, customAgentNames: Set<string>): AgentListItem {
|
||||
const isPreset = module.isPresetAgent(agent.name);
|
||||
function toListItem(agent: AgentInfo, customAgentNames: Set<string>): AgentListItem {
|
||||
const isPresetAgent_ = isPresetAgent(agent.name);
|
||||
return {
|
||||
name: agent.name,
|
||||
description: agent.description,
|
||||
mode: agent.mode,
|
||||
isPreset,
|
||||
isPreset: isPresetAgent_,
|
||||
isCustomized: customAgentNames.has(agent.name),
|
||||
model: agent.model?.model,
|
||||
maxSteps: agent.maxSteps,
|
||||
@@ -179,18 +74,6 @@ function toListItem(agent: AgentInfo, module: AgentModule, customAgentNames: Set
|
||||
* GET /agents - 获取所有 Agent 列表
|
||||
*/
|
||||
agentsRouter.get('/', async (c) => {
|
||||
const module = await initAgentModule();
|
||||
|
||||
if (!module) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
error: 'Agent module not available',
|
||||
},
|
||||
503
|
||||
);
|
||||
}
|
||||
|
||||
if (!(await ensureRegistryInitialized())) {
|
||||
return c.json(
|
||||
{
|
||||
@@ -202,11 +85,11 @@ agentsRouter.get('/', async (c) => {
|
||||
}
|
||||
|
||||
const config = getConfig();
|
||||
const userConfig = await module.loadAgentConfig(config.workdir);
|
||||
const userConfig = await loadAgentConfig(config.workdir);
|
||||
const customAgentNames = new Set(Object.keys(userConfig?.agents || {}));
|
||||
|
||||
const agents = module.agentRegistry.list();
|
||||
const items = agents.map((agent) => toListItem(agent, module, customAgentNames));
|
||||
const agents = agentRegistry.list();
|
||||
const items = agents.map((agent) => toListItem(agent, customAgentNames));
|
||||
|
||||
return c.json({
|
||||
success: true,
|
||||
@@ -218,19 +101,7 @@ agentsRouter.get('/', async (c) => {
|
||||
* GET /agents/presets - 获取预设 Agent 列表
|
||||
*/
|
||||
agentsRouter.get('/presets', async (c) => {
|
||||
const module = await initAgentModule();
|
||||
|
||||
if (!module) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
error: 'Agent module not available',
|
||||
},
|
||||
503
|
||||
);
|
||||
}
|
||||
|
||||
const presets = Object.entries(module.presetAgents).map(([name, agent]) => ({
|
||||
const presets = Object.entries(presetAgents).map(([name, agent]) => ({
|
||||
name,
|
||||
description: agent.description,
|
||||
mode: agent.mode,
|
||||
@@ -250,20 +121,8 @@ agentsRouter.get('/presets', async (c) => {
|
||||
* GET /agents/defaults - 获取全局默认配置
|
||||
*/
|
||||
agentsRouter.get('/defaults', async (c) => {
|
||||
const module = await initAgentModule();
|
||||
|
||||
if (!module) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
error: 'Agent module not available',
|
||||
},
|
||||
503
|
||||
);
|
||||
}
|
||||
|
||||
const config = getConfig();
|
||||
const userConfig = await module.loadAgentConfig(config.workdir);
|
||||
const userConfig = await loadAgentConfig(config.workdir);
|
||||
|
||||
return c.json({
|
||||
success: true,
|
||||
@@ -275,24 +134,12 @@ agentsRouter.get('/defaults', async (c) => {
|
||||
* PUT /agents/defaults - 更新全局默认配置
|
||||
*/
|
||||
agentsRouter.put('/defaults', async (c) => {
|
||||
const module = await initAgentModule();
|
||||
|
||||
if (!module) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
error: 'Agent module not available',
|
||||
},
|
||||
503
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const newDefaults = await c.req.json<AgentDefaults>();
|
||||
const config = getConfig();
|
||||
|
||||
// 加载现有配置
|
||||
let userConfig = await module.loadAgentConfig(config.workdir);
|
||||
let userConfig = await loadAgentConfig(config.workdir);
|
||||
if (!userConfig) {
|
||||
userConfig = {};
|
||||
}
|
||||
@@ -301,7 +148,7 @@ agentsRouter.put('/defaults', async (c) => {
|
||||
userConfig.defaults = newDefaults;
|
||||
|
||||
// 保存配置
|
||||
await module.saveAgentConfig(config.workdir, userConfig);
|
||||
await saveAgentConfig(config.workdir, userConfig);
|
||||
|
||||
// 重新初始化 registry 以应用新配置
|
||||
initialized = false;
|
||||
@@ -326,18 +173,6 @@ agentsRouter.put('/defaults', async (c) => {
|
||||
* GET /agents/:name - 获取单个 Agent 详情
|
||||
*/
|
||||
agentsRouter.get('/:name', async (c) => {
|
||||
const module = await initAgentModule();
|
||||
|
||||
if (!module) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
error: 'Agent module not available',
|
||||
},
|
||||
503
|
||||
);
|
||||
}
|
||||
|
||||
if (!(await ensureRegistryInitialized())) {
|
||||
return c.json(
|
||||
{
|
||||
@@ -349,7 +184,7 @@ agentsRouter.get('/:name', async (c) => {
|
||||
}
|
||||
|
||||
const name = c.req.param('name');
|
||||
const agent = module.agentRegistry.get(name);
|
||||
const agent = agentRegistry.get(name);
|
||||
|
||||
if (!agent) {
|
||||
return c.json(
|
||||
@@ -362,15 +197,15 @@ agentsRouter.get('/:name', async (c) => {
|
||||
}
|
||||
|
||||
const config = getConfig();
|
||||
const userConfig = await module.loadAgentConfig(config.workdir);
|
||||
const isPreset = module.isPresetAgent(name);
|
||||
const userConfig = await loadAgentConfig(config.workdir);
|
||||
const isPresetAgent_ = isPresetAgent(name);
|
||||
const isCustomized = !!(userConfig?.agents && name in userConfig.agents);
|
||||
|
||||
return c.json({
|
||||
success: true,
|
||||
data: {
|
||||
...agent,
|
||||
isPreset,
|
||||
isPreset: isPresetAgent_,
|
||||
isCustomized,
|
||||
},
|
||||
});
|
||||
@@ -380,18 +215,6 @@ agentsRouter.get('/:name', async (c) => {
|
||||
* POST /agents - 创建新 Agent
|
||||
*/
|
||||
agentsRouter.post('/', async (c) => {
|
||||
const module = await initAgentModule();
|
||||
|
||||
if (!module) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
error: 'Agent module not available',
|
||||
},
|
||||
503
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const body = await c.req.json<{ name: string } & Omit<AgentInfo, 'name'>>();
|
||||
const { name, ...agentConfig } = body;
|
||||
@@ -407,7 +230,7 @@ agentsRouter.post('/', async (c) => {
|
||||
}
|
||||
|
||||
// 检查名称是否与预设冲突
|
||||
if (module.isPresetAgent(name)) {
|
||||
if (isPresetAgent(name)) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
@@ -418,7 +241,7 @@ agentsRouter.post('/', async (c) => {
|
||||
}
|
||||
|
||||
const config = getConfig();
|
||||
let userConfig = await module.loadAgentConfig(config.workdir);
|
||||
let userConfig = await loadAgentConfig(config.workdir);
|
||||
if (!userConfig) {
|
||||
userConfig = {};
|
||||
}
|
||||
@@ -441,13 +264,13 @@ agentsRouter.post('/', async (c) => {
|
||||
userConfig.agents[name] = agentConfig;
|
||||
|
||||
// 保存配置
|
||||
await module.saveAgentConfig(config.workdir, userConfig);
|
||||
await saveAgentConfig(config.workdir, userConfig);
|
||||
|
||||
// 重新初始化 registry
|
||||
initialized = false;
|
||||
await ensureRegistryInitialized();
|
||||
|
||||
const createdAgent = module.agentRegistry.get(name);
|
||||
const createdAgent = agentRegistry.get(name);
|
||||
|
||||
return c.json({
|
||||
success: true,
|
||||
@@ -474,24 +297,12 @@ agentsRouter.post('/', async (c) => {
|
||||
* PUT /agents/:name - 更新 Agent
|
||||
*/
|
||||
agentsRouter.put('/:name', async (c) => {
|
||||
const module = await initAgentModule();
|
||||
|
||||
if (!module) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
error: 'Agent module not available',
|
||||
},
|
||||
503
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const name = c.req.param('name');
|
||||
const agentConfig = await c.req.json<Omit<AgentInfo, 'name'>>();
|
||||
|
||||
const config = getConfig();
|
||||
let userConfig = await module.loadAgentConfig(config.workdir);
|
||||
let userConfig = await loadAgentConfig(config.workdir);
|
||||
if (!userConfig) {
|
||||
userConfig = {};
|
||||
}
|
||||
@@ -503,24 +314,24 @@ agentsRouter.put('/:name', async (c) => {
|
||||
userConfig.agents[name] = agentConfig;
|
||||
|
||||
// 保存配置
|
||||
await module.saveAgentConfig(config.workdir, userConfig);
|
||||
await saveAgentConfig(config.workdir, userConfig);
|
||||
|
||||
// 重新初始化 registry
|
||||
initialized = false;
|
||||
await ensureRegistryInitialized();
|
||||
|
||||
const updatedAgent = module.agentRegistry.get(name);
|
||||
const isPreset = module.isPresetAgent(name);
|
||||
const updatedAgent = agentRegistry.get(name);
|
||||
const isPresetAgent_ = isPresetAgent(name);
|
||||
|
||||
return c.json({
|
||||
success: true,
|
||||
data: updatedAgent
|
||||
? {
|
||||
...updatedAgent,
|
||||
isPreset,
|
||||
isPreset: isPresetAgent_,
|
||||
isCustomized: true,
|
||||
}
|
||||
: { name, ...agentConfig, isPreset, isCustomized: true },
|
||||
: { name, ...agentConfig, isPreset: isPresetAgent_, isCustomized: true },
|
||||
});
|
||||
} catch (error) {
|
||||
return c.json(
|
||||
@@ -537,26 +348,14 @@ agentsRouter.put('/:name', async (c) => {
|
||||
* DELETE /agents/:name - 删除 Agent
|
||||
*/
|
||||
agentsRouter.delete('/:name', async (c) => {
|
||||
const module = await initAgentModule();
|
||||
|
||||
if (!module) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
error: 'Agent module not available',
|
||||
},
|
||||
503
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const name = c.req.param('name');
|
||||
const config = getConfig();
|
||||
const userConfig = await module.loadAgentConfig(config.workdir);
|
||||
const userConfig = await loadAgentConfig(config.workdir);
|
||||
|
||||
if (!userConfig?.agents || !(name in userConfig.agents)) {
|
||||
// 如果是预设 Agent,返回特定错误
|
||||
if (module.isPresetAgent(name)) {
|
||||
if (isPresetAgent(name)) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
@@ -579,7 +378,7 @@ agentsRouter.delete('/:name', async (c) => {
|
||||
delete userConfig.agents[name];
|
||||
|
||||
// 保存配置
|
||||
await module.saveAgentConfig(config.workdir, userConfig);
|
||||
await saveAgentConfig(config.workdir, userConfig);
|
||||
|
||||
// 重新初始化 registry
|
||||
initialized = false;
|
||||
|
||||
Reference in New Issue
Block a user