@huyooo/ai-chat-core 0.2.45 → 0.3.3

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.
Files changed (247) hide show
  1. package/dist/adapter/index.d.ts +11 -0
  2. package/dist/adapter/index.d.ts.map +1 -0
  3. package/dist/adapter/model-adapter.d.ts +25 -0
  4. package/dist/adapter/model-adapter.d.ts.map +1 -0
  5. package/dist/adapter/model-options.d.ts +53 -0
  6. package/dist/adapter/model-options.d.ts.map +1 -0
  7. package/dist/adapter/types.d.ts +28 -0
  8. package/dist/adapter/types.d.ts.map +1 -0
  9. package/dist/chat-runtime.d.ts +96 -0
  10. package/dist/chat-runtime.d.ts.map +1 -0
  11. package/dist/constants.d.ts +12 -0
  12. package/dist/constants.d.ts.map +1 -0
  13. package/dist/events.d.ts +605 -1
  14. package/dist/events.d.ts.map +1 -0
  15. package/dist/events.js +1 -1
  16. package/dist/extension/index.d.ts +9 -0
  17. package/dist/extension/index.d.ts.map +1 -0
  18. package/dist/extension/types.d.ts +46 -0
  19. package/dist/extension/types.d.ts.map +1 -0
  20. package/dist/families/index.d.ts +11 -0
  21. package/dist/families/index.d.ts.map +1 -0
  22. package/dist/families/presets.d.ts +31 -0
  23. package/dist/families/presets.d.ts.map +1 -0
  24. package/dist/families/resolver.d.ts +11 -0
  25. package/dist/families/resolver.d.ts.map +1 -0
  26. package/dist/families/types.d.ts +29 -0
  27. package/dist/families/types.d.ts.map +1 -0
  28. package/dist/governance/command-safety.d.ts +34 -0
  29. package/dist/governance/command-safety.d.ts.map +1 -0
  30. package/dist/governance/governance.d.ts +19 -0
  31. package/dist/governance/governance.d.ts.map +1 -0
  32. package/dist/governance/index.d.ts +12 -0
  33. package/dist/governance/index.d.ts.map +1 -0
  34. package/dist/governance/types.d.ts +29 -0
  35. package/dist/governance/types.d.ts.map +1 -0
  36. package/dist/index.d.ts +72 -804
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +51 -1
  39. package/dist/internal/management-args.d.ts +13 -0
  40. package/dist/internal/management-args.d.ts.map +1 -0
  41. package/dist/internal/management-results.d.ts +21 -0
  42. package/dist/internal/management-results.d.ts.map +1 -0
  43. package/dist/llm-config.d.ts +108 -0
  44. package/dist/llm-config.d.ts.map +1 -0
  45. package/dist/logger/core.d.ts +31 -0
  46. package/dist/logger/core.d.ts.map +1 -0
  47. package/dist/logger/index.d.ts +9 -0
  48. package/dist/logger/index.d.ts.map +1 -0
  49. package/dist/orchestrator/compression-handler.d.ts +29 -0
  50. package/dist/orchestrator/compression-handler.d.ts.map +1 -0
  51. package/dist/orchestrator/context-compressor.d.ts +51 -0
  52. package/dist/orchestrator/context-compressor.d.ts.map +1 -0
  53. package/dist/orchestrator/context-summarizer.d.ts +41 -0
  54. package/dist/orchestrator/context-summarizer.d.ts.map +1 -0
  55. package/dist/orchestrator/index.d.ts +12 -0
  56. package/dist/orchestrator/index.d.ts.map +1 -0
  57. package/dist/orchestrator/orchestrator.d.ts +46 -0
  58. package/dist/orchestrator/orchestrator.d.ts.map +1 -0
  59. package/dist/orchestrator/types.d.ts +58 -0
  60. package/dist/orchestrator/types.d.ts.map +1 -0
  61. package/dist/parts/index.d.ts +13 -0
  62. package/dist/parts/index.d.ts.map +1 -0
  63. package/dist/parts/registry.d.ts +11 -0
  64. package/dist/parts/registry.d.ts.map +1 -0
  65. package/dist/parts/summaries.d.ts +9 -0
  66. package/dist/parts/summaries.d.ts.map +1 -0
  67. package/dist/parts/types.d.ts +61 -0
  68. package/dist/parts/types.d.ts.map +1 -0
  69. package/dist/platform.d.ts +17 -0
  70. package/dist/platform.d.ts.map +1 -0
  71. package/dist/platform.js +1 -0
  72. package/dist/protocols/anthropic.d.ts +20 -0
  73. package/dist/protocols/anthropic.d.ts.map +1 -0
  74. package/dist/protocols/ark.d.ts +36 -0
  75. package/dist/protocols/ark.d.ts.map +1 -0
  76. package/dist/protocols/deepseek.d.ts +24 -0
  77. package/dist/protocols/deepseek.d.ts.map +1 -0
  78. package/dist/protocols/error-utils.d.ts +14 -0
  79. package/dist/protocols/error-utils.d.ts.map +1 -0
  80. package/dist/protocols/gemini.d.ts +24 -0
  81. package/dist/protocols/gemini.d.ts.map +1 -0
  82. package/dist/protocols/glm.d.ts +20 -0
  83. package/dist/protocols/glm.d.ts.map +1 -0
  84. package/dist/protocols/grok.d.ts +20 -0
  85. package/dist/protocols/grok.d.ts.map +1 -0
  86. package/dist/protocols/index.d.ts +31 -0
  87. package/dist/protocols/index.d.ts.map +1 -0
  88. package/dist/protocols/minimax.d.ts +38 -0
  89. package/dist/protocols/minimax.d.ts.map +1 -0
  90. package/dist/protocols/moonshot.d.ts +20 -0
  91. package/dist/protocols/moonshot.d.ts.map +1 -0
  92. package/dist/protocols/openai-sse.d.ts +33 -0
  93. package/dist/protocols/openai-sse.d.ts.map +1 -0
  94. package/dist/protocols/openai.d.ts +19 -0
  95. package/dist/protocols/openai.d.ts.map +1 -0
  96. package/dist/protocols/qwen.d.ts +26 -0
  97. package/dist/protocols/qwen.d.ts.map +1 -0
  98. package/dist/protocols/responses-sse.d.ts +30 -0
  99. package/dist/protocols/responses-sse.d.ts.map +1 -0
  100. package/dist/protocols/sse-reader.d.ts +23 -0
  101. package/dist/protocols/sse-reader.d.ts.map +1 -0
  102. package/dist/protocols/tool-arguments.d.ts +8 -0
  103. package/dist/protocols/tool-arguments.d.ts.map +1 -0
  104. package/dist/protocols/types.d.ts +148 -0
  105. package/dist/protocols/types.d.ts.map +1 -0
  106. package/dist/protocols/vercel-gateway.d.ts +15 -0
  107. package/dist/protocols/vercel-gateway.d.ts.map +1 -0
  108. package/dist/runtime.d.ts +151 -0
  109. package/dist/runtime.d.ts.map +1 -0
  110. package/dist/runtime.js +1 -0
  111. package/dist/skills/index.d.ts +14 -0
  112. package/dist/skills/index.d.ts.map +1 -0
  113. package/dist/skills/management/admin.d.ts +10 -0
  114. package/dist/skills/management/admin.d.ts.map +1 -0
  115. package/dist/skills/management/index.d.ts +11 -0
  116. package/dist/skills/management/index.d.ts.map +1 -0
  117. package/dist/skills/management/inputs.d.ts +44 -0
  118. package/dist/skills/management/inputs.d.ts.map +1 -0
  119. package/dist/skills/management/operations.d.ts +78 -0
  120. package/dist/skills/management/operations.d.ts.map +1 -0
  121. package/dist/skills/management/types.d.ts +70 -0
  122. package/dist/skills/management/types.d.ts.map +1 -0
  123. package/dist/skills/registry.d.ts +37 -0
  124. package/dist/skills/registry.d.ts.map +1 -0
  125. package/dist/skills/summaries.d.ts +9 -0
  126. package/dist/skills/summaries.d.ts.map +1 -0
  127. package/dist/skills/types.d.ts +61 -0
  128. package/dist/skills/types.d.ts.map +1 -0
  129. package/dist/test-utils/mock-sse.d.ts +13 -0
  130. package/dist/test-utils/mock-sse.d.ts.map +1 -0
  131. package/dist/tool-manager/define-tool.d.ts +35 -0
  132. package/dist/tool-manager/define-tool.d.ts.map +1 -0
  133. package/dist/tool-manager/formats.d.ts +46 -0
  134. package/dist/tool-manager/formats.d.ts.map +1 -0
  135. package/dist/tool-manager/identity.d.ts +18 -0
  136. package/dist/tool-manager/identity.d.ts.map +1 -0
  137. package/dist/tool-manager/in-process-provider.d.ts +15 -0
  138. package/dist/tool-manager/in-process-provider.d.ts.map +1 -0
  139. package/dist/tool-manager/index.d.ts +18 -0
  140. package/dist/tool-manager/index.d.ts.map +1 -0
  141. package/dist/tool-manager/manager.d.ts +18 -0
  142. package/dist/tool-manager/manager.d.ts.map +1 -0
  143. package/dist/tool-manager/mcp-provider.d.ts +21 -0
  144. package/dist/tool-manager/mcp-provider.d.ts.map +1 -0
  145. package/dist/tool-manager/summaries.d.ts +39 -0
  146. package/dist/tool-manager/summaries.d.ts.map +1 -0
  147. package/dist/tool-manager/types.d.ts +314 -0
  148. package/dist/tool-manager/types.d.ts.map +1 -0
  149. package/dist/types.d.ts +663 -0
  150. package/dist/types.d.ts.map +1 -0
  151. package/package.json +26 -15
  152. package/src/adapter/index.ts +25 -0
  153. package/src/adapter/model-adapter.ts +196 -0
  154. package/src/adapter/model-options.ts +143 -0
  155. package/src/adapter/types.ts +41 -0
  156. package/src/chat-runtime.ts +515 -0
  157. package/src/constants.ts +9 -102
  158. package/src/events.ts +364 -150
  159. package/src/extension/index.ts +24 -0
  160. package/src/extension/types.ts +49 -0
  161. package/src/families/index.ts +28 -0
  162. package/src/families/presets.ts +124 -0
  163. package/src/families/resolver.ts +22 -0
  164. package/src/families/types.ts +55 -0
  165. package/src/governance/command-safety.ts +224 -0
  166. package/src/governance/governance.ts +125 -0
  167. package/src/governance/index.ts +38 -0
  168. package/src/governance/types.ts +44 -0
  169. package/src/index.ts +250 -145
  170. package/src/internal/management-args.ts +39 -0
  171. package/src/internal/management-results.ts +60 -0
  172. package/src/llm-config.ts +137 -0
  173. package/src/logger/core.ts +96 -0
  174. package/src/logger/index.ts +8 -0
  175. package/src/orchestrator/compression-handler.ts +137 -0
  176. package/src/{providers → orchestrator}/context-compressor.ts +79 -47
  177. package/src/orchestrator/context-summarizer.ts +123 -0
  178. package/src/orchestrator/index.ts +20 -0
  179. package/src/orchestrator/orchestrator.ts +1002 -0
  180. package/src/orchestrator/types.ts +70 -0
  181. package/src/parts/index.ts +20 -0
  182. package/src/parts/registry.ts +95 -0
  183. package/src/parts/summaries.ts +40 -0
  184. package/src/parts/types.ts +63 -0
  185. package/src/platform.ts +73 -0
  186. package/src/protocols/anthropic.ts +377 -0
  187. package/src/protocols/ark.ts +300 -0
  188. package/src/protocols/deepseek.ts +192 -0
  189. package/src/{providers/protocols → protocols}/error-utils.ts +17 -20
  190. package/src/protocols/gemini.ts +352 -0
  191. package/src/protocols/glm.ts +212 -0
  192. package/src/protocols/grok.ts +98 -0
  193. package/src/protocols/index.ts +48 -0
  194. package/src/protocols/minimax.ts +308 -0
  195. package/src/protocols/moonshot.ts +186 -0
  196. package/src/protocols/openai-sse.ts +156 -0
  197. package/src/protocols/openai.ts +97 -0
  198. package/src/protocols/qwen.ts +358 -0
  199. package/src/protocols/responses-sse.ts +224 -0
  200. package/src/protocols/sse-reader.ts +54 -0
  201. package/src/protocols/tool-arguments.ts +32 -0
  202. package/src/{providers/protocols → protocols}/types.ts +46 -37
  203. package/src/protocols/vercel-gateway.ts +391 -0
  204. package/src/runtime.ts +167 -0
  205. package/src/skills/index.ts +29 -0
  206. package/src/skills/management/admin.ts +170 -0
  207. package/src/skills/management/index.ts +27 -0
  208. package/src/skills/management/inputs.ts +79 -0
  209. package/src/skills/management/operations.ts +256 -0
  210. package/src/skills/management/types.ts +57 -0
  211. package/src/skills/registry.ts +120 -0
  212. package/src/skills/summaries.ts +48 -0
  213. package/src/skills/types.ts +65 -0
  214. package/src/test-utils/mock-sse.ts +3 -3
  215. package/src/tool-manager/define-tool.ts +201 -0
  216. package/src/tool-manager/formats.ts +146 -0
  217. package/src/tool-manager/identity.ts +80 -0
  218. package/src/tool-manager/in-process-provider.ts +164 -0
  219. package/src/tool-manager/index.ts +63 -0
  220. package/src/tool-manager/manager.ts +562 -0
  221. package/src/tool-manager/mcp-provider.ts +509 -0
  222. package/src/tool-manager/summaries.ts +136 -0
  223. package/src/tool-manager/types.ts +389 -0
  224. package/src/types.ts +750 -191
  225. package/dist/events-CU5D5ray.d.ts +0 -1128
  226. package/src/agent.ts +0 -409
  227. package/src/internal/update-plan.ts +0 -2
  228. package/src/internal/web-search.ts +0 -77
  229. package/src/mcp/client-manager.ts +0 -302
  230. package/src/mcp/index.ts +0 -2
  231. package/src/mcp/types.ts +0 -43
  232. package/src/providers/context-summarizer.ts +0 -70
  233. package/src/providers/index.ts +0 -125
  234. package/src/providers/model-registry.ts +0 -466
  235. package/src/providers/orchestrator.ts +0 -839
  236. package/src/providers/protocols/anthropic.ts +0 -406
  237. package/src/providers/protocols/ark.ts +0 -362
  238. package/src/providers/protocols/deepseek.ts +0 -344
  239. package/src/providers/protocols/gemini.ts +0 -350
  240. package/src/providers/protocols/index.ts +0 -36
  241. package/src/providers/protocols/openai.ts +0 -420
  242. package/src/providers/protocols/qwen.ts +0 -315
  243. package/src/providers/types.ts +0 -264
  244. package/src/providers/unified-adapter.ts +0 -367
  245. package/src/router.ts +0 -72
  246. package/src/tools.ts +0 -162
  247. package/src/utils.ts +0 -86
package/src/agent.ts DELETED
@@ -1,409 +0,0 @@
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 type {
16
- AgentConfig,
17
- ToolExecutor,
18
- ChatOptions,
19
- ThinkingMode,
20
- Tool,
21
- ToolContext,
22
- ToolConfigItem,
23
- } from './types';
24
- import { resolveTools, MODELS } from './types';
25
- import type { ChatEvent } from './events';
26
- import { createApiError } from './events';
27
- import { createDefaultToolExecutor } from './tools';
28
- import { DEFAULT_ARK_URL, DEFAULT_QWEN_URL, DEFAULT_OPENROUTER_URL, DEFAULT_MODEL, AGENT_MODE_PROMPT } from './constants';
29
- import { routeModelToProvider, routeModelWithDetails, type ProviderType, type RouteResult } from './router';
30
- import { getModelFamily, modelSupportsNativeSearch, type ModelFamilyConfig } from './providers/model-registry';
31
- import { McpClientManager } from './mcp/client-manager';
32
- import type { McpServerConfig } from './mcp/types';
33
-
34
- // 新架构导入
35
- import type { OrchestratorContext, SimpleToolDefinition, ToolExecutionHooks } from './providers/types';
36
- import { ChatOrchestrator } from './providers/orchestrator';
37
- import { UnifiedAdapter } from './providers/unified-adapter';
38
- import { createWebSearchTool, WEB_SEARCH_TOOL_NAME } from './internal/web-search';
39
-
40
- /** 运行时配置(API Keys 和 URLs) */
41
- export interface RuntimeConfig {
42
- arkApiKey: string;
43
- arkApiUrl: string;
44
- qwenApiKey: string;
45
- qwenApiUrl: string;
46
- openrouterApiKey: string;
47
- openrouterApiUrl: string;
48
- vercelApiKey: string;
49
- tavilyApiKey: string;
50
- geminiApiKey: string;
51
- cwd: string;
52
- }
53
-
54
- /**
55
- * 混合 Agent 类
56
- *
57
- * 职责:
58
- * 1. 管理 UnifiedAdapter(统一适配器)
59
- * 2. 使用 ChatOrchestrator 统一处理工具调用
60
- * 3. 管理工具注册
61
- */
62
- export class HybridAgent {
63
- private config: RuntimeConfig;
64
- private adapter: UnifiedAdapter;
65
- private orchestrator: ChatOrchestrator;
66
- private toolExecutor: ToolExecutor;
67
- private abortController: AbortController | null = null;
68
-
69
- /** 已注册的工具 */
70
- private tools: Map<string, Tool> = new Map();
71
-
72
- /** 工具配置(用于异步初始化) */
73
- private toolConfig: ToolConfigItem[] | undefined;
74
-
75
- /** MCP 客户端管理器 */
76
- private mcpManager: McpClientManager | null = null;
77
- /** MCP 服务器配置 */
78
- private mcpConfigs: McpServerConfig[] | undefined;
79
-
80
- constructor(config: AgentConfig, toolExecutor?: ToolExecutor) {
81
- this.config = {
82
- arkApiKey: config.arkApiKey,
83
- arkApiUrl: config.arkApiUrl || DEFAULT_ARK_URL,
84
- qwenApiKey: config.qwenApiKey || '',
85
- qwenApiUrl: config.qwenApiUrl || DEFAULT_QWEN_URL,
86
- openrouterApiKey: config.openrouterApiKey || '',
87
- openrouterApiUrl: config.openrouterApiUrl || DEFAULT_OPENROUTER_URL,
88
- vercelApiKey: config.vercelApiKey || '',
89
- tavilyApiKey: config.tavilyApiKey || '',
90
- geminiApiKey: config.geminiApiKey,
91
- cwd: config.cwd || process.cwd(),
92
- };
93
-
94
- this.toolExecutor = toolExecutor || createDefaultToolExecutor(this.config.cwd);
95
-
96
- // 保存工具配置(用于异步初始化)
97
- this.toolConfig = config.tools;
98
- this.mcpConfigs = config.mcpServers;
99
- this.tools = new Map();
100
-
101
- // 初始化 UnifiedAdapter(统一适配器)
102
- this.adapter = new UnifiedAdapter({
103
- arkApiKey: this.config.arkApiKey,
104
- arkApiUrl: this.config.arkApiUrl,
105
- qwenApiKey: this.config.qwenApiKey,
106
- qwenApiUrl: this.config.qwenApiUrl,
107
- geminiApiKey: this.config.geminiApiKey,
108
- openrouterApiKey: this.config.openrouterApiKey,
109
- openrouterApiUrl: this.config.openrouterApiUrl,
110
- vercelApiKey: this.config.vercelApiKey,
111
- });
112
-
113
- // 初始化 Orchestrator(不传 maxIterations,使用 Orchestrator 默认值 25)
114
- this.orchestrator = new ChatOrchestrator({
115
- executeTool: this.executeTool.bind(this),
116
- tools: this.tools,
117
- onToolApprovalRequest: config.onToolApprovalRequest,
118
- getAutoRunConfig: config.getAutoRunConfig,
119
- summarize: config.summarize,
120
- });
121
- }
122
-
123
- /** 异步初始化工具(在第一次 chat 前调用) */
124
- private async asyncInit(): Promise<void> {
125
- if (this.toolConfig && this.tools.size === 0) {
126
- const resolvedTools = await resolveTools(this.toolConfig);
127
- for (const tool of resolvedTools) {
128
- this.tools.set(tool.name, tool);
129
- }
130
- }
131
-
132
- // 内置 Web Search(Tavily):仅在配置了 tavilyApiKey 且未被用户覆盖时注册
133
- if (this.config.tavilyApiKey && !this.tools.has(WEB_SEARCH_TOOL_NAME)) {
134
- this.tools.set(WEB_SEARCH_TOOL_NAME, createWebSearchTool(this.config.tavilyApiKey));
135
- }
136
-
137
- // MCP 工具:连接所有配置的 MCP Server,发现并注册工具
138
- if (this.mcpConfigs?.length && !this.mcpManager) {
139
- this.mcpManager = new McpClientManager();
140
- await this.mcpManager.connectAll(this.mcpConfigs);
141
-
142
- // 注册 MCP 发现的工具(不覆盖已有同名工具)
143
- for (const tool of this.mcpManager.getAllTools()) {
144
- if (!this.tools.has(tool.name)) {
145
- this.tools.set(tool.name, tool);
146
- }
147
- }
148
- }
149
- }
150
-
151
- /** 获取模型的家族配置 */
152
- getModelFamilyConfig(model: string): ModelFamilyConfig | undefined {
153
- return getModelFamily(model);
154
- }
155
-
156
- /**
157
- * 判断模型提供商(兼容旧接口)
158
- */
159
- private getModelProvider(model: string): ProviderType {
160
- return routeModelToProvider(model);
161
- }
162
-
163
- /**
164
- * 调试:获取模型路由信息
165
- */
166
- getModelRouteInfo(model: string): RouteResult & { available: boolean; familyConfig?: ModelFamilyConfig } {
167
- const result = routeModelWithDetails(model);
168
- return {
169
- ...result,
170
- available: this.adapter.supportsModel(model),
171
- familyConfig: getModelFamily(model),
172
- };
173
- }
174
-
175
- /** 构建系统提示词 */
176
- private buildSystemPrompt(options: ChatOptions): string {
177
- const model = options.model || DEFAULT_MODEL;
178
- const familyConfig = getModelFamily(model);
179
-
180
- // Agent 和 Ask 模式使用默认提示词
181
- let prompt = AGENT_MODE_PROMPT;
182
-
183
- // 宿主平台提示词:描述平台特有能力和工具
184
- if (options.platformPrompt) {
185
- prompt += '\n\n' + options.platformPrompt;
186
- }
187
-
188
- // Skills 注入:用户启用的 Skills 内容拼接到 system prompt
189
- if (options.skillContents?.length) {
190
- prompt += '\n\n【用户指令】\n' + options.skillContents.join('\n\n');
191
- }
192
-
193
- // Web Search(工具方式):仅对"不支持原生搜索"的模型提示使用 web_search_ai
194
- if (options.enableWebSearch && familyConfig && !modelSupportsNativeSearch(model)) {
195
- prompt += `\n\n【联网搜索】当用户问题需要实时信息/最新事实/可引用来源时,请先调用 ${WEB_SEARCH_TOOL_NAME} 工具获取结果,然后基于返回的 title/url/snippet 作答,并在回答中给出来源链接。`;
196
- }
197
-
198
- return prompt;
199
- }
200
-
201
- /** 获取默认深度思考模式 */
202
- private getDefaultThinkingMode(): ThinkingMode {
203
- return 'disabled';
204
- }
205
-
206
- /** 创建工具执行上下文 */
207
- private createToolContext(signal?: AbortSignal, hooks?: ToolExecutionHooks): ToolContext {
208
- const cwd = this.config.cwd;
209
- const executor = this.toolExecutor;
210
- return {
211
- cwd,
212
- exec: async (cmd: string, args?: string[]) => {
213
- const command = args?.length ? `${cmd} ${args.join(' ')}` : cmd;
214
- const r = await executor.executeCommand(command, cwd, signal, {
215
- onStdout: hooks?.onStdout,
216
- onStderr: hooks?.onStderr,
217
- });
218
- return {
219
- stdout: r.output ?? '',
220
- stderr: r.error ?? '',
221
- exitCode: r.success ? 0 : 1,
222
- };
223
- },
224
- signal,
225
- };
226
- }
227
-
228
- /** 执行工具 */
229
- private async executeTool(
230
- name: string,
231
- args: Record<string, unknown>,
232
- signal?: AbortSignal,
233
- hooks?: ToolExecutionHooks
234
- ): Promise<object> {
235
- const tool = this.tools.get(name);
236
- if (!tool) {
237
- return { error: `未知工具: ${name}` };
238
- }
239
- return await tool.execute(args, this.createToolContext(signal, hooks));
240
- }
241
-
242
- /** 获取工具定义列表 */
243
- private getToolDefinitions(enabledTools?: string[], forceInclude?: string[]): SimpleToolDefinition[] {
244
- const allTools = Array.from(this.tools.values());
245
- let selected = enabledTools !== undefined
246
- ? allTools.filter(t => enabledTools.includes(t.name))
247
- : allTools;
248
-
249
- // 强制包含指定工具(用于 enableWebSearch 这类"功能开关")
250
- if (forceInclude?.length) {
251
- for (const name of forceInclude) {
252
- if (!selected.some(t => t.name === name)) {
253
- const t = this.tools.get(name);
254
- if (t) selected = [...selected, t];
255
- }
256
- }
257
- }
258
-
259
- return selected.map(tool => ({
260
- name: tool.name,
261
- description: tool.description,
262
- parameters: tool.parameters
263
- }));
264
- }
265
-
266
- /** 获取所有工具列表(用于设置面板) */
267
- public getAllTools(): Array<{ name: string; description: string }> {
268
- return Array.from(this.tools.values()).map(tool => ({
269
- name: tool.name,
270
- description: tool.description
271
- }));
272
- }
273
-
274
- /**
275
- * 聊天入口
276
- *
277
- * 使用 ChatOrchestrator 统一处理所有 Provider 的工具调用循环
278
- */
279
- async *chat(
280
- message: string,
281
- options: ChatOptions = {},
282
- images?: string[]
283
- ): AsyncGenerator<ChatEvent> {
284
- // 异步初始化工具(如果还没初始化)
285
- await this.asyncInit();
286
-
287
- this.abortController = new AbortController();
288
- const signal = this.abortController.signal;
289
-
290
- const model = options.model || DEFAULT_MODEL;
291
-
292
- // 检查模型是否支持
293
- if (!this.adapter.supportsModel(model)) {
294
- const familyConfig = getModelFamily(model);
295
- if (!familyConfig) {
296
- yield createApiError(`未知模型: ${model}`, { code: 'MODEL_NOT_SUPPORTED' });
297
- } else {
298
- yield createApiError(`模型 ${model} 缺少 API Key 配置`, { code: 'MISSING_API_KEY' });
299
- }
300
- return;
301
- }
302
-
303
- // 获取模型家族配置
304
- const familyConfig = getModelFamily(model);
305
-
306
- // 统一 thinkingMode
307
- const rawThinkingMode = options.thinkingMode ?? this.getDefaultThinkingMode();
308
- const thinkingMode: ThinkingMode = rawThinkingMode === 'enabled' ? 'enabled' : 'disabled';
309
- const systemPrompt = this.buildSystemPrompt(options);
310
-
311
- // ask 模式:强制"纯文本回答"
312
- const isAskMode = options.mode === 'ask';
313
- const enableSearch = !isAskMode && !!options.enableWebSearch;
314
-
315
- // 对于不支持原生搜索的模型,需要强制包含联网搜索工具
316
- const forceInclude = enableSearch && familyConfig && !modelSupportsNativeSearch(model)
317
- ? [WEB_SEARCH_TOOL_NAME]
318
- : undefined;
319
-
320
- // 云端工具定义
321
- const cloudTools = isAskMode ? [] : this.getToolDefinitions(options.enabledTools, forceInclude);
322
-
323
- // 用户自定义工具(透传模式)
324
- const userTools = options.userTools || [];
325
- const userToolDefinitions = userTools.map(t => ({
326
- name: t.name,
327
- description: t.description,
328
- parameters: {
329
- ...t.parameters,
330
- required: t.parameters.required || [],
331
- },
332
- }));
333
-
334
- // 合并所有工具
335
- const tools = [...cloudTools, ...userToolDefinitions];
336
-
337
- // 客户端工具名称集合
338
- const clientToolNames = userTools.length > 0
339
- ? new Set(userTools.map(t => t.name))
340
- : undefined;
341
-
342
- // 只有家族支持 thinking 且用户启用时才真正启用
343
- const enableThinking = !isAskMode && thinkingMode === 'enabled' && (familyConfig?.supportsThinking ?? false);
344
-
345
- // 使用传入的历史
346
- const history = options.history || [];
347
-
348
- // 构建 Orchestrator 上下文
349
- const context: OrchestratorContext = {
350
- systemPrompt,
351
- history,
352
- tools,
353
- signal,
354
- images,
355
- clientToolNames,
356
- };
357
-
358
- try {
359
- // 使用 Orchestrator + UnifiedAdapter
360
- yield* this.orchestrator.chat(this.adapter, message, context, {
361
- model,
362
- enableThinking,
363
- enableSearch,
364
- autoRunConfig: options.autoRunConfig,
365
- });
366
- } finally {
367
- this.abortController = null;
368
- }
369
- }
370
-
371
- /** 中断当前请求 */
372
- abort(): void {
373
- if (this.abortController) {
374
- this.abortController.abort();
375
- }
376
- }
377
-
378
- /** 设置当前工作目录 */
379
- setCwd(dir: string): void {
380
- this.config.cwd = dir;
381
- }
382
-
383
- /** 获取当前配置 */
384
- getConfig(): RuntimeConfig {
385
- return { ...this.config };
386
- }
387
-
388
- /** 获取所有支持的模型 */
389
- getSupportedModels() {
390
- return MODELS;
391
- }
392
-
393
- /** 获取 MCP 连接状态 */
394
- getMcpConnections() {
395
- return this.mcpManager?.getConnectionInfos() ?? [];
396
- }
397
-
398
- /**
399
- * 销毁 Agent(优雅关闭所有 MCP 连接)
400
- *
401
- * 桌面客户端退出时应调用此方法。
402
- */
403
- async destroy(): Promise<void> {
404
- if (this.mcpManager) {
405
- await this.mcpManager.disconnectAll();
406
- this.mcpManager = null;
407
- }
408
- }
409
- }
@@ -1,2 +0,0 @@
1
- // 已迁移到 @huyooo/ai-chat-tools-local
2
- // import { createUpdatePlanTool } from '@huyooo/ai-chat-tools-local';
@@ -1,77 +0,0 @@
1
- /**
2
- * Web Search 工具(内部使用,Tavily 实现)
3
- *
4
- * 对外统一使用工具名 web_search_ai,各协议一致使用,与厂商内置 web_search 不冲突。
5
- */
6
-
7
- import type { Tool } from '../types';
8
-
9
- /** 联网搜索工具名(Tavily 实现,对外统一) */
10
- export const WEB_SEARCH_TOOL_NAME = 'web_search_ai';
11
-
12
- export function createWebSearchTool(tavilyApiKey: string): Tool {
13
- return {
14
- name: WEB_SEARCH_TOOL_NAME,
15
- description:
16
- '联网搜索工具。输入 query(搜索关键词/问题),返回搜索结果列表(title/url/snippet)。用于获取实时信息与可引用来源。',
17
- parameters: {
18
- type: 'object',
19
- properties: {
20
- query: { type: 'string', description: '搜索关键词或问题(必填)' },
21
- max_results: { type: 'number', description: '最大返回结果数(可选,默认 5)' },
22
- },
23
- required: ['query'],
24
- },
25
- execute: async (args, ctx) => {
26
- const query = typeof args.query === 'string' ? args.query : '';
27
- const maxResults = typeof args.max_results === 'number' && Number.isFinite(args.max_results)
28
- ? Math.max(1, Math.min(10, Math.floor(args.max_results)))
29
- : 5;
30
-
31
- if (!query.trim()) {
32
- return { query: '', results: [], error: '缺少 query' };
33
- }
34
- if (!tavilyApiKey) {
35
- return { query, results: [], error: '缺少 Tavily API Key' };
36
- }
37
-
38
- const resp = await fetch('https://api.tavily.com/search', {
39
- method: 'POST',
40
- headers: {
41
- Authorization: `Bearer ${tavilyApiKey}`,
42
- 'Content-Type': 'application/json',
43
- },
44
- body: JSON.stringify({
45
- query,
46
- max_results: maxResults,
47
- search_depth: 'basic',
48
- include_answer: false,
49
- include_raw_content: false,
50
- }),
51
- signal: ctx.signal,
52
- });
53
-
54
- if (!resp.ok) {
55
- const t = await resp.text().catch(() => '');
56
- return { query, results: [], error: `Tavily /search 错误: ${resp.status} ${t}`.trim() };
57
- }
58
-
59
- const data: unknown = await resp.json().catch(() => null);
60
-
61
- const results: Array<{ title: string; url: string; snippet: string }> = [];
62
- const arr = (data && typeof data === 'object' && Array.isArray((data as Record<string, unknown>).results))
63
- ? (data as Record<string, unknown>).results as Array<Record<string, unknown>>
64
- : [];
65
- for (const r of arr) {
66
- const url = typeof r?.url === 'string' ? r.url : '';
67
- if (!url) continue;
68
- const title = typeof r?.title === 'string' ? r.title : '';
69
- const snippet = typeof r?.content === 'string' ? r.content : '';
70
- results.push({ title, url, snippet });
71
- }
72
-
73
- return { query, results };
74
- },
75
- };
76
- }
77
-