@huyooo/ai-chat-core 0.2.19 → 0.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/events.d.ts +452 -0
- package/dist/events.js +1 -0
- package/dist/index.d.ts +202 -550
- package/dist/index.js +1 -1
- package/package.json +23 -4
- package/src/agent.ts +399 -0
- package/src/constants.ts +125 -0
- package/src/events.ts +797 -0
- package/src/index.ts +309 -0
- package/src/internal/update-plan.ts +2 -0
- package/src/internal/web-search.ts +78 -0
- package/src/mcp/client-manager.ts +301 -0
- package/src/mcp/index.ts +2 -0
- package/src/mcp/types.ts +43 -0
- package/src/providers/context-compressor.ts +149 -0
- package/src/providers/index.ts +120 -0
- package/src/providers/model-registry.ts +320 -0
- package/src/providers/orchestrator.ts +761 -0
- package/src/providers/protocols/anthropic.ts +406 -0
- package/src/providers/protocols/ark.ts +362 -0
- package/src/providers/protocols/deepseek.ts +344 -0
- package/src/providers/protocols/error-utils.ts +74 -0
- package/src/providers/protocols/gemini.ts +350 -0
- package/src/providers/protocols/index.ts +36 -0
- package/src/providers/protocols/openai.ts +420 -0
- package/src/providers/protocols/qwen.ts +326 -0
- package/src/providers/protocols/types.ts +189 -0
- package/src/providers/types.ts +272 -0
- package/src/providers/unified-adapter.ts +367 -0
- package/src/router.ts +72 -0
- package/src/test-utils/mock-sse.ts +32 -0
- package/src/tools.ts +162 -0
- package/src/types.ts +531 -0
- package/src/utils.ts +86 -0
package/src/agent.ts
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HybridAgent - 混合 AI Agent
|
|
3
|
+
*
|
|
4
|
+
* 新架构(Protocol + Family 分离):
|
|
5
|
+
* - UnifiedAdapter: 统一适配器,组合 Protocol + FamilyConfig
|
|
6
|
+
* - ChatOrchestrator: 统一处理工具调用循环、消息历史、事件发射
|
|
7
|
+
* - HybridAgent: 协调者,负责初始化和路由
|
|
8
|
+
*
|
|
9
|
+
* 设计优势:
|
|
10
|
+
* 1. Protocol 只负责 HTTP/SSE 通信
|
|
11
|
+
* 2. FamilyConfig 统一管理行为差异
|
|
12
|
+
* 3. 新增模型只需在 Registry 配置,无需修改代码
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { GoogleGenAI } from '@google/genai';
|
|
16
|
+
import type {
|
|
17
|
+
AgentConfig,
|
|
18
|
+
ToolExecutor,
|
|
19
|
+
ChatOptions,
|
|
20
|
+
ThinkingMode,
|
|
21
|
+
Tool,
|
|
22
|
+
ToolContext,
|
|
23
|
+
ToolResult,
|
|
24
|
+
ToolConfigItem,
|
|
25
|
+
} from './types';
|
|
26
|
+
import { resolveTools, MODELS } from './types';
|
|
27
|
+
import type { ChatEvent } from './events';
|
|
28
|
+
import { createApiError } from './events';
|
|
29
|
+
import { createDefaultToolExecutor } from './tools';
|
|
30
|
+
import { DEFAULT_ARK_URL, DEFAULT_QWEN_URL, DEFAULT_OPENROUTER_URL, DEFAULT_MODEL, AGENT_MODE_PROMPT } from './constants';
|
|
31
|
+
import { routeModelToProvider, routeModelWithDetails, type ProviderType, type RouteResult } from './router';
|
|
32
|
+
import { getModelFamily, modelSupportsNativeSearch, type ModelFamilyConfig } from './providers/model-registry';
|
|
33
|
+
import { McpClientManager } from './mcp/client-manager';
|
|
34
|
+
import type { McpServerConfig } from './mcp/types';
|
|
35
|
+
|
|
36
|
+
// 新架构导入
|
|
37
|
+
import type { OrchestratorContext, SimpleToolDefinition, ToolExecutionHooks } from './providers/types';
|
|
38
|
+
import { ChatOrchestrator } from './providers/orchestrator';
|
|
39
|
+
import { UnifiedAdapter } from './providers/unified-adapter';
|
|
40
|
+
import { createWebSearchTool, WEB_SEARCH_TOOL_NAME } from './internal/web-search';
|
|
41
|
+
|
|
42
|
+
/** 运行时配置(API Keys 和 URLs) */
|
|
43
|
+
export interface RuntimeConfig {
|
|
44
|
+
arkApiKey: string;
|
|
45
|
+
arkApiUrl: string;
|
|
46
|
+
qwenApiKey: string;
|
|
47
|
+
qwenApiUrl: string;
|
|
48
|
+
openrouterApiKey: string;
|
|
49
|
+
openrouterApiUrl: string;
|
|
50
|
+
vercelApiKey: string;
|
|
51
|
+
tavilyApiKey: string;
|
|
52
|
+
geminiApiKey: string;
|
|
53
|
+
cwd: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 混合 Agent 类
|
|
58
|
+
*
|
|
59
|
+
* 职责:
|
|
60
|
+
* 1. 管理 UnifiedAdapter(统一适配器)
|
|
61
|
+
* 2. 使用 ChatOrchestrator 统一处理工具调用
|
|
62
|
+
* 3. 管理工具注册
|
|
63
|
+
*/
|
|
64
|
+
export class HybridAgent {
|
|
65
|
+
private config: RuntimeConfig;
|
|
66
|
+
private adapter: UnifiedAdapter;
|
|
67
|
+
private orchestrator: ChatOrchestrator;
|
|
68
|
+
private geminiClient: GoogleGenAI;
|
|
69
|
+
private toolExecutor: ToolExecutor;
|
|
70
|
+
private abortController: AbortController | null = null;
|
|
71
|
+
|
|
72
|
+
/** 已注册的工具 */
|
|
73
|
+
private tools: Map<string, Tool> = new Map();
|
|
74
|
+
|
|
75
|
+
/** 工具配置(用于异步初始化) */
|
|
76
|
+
private toolConfig: ToolConfigItem[] | undefined;
|
|
77
|
+
|
|
78
|
+
/** MCP 客户端管理器 */
|
|
79
|
+
private mcpManager: McpClientManager | null = null;
|
|
80
|
+
/** MCP 服务器配置 */
|
|
81
|
+
private mcpConfigs: McpServerConfig[] | undefined;
|
|
82
|
+
|
|
83
|
+
constructor(config: AgentConfig, toolExecutor?: ToolExecutor) {
|
|
84
|
+
this.config = {
|
|
85
|
+
arkApiKey: config.arkApiKey,
|
|
86
|
+
arkApiUrl: config.arkApiUrl || DEFAULT_ARK_URL,
|
|
87
|
+
qwenApiKey: config.qwenApiKey || '',
|
|
88
|
+
qwenApiUrl: config.qwenApiUrl || DEFAULT_QWEN_URL,
|
|
89
|
+
openrouterApiKey: config.openrouterApiKey || '',
|
|
90
|
+
openrouterApiUrl: config.openrouterApiUrl || DEFAULT_OPENROUTER_URL,
|
|
91
|
+
vercelApiKey: config.vercelApiKey || '',
|
|
92
|
+
tavilyApiKey: config.tavilyApiKey || '',
|
|
93
|
+
geminiApiKey: config.geminiApiKey,
|
|
94
|
+
cwd: config.cwd || process.cwd(),
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
this.geminiClient = new GoogleGenAI({ apiKey: this.config.geminiApiKey });
|
|
98
|
+
this.toolExecutor = toolExecutor || createDefaultToolExecutor(this.config.cwd);
|
|
99
|
+
|
|
100
|
+
// 保存工具配置(用于异步初始化)
|
|
101
|
+
this.toolConfig = config.tools;
|
|
102
|
+
this.mcpConfigs = config.mcpServers;
|
|
103
|
+
this.tools = new Map();
|
|
104
|
+
|
|
105
|
+
// 初始化 UnifiedAdapter(统一适配器)
|
|
106
|
+
this.adapter = new UnifiedAdapter({
|
|
107
|
+
arkApiKey: this.config.arkApiKey,
|
|
108
|
+
arkApiUrl: this.config.arkApiUrl,
|
|
109
|
+
qwenApiKey: this.config.qwenApiKey,
|
|
110
|
+
qwenApiUrl: this.config.qwenApiUrl,
|
|
111
|
+
geminiApiKey: this.config.geminiApiKey,
|
|
112
|
+
openrouterApiKey: this.config.openrouterApiKey,
|
|
113
|
+
openrouterApiUrl: this.config.openrouterApiUrl,
|
|
114
|
+
vercelApiKey: this.config.vercelApiKey,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// 初始化 Orchestrator(不传 maxIterations,使用 Orchestrator 默认值 25)
|
|
118
|
+
this.orchestrator = new ChatOrchestrator({
|
|
119
|
+
executeTool: this.executeTool.bind(this),
|
|
120
|
+
tools: this.tools,
|
|
121
|
+
onToolApprovalRequest: config.onToolApprovalRequest,
|
|
122
|
+
getAutoRunConfig: config.getAutoRunConfig,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** 异步初始化工具(在第一次 chat 前调用) */
|
|
127
|
+
private async asyncInit(): Promise<void> {
|
|
128
|
+
if (this.toolConfig && this.tools.size === 0) {
|
|
129
|
+
const resolvedTools = await resolveTools(this.toolConfig);
|
|
130
|
+
for (const tool of resolvedTools) {
|
|
131
|
+
this.tools.set(tool.name, tool);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 内置 Web Search(Tavily):仅在配置了 tavilyApiKey 且未被用户覆盖时注册
|
|
136
|
+
if (this.config.tavilyApiKey && !this.tools.has(WEB_SEARCH_TOOL_NAME)) {
|
|
137
|
+
this.tools.set(WEB_SEARCH_TOOL_NAME, createWebSearchTool(this.config.tavilyApiKey));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// MCP 工具:连接所有配置的 MCP Server,发现并注册工具
|
|
141
|
+
if (this.mcpConfigs?.length && !this.mcpManager) {
|
|
142
|
+
this.mcpManager = new McpClientManager();
|
|
143
|
+
await this.mcpManager.connectAll(this.mcpConfigs);
|
|
144
|
+
|
|
145
|
+
// 注册 MCP 发现的工具(不覆盖已有同名工具)
|
|
146
|
+
for (const tool of this.mcpManager.getAllTools()) {
|
|
147
|
+
if (!this.tools.has(tool.name)) {
|
|
148
|
+
this.tools.set(tool.name, tool);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** 获取模型的家族配置 */
|
|
155
|
+
getModelFamilyConfig(model: string): ModelFamilyConfig | undefined {
|
|
156
|
+
return getModelFamily(model);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 判断模型提供商(兼容旧接口)
|
|
161
|
+
*/
|
|
162
|
+
private getModelProvider(model: string): ProviderType {
|
|
163
|
+
return routeModelToProvider(model);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* 调试:获取模型路由信息
|
|
168
|
+
*/
|
|
169
|
+
getModelRouteInfo(model: string): RouteResult & { available: boolean; familyConfig?: ModelFamilyConfig } {
|
|
170
|
+
const result = routeModelWithDetails(model);
|
|
171
|
+
return {
|
|
172
|
+
...result,
|
|
173
|
+
available: this.adapter.supportsModel(model),
|
|
174
|
+
familyConfig: getModelFamily(model),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** 构建系统提示词 */
|
|
179
|
+
private buildSystemPrompt(options: ChatOptions): string {
|
|
180
|
+
const model = options.model || DEFAULT_MODEL;
|
|
181
|
+
const familyConfig = getModelFamily(model);
|
|
182
|
+
|
|
183
|
+
// Agent 和 Ask 模式使用默认提示词
|
|
184
|
+
let prompt = AGENT_MODE_PROMPT;
|
|
185
|
+
|
|
186
|
+
// Skills 注入:用户启用的 Skills 内容拼接到 system prompt
|
|
187
|
+
if (options.skillContents?.length) {
|
|
188
|
+
prompt += '\n\n【用户指令】\n' + options.skillContents.join('\n\n');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Web Search(工具方式):仅对"不支持原生搜索"的模型提示使用 web_search_ai
|
|
192
|
+
if (options.enableWebSearch && familyConfig && !modelSupportsNativeSearch(model)) {
|
|
193
|
+
prompt += `\n\n【联网搜索】当用户问题需要实时信息/最新事实/可引用来源时,请先调用 ${WEB_SEARCH_TOOL_NAME} 工具获取结果,然后基于返回的 title/url/snippet 作答,并在回答中给出来源链接。`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return prompt;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** 获取默认深度思考模式 */
|
|
200
|
+
private getDefaultThinkingMode(): ThinkingMode {
|
|
201
|
+
return 'disabled';
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** 创建工具执行上下文 */
|
|
205
|
+
private createToolContext(signal?: AbortSignal, hooks?: ToolExecutionHooks): ToolContext {
|
|
206
|
+
return {
|
|
207
|
+
cwd: this.config.cwd,
|
|
208
|
+
geminiClient: this.geminiClient,
|
|
209
|
+
executeCommand: (command: string, cwd?: string) =>
|
|
210
|
+
this.toolExecutor.executeCommand(command, cwd || this.config.cwd, signal, {
|
|
211
|
+
onStdout: hooks?.onStdout,
|
|
212
|
+
onStderr: hooks?.onStderr,
|
|
213
|
+
}),
|
|
214
|
+
signal,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** 执行工具 */
|
|
219
|
+
private async executeTool(
|
|
220
|
+
name: string,
|
|
221
|
+
args: Record<string, unknown>,
|
|
222
|
+
signal?: AbortSignal,
|
|
223
|
+
hooks?: ToolExecutionHooks
|
|
224
|
+
): Promise<string | ToolResult> {
|
|
225
|
+
const tool = this.tools.get(name);
|
|
226
|
+
if (!tool) {
|
|
227
|
+
return `未知工具: ${name}`;
|
|
228
|
+
}
|
|
229
|
+
return await tool.execute(args, this.createToolContext(signal, hooks));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** 获取工具定义列表 */
|
|
233
|
+
private getToolDefinitions(enabledTools?: string[], forceInclude?: string[]): SimpleToolDefinition[] {
|
|
234
|
+
const allTools = Array.from(this.tools.values());
|
|
235
|
+
let selected = enabledTools !== undefined
|
|
236
|
+
? allTools.filter(t => enabledTools.includes(t.name))
|
|
237
|
+
: allTools;
|
|
238
|
+
|
|
239
|
+
// 强制包含指定工具(用于 enableWebSearch 这类"功能开关")
|
|
240
|
+
if (forceInclude?.length) {
|
|
241
|
+
for (const name of forceInclude) {
|
|
242
|
+
if (!selected.some(t => t.name === name)) {
|
|
243
|
+
const t = this.tools.get(name);
|
|
244
|
+
if (t) selected = [...selected, t];
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return selected.map(tool => ({
|
|
250
|
+
name: tool.name,
|
|
251
|
+
description: tool.description,
|
|
252
|
+
parameters: tool.parameters
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** 获取所有工具列表(用于设置面板) */
|
|
257
|
+
public getAllTools(): Array<{ name: string; description: string }> {
|
|
258
|
+
return Array.from(this.tools.values()).map(tool => ({
|
|
259
|
+
name: tool.name,
|
|
260
|
+
description: tool.description
|
|
261
|
+
}));
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* 聊天入口
|
|
266
|
+
*
|
|
267
|
+
* 使用 ChatOrchestrator 统一处理所有 Provider 的工具调用循环
|
|
268
|
+
*/
|
|
269
|
+
async *chat(
|
|
270
|
+
message: string,
|
|
271
|
+
options: ChatOptions = {},
|
|
272
|
+
images?: string[]
|
|
273
|
+
): AsyncGenerator<ChatEvent> {
|
|
274
|
+
// 异步初始化工具(如果还没初始化)
|
|
275
|
+
await this.asyncInit();
|
|
276
|
+
|
|
277
|
+
this.abortController = new AbortController();
|
|
278
|
+
const signal = this.abortController.signal;
|
|
279
|
+
|
|
280
|
+
const model = options.model || DEFAULT_MODEL;
|
|
281
|
+
|
|
282
|
+
// 检查模型是否支持
|
|
283
|
+
if (!this.adapter.supportsModel(model)) {
|
|
284
|
+
const familyConfig = getModelFamily(model);
|
|
285
|
+
if (!familyConfig) {
|
|
286
|
+
yield createApiError(`未知模型: ${model}`, { code: 'MODEL_NOT_SUPPORTED' });
|
|
287
|
+
} else {
|
|
288
|
+
yield createApiError(`模型 ${model} 缺少 API Key 配置`, { code: 'MISSING_API_KEY' });
|
|
289
|
+
}
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// 获取模型家族配置
|
|
294
|
+
const familyConfig = getModelFamily(model);
|
|
295
|
+
|
|
296
|
+
// 统一 thinkingMode
|
|
297
|
+
const rawThinkingMode = options.thinkingMode ?? this.getDefaultThinkingMode();
|
|
298
|
+
const thinkingMode: ThinkingMode = rawThinkingMode === 'enabled' ? 'enabled' : 'disabled';
|
|
299
|
+
const systemPrompt = this.buildSystemPrompt(options);
|
|
300
|
+
|
|
301
|
+
// ask 模式:强制"纯文本回答"
|
|
302
|
+
const isAskMode = options.mode === 'ask';
|
|
303
|
+
const enableSearch = !isAskMode && !!options.enableWebSearch;
|
|
304
|
+
|
|
305
|
+
// 对于不支持原生搜索的模型,需要强制包含联网搜索工具
|
|
306
|
+
const forceInclude = enableSearch && familyConfig && !modelSupportsNativeSearch(model)
|
|
307
|
+
? [WEB_SEARCH_TOOL_NAME]
|
|
308
|
+
: undefined;
|
|
309
|
+
|
|
310
|
+
// 云端工具定义
|
|
311
|
+
const cloudTools = isAskMode ? [] : this.getToolDefinitions(options.enabledTools, forceInclude);
|
|
312
|
+
|
|
313
|
+
// 用户自定义工具(透传模式)
|
|
314
|
+
const userTools = options.userTools || [];
|
|
315
|
+
const userToolDefinitions = userTools.map(t => ({
|
|
316
|
+
name: t.name,
|
|
317
|
+
description: t.description,
|
|
318
|
+
parameters: {
|
|
319
|
+
...t.parameters,
|
|
320
|
+
required: t.parameters.required || [],
|
|
321
|
+
},
|
|
322
|
+
}));
|
|
323
|
+
|
|
324
|
+
// 合并所有工具
|
|
325
|
+
const tools = [...cloudTools, ...userToolDefinitions];
|
|
326
|
+
|
|
327
|
+
// 客户端工具名称集合
|
|
328
|
+
const clientToolNames = userTools.length > 0
|
|
329
|
+
? new Set(userTools.map(t => t.name))
|
|
330
|
+
: undefined;
|
|
331
|
+
|
|
332
|
+
// 只有家族支持 thinking 且用户启用时才真正启用
|
|
333
|
+
const enableThinking = !isAskMode && thinkingMode === 'enabled' && (familyConfig?.supportsThinking ?? false);
|
|
334
|
+
|
|
335
|
+
// 使用传入的历史
|
|
336
|
+
const history = options.history || [];
|
|
337
|
+
|
|
338
|
+
// 构建 Orchestrator 上下文
|
|
339
|
+
const context: OrchestratorContext = {
|
|
340
|
+
systemPrompt,
|
|
341
|
+
history,
|
|
342
|
+
tools,
|
|
343
|
+
signal,
|
|
344
|
+
images,
|
|
345
|
+
clientToolNames,
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
try {
|
|
349
|
+
// 使用 Orchestrator + UnifiedAdapter
|
|
350
|
+
yield* this.orchestrator.chat(this.adapter, message, context, {
|
|
351
|
+
model,
|
|
352
|
+
enableThinking,
|
|
353
|
+
enableSearch,
|
|
354
|
+
autoRunConfig: options.autoRunConfig,
|
|
355
|
+
});
|
|
356
|
+
} finally {
|
|
357
|
+
this.abortController = null;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/** 中断当前请求 */
|
|
362
|
+
abort(): void {
|
|
363
|
+
if (this.abortController) {
|
|
364
|
+
this.abortController.abort();
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/** 设置当前工作目录 */
|
|
369
|
+
setCwd(dir: string): void {
|
|
370
|
+
this.config.cwd = dir;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/** 获取当前配置 */
|
|
374
|
+
getConfig(): RuntimeConfig {
|
|
375
|
+
return { ...this.config };
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/** 获取所有支持的模型 */
|
|
379
|
+
getSupportedModels() {
|
|
380
|
+
return MODELS;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/** 获取 MCP 连接状态 */
|
|
384
|
+
getMcpConnections() {
|
|
385
|
+
return this.mcpManager?.getConnectionInfos() ?? [];
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* 销毁 Agent(优雅关闭所有 MCP 连接)
|
|
390
|
+
*
|
|
391
|
+
* 桌面客户端退出时应调用此方法。
|
|
392
|
+
*/
|
|
393
|
+
async destroy(): Promise<void> {
|
|
394
|
+
if (this.mcpManager) {
|
|
395
|
+
await this.mcpManager.disconnectAll();
|
|
396
|
+
this.mcpManager = null;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 常量定义
|
|
3
|
+
*
|
|
4
|
+
* 所有模型配置统一在此管理
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// ==================== API URL ====================
|
|
8
|
+
export const DEFAULT_ARK_URL = 'https://ark.cn-beijing.volces.com/api/v3';
|
|
9
|
+
// Qwen 使用 OpenAI 兼容模式以支持工具调用
|
|
10
|
+
export const DEFAULT_QWEN_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1';
|
|
11
|
+
export const DEFAULT_OPENROUTER_URL = 'https://openrouter.ai/api/v1';
|
|
12
|
+
|
|
13
|
+
// ==================== 模型配置类型 ====================
|
|
14
|
+
interface ModelConfig {
|
|
15
|
+
id: string;
|
|
16
|
+
displayName: string;
|
|
17
|
+
isOpenRouter?: boolean;
|
|
18
|
+
/** 提供商名称(用于分组) */
|
|
19
|
+
provider?: string;
|
|
20
|
+
/** 模型描述 */
|
|
21
|
+
description?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ==================== 豆包模型 (ARK) ====================
|
|
25
|
+
export const DOUBAO_SEED_1_8: ModelConfig = {
|
|
26
|
+
id: 'doubao-seed-1-8-251215',
|
|
27
|
+
displayName: '豆包 Seed 1.8',
|
|
28
|
+
provider: '豆包',
|
|
29
|
+
};
|
|
30
|
+
export const DOUBAO_SEED_1_6: ModelConfig = {
|
|
31
|
+
id: 'doubao-seed-1-6-250615',
|
|
32
|
+
displayName: '豆包 Seed 1.6',
|
|
33
|
+
provider: '豆包',
|
|
34
|
+
};
|
|
35
|
+
export const DOUBAO_SEED_1_6_LATEST: ModelConfig = {
|
|
36
|
+
id: 'doubao-seed-1-6-251015',
|
|
37
|
+
displayName: '豆包 Seed 1.6 Latest',
|
|
38
|
+
provider: '豆包',
|
|
39
|
+
};
|
|
40
|
+
export const DOUBAO_SEED_1_6_FLASH: ModelConfig = {
|
|
41
|
+
id: 'doubao-seed-1-6-flash-250617',
|
|
42
|
+
displayName: '豆包 Seed 1.6 Flash',
|
|
43
|
+
provider: '豆包',
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// ==================== DeepSeek 模型 (ARK) ====================
|
|
47
|
+
export const DEEPSEEK_V3: ModelConfig = {
|
|
48
|
+
id: 'deepseek-v3-2-251201',
|
|
49
|
+
displayName: 'DeepSeek V3.2',
|
|
50
|
+
// 展示层显式标注:该模型通过 ARK(火山/豆包平台)托管接入
|
|
51
|
+
provider: 'DeepSeek(ARK)',
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// ==================== 通义千问模型 ====================
|
|
55
|
+
export const QWEN_MAX: ModelConfig = { id: 'qwen-max', displayName: '通义千问 Max', provider: '通义千问' };
|
|
56
|
+
export const QWEN_MAX_LATEST: ModelConfig = { id: 'qwen-max-latest', displayName: '通义千问 Max Latest', provider: '通义千问' };
|
|
57
|
+
export const QWEN_PLUS: ModelConfig = { id: 'qwen-plus', displayName: '通义千问 Plus', provider: '通义千问' };
|
|
58
|
+
export const QWEN_PLUS_LATEST: ModelConfig = { id: 'qwen-plus-latest', displayName: '通义千问 Plus Latest', provider: '通义千问' };
|
|
59
|
+
export const QWEN_TURBO: ModelConfig = { id: 'qwen-turbo', displayName: '通义千问 Turbo', provider: '通义千问' };
|
|
60
|
+
export const QWEN_TURBO_LATEST: ModelConfig = { id: 'qwen-turbo-latest', displayName: '通义千问 Turbo Latest', provider: '通义千问' };
|
|
61
|
+
export const QWEN3_235B: ModelConfig = { id: 'qwen3-235b-a22b', displayName: 'Qwen3 235B', provider: '通义千问' };
|
|
62
|
+
export const QWEN3_MAX_PREVIEW: ModelConfig = {
|
|
63
|
+
id: 'qwen3-max-preview',
|
|
64
|
+
displayName: '通义千问 3 Max',
|
|
65
|
+
provider: '通义千问',
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// ==================== Gemini 模型 ====================
|
|
69
|
+
export const GEMINI_2_5_FLASH: ModelConfig = { id: 'gemini-2.5-flash-preview-05-20', displayName: 'Gemini 2.5 Flash', provider: 'Gemini' };
|
|
70
|
+
export const GEMINI_2_5_PRO: ModelConfig = { id: 'gemini-2.5-pro-preview-05-06', displayName: 'Gemini 2.5 Pro', provider: 'Gemini' };
|
|
71
|
+
export const GEMINI_2_0_FLASH: ModelConfig = { id: 'gemini-2.0-flash', displayName: 'Gemini 2.0 Flash', provider: 'Gemini' };
|
|
72
|
+
export const GEMINI_2_0_FLASH_LITE: ModelConfig = { id: 'gemini-2.0-flash-lite', displayName: 'Gemini 2.0 Flash Lite', provider: 'Gemini' };
|
|
73
|
+
export const GEMINI_3_PRO: ModelConfig = {
|
|
74
|
+
id: 'gemini-3-pro-preview',
|
|
75
|
+
displayName: 'Gemini 3 Pro',
|
|
76
|
+
provider: 'Gemini',
|
|
77
|
+
};
|
|
78
|
+
// 图片模型(仅 id)
|
|
79
|
+
export const GEMINI_IMAGE_MODEL = 'gemini-2.0-flash';
|
|
80
|
+
export const GEMINI_IMAGE_GEN_MODEL = 'gemini-3-pro-image-preview';
|
|
81
|
+
|
|
82
|
+
// ==================== OpenRouter 模型 ====================
|
|
83
|
+
export const OR_GPT_5_1: ModelConfig = {
|
|
84
|
+
id: 'openai/gpt-5.1-codex',
|
|
85
|
+
displayName: 'GPT-5.1 Codex',
|
|
86
|
+
isOpenRouter: true,
|
|
87
|
+
provider: 'OpenAI',
|
|
88
|
+
};
|
|
89
|
+
export const CLAUDE_OPUS_4_5: ModelConfig = {
|
|
90
|
+
id: 'anthropic/claude-opus-4.5',
|
|
91
|
+
displayName: 'Claude Opus 4.5',
|
|
92
|
+
provider: 'Anthropic',
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// ==================== 前端显示的模型列表 ====================
|
|
96
|
+
export const DISPLAY_MODELS: ModelConfig[] = [
|
|
97
|
+
// 原生模型
|
|
98
|
+
DOUBAO_SEED_1_6,
|
|
99
|
+
DEEPSEEK_V3,
|
|
100
|
+
QWEN3_MAX_PREVIEW,
|
|
101
|
+
GEMINI_3_PRO,
|
|
102
|
+
// OpenRouter 模型
|
|
103
|
+
OR_GPT_5_1,
|
|
104
|
+
// Vercel AI SDK 模型
|
|
105
|
+
CLAUDE_OPUS_4_5,
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
// ==================== 默认配置 ====================
|
|
109
|
+
export const DEFAULT_MODEL = DOUBAO_SEED_1_6.id;
|
|
110
|
+
|
|
111
|
+
/** agent 模式提示词 */
|
|
112
|
+
export const AGENT_MODE_PROMPT = `你是一个专业的 AI 助手,具备自主执行复杂任务的能力。
|
|
113
|
+
|
|
114
|
+
## 工作方式
|
|
115
|
+
1. **分析任务**:理解用户需求,拆解为可执行的步骤
|
|
116
|
+
2. **逐步执行**:按步骤依次调用工具,检查每步结果
|
|
117
|
+
3. **自我验证**:工具执行后检查结果是否符合预期
|
|
118
|
+
4. **自动纠正**:发现问题时尝试替代方案,不要停下来问用户
|
|
119
|
+
5. **总结汇报**:所有步骤完成后,给出简洁的结果总结
|
|
120
|
+
|
|
121
|
+
## 输出规范
|
|
122
|
+
- 不使用表情符号(emoji),除非用户要求
|
|
123
|
+
- 使用 Markdown 格式组织内容
|
|
124
|
+
- 代码块使用正确的语言标识`;
|
|
125
|
+
|