@huyooo/ai-chat-core 0.2.44 → 0.3.2

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
@@ -1,315 +0,0 @@
1
- /**
2
- * Qwen Protocol(通义千问 OpenAI 兼容模式 API)
3
- *
4
- * 使用 OpenAI 兼容端点以支持工具调用:
5
- * https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions
6
- */
7
-
8
- import type {
9
- Protocol,
10
- ProtocolConfig,
11
- ProtocolMessage,
12
- ProtocolToolDefinition,
13
- ProtocolRequestOptions,
14
- RawEvent,
15
- RawToolCall,
16
- } from './types';
17
- import { DebugLogger } from '../../utils';
18
- import { friendlyHttpError } from './error-utils';
19
-
20
- const logger = DebugLogger.module('QwenProtocol');
21
-
22
- // OpenAI 兼容模式端点
23
- const DEFAULT_QWEN_COMPATIBLE_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1';
24
-
25
- /**
26
- * Qwen Protocol 实现(OpenAI 兼容模式)
27
- */
28
- export class QwenProtocol implements Protocol {
29
- readonly name = 'qwen';
30
-
31
- private apiKey: string;
32
- private apiUrl: string;
33
-
34
- constructor(config: ProtocolConfig) {
35
- this.apiKey = config.apiKey;
36
- // 使用兼容模式端点
37
- this.apiUrl = config.apiUrl ?? DEFAULT_QWEN_COMPATIBLE_URL;
38
- }
39
-
40
- /**
41
- * 发送请求并返回原始事件流
42
- */
43
- async *stream(
44
- messages: ProtocolMessage[],
45
- tools: ProtocolToolDefinition[],
46
- options: ProtocolRequestOptions
47
- ): AsyncGenerator<RawEvent> {
48
- const requestBody = this.buildRequestBody(messages, tools, options);
49
- const url = `${this.apiUrl}/chat/completions`;
50
-
51
- logger.debug('发送 Qwen 请求(兼容模式)', {
52
- url,
53
- model: options.model,
54
- enableThinking: options.enableThinking,
55
- toolsCount: tools.length,
56
- });
57
-
58
- const response = await fetch(url, {
59
- method: 'POST',
60
- headers: {
61
- 'Authorization': `Bearer ${this.apiKey}`,
62
- 'Content-Type': 'application/json',
63
- },
64
- body: JSON.stringify(requestBody),
65
- signal: options.signal,
66
- });
67
-
68
- if (!response.ok) {
69
- const errorText = await response.text();
70
- logger.error('Qwen API 错误', { status: response.status, body: errorText.slice(0, 500) });
71
- yield { type: 'error', error: friendlyHttpError(response.status, errorText, 'Qwen') };
72
- return;
73
- }
74
-
75
- const reader = response.body?.getReader();
76
- if (!reader) {
77
- yield { type: 'error', error: '无法获取响应流' };
78
- return;
79
- }
80
-
81
- yield* this.parseSSE(reader, options.enableThinking);
82
- }
83
-
84
- /**
85
- * 构建请求体(OpenAI 格式)
86
- */
87
- private buildRequestBody(
88
- messages: ProtocolMessage[],
89
- tools: ProtocolToolDefinition[],
90
- options: ProtocolRequestOptions
91
- ): Record<string, unknown> {
92
- const convertedMessages = this.convertMessages(messages);
93
-
94
- const body: Record<string, unknown> = {
95
- model: options.model,
96
- messages: convertedMessages,
97
- stream: true,
98
- // 请求返回 Token 使用统计(Chat Completions 格式)
99
- stream_options: { include_usage: true },
100
- };
101
-
102
- // 启用 thinking(Qwen 直接在请求体中设置)
103
- if (options.enableThinking) {
104
- body.enable_thinking = true;
105
- body.thinking_budget = 38400;
106
- }
107
-
108
- // 注意:Qwen 搜索通过 Tavily web_search 工具实现(searchStrategy: tavily)
109
- // 不使用原生 enable_search 参数,保持与其他 Provider 一致
110
-
111
- // 添加工具
112
- if (tools.length > 0) {
113
- body.tools = tools.map(t => ({
114
- type: 'function',
115
- function: {
116
- name: t.name,
117
- description: t.description,
118
- parameters: t.parameters,
119
- },
120
- }));
121
- }
122
-
123
- return body;
124
- }
125
-
126
- /**
127
- * 转换消息格式(OpenAI 标准格式)
128
- */
129
- private convertMessages(messages: ProtocolMessage[]): unknown[] {
130
- const result: unknown[] = [];
131
-
132
- for (const msg of messages) {
133
- switch (msg.role) {
134
- case 'system':
135
- result.push({ role: 'system', content: msg.content });
136
- break;
137
-
138
- case 'user': {
139
- // 当只有图片没有文字时提供默认提示
140
- const textContent = msg.content || (msg.images?.length ? '请分析这张图片' : '');
141
- if (msg.images?.length) {
142
- const content: unknown[] = [{ type: 'text', text: textContent }];
143
- for (const img of msg.images) {
144
- content.push({
145
- type: 'image_url',
146
- image_url: { url: img.startsWith('data:') ? img : `data:image/jpeg;base64,${img}` },
147
- });
148
- }
149
- result.push({ role: 'user', content });
150
- } else {
151
- result.push({ role: 'user', content: textContent });
152
- }
153
- break;
154
- }
155
-
156
- case 'assistant':
157
- if (msg.toolCalls?.length) {
158
- result.push({
159
- role: 'assistant',
160
- content: msg.content || null,
161
- tool_calls: msg.toolCalls.map(tc => ({
162
- id: tc.id,
163
- type: 'function',
164
- function: { name: tc.name, arguments: tc.arguments },
165
- })),
166
- });
167
- } else {
168
- result.push({ role: 'assistant', content: msg.content });
169
- }
170
- break;
171
-
172
- case 'tool':
173
- result.push({
174
- role: 'tool',
175
- tool_call_id: msg.toolCallId,
176
- content: msg.content,
177
- });
178
- break;
179
- }
180
- }
181
-
182
- return result;
183
- }
184
-
185
- /**
186
- * 解析 SSE 流(OpenAI 格式)
187
- */
188
- private async *parseSSE(
189
- reader: ReadableStreamDefaultReader<Uint8Array>,
190
- enableThinking: boolean
191
- ): AsyncGenerator<RawEvent> {
192
- const decoder = new TextDecoder();
193
- let buffer = '';
194
- const toolCallsMap = new Map<number, RawToolCall>();
195
- let textStarted = false;
196
- let thinkingDone = false;
197
- let lastUsage: { promptTokens: number; completionTokens: number; totalTokens: number } | undefined;
198
- // 不在 finish_reason 处立即 return,因为 usage chunk 在 finish_reason 之后、[DONE] 之前到达
199
- let lastFinishReason: string | undefined;
200
-
201
- while (true) {
202
- const { done, value } = await reader.read();
203
- if (done) break;
204
-
205
- buffer += decoder.decode(value, { stream: true });
206
- const lines = buffer.split('\n');
207
- buffer = lines.pop() || '';
208
-
209
- for (const line of lines) {
210
- if (!line.startsWith('data:')) continue;
211
-
212
- const data = line.slice(5).trim();
213
- if (!data || data === '[DONE]') {
214
- if (data === '[DONE]') {
215
- const toolCalls = Array.from(toolCallsMap.values());
216
- if (toolCalls.length > 0) {
217
- for (const tc of toolCalls) {
218
- yield { type: 'tool_call_done', toolCall: tc };
219
- }
220
- yield { type: 'done', finishReason: 'tool_calls', usage: lastUsage };
221
- } else {
222
- const reason: RawEvent['finishReason'] = (lastFinishReason === 'tool_calls' || lastFinishReason === 'length' || lastFinishReason === 'error')
223
- ? lastFinishReason
224
- : 'stop';
225
- yield { type: 'done', finishReason: reason, usage: lastUsage };
226
- }
227
- return;
228
- }
229
- continue;
230
- }
231
-
232
- try {
233
- const json = JSON.parse(data);
234
-
235
- if (json.usage) {
236
- lastUsage = {
237
- promptTokens: json.usage.prompt_tokens || 0,
238
- completionTokens: json.usage.completion_tokens || 0,
239
- totalTokens: json.usage.total_tokens || (json.usage.prompt_tokens || 0) + (json.usage.completion_tokens || 0),
240
- };
241
- }
242
-
243
- const choice = json.choices?.[0];
244
- if (!choice) continue;
245
-
246
- const delta = choice.delta;
247
- if (!delta) continue;
248
-
249
- if (enableThinking && delta.reasoning_content && !thinkingDone) {
250
- yield { type: 'thinking_delta', delta: delta.reasoning_content };
251
- }
252
-
253
- if (delta.content) {
254
- if (enableThinking && !textStarted && !thinkingDone) {
255
- thinkingDone = true;
256
- yield { type: 'thinking_done' };
257
- }
258
- textStarted = true;
259
- yield { type: 'text_delta', delta: delta.content };
260
- }
261
-
262
- if (delta.tool_calls?.length) {
263
- for (const tc of delta.tool_calls) {
264
- const index = tc.index ?? 0;
265
- const existing = toolCallsMap.get(index);
266
-
267
- if (existing) {
268
- if (tc.function?.arguments) {
269
- existing.arguments += tc.function.arguments;
270
- }
271
- } else {
272
- toolCallsMap.set(index, {
273
- id: tc.id || `call_${index}`,
274
- name: tc.function?.name || '',
275
- arguments: tc.function?.arguments || '',
276
- });
277
- yield {
278
- type: 'tool_call_start',
279
- toolCall: { id: tc.id || `call_${index}`, name: tc.function?.name || '' }
280
- };
281
- }
282
- }
283
- }
284
-
285
- if (choice.finish_reason) {
286
- lastFinishReason = choice.finish_reason;
287
- }
288
- } catch {
289
- // 忽略解析错误
290
- }
291
- }
292
- }
293
-
294
- // 流异常中断兜底
295
- const toolCalls = Array.from(toolCallsMap.values());
296
- if (toolCalls.length > 0) {
297
- for (const tc of toolCalls) {
298
- yield { type: 'tool_call_done', toolCall: tc };
299
- }
300
- yield { type: 'done', finishReason: 'tool_calls', usage: lastUsage };
301
- } else {
302
- const reason: RawEvent['finishReason'] = (lastFinishReason === 'tool_calls' || lastFinishReason === 'length' || lastFinishReason === 'error')
303
- ? lastFinishReason
304
- : 'stop';
305
- yield { type: 'done', finishReason: reason, usage: lastUsage };
306
- }
307
- }
308
- }
309
-
310
- /**
311
- * 创建 Qwen Protocol
312
- */
313
- export function createQwenProtocol(config: ProtocolConfig): QwenProtocol {
314
- return new QwenProtocol(config);
315
- }
@@ -1,264 +0,0 @@
1
- /**
2
- * Provider 统一类型定义
3
- *
4
- * 核心设计原则:
5
- * 1. Adapter 只负责 API 格式转换,不处理业务逻辑
6
- * 2. Orchestrator 统一处理工具调用循环、消息历史、事件发射
7
- * 3. 所有 Adapter 返回标准化的 StreamChunk
8
- */
9
-
10
- import type { ChatMessage, Tool } from '../types';
11
-
12
-
13
- /** 简化的工具定义(供 Adapter 使用) */
14
- import type { JsonSchemaObject } from '../types';
15
-
16
- export interface SimpleToolDefinition {
17
- name: string;
18
- description: string;
19
- parameters: JsonSchemaObject;
20
- }
21
-
22
- // ==================== 标准化流式响应 ====================
23
-
24
- /** 流式响应块类型 */
25
- export type StreamChunkType =
26
- | 'text' // 文本内容
27
- | 'thinking' // 思考内容
28
- | 'thinking_done' // 思考完成
29
- | 'tool_call' // 工具调用请求
30
- | 'search_result' // 搜索结果
31
- | 'done' // 响应完成
32
- | 'error'; // 错误
33
-
34
- /** 工具调用请求 */
35
- export interface ToolCallRequest {
36
- id: string;
37
- name: string;
38
- arguments: string;
39
- /** Gemini 模型需要的 thought_signature(用于工具调用循环) */
40
- thought_signature?: string;
41
- }
42
-
43
- /** 搜索结果项 */
44
- export interface SearchResultItem {
45
- title: string;
46
- url: string;
47
- snippet: string;
48
- }
49
-
50
- /** 流式响应块 - 所有 Adapter 必须返回此格式 */
51
- /** Token 使用统计 */
52
- export interface StreamTokenUsage {
53
- promptTokens?: number;
54
- completionTokens?: number;
55
- totalTokens?: number;
56
- reasoningTokens?: number;
57
- cachedTokens?: number;
58
- }
59
-
60
- export interface StreamChunk {
61
- type: StreamChunkType;
62
-
63
- // 文本内容 (type: 'text')
64
- text?: string;
65
-
66
- // 思考内容 (type: 'thinking')
67
- thinking?: string;
68
-
69
- // 工具调用 (type: 'tool_call')
70
- toolCall?: ToolCallRequest;
71
-
72
- // 搜索结果 (type: 'search_result')
73
- searchResults?: SearchResultItem[];
74
-
75
- // 完成信号 (type: 'done')
76
- finishReason?: 'stop' | 'tool_calls' | 'length' | 'error';
77
- /** Token 使用统计(done 事件携带) */
78
- usage?: StreamTokenUsage;
79
-
80
- // 错误信息 (type: 'error')
81
- error?: string;
82
- }
83
-
84
- // ==================== 标准化消息格式 ====================
85
-
86
- /** 标准化消息 - Orchestrator 内部使用 */
87
- export interface StandardMessage {
88
- role: 'system' | 'user' | 'assistant' | 'tool';
89
- content: string;
90
-
91
- // 图片(用户消息)
92
- images?: string[];
93
-
94
- // 工具调用(assistant 消息)
95
- toolCalls?: ToolCallRequest[];
96
-
97
- // 工具调用 ID(tool 消息)
98
- toolCallId?: string;
99
-
100
- // 工具名称(tool 消息,Gemini 需要)
101
- toolName?: string;
102
- }
103
-
104
- // ==================== Adapter 接口 ====================
105
-
106
- /** Adapter 配置 */
107
- export interface AdapterConfig {
108
- apiKey: string;
109
- apiUrl?: string;
110
- /** Tavily API Key(用于统一 Web Search) */
111
- tavilyApiKey?: string;
112
- }
113
-
114
- /** 单次调用选项 */
115
- export interface StreamOnceOptions {
116
- /** 模型 ID */
117
- model: string;
118
- /** 是否启用思考 */
119
- enableThinking?: boolean;
120
- /** 是否启用搜索 */
121
- enableSearch?: boolean;
122
- /** 中断信号 */
123
- signal: AbortSignal;
124
- }
125
-
126
- /**
127
- * Provider Adapter 接口
128
- *
129
- * 职责:
130
- * - 将标准消息转换为 API 特定格式
131
- * - 调用 API 并返回标准化的 StreamChunk
132
- * - 不处理工具执行、消息历史维护
133
- */
134
- export interface ProviderAdapter {
135
- /** 适配器名称 */
136
- readonly name: string;
137
-
138
- /** 支持的模型列表 */
139
- readonly supportedModels: string[];
140
-
141
- /**
142
- * 单次流式调用
143
- *
144
- * @param messages 标准化消息列表
145
- * @param tools 工具定义列表
146
- * @param options 调用选项
147
- * @returns 标准化的流式响应
148
- */
149
- streamOnce(
150
- messages: StandardMessage[],
151
- tools: SimpleToolDefinition[],
152
- options: StreamOnceOptions
153
- ): AsyncGenerator<StreamChunk>;
154
-
155
- /**
156
- * 检查是否支持指定模型
157
- */
158
- supportsModel(model: string): boolean;
159
- }
160
-
161
- // ==================== Orchestrator 类型 ====================
162
-
163
- export interface ToolExecutionHooks {
164
- /** 工具调用 ID(用于把输出归属到具体 tool_call 卡片) */
165
- toolCallId: string;
166
- /** 工具名称 */
167
- toolName: string;
168
- /** stdout 增量 */
169
- onStdout?: (chunk: string) => void;
170
- /** stderr 增量 */
171
- onStderr?: (chunk: string) => void;
172
- }
173
-
174
- export type ToolExecutor = (
175
- name: string,
176
- args: Record<string, unknown>,
177
- signal?: AbortSignal,
178
- hooks?: ToolExecutionHooks
179
- ) => Promise<object>;
180
-
181
- /** 自动运行配置 */
182
- export interface AutoRunConfig {
183
- /**
184
- * 自动运行模式
185
- * - 'run-everything': 运行所有内容(自动执行)
186
- * - 'manual': 手动批准(每次执行前询问)
187
- */
188
- mode?: 'run-everything' | 'manual';
189
- }
190
-
191
- /** 工具批准回调函数 */
192
- export type ToolApprovalCallback = (toolCall: {
193
- id: string;
194
- name: string;
195
- args: Record<string, unknown>;
196
- }) => Promise<boolean>;
197
-
198
- /** 获取自动运行配置回调 */
199
- export type GetAutoRunConfigCallback = () => Promise<AutoRunConfig | undefined>;
200
-
201
- /** Orchestrator 配置 */
202
- export interface OrchestratorConfig {
203
- /** 最大迭代次数 */
204
- maxIterations?: number;
205
- /** 工具执行器 */
206
- executeTool: ToolExecutor;
207
- /** 完整的工具列表(用于获取 ui/requiresApproval/timeout),key: 工具名称 */
208
- tools?: Map<string, Tool>;
209
- /** 自动运行配置(静态配置,优先使用 getAutoRunConfig) */
210
- autoRunConfig?: AutoRunConfig;
211
- /**
212
- * 动态获取自动运行配置回调
213
- * 每次检查工具批准时调用,获取最新配置
214
- */
215
- getAutoRunConfig?: GetAutoRunConfigCallback;
216
- /**
217
- * 工具批准回调(manual 模式使用)
218
- * 返回 true 表示批准执行,false 表示跳过
219
- */
220
- onToolApprovalRequest?: ToolApprovalCallback;
221
- /**
222
- * 客户端工具名称集合(透传模式)
223
- *
224
- * 这些工具不在服务端执行,而是:
225
- * 1. 发送 tool_call_request 事件给客户端
226
- * 2. 结束本轮对话
227
- * 3. 客户端执行后,发新请求继续对话
228
- */
229
- clientToolNames?: Set<string>;
230
- /** 上下文总结回调(走 ai-server 等外部服务) */
231
- summarize?: (systemPrompt: string, userPrompt: string) => Promise<string>;
232
- }
233
-
234
- /** Orchestrator 上下文 */
235
- export interface OrchestratorContext {
236
- /** 系统提示 */
237
- systemPrompt: string;
238
- /** 对话历史(会被修改) */
239
- history: ChatMessage[];
240
- /** 工具定义 */
241
- tools: SimpleToolDefinition[];
242
- /** 中断信号 */
243
- signal: AbortSignal;
244
- /** 图片列表 */
245
- images?: string[];
246
- /**
247
- * 客户端工具名称集合(透传模式)
248
- *
249
- * 这些工具不在服务端执行,而是发送 tool_call_request 事件给客户端
250
- */
251
- clientToolNames?: Set<string>;
252
- }
253
-
254
- /** Orchestrator 选项 */
255
- export interface OrchestratorOptions {
256
- /** 模型 ID */
257
- model: string;
258
- /** 是否启用思考 */
259
- enableThinking?: boolean;
260
- /** 是否启用搜索 */
261
- enableSearch?: boolean;
262
- /** 自动运行配置 */
263
- autoRunConfig?: AutoRunConfig;
264
- }