refactor: 清理代码结构,统一重复定义,移除未使用代码

- 提取 Provider 配置到公共模块 core/providers.ts
- 统一 PermissionAction/PermissionRule 类型定义到 permission/types.ts
- 移除 core/agent.ts 中未使用的 legacyTools 系统
- 移除 tools/index.ts 中未使用的 allTools 导出
- 减少约 125 行重复/冗余代码
This commit is contained in:
2025-12-11 18:42:07 +08:00
parent abbb03bf50
commit d0d0e8dbaf
5 changed files with 98 additions and 158 deletions
+6 -48
View File
@@ -1,7 +1,3 @@
import { createAnthropic } from '@ai-sdk/anthropic';
import { createDeepSeek } from '@ai-sdk/deepseek';
import { createOpenAI } from '@ai-sdk/openai';
import { createQwen } from 'qwen-ai-provider-v5';
import {
generateText,
streamText,
@@ -10,7 +6,7 @@ import {
type Tool as AITool,
type LanguageModel,
} from 'ai';
import type { Tool, ToolResult, ProviderType, AgentConfig, ContentBlock } from '../types/index.js';
import type { Tool, ToolResult, AgentConfig, ContentBlock } from '../types/index.js';
import { buildZodSchema } from '../types/index.js';
import { ToolRegistry } from '../tools/registry.js';
import type {
@@ -20,44 +16,7 @@ import type {
ImageData,
} from './types.js';
import { checkBashPermission } from './permission-merger.js';
// Provider 配置
interface ProviderOptions {
apiKey: string;
baseUrl?: string;
}
// Provider 工厂函数类型
type ProviderFactory = (options: ProviderOptions) => (model: string) => LanguageModel;
/**
* 检查 baseUrl 是否为阿里云百炼/DashScope
*/
function isDashScopeUrl(baseUrl?: string): boolean {
if (!baseUrl) return false;
return baseUrl.includes('dashscope');
}
// Provider 注册表
const providers: Record<ProviderType, ProviderFactory> = {
anthropic: ({ apiKey, baseUrl }) => {
const client = createAnthropic({ apiKey, baseURL: baseUrl });
return (model) => client(model);
},
deepseek: ({ apiKey, baseUrl }) => {
const client = createDeepSeek({ apiKey, baseURL: baseUrl });
return (model) => client(model);
},
openai: ({ apiKey, baseUrl }) => {
// 如果是百炼的 URL,使用 qwen provider
if (isDashScopeUrl(baseUrl)) {
const client = createQwen({ apiKey, baseURL: baseUrl });
return (model) => client(model);
}
const client = createOpenAI({ apiKey, baseURL: baseUrl });
return (model) => client(model);
},
};
import { getModelFactory } from '../core/providers.js';
/**
* Agent 执行器
@@ -80,11 +39,10 @@ export class AgentExecutor {
// 获取模型工厂
const provider = agentInfo.model?.provider ?? baseConfig.provider;
const providerFactory = providers[provider];
if (!providerFactory) {
throw new Error(`不支持的 provider: ${provider}`);
}
this.getModel = providerFactory({ apiKey: baseConfig.apiKey, baseUrl: baseConfig.baseUrl });
this.getModel = getModelFactory(provider, {
apiKey: baseConfig.apiKey,
baseUrl: baseConfig.baseUrl,
});
}
/**
+4 -13
View File
@@ -1,4 +1,8 @@
import type { ProviderType } from '../types/index.js';
import type { PermissionAction, PermissionRule } from '../permission/types.js';
// 重新导出权限类型,方便外部使用
export type { PermissionAction, PermissionRule };
/**
* Agent 模式
@@ -8,19 +12,6 @@ import type { ProviderType } from '../types/index.js';
*/
export type AgentMode = 'primary' | 'subagent' | 'all';
/**
* 权限动作
*/
export type PermissionAction = 'allow' | 'deny' | 'ask';
/**
* 权限规则(支持通配符模式)
*/
export interface PermissionRule {
pattern: string;
action: PermissionAction;
}
/**
* Agent Bash 权限配置
*/
+23 -94
View File
@@ -1,7 +1,3 @@
import { createAnthropic } from '@ai-sdk/anthropic';
import { createDeepSeek } from '@ai-sdk/deepseek';
import { createOpenAI } from '@ai-sdk/openai';
import { createQwen } from 'qwen-ai-provider-v5';
import {
generateText,
streamText,
@@ -10,7 +6,7 @@ import {
type Tool as AITool,
type LanguageModel,
} from 'ai';
import type { Tool, ToolResult, Message, AgentConfig, ProviderType, UserInput, ContentBlock } from '../types/index.js';
import type { Tool, ToolResult, Message, AgentConfig, UserInput, ContentBlock } from '../types/index.js';
import { buildZodSchema } from '../types/index.js';
import { ToolRegistry } from '../tools/registry.js';
import { SessionManager } from '../session/index.js';
@@ -22,44 +18,7 @@ import {
import type { AgentInfo, ImageData } from '../agent/types.js';
import { agentRegistry, AgentExecutor } from '../agent/index.js';
import { loadVisionConfig } from '../utils/config.js';
// Provider 配置
interface ProviderOptions {
apiKey: string;
baseUrl?: string;
}
// Provider 工厂函数类型
type ProviderFactory = (options: ProviderOptions) => (model: string) => LanguageModel;
/**
* 检查 baseUrl 是否为阿里云百炼/DashScope
*/
function isDashScopeUrl(baseUrl?: string): boolean {
if (!baseUrl) return false;
return baseUrl.includes('dashscope');
}
// Provider 注册表
const providers: Record<ProviderType, ProviderFactory> = {
anthropic: ({ apiKey, baseUrl }) => {
const client = createAnthropic({ apiKey, baseURL: baseUrl });
return (model) => client(model);
},
deepseek: ({ apiKey, baseUrl }) => {
const client = createDeepSeek({ apiKey, baseURL: baseUrl });
return (model) => client(model);
},
openai: ({ apiKey, baseUrl }) => {
// 如果是百炼的 URL,使用 qwen provider
if (isDashScopeUrl(baseUrl)) {
const client = createQwen({ apiKey, baseURL: baseUrl });
return (model) => client(model);
}
const client = createOpenAI({ apiKey, baseURL: baseUrl });
return (model) => client(model);
},
};
import { getModelFactory } from './providers.js';
export class Agent {
private getModel: (model: string) => LanguageModel;
@@ -72,9 +31,6 @@ export class Agent {
// 已发现的工具(通过 tool_search 发现的)
private discoveredTools: Set<string> = new Set();
// 兼容旧模式:直接注册的工具
private legacyTools: Map<string, Tool> = new Map();
// 会话管理器(可选)
private sessionManager: SessionManager | null = null;
@@ -91,11 +47,10 @@ export class Agent {
this.config = config;
this.originalSystemPrompt = config.systemPrompt;
const providerFactory = providers[config.provider];
if (!providerFactory) {
throw new Error(`不支持的 provider: ${config.provider}`);
}
this.getModel = providerFactory({ apiKey: config.apiKey, baseUrl: config.baseUrl });
this.getModel = getModelFactory(config.provider, {
apiKey: config.apiKey,
baseUrl: config.baseUrl,
});
// 初始化压缩管理器
this.compressionManager = new CompressionManager(compressionConfig);
@@ -130,41 +85,20 @@ export class Agent {
return this.sessionManager;
}
/**
* 注册单个工具(兼容旧代码)
*/
registerTool(customTool: Tool): void {
this.legacyTools.set(customTool.name, customTool);
}
/**
* 批量注册工具(兼容旧代码)
*/
registerTools(tools: Tool[]): void {
for (const tool of tools) {
this.legacyTools.set(tool.name, tool);
}
}
/**
* 获取当前可用的工具
* - 如果使用 registry 模式:返回核心工具 + 已发现的工具
* - 如果使用旧模式:返回所有注册的工具
* - 如果当前有 Agent 模式,应用工具过滤
* 返回核心工具 + 已发现的工具,如果当前有 Agent 模式,应用工具过滤
*/
private getAvailableTools(): Tool[] {
let tools: Tool[];
if (this.registry) {
// 新模式:核心工具 + 已发现的工具
const coreTools = this.registry.getCoreTools();
const discoveredTools = this.registry.getTools([...this.discoveredTools]);
tools = [...coreTools, ...discoveredTools];
} else {
// 旧模式:返回所有注册的工具
tools = [...this.legacyTools.values()];
if (!this.registry) {
throw new Error('工具注册表未初始化,请先调用 setRegistry()');
}
// 核心工具 + 已发现的工具
const coreTools = this.registry.getCoreTools();
const discoveredTools = this.registry.getTools([...this.discoveredTools]);
let tools = [...coreTools, ...discoveredTools];
// 应用 Agent 模式的工具过滤
if (this.currentAgentMode?.tools) {
tools = this.filterToolsByAgentConfig(tools);
@@ -435,21 +369,16 @@ export class Agent {
* 获取当前可用工具的数量
*/
getToolCount(): { core: number; discovered: number; total: number } {
if (this.registry) {
const coreCount = this.registry.getCoreTools().length;
const discoveredCount = this.discoveredTools.size;
return {
core: coreCount,
discovered: discoveredCount,
total: coreCount + discoveredCount,
};
} else {
return {
core: this.legacyTools.size,
discovered: 0,
total: this.legacyTools.size,
};
if (!this.registry) {
return { core: 0, discovered: 0, total: 0 };
}
const coreCount = this.registry.getCoreTools().length;
const discoveredCount = this.discoveredTools.size;
return {
core: coreCount,
discovered: discoveredCount,
total: coreCount + discoveredCount,
};
}
/**
+65
View File
@@ -0,0 +1,65 @@
import { createAnthropic } from '@ai-sdk/anthropic';
import { createDeepSeek } from '@ai-sdk/deepseek';
import { createOpenAI } from '@ai-sdk/openai';
import { createQwen } from 'qwen-ai-provider-v5';
import type { LanguageModel } from 'ai';
import type { ProviderType } from '../types/index.js';
/**
* Provider 配置选项
*/
export interface ProviderOptions {
apiKey: string;
baseUrl?: string;
}
/**
* Provider 工厂函数类型
*/
export type ProviderFactory = (options: ProviderOptions) => (model: string) => LanguageModel;
/**
* 检查 baseUrl 是否为阿里云百炼/DashScope
*/
function isDashScopeUrl(baseUrl?: string): boolean {
if (!baseUrl) return false;
return baseUrl.includes('dashscope');
}
/**
* Provider 注册表
* 支持 Anthropic、DeepSeek、OpenAI 及 OpenAI 兼容 API(如阿里云百炼)
*/
export const providers: Record<ProviderType, ProviderFactory> = {
anthropic: ({ apiKey, baseUrl }) => {
const client = createAnthropic({ apiKey, baseURL: baseUrl });
return (model) => client(model);
},
deepseek: ({ apiKey, baseUrl }) => {
const client = createDeepSeek({ apiKey, baseURL: baseUrl });
return (model) => client(model);
},
openai: ({ apiKey, baseUrl }) => {
// 如果是百炼的 URL,使用 qwen provider
if (isDashScopeUrl(baseUrl)) {
const client = createQwen({ apiKey, baseURL: baseUrl });
return (model) => client(model);
}
const client = createOpenAI({ apiKey, baseURL: baseUrl });
return (model) => client(model);
},
};
/**
* 获取模型工厂函数
*/
export function getModelFactory(
provider: ProviderType,
options: ProviderOptions
): (model: string) => LanguageModel {
const factory = providers[provider];
if (!factory) {
throw new Error(`不支持的 provider: ${provider}`);
}
return factory(options);
}
-3
View File
@@ -100,6 +100,3 @@ export { todoManager } from './todo/index.js';
export { initTaskContext, updateTaskDescription } from './task/index.js';
export { updateSkillDescription } from './skill/index.js';
export type { ToolWithMetadata, ToolMetadata, ToolCategory, ToolSearchResult } from './types.js';
// 兼容旧代码:导出所有工具数组(基础 Tool 类型)
export const allTools = toolRegistry.getAllTools();