@lobehub/chat 1.61.5 → 1.62.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/changelog/v1.json +21 -0
  3. package/docs/self-hosting/advanced/auth/next-auth/casdoor.mdx +2 -1
  4. package/docs/self-hosting/advanced/auth/next-auth/casdoor.zh-CN.mdx +2 -1
  5. package/locales/en-US/components.json +3 -3
  6. package/package.json +2 -2
  7. package/src/app/(backend)/api/webhooks/casdoor/route.ts +5 -7
  8. package/src/app/(backend)/api/webhooks/casdoor/validateRequest.ts +7 -4
  9. package/src/components/ModelSelect/index.tsx +24 -2
  10. package/src/components/Thinking/index.tsx +7 -2
  11. package/src/config/aiModels/jina.ts +7 -5
  12. package/src/config/aiModels/perplexity.ts +8 -0
  13. package/src/config/llm.ts +8 -0
  14. package/src/database/client/migrations.json +12 -8
  15. package/src/database/migrations/0015_add_message_search_metadata.sql +2 -0
  16. package/src/database/migrations/meta/0015_snapshot.json +3616 -0
  17. package/src/database/migrations/meta/_journal.json +7 -0
  18. package/src/database/schemas/message.ts +3 -1
  19. package/src/database/server/models/message.ts +2 -0
  20. package/src/features/Conversation/components/ChatItem/index.tsx +10 -1
  21. package/src/features/Conversation/components/MarkdownElements/Thinking/Render.tsx +5 -1
  22. package/src/features/Conversation/components/MarkdownElements/remarkPlugins/createRemarkCustomTagPlugin.ts +1 -0
  23. package/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.test.ts +107 -0
  24. package/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.ts +6 -0
  25. package/src/libs/agent-runtime/perplexity/index.test.ts +156 -12
  26. package/src/libs/agent-runtime/utils/streams/anthropic.ts +3 -3
  27. package/src/libs/agent-runtime/utils/streams/bedrock/claude.ts +6 -2
  28. package/src/libs/agent-runtime/utils/streams/bedrock/llama.ts +3 -3
  29. package/src/libs/agent-runtime/utils/streams/google-ai.ts +3 -3
  30. package/src/libs/agent-runtime/utils/streams/ollama.ts +3 -3
  31. package/src/libs/agent-runtime/utils/streams/openai.ts +26 -8
  32. package/src/libs/agent-runtime/utils/streams/protocol.ts +33 -8
  33. package/src/libs/agent-runtime/utils/streams/vertex-ai.ts +3 -3
  34. package/src/locales/default/components.ts +1 -0
  35. package/src/server/globalConfig/index.test.ts +81 -0
  36. package/src/server/routers/lambda/user.test.ts +305 -0
  37. package/src/server/services/nextAuthUser/index.ts +2 -2
  38. package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +17 -6
  39. package/src/store/chat/slices/message/action.ts +12 -7
  40. package/src/types/aiModel.ts +5 -0
  41. package/src/types/message/base.ts +13 -0
  42. package/src/types/message/chat.ts +3 -2
  43. package/src/utils/errorResponse.test.ts +37 -1
  44. package/src/utils/fetch/fetchSSE.ts +17 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,64 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 1.62.0](https://github.com/lobehub/lobe-chat/compare/v1.61.6...v1.62.0)
6
+
7
+ <sup>Released on **2025-02-20**</sup>
8
+
9
+ #### ✨ Features
10
+
11
+ - **misc**: Support pplx search grounding.
12
+
13
+ #### 🐛 Bug Fixes
14
+
15
+ - **misc**: Azure AI env var configuration issue..
16
+
17
+ <br/>
18
+
19
+ <details>
20
+ <summary><kbd>Improvements and Fixes</kbd></summary>
21
+
22
+ #### What's improved
23
+
24
+ - **misc**: Support pplx search grounding, closes [#6331](https://github.com/lobehub/lobe-chat/issues/6331) ([ccb0003](https://github.com/lobehub/lobe-chat/commit/ccb0003))
25
+
26
+ #### What's fixed
27
+
28
+ - **misc**: Azure AI env var configuration issue., closes [#6346](https://github.com/lobehub/lobe-chat/issues/6346) ([3fc61bb](https://github.com/lobehub/lobe-chat/commit/3fc61bb))
29
+
30
+ </details>
31
+
32
+ <div align="right">
33
+
34
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
35
+
36
+ </div>
37
+
38
+ ### [Version 1.61.6](https://github.com/lobehub/lobe-chat/compare/v1.61.5...v1.61.6)
39
+
40
+ <sup>Released on **2025-02-20**</sup>
41
+
42
+ #### 🐛 Bug Fixes
43
+
44
+ - **misc**: Casdoor webhooks error.
45
+
46
+ <br/>
47
+
48
+ <details>
49
+ <summary><kbd>Improvements and Fixes</kbd></summary>
50
+
51
+ #### What's fixed
52
+
53
+ - **misc**: Casdoor webhooks error, closes [#6304](https://github.com/lobehub/lobe-chat/issues/6304) ([7a458b9](https://github.com/lobehub/lobe-chat/commit/7a458b9))
54
+
55
+ </details>
56
+
57
+ <div align="right">
58
+
59
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
60
+
61
+ </div>
62
+
5
63
  ### [Version 1.61.5](https://github.com/lobehub/lobe-chat/compare/v1.61.4...v1.61.5)
6
64
 
7
65
  <sup>Released on **2025-02-19**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,25 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "features": [
5
+ "Support pplx search grounding."
6
+ ],
7
+ "fixes": [
8
+ "Azure AI env var configuration issue.."
9
+ ]
10
+ },
11
+ "date": "2025-02-20",
12
+ "version": "1.62.0"
13
+ },
14
+ {
15
+ "children": {
16
+ "fixes": [
17
+ "Casdoor webhooks error."
18
+ ]
19
+ },
20
+ "date": "2025-02-20",
21
+ "version": "1.61.6"
22
+ },
2
23
  {
3
24
  "children": {
4
25
  "improvements": [
@@ -106,6 +106,8 @@ If you are deploying using a public network, the following assumptions apply:
106
106
 
107
107
  ### Configure Webhook (Optional)
108
108
 
109
+ > Available on Casdoor `>=1.843.0`.
110
+
109
111
  Configure the Casdoor webhook so that LobeChat can receive notifications when user information is updated.
110
112
 
111
113
  Go to `Admin` -> `Webhooks`, add a webhook, and fill in the following fields:
@@ -118,7 +120,6 @@ If you are deploying using a public network, the following assumptions apply:
118
120
  > The secret is generated by yourself, you can visit [https://generate-secret.vercel.app/10](https://generate-secret.vercel.app/10) to generate a 10 bit secret.
119
121
 
120
122
  - Event: `update-user`
121
- - Is user extented: `true`
122
123
 
123
124
  Save and Exit, then copy the Webhook secret and fill it in the environment variable \`CASDOOR\_WEBHOOK\_SECRET.
124
125
 
@@ -95,6 +95,8 @@ tags:
95
95
 
96
96
  ### 配置 Webhook (可选)
97
97
 
98
+ > 在 Casdoor `>=1.843.0` 上可用。
99
+
98
100
  配置 Casdoor 的 Webhook 以便在用户信息更新时同步到 LobeChat 。
99
101
 
100
102
  前往 `管理工具` -> `Webhooks`,创建一个 Webhook,添加一个 Webhook,填写以下字段:
@@ -107,7 +109,6 @@ tags:
107
109
  > 密钥由你自己生成,用于验证 Casdoor 发送的请求是否合法。 可以前往 [https://generate-secret.vercel.app/10](https://generate-secret.vercel.app/10) 生成一个 10 位的密钥。
108
110
 
109
111
  - 事件:`update-user`
110
- - 拓展用户字段:`true`
111
112
 
112
113
  保存,并退出。 将该密钥填写到环境变量中的 `CASDOOR_WEBHOOK_SECRET`。
113
114
 
@@ -111,8 +111,8 @@
111
111
  }
112
112
  },
113
113
  "Thinking": {
114
- "thinking": "Deep in thought...",
115
- "thought": "Deeply thought (took {{duration}} seconds)",
116
- "thoughtWithDuration": "Deeply thought"
114
+ "thinking": "Deep Thinking...",
115
+ "thought": "Deeply Thought (in {{duration}} seconds)",
116
+ "thoughtWithDuration": "Deeply Thought"
117
117
  }
118
118
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.61.5",
3
+ "version": "1.62.0",
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",
@@ -129,7 +129,7 @@
129
129
  "@lobehub/chat-plugins-gateway": "^1.9.0",
130
130
  "@lobehub/icons": "^1.73.1",
131
131
  "@lobehub/tts": "^1.28.0",
132
- "@lobehub/ui": "^1.164.15",
132
+ "@lobehub/ui": "^1.165.0",
133
133
  "@neondatabase/serverless": "^0.10.4",
134
134
  "@next/third-parties": "^15.1.4",
135
135
  "@react-spring/web": "^9.7.5",
@@ -16,9 +16,7 @@ export const POST = async (req: Request): Promise<NextResponse> => {
16
16
  );
17
17
  }
18
18
 
19
- const { action, extendedUser } = payload;
20
-
21
- pino.trace(`casdoor webhook payload: ${{ action, extendedUser }}`);
19
+ const { action, object } = payload;
22
20
 
23
21
  const nextAuthUserService = new NextAuthUserService();
24
22
  switch (action) {
@@ -26,12 +24,12 @@ export const POST = async (req: Request): Promise<NextResponse> => {
26
24
  return nextAuthUserService.safeUpdateUser(
27
25
  {
28
26
  provider: 'casdoor',
29
- providerAccountId: extendedUser.id,
27
+ providerAccountId: object.id,
30
28
  },
31
29
  {
32
- avatar: extendedUser?.avatar,
33
- email: extendedUser?.email,
34
- fullName: extendedUser.displayName,
30
+ avatar: object?.avatar,
31
+ email: object?.email,
32
+ fullName: object.displayName,
35
33
  },
36
34
  );
37
35
  }
@@ -11,8 +11,9 @@ export type CasdoorUserEntity = {
11
11
 
12
12
  interface CasdoorWebhookPayload {
13
13
  action: string;
14
- // Only support user event currently
15
- extendedUser: CasdoorUserEntity;
14
+ // The object is the user entity that is updated.
15
+ // ref: https://github.com/casdoor/casdoor/issues/1918#issuecomment-1572218847
16
+ object: CasdoorUserEntity;
16
17
  }
17
18
 
18
19
  export const validateRequest = async (request: Request, secret?: string) => {
@@ -21,7 +22,9 @@ export const validateRequest = async (request: Request, secret?: string) => {
21
22
  const casdoorSecret = headerPayload.get('casdoor-secret')!;
22
23
  try {
23
24
  if (casdoorSecret === secret) {
24
- return JSON.parse(payloadString) as CasdoorWebhookPayload;
25
+ return JSON.parse(payloadString, (k, v) =>
26
+ k === 'object' && typeof v === 'string' ? JSON.parse(v) : v,
27
+ ) as CasdoorWebhookPayload;
25
28
  } else {
26
29
  console.warn(
27
30
  '[Casdoor]: secret verify failed, please check your secret in `CASDOOR_WEBHOOK_SECRET`',
@@ -32,7 +35,7 @@ export const validateRequest = async (request: Request, secret?: string) => {
32
35
  if (!authEnv.CASDOOR_WEBHOOK_SECRET) {
33
36
  throw new Error('`CASDOOR_WEBHOOK_SECRET` environment variable is missing.');
34
37
  }
35
- console.error('[Casdoor]: incoming webhook failed in verification.\n', e);
38
+ console.error('[Casdoor]: incoming webhook failed in verification.\n', e, payloadString);
36
39
  return;
37
40
  }
38
41
  };
@@ -2,7 +2,14 @@ import { IconAvatarProps, ModelIcon, ProviderIcon } from '@lobehub/icons';
2
2
  import { Avatar, Icon, Tooltip } from '@lobehub/ui';
3
3
  import { Typography } from 'antd';
4
4
  import { createStyles } from 'antd-style';
5
- import { Infinity, AtomIcon, LucideEye, LucidePaperclip, ToyBrick } from 'lucide-react';
5
+ import {
6
+ Infinity,
7
+ AtomIcon,
8
+ LucideEye,
9
+ LucideGlobe,
10
+ LucidePaperclip,
11
+ ToyBrick,
12
+ } from 'lucide-react';
6
13
  import numeral from 'numeral';
7
14
  import { rgba } from 'polished';
8
15
  import { FC, memo } from 'react';
@@ -14,7 +21,7 @@ import { AiProviderSourceType } from '@/types/aiProvider';
14
21
  import { ChatModelCard } from '@/types/llm';
15
22
  import { formatTokenNumber } from '@/utils/format';
16
23
 
17
- const useStyles = createStyles(({ css, token }) => ({
24
+ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
18
25
  custom: css`
19
26
  width: 36px;
20
27
  height: 20px;
@@ -41,6 +48,10 @@ const useStyles = createStyles(({ css, token }) => ({
41
48
  color: ${token.geekblue};
42
49
  background: ${token.geekblue1};
43
50
  `,
51
+ tagCyan: css`
52
+ color: ${isDarkMode ? token.cyan7 : token.cyan10};
53
+ background: ${isDarkMode ? token.cyan1 : token.cyan2};
54
+ `,
44
55
  tagGreen: css`
45
56
  color: ${token.green};
46
57
  background: ${token.green1};
@@ -122,6 +133,17 @@ export const ModelInfoTags = memo<ModelInfoTagsProps>(
122
133
  </div>
123
134
  </Tooltip>
124
135
  )}
136
+ {model.search && (
137
+ <Tooltip
138
+ placement={placement}
139
+ styles={{ root: { pointerEvents: 'none' } }}
140
+ title={t('ModelSelect.featureTag.search')}
141
+ >
142
+ <div className={cx(styles.tag, styles.tagCyan)} style={{ cursor: 'pointer' }} title="">
143
+ <Icon icon={LucideGlobe} />
144
+ </div>
145
+ </Tooltip>
146
+ )}
125
147
  {typeof model.contextWindowTokens === 'number' && (
126
148
  <Tooltip
127
149
  placement={placement}
@@ -7,6 +7,8 @@ import { CSSProperties, memo, useEffect, useState } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
  import { Flexbox } from 'react-layout-kit';
9
9
 
10
+ import { CitationItem } from '@/types/message';
11
+
10
12
  const useStyles = createStyles(({ css, token, isDarkMode }) => ({
11
13
  container: css`
12
14
  width: fit-content;
@@ -59,13 +61,14 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
59
61
  }));
60
62
 
61
63
  interface ThinkingProps {
64
+ citations?: CitationItem[];
62
65
  content?: string;
63
66
  duration?: number;
64
67
  style?: CSSProperties;
65
68
  thinking?: boolean;
66
69
  }
67
70
 
68
- const Thinking = memo<ThinkingProps>(({ content, duration, thinking, style }) => {
71
+ const Thinking = memo<ThinkingProps>(({ content, duration, thinking, style, citations }) => {
69
72
  const { t } = useTranslation(['components', 'common']);
70
73
  const { styles, cx } = useStyles();
71
74
 
@@ -135,7 +138,9 @@ const Thinking = memo<ThinkingProps>(({ content, duration, thinking, style }) =>
135
138
  }}
136
139
  >
137
140
  {typeof content === 'string' ? (
138
- <Markdown variant={'chat'}>{content}</Markdown>
141
+ <Markdown citations={citations} variant={'chat'}>
142
+ {content}
143
+ </Markdown>
139
144
  ) : (
140
145
  content
141
146
  )}
@@ -4,19 +4,21 @@ const jinaChatModels: AIChatModelCard[] = [
4
4
  {
5
5
  abilities: {
6
6
  reasoning: true,
7
+ search: true,
7
8
  },
8
9
  contextWindowTokens: 1_000_000,
9
- description: '深度搜索结合了网络搜索、阅读和推理,可进行全面调查。您可以将其视为一个代理,接受您的研究任务 - 它会进行广泛搜索并经过多次迭代,然后才能给出答案。这个过程涉及持续的研究、推理和从各个角度解决问题。这与直接从预训练数据生成答案的标准大模型以及依赖一次性表面搜索的传统 RAG 系统有着根本的不同。',
10
+ description:
11
+ '深度搜索结合了网络搜索、阅读和推理,可进行全面调查。您可以将其视为一个代理,接受您的研究任务 - 它会进行广泛搜索并经过多次迭代,然后才能给出答案。这个过程涉及持续的研究、推理和从各个角度解决问题。这与直接从预训练数据生成答案的标准大模型以及依赖一次性表面搜索的传统 RAG 系统有着根本的不同。',
10
12
  displayName: 'Jina DeepSearch v1',
11
13
  enabled: true,
12
14
  id: 'jina-deepsearch-v1',
13
15
  pricing: {
14
16
  input: 0.02,
15
- output: 0.02
17
+ output: 0.02,
16
18
  },
17
- type: 'chat'
18
- }
19
- ]
19
+ type: 'chat',
20
+ },
21
+ ];
20
22
 
21
23
  export const allModels = [...jinaChatModels];
22
24
 
@@ -4,6 +4,7 @@ const perplexityChatModels: AIChatModelCard[] = [
4
4
  {
5
5
  abilities: {
6
6
  reasoning: true,
7
+ search: true,
7
8
  },
8
9
  contextWindowTokens: 127_072,
9
10
  description: '由 DeepSeek 推理模型提供支持的新 API 产品。',
@@ -16,6 +17,7 @@ const perplexityChatModels: AIChatModelCard[] = [
16
17
  {
17
18
  abilities: {
18
19
  reasoning: true,
20
+ search: true,
19
21
  },
20
22
  contextWindowTokens: 127_072,
21
23
  description: '由 DeepSeek 推理模型提供支持的新 API 产品。',
@@ -26,6 +28,9 @@ const perplexityChatModels: AIChatModelCard[] = [
26
28
  type: 'chat',
27
29
  },
28
30
  {
31
+ abilities: {
32
+ search: true,
33
+ },
29
34
  contextWindowTokens: 200_000,
30
35
  description: '支持搜索上下文的高级搜索产品,支持高级查询和跟进。',
31
36
  displayName: 'Sonar Pro',
@@ -34,6 +39,9 @@ const perplexityChatModels: AIChatModelCard[] = [
34
39
  type: 'chat',
35
40
  },
36
41
  {
42
+ abilities: {
43
+ search: true,
44
+ },
37
45
  contextWindowTokens: 127_072,
38
46
  description: '基于搜索上下文的轻量级搜索产品,比 Sonar Pro 更快、更便宜。',
39
47
  displayName: 'Sonar',
package/src/config/llm.ts CHANGED
@@ -15,6 +15,10 @@ export const getLLMConfig = () => {
15
15
  AZURE_API_VERSION: z.string().optional(),
16
16
  AZURE_ENDPOINT: z.string().optional(),
17
17
 
18
+ ENABLED_AZUREAI: z.boolean(),
19
+ AZUREAI_ENDPOINT: z.string().optional(),
20
+ AZUREAI_ENDPOINT_KEY: z.string().optional(),
21
+
18
22
  ENABLED_ZHIPU: z.boolean(),
19
23
  ZHIPU_API_KEY: z.string().optional(),
20
24
 
@@ -155,6 +159,10 @@ export const getLLMConfig = () => {
155
159
  AZURE_API_VERSION: process.env.AZURE_API_VERSION,
156
160
  AZURE_ENDPOINT: process.env.AZURE_ENDPOINT,
157
161
 
162
+ ENABLED_AZUREAI: !!process.env.AZUREAI_ENDPOINT_KEY,
163
+ AZUREAI_ENDPOINT_KEY: process.env.AZUREAI_ENDPOINT_KEY,
164
+ AZUREAI_ENDPOINT: process.env.AZUREAI_ENDPOINT,
165
+
158
166
  ENABLED_ZHIPU: !!process.env.ZHIPU_API_KEY,
159
167
  ZHIPU_API_KEY: process.env.ZHIPU_API_KEY,
160
168
 
@@ -223,10 +223,7 @@
223
223
  "hash": "9646161fa041354714f823d726af27247bcd6e60fa3be5698c0d69f337a5700b"
224
224
  },
225
225
  {
226
- "sql": [
227
- "DROP TABLE \"user_budgets\";",
228
- "\nDROP TABLE \"user_subscriptions\";"
229
- ],
226
+ "sql": ["DROP TABLE \"user_budgets\";", "\nDROP TABLE \"user_subscriptions\";"],
230
227
  "bps": true,
231
228
  "folderMillis": 1729699958471,
232
229
  "hash": "7dad43a2a25d1aec82124a4e53f8d82f8505c3073f23606c1dc5d2a4598eacf9"
@@ -298,11 +295,18 @@
298
295
  "hash": "845a692ceabbfc3caf252a97d3e19a213bc0c433df2689900135f9cfded2cf49"
299
296
  },
300
297
  {
301
- "sql": [
302
- "ALTER TABLE \"messages\" ADD COLUMN \"reasoning\" jsonb;"
303
- ],
298
+ "sql": ["ALTER TABLE \"messages\" ADD COLUMN \"reasoning\" jsonb;"],
304
299
  "bps": true,
305
300
  "folderMillis": 1737609172353,
306
301
  "hash": "2cb36ae4fcdd7b7064767e04bfbb36ae34518ff4bb1b39006f2dd394d1893868"
302
+ },
303
+ {
304
+ "sql": [
305
+ "ALTER TABLE \"messages\" ADD COLUMN \"search\" jsonb;",
306
+ "\nALTER TABLE \"messages\" ADD COLUMN \"metadata\" jsonb;"
307
+ ],
308
+ "bps": true,
309
+ "folderMillis": 1739901891891,
310
+ "hash": "78d8fefd8c58938d7bc3da2295a73b35ce2e8d7cb2820f8e817acdb8dd5bebb2"
307
311
  }
308
- ]
312
+ ]
@@ -0,0 +1,2 @@
1
+ ALTER TABLE "messages" ADD COLUMN "search" jsonb;--> statement-breakpoint
2
+ ALTER TABLE "messages" ADD COLUMN "metadata" jsonb;