refactor: 清理代码结构,统一重复定义,移除未使用代码
- 提取 Provider 配置到公共模块 core/providers.ts - 统一 PermissionAction/PermissionRule 类型定义到 permission/types.ts - 移除 core/agent.ts 中未使用的 legacyTools 系统 - 移除 tools/index.ts 中未使用的 allTools 导出 - 减少约 125 行重复/冗余代码
This commit is contained in:
+6
-48
@@ -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
@@ -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
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user