my-ai-chat-framework 1.0.2 → 1.1.0

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.
@@ -1,18 +1,14 @@
1
1
  class MessageFormatter {
2
2
  /**
3
- * 将消息转换为标准格式(过滤掉自定义元数据)
3
+ * 将消息转换为标准格式(不再过滤自定义元数据,只确保必需字段)
4
4
  */
5
5
  static toStandardFormat(message) {
6
6
  const { role, content } = message;
7
7
  const standardMessage = { role, content };
8
- if (message.reasoning_content) {
9
- standardMessage.reasoning_content = message.reasoning_content;
10
- }
11
- if (message.tool_calls) {
12
- standardMessage.tool_calls = message.tool_calls;
13
- }
14
- if (message.tool_call_id) {
15
- standardMessage.tool_call_id = message.tool_call_id;
8
+ for (const [key, value] of Object.entries(message)) {
9
+ if (key !== "role" && key !== "content" && value !== void 0) {
10
+ standardMessage[key] = value;
11
+ }
16
12
  }
17
13
  return standardMessage;
18
14
  }
@@ -95,6 +91,17 @@ class MessageFormatter {
95
91
  }
96
92
  };
97
93
  }
94
+ /**
95
+ * 过滤消息以供API使用(只移除空content的消息,保留所有字段)
96
+ */
97
+ static filterForAPI(messages) {
98
+ return messages.filter((msg) => {
99
+ if (msg.role === "tool") {
100
+ return true;
101
+ }
102
+ return msg.content !== "" && msg.content !== void 0 && msg.content !== null;
103
+ });
104
+ }
98
105
  }
99
106
  class Messages {
100
107
  constructor() {
@@ -111,7 +118,7 @@ class Messages {
111
118
  /**
112
119
  * 添加消息(通用方法)
113
120
  * @param {string} role - 角色:user/assistant/system/tool
114
- * @param {string} content - 消息内容
121
+ * @param {string} content - 消息内容(允许空字符串)
115
122
  * @param {object} metadata - 额外元数据
116
123
  * @returns {number} 新消息的索引
117
124
  */
@@ -125,12 +132,12 @@ class Messages {
125
132
  throw new Error("tool消息必须包含tool_call_id");
126
133
  }
127
134
  } else {
128
- if (typeof content !== "string") {
129
- throw new Error("消息内容必须是字符串");
130
- }
131
135
  if (content === void 0 || content === null) {
132
136
  throw new Error("消息内容不能为undefined或null");
133
137
  }
138
+ if (typeof content !== "string") {
139
+ throw new Error("消息内容必须是字符串");
140
+ }
134
141
  }
135
142
  const message = {
136
143
  role,
@@ -248,16 +255,16 @@ class Messages {
248
255
  }
249
256
  // ========== 消息修改 ==========
250
257
  /**
251
- * 更新消息内容
258
+ * 更新消息内容(允许空字符串)
252
259
  */
253
260
  updateMessage(index2, content) {
254
261
  if (!Number.isInteger(index2) || index2 < 0 || index2 >= this.messages.length) {
255
262
  throw new Error(`无效的消息索引: ${index2}`);
256
263
  }
257
- if (typeof content !== "string" || !content.trim()) {
258
- throw new Error("消息内容不能为空");
264
+ if (typeof content !== "string") {
265
+ throw new Error("消息内容必须是字符串");
259
266
  }
260
- this.messages[index2].content = content.trim();
267
+ this.messages[index2].content = content;
261
268
  this.messages[index2].lastModified = /* @__PURE__ */ new Date();
262
269
  return this;
263
270
  }
@@ -281,6 +288,30 @@ class Messages {
281
288
  this.messages[index2].lastModified = /* @__PURE__ */ new Date();
282
289
  return this;
283
290
  }
291
+ /**
292
+ * 批量设置消息字段
293
+ */
294
+ setMessageFields(index2, fields) {
295
+ if (!Number.isInteger(index2) || index2 < 0 || index2 >= this.messages.length) {
296
+ throw new Error(`无效的消息索引: ${index2}`);
297
+ }
298
+ for (const [field, value] of Object.entries(fields)) {
299
+ if (value !== void 0 && value !== null) {
300
+ this.messages[index2][field] = value;
301
+ }
302
+ }
303
+ this.messages[index2].lastModified = /* @__PURE__ */ new Date();
304
+ return this;
305
+ }
306
+ /**
307
+ * 批量更新最后一条消息的字段
308
+ */
309
+ updateLastMessageFields(fields) {
310
+ if (this.messages.length === 0) {
311
+ throw new Error("没有消息可以修改");
312
+ }
313
+ return this.setMessageFields(this.messages.length - 1, fields);
314
+ }
284
315
  // ========== 消息删除 ==========
285
316
  /**
286
317
  * 删除消息
@@ -791,9 +822,10 @@ class RequestBuilder {
791
822
  baseRounds,
792
823
  cycleRounds
793
824
  );
825
+ const filteredMessages = MessageFormatter.filterForAPI(formattedMessages);
794
826
  const request = {
795
827
  model: this.model,
796
- messages: formattedMessages,
828
+ messages: filteredMessages,
797
829
  ...this.config
798
830
  };
799
831
  let tools = [];
@@ -2052,8 +2084,8 @@ function requireAxios$1() {
2052
2084
  var Axios = requireAxios$2();
2053
2085
  var mergeConfig2 = requireMergeConfig();
2054
2086
  var defaults = requireDefaults();
2055
- function createInstance(defaultConfig) {
2056
- var context = new Axios(defaultConfig);
2087
+ function createInstance(defaultConfig2) {
2088
+ var context = new Axios(defaultConfig2);
2057
2089
  var instance = bind2(Axios.prototype.request, context);
2058
2090
  utils2.extend(instance, Axios.prototype, context);
2059
2091
  utils2.extend(instance, context);
@@ -2142,12 +2174,14 @@ class ApiClient extends EventEmitter {
2142
2174
  this.cancelTokenSource = null;
2143
2175
  }
2144
2176
  }
2145
- async strSend(body, onProgress = () => {
2146
- }, onDone = () => {
2147
- }) {
2177
+ async strSend(body, onProgress, onDone) {
2148
2178
  this.isGenerating = true;
2149
2179
  this.cancelTokenSource = axios.CancelToken.source();
2150
2180
  try {
2181
+ const safeOnProgress = typeof onProgress === "function" ? onProgress : () => {
2182
+ };
2183
+ const safeOnDone = typeof onDone === "function" ? onDone : () => {
2184
+ };
2151
2185
  this.emit("stream-start", { body });
2152
2186
  const requestBody = this._buildRequestBody(body);
2153
2187
  const response = await fetch(this.url, {
@@ -2167,10 +2201,20 @@ class ApiClient extends EventEmitter {
2167
2201
  const decoder = new TextDecoder();
2168
2202
  let buffer = "";
2169
2203
  const message = {
2204
+ // 基础信息(符合Messages格式)
2205
+ role: "assistant",
2170
2206
  content: "",
2171
2207
  reasoning_content: "",
2172
- tool_calls: []
2173
- // 新增:收集工具调用
2208
+ timestamp: /* @__PURE__ */ new Date(),
2209
+ // 工具调用
2210
+ tool_calls: [],
2211
+ // 流式元数据
2212
+ streamMetadata: {
2213
+ chunkCount: 0,
2214
+ firstChunkTime: Date.now(),
2215
+ lastChunkTime: null,
2216
+ isStreaming: true
2217
+ }
2174
2218
  };
2175
2219
  while (true) {
2176
2220
  const { done, value } = await reader.read();
@@ -2183,12 +2227,14 @@ class ApiClient extends EventEmitter {
2183
2227
  if (!cleanChunk) continue;
2184
2228
  if (cleanChunk === "[DONE]") {
2185
2229
  this.emit("stream-done", { message });
2186
- onDone({ ...message });
2230
+ safeOnDone({ ...message });
2187
2231
  return;
2188
2232
  }
2189
2233
  try {
2190
2234
  const obj = JSON.parse(cleanChunk);
2191
2235
  console.log("🔍 收到流式chunk:", obj);
2236
+ message.streamMetadata.chunkCount++;
2237
+ message.streamMetadata.lastChunkTime = Date.now();
2192
2238
  if (obj.choices?.[0]?.delta?.content) {
2193
2239
  message.content += obj.choices[0].delta.content;
2194
2240
  }
@@ -2217,8 +2263,12 @@ class ApiClient extends EventEmitter {
2217
2263
  }
2218
2264
  });
2219
2265
  }
2220
- this.emit("stream-chunk", { chunk: obj, message });
2221
- onProgress({ ...message });
2266
+ this.emit("stream-chunk", {
2267
+ chunk: obj,
2268
+ message: { ...message }
2269
+ // 发送副本
2270
+ });
2271
+ safeOnProgress({ ...message });
2222
2272
  } catch (e) {
2223
2273
  console.error("🔍 解析chunk错误:", e, "原始数据:", cleanChunk);
2224
2274
  }
@@ -2227,8 +2277,10 @@ class ApiClient extends EventEmitter {
2227
2277
  break;
2228
2278
  }
2229
2279
  }
2230
- this.emit("stream-done", { message });
2231
- onDone({ ...message });
2280
+ message.streamMetadata.isStreaming = false;
2281
+ message.streamMetadata.completedAt = /* @__PURE__ */ new Date();
2282
+ this.emit("stream-done", { message: { ...message } });
2283
+ safeOnDone({ ...message });
2232
2284
  } catch (error) {
2233
2285
  if (error.name === "AbortError" || axios.isCancel(error)) {
2234
2286
  const cancelError = new Error("请求被中断");
@@ -2312,15 +2364,227 @@ class ApiClient extends EventEmitter {
2312
2364
  throw new Error("无法识别的聊天数据格式");
2313
2365
  }
2314
2366
  }
2367
+ class ConfigManager extends EventEmitter {
2368
+ constructor(defaultConfig2 = {}) {
2369
+ super();
2370
+ this._config = JSON.parse(JSON.stringify(defaultConfig2));
2371
+ this._handlers = /* @__PURE__ */ new Map();
2372
+ this.config = this._createProxy(this._config);
2373
+ }
2374
+ /**
2375
+ * 创建配置代理
2376
+ */
2377
+ _createProxy(target, path = "") {
2378
+ return new Proxy(target, {
2379
+ set: (obj, prop, value) => {
2380
+ const oldValue = obj[prop];
2381
+ const fullPath = path ? `${path}.${prop}` : prop;
2382
+ if (value && typeof value === "object" && !Array.isArray(value)) {
2383
+ value = this._createProxy(value, fullPath);
2384
+ }
2385
+ obj[prop] = value;
2386
+ this._triggerChange(fullPath, oldValue, value);
2387
+ return true;
2388
+ },
2389
+ deleteProperty: (obj, prop) => {
2390
+ const oldValue = obj[prop];
2391
+ const fullPath = path ? `${path}.${prop}` : prop;
2392
+ delete obj[prop];
2393
+ this.emit("config-deleted", {
2394
+ path: fullPath,
2395
+ oldValue,
2396
+ timestamp: /* @__PURE__ */ new Date()
2397
+ });
2398
+ return true;
2399
+ }
2400
+ });
2401
+ }
2402
+ /**
2403
+ * 注册配置处理器
2404
+ */
2405
+ registerHandler(path, handler) {
2406
+ if (!this._handlers.has(path)) {
2407
+ this._handlers.set(path, []);
2408
+ }
2409
+ this._handlers.get(path).push(handler);
2410
+ return this;
2411
+ }
2412
+ /**
2413
+ * 移除配置处理器
2414
+ */
2415
+ removeHandler(path, handler) {
2416
+ const handlers = this._handlers.get(path);
2417
+ if (handlers) {
2418
+ const index2 = handlers.indexOf(handler);
2419
+ if (index2 > -1) {
2420
+ handlers.splice(index2, 1);
2421
+ }
2422
+ }
2423
+ return this;
2424
+ }
2425
+ /**
2426
+ * 触发配置变更
2427
+ */
2428
+ _triggerChange(path, oldValue, newValue) {
2429
+ this.emit("config-changed", {
2430
+ path,
2431
+ oldValue,
2432
+ newValue,
2433
+ timestamp: /* @__PURE__ */ new Date()
2434
+ });
2435
+ this.emit(`config-changed:${path}`, {
2436
+ oldValue,
2437
+ newValue,
2438
+ timestamp: /* @__PURE__ */ new Date()
2439
+ });
2440
+ const handlers = this._handlers.get(path);
2441
+ if (handlers) {
2442
+ handlers.forEach((handler) => {
2443
+ try {
2444
+ handler(newValue, oldValue, path);
2445
+ } catch (error) {
2446
+ console.error(`配置处理器执行失败 (${path}):`, error);
2447
+ }
2448
+ });
2449
+ }
2450
+ const pathParts = path.split(".");
2451
+ for (let i = pathParts.length - 1; i >= 0; i--) {
2452
+ const parentPath = pathParts.slice(0, i).join(".");
2453
+ const wildcardPath = parentPath ? `${parentPath}.*` : "*";
2454
+ const parentHandlers = this._handlers.get(wildcardPath);
2455
+ if (parentHandlers) {
2456
+ parentHandlers.forEach((handler) => {
2457
+ try {
2458
+ handler(newValue, oldValue, path);
2459
+ } catch (error) {
2460
+ console.error(`通配符处理器执行失败 (${wildcardPath}):`, error);
2461
+ }
2462
+ });
2463
+ }
2464
+ }
2465
+ }
2466
+ /**
2467
+ * 获取配置快照(非代理版本)
2468
+ */
2469
+ getSnapshot() {
2470
+ return JSON.parse(JSON.stringify(this._config));
2471
+ }
2472
+ /**
2473
+ * 批量更新配置
2474
+ */
2475
+ update(newConfig) {
2476
+ Object.keys(newConfig).forEach((key) => {
2477
+ this.config[key] = newConfig[key];
2478
+ });
2479
+ return this;
2480
+ }
2481
+ /**
2482
+ * 重置为默认值
2483
+ */
2484
+ reset() {
2485
+ const oldConfig = this.getSnapshot();
2486
+ this._config = JSON.parse(JSON.stringify(this._defaultConfig));
2487
+ this.config = this._createProxy(this._config);
2488
+ this.emit("config-reset", {
2489
+ oldConfig,
2490
+ newConfig: this.getSnapshot(),
2491
+ timestamp: /* @__PURE__ */ new Date()
2492
+ });
2493
+ return this;
2494
+ }
2495
+ }
2496
+ const defaultConfig = {
2497
+ api: {
2498
+ key: "",
2499
+ url: "https://api.deepseek.com/v1/chat/completions",
2500
+ timeout: 3e4
2501
+ },
2502
+ model: {
2503
+ name: "deepseek-chat",
2504
+ temperature: 0.7,
2505
+ // maxTokens: 2000,
2506
+ stream: false,
2507
+ reasoningEffort: "medium"
2508
+ },
2509
+ conversation: {
2510
+ baseRounds: 10,
2511
+ cycleRounds: 5
2512
+ },
2513
+ debug: false
2514
+ };
2315
2515
  class ChatService extends EventEmitter {
2316
- constructor(apiKey, model = "deepseek-chat", config = {}) {
2516
+ constructor(options = {}) {
2317
2517
  super();
2518
+ this.autoAddMessages = options.autoAddMessages ?? true;
2519
+ this.configManager = new ConfigManager({
2520
+ ...defaultConfig,
2521
+ ...options
2522
+ });
2318
2523
  this.messages = new Messages();
2319
- this.apiClient = new ApiClient(apiKey);
2320
- this.requestBuilder = new RequestBuilder(model, this.messages, config);
2524
+ this.apiClient = new ApiClient(
2525
+ this.configManager.config.api.key,
2526
+ this.configManager.config.api.url
2527
+ );
2528
+ this.requestBuilder = new RequestBuilder(
2529
+ this.configManager.config.model.name,
2530
+ this.messages,
2531
+ {
2532
+ temperature: this.configManager.config.model.temperature,
2533
+ max_tokens: this.configManager.config.model.maxTokens,
2534
+ stream: this.configManager.config.model.stream,
2535
+ reasoning_effort: this.configManager.config.model.reasoningEffort
2536
+ }
2537
+ );
2321
2538
  this.toolManager = new ToolManager();
2539
+ this._setupConfigHandlers();
2322
2540
  this._setupDefaultListeners();
2323
2541
  }
2542
+ /**
2543
+ * 设置配置变更处理器
2544
+ */
2545
+ _setupConfigHandlers() {
2546
+ this.configManager.registerHandler("api.key", (newValue) => {
2547
+ this.apiClient.setApiKey(newValue);
2548
+ });
2549
+ this.configManager.registerHandler("api.url", (newValue) => {
2550
+ this.apiClient.setApiUrl(newValue);
2551
+ });
2552
+ this.configManager.registerHandler("model.name", (newValue) => {
2553
+ this.requestBuilder.model = newValue;
2554
+ });
2555
+ this.configManager.registerHandler("model.temperature", (newValue) => {
2556
+ this.requestBuilder.config.temperature = newValue;
2557
+ });
2558
+ this.configManager.registerHandler("model.stream", (newValue) => {
2559
+ this.requestBuilder.config.stream = newValue;
2560
+ });
2561
+ this.configManager.registerHandler("debug", (newValue) => {
2562
+ if (newValue) {
2563
+ console.log("🔧 调试模式已启用");
2564
+ }
2565
+ });
2566
+ this.configManager.on("config-changed", (data) => {
2567
+ this.emit("service-config-changed", data);
2568
+ });
2569
+ }
2570
+ /**
2571
+ * 便捷方法:快速设置 API
2572
+ */
2573
+ setApi(key, url) {
2574
+ this.configManager.update({
2575
+ api: { key, url }
2576
+ });
2577
+ return this;
2578
+ }
2579
+ /**
2580
+ * 便捷方法:快速设置模型
2581
+ */
2582
+ setModel(name, temperature = 0.7) {
2583
+ this.configManager.update({
2584
+ model: { name, temperature }
2585
+ });
2586
+ return this;
2587
+ }
2324
2588
  _setupDefaultListeners() {
2325
2589
  this.apiClient.on("request-start", (data) => {
2326
2590
  this.emit("request-start", data);
@@ -2360,7 +2624,8 @@ class ChatService extends EventEmitter {
2360
2624
  this.emit("sending", {
2361
2625
  role: "user",
2362
2626
  content: userMessage,
2363
- timestamp: /* @__PURE__ */ new Date()
2627
+ timestamp: /* @__PURE__ */ new Date(),
2628
+ eventType: "sending"
2364
2629
  });
2365
2630
  this.messages.addUserMessage(userMessage);
2366
2631
  const requestBody = this.requestBuilder.toJSON(
@@ -2372,7 +2637,8 @@ class ChatService extends EventEmitter {
2372
2637
  if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {
2373
2638
  return await this._handleToolCalls(aiMessage);
2374
2639
  } else {
2375
- return await this._handleNormalResponse(aiMessage);
2640
+ const eventData = await this._handleNormalResponse(aiMessage);
2641
+ return eventData.content;
2376
2642
  }
2377
2643
  } catch (error) {
2378
2644
  this.emit("error", {
@@ -2387,12 +2653,10 @@ class ChatService extends EventEmitter {
2387
2653
  * 处理工具调用(支持循环调用)
2388
2654
  */
2389
2655
  async _handleToolCalls(aiMessage, maxIterations = 5) {
2390
- console.log("🔍 处理工具调用,aiMessage:", aiMessage);
2391
2656
  let iteration = 0;
2392
2657
  let currentMessage = aiMessage;
2393
2658
  while (iteration < maxIterations) {
2394
2659
  iteration++;
2395
- console.log(`🔄 工具调用迭代 ${iteration}/${maxIterations}`);
2396
2660
  this.messages.addAssistantMessage(currentMessage.content || "", {
2397
2661
  tool_calls: currentMessage.tool_calls,
2398
2662
  reasoning_content: currentMessage.reasoning_content || ""
@@ -2406,54 +2670,61 @@ class ChatService extends EventEmitter {
2406
2670
  iteration
2407
2671
  });
2408
2672
  const toolResults = await this.toolManager.executeToolCalls(currentMessage.tool_calls);
2409
- console.log("🔍 工具执行结果:", toolResults);
2410
2673
  for (const result of toolResults) {
2411
- console.log("🔍 添加工具消息,result:", result);
2412
2674
  this.messages.addToolMessage(
2413
2675
  result.result || result.error || "",
2414
2676
  result.tool_call_id
2415
2677
  );
2416
2678
  }
2417
- console.log("🔍 当前所有消息:", this.messages.getMessages());
2418
2679
  const requestBody = this.requestBuilder.toJSON();
2419
- console.log("🔍 第", iteration, "次请求体:", requestBody);
2420
2680
  const response = await this.apiClient.send(requestBody);
2421
2681
  currentMessage = response.choices[0].message;
2422
2682
  if (!currentMessage.tool_calls || currentMessage.tool_calls.length === 0) {
2423
- console.log("✅ 工具调用完成,AI给出最终回复");
2424
2683
  break;
2425
2684
  }
2426
- console.log("🔄 AI请求了新的工具调用,继续处理...");
2427
2685
  }
2428
- this.messages.addAssistantMessage(currentMessage.content || "", {
2429
- reasoning_content: currentMessage.reasoning_content || ""
2430
- // ✅ 新增:保存最终思考内容
2686
+ const eventData = await this._handleAssistantResponse(currentMessage, {
2687
+ toolIterations: iteration
2431
2688
  });
2432
- this.emit("message", {
2689
+ return eventData.content;
2690
+ }
2691
+ /**
2692
+ * 处理助手回复(统一方法,用于普通和流式请求)
2693
+ */
2694
+ async _handleAssistantResponse(aiMessage, options = {}) {
2695
+ const { isStreaming = false, toolIterations = 0, skipAddMessage = false } = options;
2696
+ const shouldAddMessage = this.autoAddMessages && !skipAddMessage;
2697
+ if (shouldAddMessage) {
2698
+ this.messages.addAssistantMessage(aiMessage.content || "", {
2699
+ reasoning_content: aiMessage.reasoning_content
2700
+ });
2701
+ }
2702
+ const eventData = {
2703
+ // 基础字段(Messages格式)
2433
2704
  role: "assistant",
2434
- content: currentMessage.content,
2435
- reasoning_content: currentMessage.reasoning_content,
2436
- // ✅ 新增:包含思考内容
2705
+ content: aiMessage.content || "",
2437
2706
  timestamp: /* @__PURE__ */ new Date(),
2438
- response: { choices: [{ message: currentMessage }] },
2439
- toolIterations: iteration
2440
- });
2441
- return currentMessage.content;
2707
+ // 扩展字段
2708
+ ...aiMessage.reasoning_content && { reasoning_content: aiMessage.reasoning_content },
2709
+ ...aiMessage.tool_calls && { tool_calls: aiMessage.tool_calls },
2710
+ ...aiMessage.tool_call_id && { tool_call_id: aiMessage.tool_call_id },
2711
+ // 框架元数据
2712
+ isStreaming,
2713
+ toolIterations,
2714
+ eventType: isStreaming ? "stream-complete" : "response-complete",
2715
+ // 保留原始响应(只有普通请求有)
2716
+ ...isStreaming ? {} : {
2717
+ response: { choices: [{ message: aiMessage }] }
2718
+ }
2719
+ };
2720
+ this.emit("message", eventData);
2721
+ return eventData;
2442
2722
  }
2443
2723
  /**
2444
2724
  * 处理普通回复
2445
2725
  */
2446
2726
  async _handleNormalResponse(aiMessage) {
2447
- this.messages.addAssistantMessage(aiMessage.content || "", {
2448
- reasoning_content: aiMessage.reasoning_content
2449
- });
2450
- this.emit("message", {
2451
- role: "assistant",
2452
- content: aiMessage.content,
2453
- timestamp: /* @__PURE__ */ new Date(),
2454
- response: { choices: [{ message: aiMessage }] }
2455
- });
2456
- return aiMessage.content;
2727
+ return await this._handleAssistantResponse(aiMessage);
2457
2728
  }
2458
2729
  /**
2459
2730
  * 流式发送消息(支持工具调用)
@@ -2463,7 +2734,8 @@ class ChatService extends EventEmitter {
2463
2734
  this.emit("sending", {
2464
2735
  role: "user",
2465
2736
  content: userMessage,
2466
- timestamp: /* @__PURE__ */ new Date()
2737
+ timestamp: /* @__PURE__ */ new Date(),
2738
+ eventType: "sending"
2467
2739
  });
2468
2740
  this.messages.addUserMessage(userMessage);
2469
2741
  const requestBuilder = new RequestBuilder(this.requestBuilder.model, this.messages, {
@@ -2477,19 +2749,31 @@ class ChatService extends EventEmitter {
2477
2749
  );
2478
2750
  const response = await this.apiClient.strSend(
2479
2751
  requestBody,
2480
- (chunk) => {
2752
+ // 如果 onProgress 是函数就调用,否则用空函数
2753
+ typeof onProgress === "function" ? (chunk) => {
2481
2754
  this.emit("stream-progress", chunk);
2482
2755
  onProgress(chunk);
2756
+ } : (chunk) => {
2757
+ this.emit("stream-progress", chunk);
2483
2758
  },
2484
- async (finalMessage) => {
2759
+ typeof onDone === "function" ? async (finalMessage) => {
2485
2760
  if (finalMessage.tool_calls && finalMessage.tool_calls.length > 0) {
2486
2761
  await this._handleStreamToolCalls(finalMessage, onProgress, onDone);
2487
2762
  } else {
2488
- this.messages.addAssistantMessage(finalMessage.content || "", {
2489
- reasoning_content: finalMessage.reasoning_content
2763
+ const eventData = await this._handleAssistantResponse(finalMessage, {
2764
+ isStreaming: true,
2765
+ skipAddMessage: true
2766
+ });
2767
+ onDone(eventData);
2768
+ }
2769
+ } : async (finalMessage) => {
2770
+ if (finalMessage.tool_calls && finalMessage.tool_calls.length > 0) {
2771
+ await this._handleStreamToolCalls(finalMessage);
2772
+ } else {
2773
+ await this._handleAssistantResponse(finalMessage, {
2774
+ isStreaming: true,
2775
+ skipAddMessage: true
2490
2776
  });
2491
- this.emit("stream-done", { message: finalMessage });
2492
- onDone(finalMessage);
2493
2777
  }
2494
2778
  }
2495
2779
  );
@@ -2531,9 +2815,11 @@ class ChatService extends EventEmitter {
2531
2815
  await new Promise((resolve, reject) => {
2532
2816
  this.apiClient.strSend(
2533
2817
  requestBody,
2534
- (chunk) => {
2818
+ typeof onProgress === "function" ? (chunk) => {
2535
2819
  this.emit("stream-progress", chunk);
2536
2820
  onProgress(chunk);
2821
+ } : (chunk) => {
2822
+ this.emit("stream-progress", chunk);
2537
2823
  },
2538
2824
  (finalMessage) => {
2539
2825
  currentMessage = finalMessage;
@@ -2549,17 +2835,14 @@ class ChatService extends EventEmitter {
2549
2835
  break;
2550
2836
  }
2551
2837
  }
2552
- this.messages.addAssistantMessage(currentMessage.content, {
2553
- reasoning_content: currentMessage.reasoning_content || ""
2554
- // ✅ 新增:保存最终思考内容
2838
+ const eventData = await this._handleAssistantResponse(currentMessage, {
2839
+ isStreaming: true,
2840
+ toolIterations: iteration,
2841
+ skipAddMessage: true
2555
2842
  });
2556
- this.emit("stream-done", {
2557
- message: currentMessage,
2558
- reasoning_content: currentMessage.reasoning_content,
2559
- // ✅ 新增:包含思考内容
2560
- toolIterations: iteration
2561
- });
2562
- onDone(currentMessage);
2843
+ if (typeof onDone === "function") {
2844
+ onDone(eventData);
2845
+ }
2563
2846
  }
2564
2847
  /**
2565
2848
  * 撤回消息
@@ -2615,7 +2898,8 @@ const index = {
2615
2898
  EventEmitter,
2616
2899
  MessageFormatter,
2617
2900
  ToolManager,
2618
- ChatService
2901
+ ChatService,
2902
+ defaultConfig
2619
2903
  };
2620
2904
  export {
2621
2905
  ApiClient,