@lobehub/chat 1.93.0 → 1.93.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.93.2](https://github.com/lobehub/lobe-chat/compare/v1.93.1...v1.93.2)
6
+
7
+ <sup>Released on **2025-06-09**</sup>
8
+
9
+ #### ♻ Code Refactoring
10
+
11
+ - **misc**: Refactor `<think>` & `</think>` handling.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Code refactoring
19
+
20
+ - **misc**: Refactor `<think>` & `</think>` handling, closes [#8121](https://github.com/lobehub/lobe-chat/issues/8121) ([04ac353](https://github.com/lobehub/lobe-chat/commit/04ac353))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
30
+ ### [Version 1.93.1](https://github.com/lobehub/lobe-chat/compare/v1.93.0...v1.93.1)
31
+
32
+ <sup>Released on **2025-06-08**</sup>
33
+
34
+ #### 🐛 Bug Fixes
35
+
36
+ - **misc**: Fix openai default Responses API issue.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### What's fixed
44
+
45
+ - **misc**: Fix openai default Responses API issue, closes [#8124](https://github.com/lobehub/lobe-chat/issues/8124) ([7f6ccf2](https://github.com/lobehub/lobe-chat/commit/7f6ccf2))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ## [Version 1.93.0](https://github.com/lobehub/lobe-chat/compare/v1.92.3...v1.93.0)
6
56
 
7
57
  <sup>Released on **2025-06-08**</sup>
package/README.md CHANGED
@@ -206,7 +206,7 @@ We have implemented support for the following model service providers:
206
206
  - **[Groq](https://lobechat.com/discover/provider/groq)**: Groq's LPU inference engine has excelled in the latest independent large language model (LLM) benchmarks, redefining the standards for AI solutions with its remarkable speed and efficiency. Groq represents instant inference speed, demonstrating strong performance in cloud-based deployments.
207
207
  - **[Perplexity](https://lobechat.com/discover/provider/perplexity)**: Perplexity is a leading provider of conversational generation models, offering various advanced Llama 3.1 models that support both online and offline applications, particularly suited for complex natural language processing tasks.
208
208
  - **[Mistral](https://lobechat.com/discover/provider/mistral)**: Mistral provides advanced general, specialized, and research models widely used in complex reasoning, multilingual tasks, and code generation. Through functional calling interfaces, users can integrate custom functionalities for specific applications.
209
- - **[ModelScope](https://lobechat.com/discover/provider/modelscope)**:
209
+ - **[ModelScope](https://lobechat.com/discover/provider/modelscope)**: ModelScope is a model-as-a-service platform launched by Alibaba Cloud, offering a wide range of AI models and inference services.
210
210
  - **[Ai21Labs](https://lobechat.com/discover/provider/ai21)**: AI21 Labs builds foundational models and AI systems for enterprises, accelerating the application of generative AI in production.
211
211
  - **[Upstage](https://lobechat.com/discover/provider/upstage)**: Upstage focuses on developing AI models for various business needs, including Solar LLM and document AI, aiming to achieve artificial general intelligence (AGI) for work. It allows for the creation of simple conversational agents through Chat API and supports functional calling, translation, embedding, and domain-specific applications.
212
212
  - **[xAI (Grok)](https://lobechat.com/discover/provider/xai)**: xAI is a company dedicated to building artificial intelligence to accelerate human scientific discovery. Our mission is to advance our collective understanding of the universe.
@@ -367,14 +367,14 @@ Our marketplace is not just a showcase platform but also a collaborative space.
367
367
 
368
368
  <!-- AGENT LIST -->
369
369
 
370
- | Recent Submits | Description |
371
- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
372
- | [Academic Paper Reading Mentor](https://lobechat.com/discover/assistant/paper-understanding)<br/><sup>By **[AdijeShen](https://github.com/AdijeShen)** on **2025-05-09**</sup> | Skilled at explaining complex academic papers in an easy-to-understand manner<br/>`academic-knowledge` `paper-analysis` |
373
- | [Nutritional Advisor](https://lobechat.com/discover/assistant/nutritionist)<br/><sup>By **[egornomic](https://github.com/egornomic)** on **2025-04-15**</sup> | Specializes in providing detailed nutritional information for food items.<br/>`nutrition` `food` `health` `information` |
374
- | [Rewrite in Translation Style](https://lobechat.com/discover/assistant/rewrite-in-a-translation-tone)<br/><sup>By **[q2019715](https://github.com/q2019715)** on **2025-03-13**</sup> | Rewrite a passage in a translation style<br/>`translation-style` `creative-writing` `language-style` `text-rewriting` `culture` |
375
- | [Academic Paper Review Expert](https://lobechat.com/discover/assistant/academic-paper-overview)<br/><sup>By **[arvinxx](https://github.com/arvinxx)** on **2025-03-11**</sup> | An academic research assistant skilled in high-quality literature retrieval and analysis<br/>`academic-research` `literature-retrieval` `data-analysis` `information-extraction` `consultation` |
370
+ | Recent Submits | Description |
371
+ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
372
+ | [Academic Paper Reading Mentor](https://lobechat.com/discover/assistant/paper-understanding)<br/><sup>By **[AdijeShen](https://github.com/AdijeShen)** on **2025-05-09**</sup> | Expert in explaining complex academic papers in simple and understandable language<br/>`academic-knowledge` `paper-analysis` |
373
+ | [Nutritional Advisor](https://lobechat.com/discover/assistant/nutritionist)<br/><sup>By **[egornomic](https://github.com/egornomic)** on **2025-04-15**</sup> | Specializes in providing detailed nutritional information for food items.<br/>`nutrition` `food` `health` `information` |
374
+ | [Rewritten in Translation Style](https://lobechat.com/discover/assistant/rewrite-in-a-translation-tone)<br/><sup>By **[q2019715](https://github.com/q2019715)** on **2025-03-13**</sup> | Rewrites a paragraph in a translation style<br/>`translation-style` `creative-writing` `language-style` `text-rewriting` `culture` |
375
+ | [Academic Paper Review Expert](https://lobechat.com/discover/assistant/academic-paper-overview)<br/><sup>By **[arvinxx](https://github.com/arvinxx)** on **2025-03-11**</sup> | An academic research assistant skilled in high-quality literature retrieval and analysis<br/>`academic-research` `literature-search` `data-analysis` `information-extraction` `consulting` |
376
376
 
377
- > 📊 Total agents: [<kbd>**501**</kbd> ](https://lobechat.com/discover/assistants)
377
+ > 📊 Total agents: [<kbd>**499**</kbd> ](https://lobechat.com/discover/assistants)
378
378
 
379
379
  <!-- AGENT LIST -->
380
380
 
package/README.zh-CN.md CHANGED
@@ -206,7 +206,7 @@ LobeChat 支持文件上传与知识库功能,你可以上传文件、图片
206
206
  - **[Groq](https://lobechat.com/discover/provider/groq)**: Groq 的 LPU 推理引擎在最新的独立大语言模型(LLM)基准测试中表现卓越,以其惊人的速度和效率重新定义了 AI 解决方案的标准。Groq 是一种即时推理速度的代表,在基于云的部署中展现了良好的性能。
207
207
  - **[Perplexity](https://lobechat.com/discover/provider/perplexity)**: Perplexity 是一家领先的对话生成模型提供商,提供多种先进的 Llama 3.1 模型,支持在线和离线应用,特别适用于复杂的自然语言处理任务。
208
208
  - **[Mistral](https://lobechat.com/discover/provider/mistral)**: Mistral 提供先进的通用、专业和研究型模型,广泛应用于复杂推理、多语言任务、代码生成等领域,通过功能调用接口,用户可以集成自定义功能,实现特定应用。
209
- - **[ModelScope](https://lobechat.com/discover/provider/modelscope)**:
209
+ - **[ModelScope](https://lobechat.com/discover/provider/modelscope)**: ModelScope 是阿里云推出的模型即服务平台,提供丰富的 AI 模型和推理服务。
210
210
  - **[Ai21Labs](https://lobechat.com/discover/provider/ai21)**: AI21 Labs 为企业构建基础模型和人工智能系统,加速生成性人工智能在生产中的应用。
211
211
  - **[Upstage](https://lobechat.com/discover/provider/upstage)**: Upstage 专注于为各种商业需求开发 AI 模型,包括 Solar LLM 和文档 AI,旨在实现工作的人造通用智能(AGI)。通过 Chat API 创建简单的对话代理,并支持功能调用、翻译、嵌入以及特定领域应用。
212
212
  - **[xAI (Grok)](https://lobechat.com/discover/provider/xai)**: xAI 是一家致力于构建人工智能以加速人类科学发现的公司。我们的使命是推动我们对宇宙的共同理解。
@@ -359,11 +359,11 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
359
359
  | 最近新增 | 描述 |
360
360
  | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
361
361
  | [学术论文阅读导师](https://lobechat.com/discover/assistant/paper-understanding)<br/><sup>By **[AdijeShen](https://github.com/AdijeShen)** on **2025-05-09**</sup> | 擅长将复杂学术论文通俗易懂讲解<br/>`学术知道` `论文解析` |
362
- | [营养顾问](https://lobechat.com/discover/assistant/nutritionist)<br/><sup>By **[egornomic](https://github.com/egornomic)** on **2025-04-15**</sup> | 专注于提供食品的详细营养信息。<br/>`营养` `食品` `健康` `信息` |
362
+ | [营养顾问](https://lobechat.com/discover/assistant/nutritionist)<br/><sup>By **[egornomic](https://github.com/egornomic)** on **2025-04-15**</sup> | 专注于提供食品项目的详细营养信息。<br/>`营养` `食品` `健康` `信息` |
363
363
  | [改写为翻译腔](https://lobechat.com/discover/assistant/rewrite-in-a-translation-tone)<br/><sup>By **[q2019715](https://github.com/q2019715)** on **2025-03-13**</sup> | 将一段话重写为翻译腔<br/>`翻译腔` `创意写作` `语言风格` `文段重写` `文化` |
364
364
  | [学术论文综述专家](https://lobechat.com/discover/assistant/academic-paper-overview)<br/><sup>By **[arvinxx](https://github.com/arvinxx)** on **2025-03-11**</sup> | 擅长高质量文献检索与分析的学术研究助手<br/>`学术研究` `文献检索` `数据分析` `信息提取` `咨询` |
365
365
 
366
- > 📊 Total agents: [<kbd>**501**</kbd> ](https://lobechat.com/discover/assistants)
366
+ > 📊 Total agents: [<kbd>**499**</kbd> ](https://lobechat.com/discover/assistants)
367
367
 
368
368
  <!-- AGENT LIST -->
369
369
 
package/changelog/v1.json CHANGED
@@ -1,4 +1,22 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Refactor <think> & </think> handling."
6
+ ]
7
+ },
8
+ "date": "2025-06-09",
9
+ "version": "1.93.2"
10
+ },
11
+ {
12
+ "children": {
13
+ "fixes": [
14
+ "Fix openai default Responses API issue."
15
+ ]
16
+ },
17
+ "date": "2025-06-08",
18
+ "version": "1.93.1"
19
+ },
2
20
  {
3
21
  "children": {
4
22
  "features": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.93.0",
3
+ "version": "1.93.2",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -231,16 +231,16 @@ describe('LobePerplexityAI', () => {
231
231
  expect(noSpeedStream).toEqual(
232
232
  [
233
233
  'id: 506d64fb-e7f2-4d94-b80f-158369e9446d',
234
- 'event: text',
235
- 'data: "<think>"\n',
234
+ 'event: reasoning',
235
+ 'data: ""\n',
236
236
  'id: 506d64fb-e7f2-4d94-b80f-158369e9446d',
237
237
  'event: grounding',
238
238
  'data: {"citations":[{"title":"https://www.weather.com.cn/weather/101210101.shtml","url":"https://www.weather.com.cn/weather/101210101.shtml"},{"title":"https://tianqi.moji.com/weather/china/zhejiang/hangzhou","url":"https://tianqi.moji.com/weather/china/zhejiang/hangzhou"},{"title":"https://weather.cma.cn/web/weather/58457.html","url":"https://weather.cma.cn/web/weather/58457.html"},{"title":"https://tianqi.so.com/weather/101210101","url":"https://tianqi.so.com/weather/101210101"},{"title":"https://www.accuweather.com/zh/cn/hangzhou/106832/weather-forecast/106832","url":"https://www.accuweather.com/zh/cn/hangzhou/106832/weather-forecast/106832"},{"title":"https://www.hzqx.com","url":"https://www.hzqx.com"},{"title":"https://www.hzqx.com/pc/hztq/","url":"https://www.hzqx.com/pc/hztq/"}]}\n',
239
239
  'id: 506d64fb-e7f2-4d94-b80f-158369e9446d',
240
- 'event: text',
240
+ 'event: reasoning',
241
241
  'data: "杭州今"\n',
242
242
  'id: 506d64fb-e7f2-4d94-b80f-158369e9446d',
243
- 'event: text',
243
+ 'event: reasoning',
244
244
  'data: "天和未来几天的"\n',
245
245
  'id: 506d64fb-e7f2-4d94-b80f-158369e9446d',
246
246
  'event: usage',
@@ -7,6 +7,65 @@ import { OllamaStream } from './ollama';
7
7
 
8
8
  describe('OllamaStream', () => {
9
9
  describe('should transform Ollama stream to protocol stream', () => {
10
+ it('reasoning', async () => {
11
+ vi.spyOn(uuidModule, 'nanoid').mockReturnValueOnce('2');
12
+
13
+ const messages = [
14
+ '<think>',
15
+ '这是一个思考过程',
16
+ ',需要仔细分析问题。',
17
+ '</think>',
18
+ '根据分析,我的答案是:',
19
+ '这是最终答案。',
20
+ ];
21
+
22
+ const mockOllamaStream = new ReadableStream<ChatResponse>({
23
+ start(controller) {
24
+ messages.forEach((content) => {
25
+ controller.enqueue({ message: { content }, done: false } as ChatResponse);
26
+ });
27
+ controller.enqueue({ message: { content: '' }, done: true } as ChatResponse);
28
+ controller.close();
29
+ },
30
+ });
31
+
32
+ const protocolStream = OllamaStream(mockOllamaStream);
33
+
34
+ const decoder = new TextDecoder();
35
+ const chunks = [];
36
+
37
+ // @ts-ignore
38
+ for await (const chunk of protocolStream) {
39
+ chunks.push(decoder.decode(chunk, { stream: true }));
40
+ }
41
+
42
+ expect(chunks).toEqual(
43
+ [
44
+ 'id: chat_2',
45
+ 'event: reasoning',
46
+ `data: ""\n`,
47
+ 'id: chat_2',
48
+ 'event: reasoning',
49
+ `data: "这是一个思考过程"\n`,
50
+ 'id: chat_2',
51
+ 'event: reasoning',
52
+ `data: ",需要仔细分析问题。"\n`,
53
+ 'id: chat_2',
54
+ 'event: text',
55
+ `data: ""\n`,
56
+ 'id: chat_2',
57
+ 'event: text',
58
+ `data: "根据分析,我的答案是:"\n`,
59
+ 'id: chat_2',
60
+ 'event: text',
61
+ `data: "这是最终答案。"\n`,
62
+ 'id: chat_2',
63
+ 'event: stop',
64
+ `data: "finished"\n`,
65
+ ].map((line) => `${line}\n`)
66
+ );
67
+ });
68
+
10
69
  it('text', async () => {
11
70
  vi.spyOn(uuidModule, 'nanoid').mockReturnValueOnce('1');
12
71
 
@@ -32,7 +32,20 @@ const transformOllamaStream = (chunk: ChatResponse, stack: StreamContext): Strea
32
32
  type: 'tool_calls',
33
33
  };
34
34
  }
35
- return { data: chunk.message.content, id: stack.id, type: 'text' };
35
+
36
+ // 判断是否有 <think> 或 </think> 标签,更新 thinkingInContent 状态
37
+ if (chunk.message.content.includes('<think>')) {
38
+ stack.thinkingInContent = true;
39
+ } else if (chunk.message.content.includes('</think>')) {
40
+ stack.thinkingInContent = false;
41
+ }
42
+
43
+ // 清除 <think> 及 </think> 标签,并根据当前思考模式确定返回类型
44
+ return {
45
+ data: chunk.message.content.replaceAll(/<\/?think>/g, ''),
46
+ id: stack.id,
47
+ type: stack?.thinkingInContent ? 'reasoning' : 'text',
48
+ };
36
49
  };
37
50
 
38
51
  export const OllamaStream = (
@@ -904,6 +904,169 @@ describe('OpenAIStream', () => {
904
904
  });
905
905
 
906
906
  describe('Reasoning', () => {
907
+ it('should handle <think></think> tags in streaming content', async () => {
908
+ const data = [
909
+ {
910
+ id: '1',
911
+ object: 'chat.completion.chunk',
912
+ created: 1737563070,
913
+ model: 'deepseek-reasoner',
914
+ system_fingerprint: 'fp_1c5d8833bc',
915
+ choices: [
916
+ {
917
+ index: 0,
918
+ delta: { content: '<think>' },
919
+ logprobs: null,
920
+ finish_reason: null,
921
+ },
922
+ ],
923
+ },
924
+ {
925
+ id: '1',
926
+ object: 'chat.completion.chunk',
927
+ created: 1737563070,
928
+ model: 'deepseek-reasoner',
929
+ system_fingerprint: 'fp_1c5d8833bc',
930
+ choices: [
931
+ {
932
+ index: 0,
933
+ delta: { content: '这是一个思考过程' },
934
+ logprobs: null,
935
+ finish_reason: null,
936
+ },
937
+ ],
938
+ },
939
+ {
940
+ id: '1',
941
+ object: 'chat.completion.chunk',
942
+ created: 1737563070,
943
+ model: 'deepseek-reasoner',
944
+ system_fingerprint: 'fp_1c5d8833bc',
945
+ choices: [
946
+ {
947
+ index: 0,
948
+ delta: { content: ',需要仔细分析问题。' },
949
+ logprobs: null,
950
+ finish_reason: null,
951
+ },
952
+ ],
953
+ },
954
+ {
955
+ id: '1',
956
+ object: 'chat.completion.chunk',
957
+ created: 1737563070,
958
+ model: 'deepseek-reasoner',
959
+ system_fingerprint: 'fp_1c5d8833bc',
960
+ choices: [
961
+ {
962
+ index: 0,
963
+ delta: { content: '</think>' },
964
+ logprobs: null,
965
+ finish_reason: null,
966
+ },
967
+ ],
968
+ },
969
+ {
970
+ id: '1',
971
+ object: 'chat.completion.chunk',
972
+ created: 1737563070,
973
+ model: 'deepseek-reasoner',
974
+ system_fingerprint: 'fp_1c5d8833bc',
975
+ choices: [
976
+ {
977
+ index: 0,
978
+ delta: { content: '根据分析,我的答案是:' },
979
+ logprobs: null,
980
+ finish_reason: null,
981
+ },
982
+ ],
983
+ },
984
+ {
985
+ id: '1',
986
+ object: 'chat.completion.chunk',
987
+ created: 1737563070,
988
+ model: 'deepseek-reasoner',
989
+ system_fingerprint: 'fp_1c5d8833bc',
990
+ choices: [
991
+ {
992
+ index: 0,
993
+ delta: { content: '这是最终答案。' },
994
+ logprobs: null,
995
+ finish_reason: null,
996
+ },
997
+ ],
998
+ },
999
+ {
1000
+ id: '1',
1001
+ object: 'chat.completion.chunk',
1002
+ created: 1737563070,
1003
+ model: 'deepseek-reasoner',
1004
+ system_fingerprint: 'fp_1c5d8833bc',
1005
+ choices: [
1006
+ {
1007
+ index: 0,
1008
+ delta: { content: '' },
1009
+ logprobs: null,
1010
+ finish_reason: 'stop',
1011
+ },
1012
+ ],
1013
+ usage: {
1014
+ prompt_tokens: 10,
1015
+ completion_tokens: 50,
1016
+ total_tokens: 60,
1017
+ prompt_tokens_details: { cached_tokens: 0 },
1018
+ completion_tokens_details: { reasoning_tokens: 20 },
1019
+ prompt_cache_hit_tokens: 0,
1020
+ prompt_cache_miss_tokens: 10,
1021
+ },
1022
+ },
1023
+ ];
1024
+
1025
+ const mockOpenAIStream = new ReadableStream({
1026
+ start(controller) {
1027
+ data.forEach((chunk) => {
1028
+ controller.enqueue(chunk);
1029
+ });
1030
+ controller.close();
1031
+ },
1032
+ });
1033
+
1034
+ const protocolStream = OpenAIStream(mockOpenAIStream);
1035
+ const decoder = new TextDecoder();
1036
+ const chunks = [];
1037
+
1038
+ // @ts-ignore
1039
+ for await (const chunk of protocolStream) {
1040
+ chunks.push(decoder.decode(chunk, { stream: true }));
1041
+ }
1042
+
1043
+ expect(chunks).toEqual(
1044
+ [
1045
+ 'id: 1',
1046
+ 'event: reasoning',
1047
+ `data: ""\n`,
1048
+ 'id: 1',
1049
+ 'event: reasoning',
1050
+ `data: "这是一个思考过程"\n`,
1051
+ 'id: 1',
1052
+ 'event: reasoning',
1053
+ `data: ",需要仔细分析问题。"\n`,
1054
+ 'id: 1',
1055
+ 'event: text',
1056
+ `data: ""\n`,
1057
+ 'id: 1',
1058
+ 'event: text',
1059
+ `data: "根据分析,我的答案是:"\n`,
1060
+ 'id: 1',
1061
+ 'event: text',
1062
+ `data: "这是最终答案。"\n`,
1063
+ 'id: 1',
1064
+ 'event: usage',
1065
+ `data: {"inputCacheMissTokens":10,"inputTextTokens":10,"outputReasoningTokens":20,"outputTextTokens":30,"totalInputTokens":10,"totalOutputTokens":50,"totalTokens":60}\n`,
1066
+ ].map((i) => `${i}\n`),
1067
+ );
1068
+ });
1069
+
907
1070
  it('should handle reasoning event in official DeepSeek api', async () => {
908
1071
  const data = [
909
1072
  {
@@ -210,6 +210,17 @@ const transformOpenAIStream = (
210
210
  }
211
211
 
212
212
  if (typeof content === 'string') {
213
+ // 清除 <think> 及 </think> 标签
214
+ const thinkingContent = content.replaceAll(/<\/?think>/g, '');
215
+
216
+ // 判断是否有 <think> 或 </think> 标签,更新 thinkingInContent 状态
217
+ if (content.includes('<think>')) {
218
+ streamContext.thinkingInContent = true;
219
+ } else if (content.includes('</think>')) {
220
+ streamContext.thinkingInContent = false;
221
+ }
222
+
223
+ // 判断是否有 citations 内容,更新 returnedCitation 状态
213
224
  if (!streamContext?.returnedCitation) {
214
225
  const citations =
215
226
  // in Perplexity api, the citation is in every chunk, but we only need to return it once
@@ -237,12 +248,17 @@ const transformOpenAIStream = (
237
248
  id: chunk.id,
238
249
  type: 'grounding',
239
250
  },
240
- { data: content, id: chunk.id, type: 'text' },
251
+ { data: thinkingContent, id: chunk.id, type: streamContext?.thinkingInContent ? 'reasoning' : 'text' },
241
252
  ];
242
253
  }
243
254
  }
244
255
 
245
- return { data: content, id: chunk.id, type: 'text' };
256
+ // 根据当前思考模式确定返回类型
257
+ return {
258
+ data: thinkingContent,
259
+ id: chunk.id,
260
+ type: streamContext?.thinkingInContent ? 'reasoning' : 'text',
261
+ };
246
262
  }
247
263
  }
248
264
 
@@ -31,6 +31,18 @@ export interface StreamContext {
31
31
  id: string;
32
32
  name: string;
33
33
  };
34
+ /**
35
+ * Indicates whether the current state is within a "thinking" segment of the model output
36
+ * (e.g., when processing lmstudio responses).
37
+ *
38
+ * When parsing output containing <think> and </think> tags:
39
+ * - Set to `true` upon encountering a <think> tag (entering reasoning mode)
40
+ * - Set to `false` upon encountering a </think> tag (exiting reasoning mode)
41
+ *
42
+ * While `thinkingInContent` is `true`, subsequent content should be stored in `reasoning_content`.
43
+ * When `false`, content should be stored in the regular `content` field.
44
+ */
45
+ thinkingInContent?: boolean;
34
46
  tool?: {
35
47
  id: string;
36
48
  index: number;
@@ -618,7 +618,6 @@ describe('ChatService', () => {
618
618
  stream: true,
619
619
  ...DEFAULT_AGENT_CONFIG.params,
620
620
  ...params,
621
- apiMode: 'responses',
622
621
  };
623
622
 
624
623
  await chatService.getChatCompletion(params, options);
@@ -682,7 +681,6 @@ describe('ChatService', () => {
682
681
  stream: true,
683
682
  ...DEFAULT_AGENT_CONFIG.params,
684
683
  ...params,
685
- apiMode: 'responses',
686
684
  };
687
685
 
688
686
  const result = await chatService.getChatCompletion(params, options);
@@ -106,7 +106,7 @@ const isProviderEnableResponseApi = (id: string) => (s: AIProviderStoreState) =>
106
106
 
107
107
  if (typeof enableResponseApi === 'boolean') return enableResponseApi;
108
108
 
109
- return id === 'openai';
109
+ return false;
110
110
  };
111
111
 
112
112
  export const aiProviderSelectors = {