Files
ai-terminal-assistant/packages/server/src/routes/agents.ts
T
kurihada 1b7d55848d 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: 添加类型导入
2025-12-16 20:19:24 +08:00

401 lines
8.5 KiB
TypeScript

/**
* Agents API Routes
*
* 提供 Agent 预设管理的 REST API
*/
import { Hono } from 'hono';
import { getConfig } from './config.js';
import type {
AgentMode,
AgentInfo,
AgentConfigFile,
AgentModelConfig,
AgentPermission,
} from '@ai-assistant/core';
import {
agentRegistry,
loadAgentConfig,
saveAgentConfig,
presetAgents,
isPresetAgent,
} from '@ai-assistant/core';
// API 响应类型
interface AgentListItem {
name: string;
description: string;
mode: AgentMode;
isPreset: boolean;
isCustomized: boolean;
model?: string;
maxSteps?: number;
}
interface AgentDefaults {
maxSteps?: number;
model?: AgentModelConfig;
permission?: AgentPermission;
}
export const agentsRouter = new Hono();
// 初始化状态
let initialized = false;
/**
* 确保 AgentRegistry 已初始化
*/
async function ensureRegistryInitialized(): Promise<boolean> {
if (!initialized) {
await agentRegistry.init();
initialized = true;
}
return true;
}
/**
* 将 AgentInfo 转换为 AgentListItem
*/
function toListItem(agent: AgentInfo, customAgentNames: Set<string>): AgentListItem {
const isPresetAgent_ = isPresetAgent(agent.name);
return {
name: agent.name,
description: agent.description,
mode: agent.mode,
isPreset: isPresetAgent_,
isCustomized: customAgentNames.has(agent.name),
model: agent.model?.model,
maxSteps: agent.maxSteps,
};
}
/**
* GET /agents - 获取所有 Agent 列表
*/
agentsRouter.get('/', async (c) => {
if (!(await ensureRegistryInitialized())) {
return c.json(
{
success: false,
error: 'Failed to initialize agent registry',
},
503
);
}
const config = getConfig();
const userConfig = await loadAgentConfig(config.workdir);
const customAgentNames = new Set(Object.keys(userConfig?.agents || {}));
const agents = agentRegistry.list();
const items = agents.map((agent) => toListItem(agent, customAgentNames));
return c.json({
success: true,
data: items,
});
});
/**
* GET /agents/presets - 获取预设 Agent 列表
*/
agentsRouter.get('/presets', async (c) => {
const presets = Object.entries(presetAgents).map(([name, agent]) => ({
name,
description: agent.description,
mode: agent.mode,
isPreset: true,
isCustomized: false,
model: agent.model?.model,
maxSteps: agent.maxSteps,
}));
return c.json({
success: true,
data: presets,
});
});
/**
* GET /agents/defaults - 获取全局默认配置
*/
agentsRouter.get('/defaults', async (c) => {
const config = getConfig();
const userConfig = await loadAgentConfig(config.workdir);
return c.json({
success: true,
data: userConfig?.defaults || {},
});
});
/**
* PUT /agents/defaults - 更新全局默认配置
*/
agentsRouter.put('/defaults', async (c) => {
try {
const newDefaults = await c.req.json<AgentDefaults>();
const config = getConfig();
// 加载现有配置
let userConfig = await loadAgentConfig(config.workdir);
if (!userConfig) {
userConfig = {};
}
// 更新 defaults
userConfig.defaults = newDefaults;
// 保存配置
await saveAgentConfig(config.workdir, userConfig);
// 重新初始化 registry 以应用新配置
initialized = false;
await ensureRegistryInitialized();
return c.json({
success: true,
data: newDefaults,
});
} catch (error) {
return c.json(
{
success: false,
error: error instanceof Error ? error.message : 'Failed to update defaults',
},
500
);
}
});
/**
* GET /agents/:name - 获取单个 Agent 详情
*/
agentsRouter.get('/:name', async (c) => {
if (!(await ensureRegistryInitialized())) {
return c.json(
{
success: false,
error: 'Failed to initialize agent registry',
},
503
);
}
const name = c.req.param('name');
const agent = agentRegistry.get(name);
if (!agent) {
return c.json(
{
success: false,
error: `Agent '${name}' not found`,
},
404
);
}
const config = getConfig();
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: isPresetAgent_,
isCustomized,
},
});
});
/**
* POST /agents - 创建新 Agent
*/
agentsRouter.post('/', async (c) => {
try {
const body = await c.req.json<{ name: string } & Omit<AgentInfo, 'name'>>();
const { name, ...agentConfig } = body;
if (!name || typeof name !== 'string') {
return c.json(
{
success: false,
error: 'Agent name is required',
},
400
);
}
// 检查名称是否与预设冲突
if (isPresetAgent(name)) {
return c.json(
{
success: false,
error: `Cannot create agent with preset name '${name}'. Use PUT to customize a preset.`,
},
400
);
}
const config = getConfig();
let userConfig = await loadAgentConfig(config.workdir);
if (!userConfig) {
userConfig = {};
}
if (!userConfig.agents) {
userConfig.agents = {};
}
// 检查是否已存在
if (name in userConfig.agents) {
return c.json(
{
success: false,
error: `Agent '${name}' already exists`,
},
409
);
}
// 添加新 Agent
userConfig.agents[name] = agentConfig;
// 保存配置
await saveAgentConfig(config.workdir, userConfig);
// 重新初始化 registry
initialized = false;
await ensureRegistryInitialized();
const createdAgent = agentRegistry.get(name);
return c.json({
success: true,
data: createdAgent
? {
...createdAgent,
isPreset: false,
isCustomized: false,
}
: { name, ...agentConfig, isPreset: false, isCustomized: false },
});
} catch (error) {
return c.json(
{
success: false,
error: error instanceof Error ? error.message : 'Failed to create agent',
},
500
);
}
});
/**
* PUT /agents/:name - 更新 Agent
*/
agentsRouter.put('/:name', async (c) => {
try {
const name = c.req.param('name');
const agentConfig = await c.req.json<Omit<AgentInfo, 'name'>>();
const config = getConfig();
let userConfig = await loadAgentConfig(config.workdir);
if (!userConfig) {
userConfig = {};
}
if (!userConfig.agents) {
userConfig.agents = {};
}
// 更新 Agent(支持覆盖预设)
userConfig.agents[name] = agentConfig;
// 保存配置
await saveAgentConfig(config.workdir, userConfig);
// 重新初始化 registry
initialized = false;
await ensureRegistryInitialized();
const updatedAgent = agentRegistry.get(name);
const isPresetAgent_ = isPresetAgent(name);
return c.json({
success: true,
data: updatedAgent
? {
...updatedAgent,
isPreset: isPresetAgent_,
isCustomized: true,
}
: { name, ...agentConfig, isPreset: isPresetAgent_, isCustomized: true },
});
} catch (error) {
return c.json(
{
success: false,
error: error instanceof Error ? error.message : 'Failed to update agent',
},
500
);
}
});
/**
* DELETE /agents/:name - 删除 Agent
*/
agentsRouter.delete('/:name', async (c) => {
try {
const name = c.req.param('name');
const config = getConfig();
const userConfig = await loadAgentConfig(config.workdir);
if (!userConfig?.agents || !(name in userConfig.agents)) {
// 如果是预设 Agent,返回特定错误
if (isPresetAgent(name)) {
return c.json(
{
success: false,
error: `Cannot delete preset agent '${name}'`,
},
400
);
}
return c.json(
{
success: false,
error: `Agent '${name}' not found in user configuration`,
},
404
);
}
// 删除 Agent
delete userConfig.agents[name];
// 保存配置
await saveAgentConfig(config.workdir, userConfig);
// 重新初始化 registry
initialized = false;
await ensureRegistryInitialized();
return c.json({
success: true,
data: null,
});
} catch (error) {
return c.json(
{
success: false,
error: error instanceof Error ? error.message : 'Failed to delete agent',
},
500
);
}
});