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:
2025-12-16 20:19:24 +08:00
parent 026429cb2f
commit 1b7d55848d
14 changed files with 283 additions and 1240 deletions
+43 -244
View File
@@ -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;