@lobehub/chat 1.108.0 → 1.108.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 (82) hide show
  1. package/.cursor/rules/testing-guide/testing-guide.mdc +18 -0
  2. package/CHANGELOG.md +58 -0
  3. package/README.md +3 -2
  4. package/README.zh-CN.md +3 -2
  5. package/changelog/v1.json +21 -0
  6. package/package.json +3 -3
  7. package/src/app/(backend)/trpc/desktop/[trpc]/route.ts +1 -1
  8. package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/Checker.tsx +15 -2
  9. package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/index.tsx +30 -3
  10. package/src/app/[variants]/layout.tsx +1 -0
  11. package/src/components/Analytics/LobeAnalyticsProvider.tsx +10 -13
  12. package/src/components/Analytics/LobeAnalyticsProviderWrapper.tsx +16 -4
  13. package/src/database/models/__tests__/_test_template.ts +1 -1
  14. package/src/database/models/__tests__/agent.test.ts +1 -1
  15. package/src/database/models/__tests__/aiModel.test.ts +1 -1
  16. package/src/database/models/__tests__/aiProvider.test.ts +1 -1
  17. package/src/database/models/__tests__/asyncTask.test.ts +1 -1
  18. package/src/database/models/__tests__/chunk.test.ts +1 -1
  19. package/src/database/models/__tests__/file.test.ts +1 -1
  20. package/src/database/models/__tests__/generationTopic.test.ts +1 -1
  21. package/src/database/models/__tests__/knowledgeBase.test.ts +1 -1
  22. package/src/database/models/__tests__/message.test.ts +1 -1
  23. package/src/database/models/__tests__/session.test.ts +1 -1
  24. package/src/database/models/__tests__/sessionGroup.test.ts +1 -1
  25. package/src/database/models/__tests__/topic.test.ts +1 -1
  26. package/src/database/models/_template.ts +1 -1
  27. package/src/database/models/agent.ts +1 -1
  28. package/src/database/models/aiModel.ts +1 -1
  29. package/src/database/models/aiProvider.ts +1 -1
  30. package/src/database/models/apiKey.ts +1 -1
  31. package/src/database/models/asyncTask.ts +1 -1
  32. package/src/database/models/chunk.ts +1 -2
  33. package/src/database/models/document.ts +1 -1
  34. package/src/database/models/embedding.ts +1 -2
  35. package/src/database/models/file.ts +1 -2
  36. package/src/database/models/generationTopic.ts +1 -1
  37. package/src/database/models/knowledgeBase.ts +1 -1
  38. package/src/database/models/message.ts +1 -2
  39. package/src/database/models/plugin.ts +1 -1
  40. package/src/database/models/session.ts +15 -2
  41. package/src/database/models/sessionGroup.ts +1 -1
  42. package/src/database/models/thread.ts +1 -1
  43. package/src/database/models/topic.ts +1 -2
  44. package/src/database/models/user.ts +1 -1
  45. package/src/database/repositories/dataExporter/index.ts +1 -1
  46. package/src/database/repositories/dataImporter/__tests__/index.test.ts +1 -1
  47. package/src/database/repositories/dataImporter/deprecated/__tests__/index.test.ts +1 -1
  48. package/src/database/repositories/dataImporter/deprecated/index.ts +1 -2
  49. package/src/database/repositories/dataImporter/index.ts +1 -1
  50. package/src/database/server/models/__tests__/adapter.test.ts +1 -1
  51. package/src/database/server/models/__tests__/nextauth.test.ts +1 -1
  52. package/src/database/server/models/__tests__/user.test.ts +1 -1
  53. package/src/database/server/models/ragEval/dataset.ts +1 -1
  54. package/src/database/server/models/ragEval/datasetRecord.ts +1 -1
  55. package/src/database/server/models/ragEval/evaluation.ts +1 -2
  56. package/src/database/server/models/ragEval/evaluationRecord.ts +1 -1
  57. package/src/database/utils/genWhere.ts +1 -2
  58. package/src/features/User/UserAvatar.tsx +18 -2
  59. package/src/libs/model-runtime/RouterRuntime/createRuntime.test.ts +538 -0
  60. package/src/libs/model-runtime/RouterRuntime/createRuntime.ts +50 -13
  61. package/src/libs/model-runtime/RouterRuntime/index.ts +1 -1
  62. package/src/libs/model-runtime/aihubmix/index.ts +10 -5
  63. package/src/libs/model-runtime/ppio/index.test.ts +3 -6
  64. package/src/libs/model-runtime/utils/openaiCompatibleFactory/index.ts +8 -6
  65. package/src/libs/next-auth/adapter/index.ts +1 -1
  66. package/src/libs/oidc-provider/adapter.ts +1 -2
  67. package/src/server/globalConfig/genServerAiProviderConfig.test.ts +22 -25
  68. package/src/server/globalConfig/genServerAiProviderConfig.ts +34 -22
  69. package/src/server/globalConfig/index.ts +1 -1
  70. package/src/server/routers/lambda/chunk.ts +1 -1
  71. package/src/server/services/discover/index.ts +11 -2
  72. package/src/services/chat.ts +1 -1
  73. package/src/services/session/client.test.ts +1 -1
  74. package/src/store/aiInfra/slices/aiProvider/__tests__/action.test.ts +211 -0
  75. package/src/store/aiInfra/slices/aiProvider/action.ts +46 -35
  76. package/src/store/user/slices/modelList/action.test.ts +5 -5
  77. package/src/store/user/slices/modelList/action.ts +4 -4
  78. package/src/styles/antdOverride.ts +6 -0
  79. package/src/utils/getFallbackModelProperty.test.ts +52 -45
  80. package/src/utils/getFallbackModelProperty.ts +4 -3
  81. package/src/utils/parseModels.test.ts +107 -98
  82. package/src/utils/parseModels.ts +10 -8
@@ -430,6 +430,22 @@ expect(result!.status).toBe('success');
430
430
  // ✅ 使用 any 类型简化复杂的 Mock 设置
431
431
  const mockStream = new ReadableStream() as any;
432
432
  mockStream.toReadableStream = () => mockStream;
433
+
434
+ // ✅ 使用中括号访问私有属性和方法(推荐)
435
+ class MyClass {
436
+ private _cache = new Map();
437
+ private getFromCache(key: string) { /* ... */ }
438
+ }
439
+
440
+ const instance = new MyClass();
441
+
442
+ // 推荐:使用中括号访问私有成员
443
+ await instance['getFromCache']('test-key');
444
+ expect(instance['_cache'].size).toBe(1);
445
+
446
+ // 避免:使用 as any 访问私有成员
447
+ await (instance as any).getFromCache('test-key'); // ❌ 不推荐
448
+ expect((instance as any)._cache.size).toBe(1); // ❌ 不推荐
433
449
  ```
434
450
 
435
451
  #### 🎯 适用场景
@@ -437,11 +453,13 @@ mockStream.toReadableStream = () => mockStream;
437
453
  - **Mock 对象**: 对于测试用的 Mock 数据,使用 `as any` 避免复杂的类型定义
438
454
  - **第三方库**: 处理复杂的第三方库类型时,适当使用 `any` 提高效率
439
455
  - **测试断言**: 在确定对象存在的测试场景中,使用 `!` 非空断言
456
+ - **私有成员访问**: 优先使用中括号 `instance['privateMethod']()` 而不是 `(instance as any).privateMethod()`
440
457
  - **临时调试**: 快速编写测试时,先用 `any` 保证功能,后续可选择性地优化类型
441
458
 
442
459
  #### ⚠️ 注意事项
443
460
 
444
461
  - **适度使用**: 不要过度依赖 `any`,核心业务逻辑的类型仍应保持严格
462
+ - **私有成员访问优先级**: 中括号访问 > `as any` 转换,保持更好的类型安全性
445
463
  - **文档说明**: 对于使用 `any` 的复杂场景,添加注释说明原因
446
464
  - **测试覆盖**: 确保即使使用了 `any`,测试仍能有效验证功能正确性
447
465
 
package/CHANGELOG.md CHANGED
@@ -2,6 +2,64 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.108.2](https://github.com/lobehub/lobe-chat/compare/v1.108.1...v1.108.2)
6
+
7
+ <sup>Released on **2025-08-05**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Provider config checker uses outdated API key.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Provider config checker uses outdated API key, closes [#8666](https://github.com/lobehub/lobe-chat/issues/8666) ([3a3e73e](https://github.com/lobehub/lobe-chat/commit/3a3e73e))
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.108.1](https://github.com/lobehub/lobe-chat/compare/v1.108.0...v1.108.1)
31
+
32
+ <sup>Released on **2025-08-05**</sup>
33
+
34
+ #### 🐛 Bug Fixes
35
+
36
+ - **misc**: Fix remote avatar broken in desktop.
37
+
38
+ #### 💄 Styles
39
+
40
+ - **misc**: Update mask style.
41
+
42
+ <br/>
43
+
44
+ <details>
45
+ <summary><kbd>Improvements and Fixes</kbd></summary>
46
+
47
+ #### What's fixed
48
+
49
+ - **misc**: Fix remote avatar broken in desktop, closes [#8673](https://github.com/lobehub/lobe-chat/issues/8673) ([7eae430](https://github.com/lobehub/lobe-chat/commit/7eae430))
50
+
51
+ #### Styles
52
+
53
+ - **misc**: Update mask style, closes [#8555](https://github.com/lobehub/lobe-chat/issues/8555) ([b4ac89d](https://github.com/lobehub/lobe-chat/commit/b4ac89d))
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.108.0](https://github.com/lobehub/lobe-chat/compare/v1.107.6...v1.108.0)
6
64
 
7
65
  <sup>Released on **2025-08-05**</sup>
package/README.md CHANGED
@@ -250,7 +250,7 @@ We have implemented support for the following model service providers:
250
250
  - **[HuggingFace](https://lobechat.com/discover/provider/huggingface)**: The HuggingFace Inference API provides a fast and free way for you to explore thousands of models for various tasks. Whether you are prototyping for a new application or experimenting with the capabilities of machine learning, this API gives you instant access to high-performance models across multiple domains.
251
251
  - **[Cloudflare Workers AI](https://lobechat.com/discover/provider/cloudflare)**: Run serverless GPU-powered machine learning models on Cloudflare's global network.
252
252
 
253
- <details><summary><kbd>See more providers (+31)</kbd></summary>
253
+ <details><summary><kbd>See more providers (+32)</kbd></summary>
254
254
 
255
255
  - **[GitHub](https://lobechat.com/discover/provider/github)**: With GitHub Models, developers can become AI engineers and leverage the industry's leading AI models.
256
256
  - **[Novita](https://lobechat.com/discover/provider/novita)**: Novita AI is a platform providing a variety of large language models and AI image generation API services, flexible, reliable, and cost-effective. It supports the latest open-source models like Llama3 and Mistral, offering a comprehensive, user-friendly, and auto-scaling API solution for generative AI application development, suitable for the rapid growth of AI startups.
@@ -283,10 +283,11 @@ We have implemented support for the following model service providers:
283
283
  - **[Search1API](https://lobechat.com/discover/provider/search1api)**: Search1API provides access to the DeepSeek series of models that can connect to the internet as needed, including standard and fast versions, supporting a variety of model sizes.
284
284
  - **[InfiniAI](https://lobechat.com/discover/provider/infiniai)**: Provides high-performance, easy-to-use, and secure large model services for application developers, covering the entire process from large model development to service deployment.
285
285
  - **[Qiniu](https://lobechat.com/discover/provider/qiniu)**: Qiniu, as a long-established cloud service provider, delivers cost-effective and reliable AI inference services for both real-time and batch processing, with a simple and user-friendly experience.
286
+ - **[302.AI](https://lobechat.com/discover/provider/ai302)**:
286
287
 
287
288
  </details>
288
289
 
289
- > 📊 Total providers: [<kbd>**41**</kbd>](https://lobechat.com/discover/providers)
290
+ > 📊 Total providers: [<kbd>**42**</kbd>](https://lobechat.com/discover/providers)
290
291
 
291
292
  <!-- PROVIDER LIST -->
292
293
 
package/README.zh-CN.md CHANGED
@@ -250,7 +250,7 @@ LobeChat 支持文件上传与知识库功能,你可以上传文件、图片
250
250
  - **[HuggingFace](https://lobechat.com/discover/provider/huggingface)**: HuggingFace Inference API 提供了一种快速且免费的方式,让您可以探索成千上万种模型,适用于各种任务。无论您是在为新应用程序进行原型设计,还是在尝试机器学习的功能,这个 API 都能让您即时访问多个领域的高性能模型。
251
251
  - **[Cloudflare Workers AI](https://lobechat.com/discover/provider/cloudflare)**: 在 Cloudflare 的全球网络上运行由无服务器 GPU 驱动的机器学习模型。
252
252
 
253
- <details><summary><kbd>See more providers (+31)</kbd></summary>
253
+ <details><summary><kbd>See more providers (+32)</kbd></summary>
254
254
 
255
255
  - **[GitHub](https://lobechat.com/discover/provider/github)**: 通过 GitHub 模型,开发人员可以成为 AI 工程师,并使用行业领先的 AI 模型进行构建。
256
256
  - **[Novita](https://lobechat.com/discover/provider/novita)**: Novita AI 是一个提供多种大语言模型与 AI 图像生成的 API 服务的平台,灵活、可靠且具有成本效益。它支持 Llama3、Mistral 等最新的开源模型,并为生成式 AI 应用开发提供了全面、用户友好且自动扩展的 API 解决方案,适合 AI 初创公司的快速发展。
@@ -283,10 +283,11 @@ LobeChat 支持文件上传与知识库功能,你可以上传文件、图片
283
283
  - **[Search1API](https://lobechat.com/discover/provider/search1api)**: Search1API 提供可根据需要自行联网的 DeepSeek 系列模型的访问,包括标准版和快速版本,支持多种参数规模的模型选择。
284
284
  - **[InfiniAI](https://lobechat.com/discover/provider/infiniai)**: 为应用开发者提供高性能、易上手、安全可靠的大模型服务,覆盖从大模型开发到大模型服务化部署的全流程。
285
285
  - **[Qiniu](https://lobechat.com/discover/provider/qiniu)**: 七牛作为老牌云服务厂商,提供高性价比稳定的实时、批量 AI 推理服务,简单易用。
286
+ - **[302.AI](https://lobechat.com/discover/provider/ai302)**:
286
287
 
287
288
  </details>
288
289
 
289
- > 📊 Total providers: [<kbd>**41**</kbd>](https://lobechat.com/discover/providers)
290
+ > 📊 Total providers: [<kbd>**42**</kbd>](https://lobechat.com/discover/providers)
290
291
 
291
292
  <!-- PROVIDER LIST -->
292
293
 
package/changelog/v1.json CHANGED
@@ -1,4 +1,25 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "fixes": [
5
+ "Provider config checker uses outdated API key."
6
+ ]
7
+ },
8
+ "date": "2025-08-05",
9
+ "version": "1.108.2"
10
+ },
11
+ {
12
+ "children": {
13
+ "fixes": [
14
+ "Fix remote avatar broken in desktop."
15
+ ],
16
+ "improvements": [
17
+ "Update mask style."
18
+ ]
19
+ },
20
+ "date": "2025-08-05",
21
+ "version": "1.108.1"
22
+ },
2
23
  {
3
24
  "children": {
4
25
  "features": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.108.0",
3
+ "version": "1.108.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",
@@ -146,7 +146,7 @@
146
146
  "@lobechat/electron-server-ipc": "workspace:*",
147
147
  "@lobechat/file-loaders": "workspace:*",
148
148
  "@lobechat/web-crawler": "workspace:*",
149
- "@lobehub/analytics": "^1.5.1",
149
+ "@lobehub/analytics": "^1.6.0",
150
150
  "@lobehub/charts": "^2.0.0",
151
151
  "@lobehub/chat-plugin-sdk": "^1.32.4",
152
152
  "@lobehub/chat-plugins-gateway": "^1.9.0",
@@ -182,7 +182,7 @@
182
182
  "debug": "^4.4.1",
183
183
  "dexie": "^3.2.7",
184
184
  "diff": "^7.0.0",
185
- "drizzle-orm": "^0.41.0",
185
+ "drizzle-orm": "^0.44.0",
186
186
  "drizzle-zod": "^0.5.1",
187
187
  "epub2": "^3.0.2",
188
188
  "fast-deep-equal": "^3.1.3",
@@ -15,7 +15,7 @@ const handler = (req: NextRequest) =>
15
15
  endpoint: '/trpc/desktop',
16
16
 
17
17
  onError: ({ error, path, type }) => {
18
- pino.info(`Error in tRPC handler (tools) on path: ${path}, type: ${type}`);
18
+ pino.info(`Error in tRPC handler (desktop) on path: ${path}, type: ${type}`);
19
19
  console.error(error);
20
20
  },
21
21
 
@@ -46,11 +46,13 @@ export type CheckErrorRender = (props: {
46
46
  interface ConnectionCheckerProps {
47
47
  checkErrorRender?: CheckErrorRender;
48
48
  model: string;
49
+ onAfterCheck: () => Promise<void>;
50
+ onBeforeCheck: () => Promise<void>;
49
51
  provider: string;
50
52
  }
51
53
 
52
54
  const Checker = memo<ConnectionCheckerProps>(
53
- ({ model, provider, checkErrorRender: CheckErrorRender }) => {
55
+ ({ model, provider, checkErrorRender: CheckErrorRender, onBeforeCheck, onAfterCheck }) => {
54
56
  const { t } = useTranslation('setting');
55
57
 
56
58
  const isProviderConfigUpdating = useAiInfraStore(
@@ -152,7 +154,18 @@ const Checker = memo<ConnectionCheckerProps>(
152
154
  value={checkModel}
153
155
  virtual
154
156
  />
155
- <Button disabled={isProviderConfigUpdating} loading={loading} onClick={checkConnection}>
157
+ <Button
158
+ disabled={isProviderConfigUpdating}
159
+ loading={loading}
160
+ onClick={async () => {
161
+ await onBeforeCheck();
162
+ try {
163
+ await checkConnection();
164
+ } finally {
165
+ await onAfterCheck();
166
+ }
167
+ }}
168
+ >
156
169
  {t('llm.checker.button')}
157
170
  </Button>
158
171
  </Flexbox>
@@ -14,7 +14,7 @@ import { Skeleton, Switch } from 'antd';
14
14
  import { createStyles } from 'antd-style';
15
15
  import { Loader2Icon, LockIcon } from 'lucide-react';
16
16
  import Link from 'next/link';
17
- import { ReactNode, memo, useLayoutEffect } from 'react';
17
+ import { ReactNode, memo, useCallback, useLayoutEffect, useRef } from 'react';
18
18
  import { Trans, useTranslation } from 'react-i18next';
19
19
  import { Center, Flexbox } from 'react-layout-kit';
20
20
  import urlJoin from 'url-join';
@@ -173,7 +173,24 @@ const ProviderConfig = memo<ProviderConfigProps>(
173
173
  form.setFieldsValue(data);
174
174
  }, [isLoading, id, data]);
175
175
 
176
- const { run: debouncedUpdate } = useDebounceFn(updateAiProviderConfig, { wait: 500 });
176
+ // 标记是否正在进行连接测试
177
+ const isCheckingConnection = useRef(false);
178
+
179
+ const handleValueChange = useCallback(
180
+ (...params: Parameters<typeof updateAiProviderConfig>) => {
181
+ // 虽然 debouncedHandleValueChange 早于 onBeforeCheck 执行,
182
+ // 但是由于 debouncedHandleValueChange 因为 debounce 的原因,本来就会晚 500ms 执行
183
+ // 所以 isCheckingConnection.current 这时候已经更新了
184
+ // 测试链接时已经出发一次了 updateAiProviderConfig , 不应该重复更新
185
+ if (isCheckingConnection.current) return;
186
+
187
+ updateAiProviderConfig(...params);
188
+ },
189
+ [updateAiProviderConfig],
190
+ );
191
+ const { run: debouncedHandleValueChange } = useDebounceFn(handleValueChange, {
192
+ wait: 500,
193
+ });
177
194
 
178
195
  const isCustom = source === AiProviderSourceEnum.Custom;
179
196
 
@@ -318,6 +335,16 @@ const ProviderConfig = memo<ProviderConfigProps>(
318
335
  <Checker
319
336
  checkErrorRender={checkErrorRender}
320
337
  model={data?.checkModel || checkModel!}
338
+ onAfterCheck={async () => {
339
+ // 重置连接测试状态,允许后续的 onValuesChange 更新
340
+ isCheckingConnection.current = false;
341
+ }}
342
+ onBeforeCheck={async () => {
343
+ // 设置连接测试状态,阻止 onValuesChange 的重复请求
344
+ isCheckingConnection.current = true;
345
+ // 主动保存表单最新值,确保 fetchAiProviderRuntimeState 获取最新数据
346
+ await updateAiProviderConfig(id, form.getFieldsValue());
347
+ }}
321
348
  provider={id}
322
349
  />
323
350
  ),
@@ -389,7 +416,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
389
416
  form={form}
390
417
  items={[model]}
391
418
  onValuesChange={(_, values) => {
392
- debouncedUpdate(id, values);
419
+ debouncedHandleValueChange(id, values);
393
420
  }}
394
421
  variant={'borderless'}
395
422
  {...FORM_STYLE}
@@ -34,6 +34,7 @@ const RootLayout = async ({ children, params, modal }: RootLayoutProps) => {
34
34
  <html dir={direction} lang={locale} suppressHydrationWarning>
35
35
  <head>
36
36
  {process.env.DEBUG_REACT_SCAN === '1' && (
37
+ // eslint-disable-next-line @next/next/no-sync-scripts
37
38
  <script crossOrigin="anonymous" src="https://unpkg.com/react-scan/dist/auto.global.js" />
38
39
  )}
39
40
  </head>
@@ -1,6 +1,10 @@
1
1
  'use client';
2
2
 
3
- import { createSingletonAnalytics } from '@lobehub/analytics';
3
+ import {
4
+ GoogleAnalyticsProviderConfig,
5
+ PostHogProviderAnalyticsConfig,
6
+ createSingletonAnalytics,
7
+ } from '@lobehub/analytics';
4
8
  import { AnalyticsProvider } from '@lobehub/analytics/react';
5
9
  import { ReactNode, memo, useMemo } from 'react';
6
10
 
@@ -10,16 +14,14 @@ import { isDev } from '@/utils/env';
10
14
 
11
15
  type Props = {
12
16
  children: ReactNode;
13
- debugPosthog: boolean;
14
- posthogEnabled: boolean;
15
- posthogHost: string;
16
- posthogToken: string;
17
+ ga4Config: GoogleAnalyticsProviderConfig;
18
+ postHogConfig: PostHogProviderAnalyticsConfig;
17
19
  };
18
20
 
19
21
  let analyticsInstance: ReturnType<typeof createSingletonAnalytics> | null = null;
20
22
 
21
23
  export const LobeAnalyticsProvider = memo(
22
- ({ children, posthogHost, posthogToken, posthogEnabled, debugPosthog }: Props) => {
24
+ ({ children, ga4Config, postHogConfig }: Props) => {
23
25
  const analytics = useMemo(() => {
24
26
  if (analyticsInstance) {
25
27
  return analyticsInstance;
@@ -29,13 +31,8 @@ export const LobeAnalyticsProvider = memo(
29
31
  business: BUSINESS_LINE,
30
32
  debug: isDev,
31
33
  providers: {
32
- posthog: {
33
- debug: debugPosthog,
34
- enabled: posthogEnabled,
35
- host: posthogHost,
36
- key: posthogToken,
37
- person_profiles: 'always',
38
- },
34
+ ga4: ga4Config,
35
+ posthog: postHogConfig,
39
36
  },
40
37
  });
41
38
 
@@ -2,6 +2,7 @@ import { ReactNode, memo } from 'react';
2
2
 
3
3
  import { LobeAnalyticsProvider } from '@/components/Analytics/LobeAnalyticsProvider';
4
4
  import { analyticsEnv } from '@/config/analytics';
5
+ import { isDev } from '@/utils/env';
5
6
 
6
7
  type Props = {
7
8
  children: ReactNode;
@@ -10,10 +11,21 @@ type Props = {
10
11
  export const LobeAnalyticsProviderWrapper = memo<Props>(({ children }) => {
11
12
  return (
12
13
  <LobeAnalyticsProvider
13
- debugPosthog={analyticsEnv.DEBUG_POSTHOG_ANALYTICS}
14
- posthogEnabled={analyticsEnv.ENABLED_POSTHOG_ANALYTICS}
15
- posthogHost={analyticsEnv.POSTHOG_HOST}
16
- posthogToken={analyticsEnv.POSTHOG_KEY ?? ''}
14
+ ga4Config={{
15
+ debug: isDev,
16
+ enabled: analyticsEnv.ENABLE_GOOGLE_ANALYTICS,
17
+ gtagConfig: {
18
+ debug_mode: isDev,
19
+ },
20
+ measurementId: analyticsEnv.GOOGLE_ANALYTICS_MEASUREMENT_ID ?? '',
21
+ }}
22
+ postHogConfig={{
23
+ debug: analyticsEnv.DEBUG_POSTHOG_ANALYTICS,
24
+ enabled: analyticsEnv.ENABLED_POSTHOG_ANALYTICS,
25
+ host: analyticsEnv.POSTHOG_HOST,
26
+ key: analyticsEnv.POSTHOG_KEY ?? '',
27
+ person_profiles: 'always',
28
+ }}
17
29
  >
18
30
  {children}
19
31
  </LobeAnalyticsProvider>
@@ -1,5 +1,5 @@
1
1
  // @vitest-environment node
2
- import { eq } from 'drizzle-orm/expressions';
2
+ import { eq } from 'drizzle-orm';
3
3
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
4
4
 
5
5
  import { LobeChatDatabase } from '@/database/type';
@@ -1,5 +1,5 @@
1
1
  // @vitest-environment node
2
- import { eq } from 'drizzle-orm/expressions';
2
+ import { eq } from 'drizzle-orm';
3
3
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
4
4
 
5
5
  import { LobeChatDatabase } from '@/database/type';
@@ -1,5 +1,5 @@
1
1
  // @vitest-environment node
2
- import { eq } from 'drizzle-orm/expressions';
2
+ import { eq } from 'drizzle-orm';
3
3
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
4
4
 
5
5
  import { LobeChatDatabase } from '@/database/type';
@@ -1,5 +1,5 @@
1
1
  // @vitest-environment node
2
- import { eq } from 'drizzle-orm/expressions';
2
+ import { eq } from 'drizzle-orm';
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
 
5
5
  import { LobeChatDatabase } from '@/database/type';
@@ -1,5 +1,5 @@
1
1
  // @vitest-environment node
2
- import { eq } from 'drizzle-orm/expressions';
2
+ import { eq } from 'drizzle-orm';
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
 
5
5
  import { LobeChatDatabase } from '@/database/type';
@@ -1,5 +1,5 @@
1
1
  // @vitest-environment node
2
- import { eq } from 'drizzle-orm/expressions';
2
+ import { eq } from 'drizzle-orm';
3
3
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
4
4
 
5
5
  import { LobeChatDatabase } from '@/database/type';
@@ -1,5 +1,5 @@
1
1
  // @vitest-environment node
2
- import { eq, inArray } from 'drizzle-orm/expressions';
2
+ import { eq, inArray } from 'drizzle-orm';
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
 
5
5
  import { LobeChatDatabase } from '@/database/type';
@@ -1,5 +1,5 @@
1
1
  // @vitest-environment node
2
- import { eq } from 'drizzle-orm/expressions';
2
+ import { eq } from 'drizzle-orm';
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
 
5
5
  import { LobeChatDatabase } from '@/database/type';
@@ -1,5 +1,5 @@
1
1
  // @vitest-environment node
2
- import { and, eq } from 'drizzle-orm/expressions';
2
+ import { and, eq } from 'drizzle-orm';
3
3
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
4
4
 
5
5
  import { LobeChatDatabase } from '@/database/type';
@@ -1,5 +1,5 @@
1
1
  import dayjs from 'dayjs';
2
- import { eq } from 'drizzle-orm/expressions';
2
+ import { eq } from 'drizzle-orm';
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
 
5
5
  import { getTestDB } from '@/database/models/__tests__/_util';
@@ -1,4 +1,4 @@
1
- import { and, eq, inArray } from 'drizzle-orm/expressions';
1
+ import { and, eq, inArray } from 'drizzle-orm';
2
2
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
3
 
4
4
  import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
@@ -1,5 +1,5 @@
1
1
  // @vitest-environment node
2
- import { eq } from 'drizzle-orm/expressions';
2
+ import { eq } from 'drizzle-orm';
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
 
5
5
  import { LobeChatDatabase } from '@/database/type';
@@ -1,4 +1,4 @@
1
- import { eq, inArray } from 'drizzle-orm/expressions';
1
+ import { eq, inArray } from 'drizzle-orm';
2
2
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
3
 
4
4
  import { LobeChatDatabase } from '@/database/type';
@@ -1,4 +1,4 @@
1
- import { and, desc, eq } from 'drizzle-orm/expressions';
1
+ import { and, desc, eq } from 'drizzle-orm';
2
2
 
3
3
  import { LobeChatDatabase } from '@/database/type';
4
4
 
@@ -1,4 +1,4 @@
1
- import { and, desc, eq, inArray } from 'drizzle-orm/expressions';
1
+ import { and, desc, eq, inArray } from 'drizzle-orm';
2
2
 
3
3
  import {
4
4
  agents,
@@ -1,4 +1,4 @@
1
- import { and, asc, desc, eq, inArray } from 'drizzle-orm/expressions';
1
+ import { and, asc, desc, eq, inArray } from 'drizzle-orm';
2
2
 
3
3
  import { LobeChatDatabase } from '@/database/type';
4
4
  import {
@@ -1,4 +1,4 @@
1
- import { and, asc, desc, eq } from 'drizzle-orm/expressions';
1
+ import { and, asc, desc, eq } from 'drizzle-orm';
2
2
  import { isEmpty } from 'lodash-es';
3
3
 
4
4
  import { DEFAULT_MODEL_PROVIDER_LIST } from '@/config/modelProviders';
@@ -1,4 +1,4 @@
1
- import { and, desc, eq } from 'drizzle-orm/expressions';
1
+ import { and, desc, eq } from 'drizzle-orm';
2
2
 
3
3
  import { LobeChatDatabase } from '@/database/type';
4
4
  import { generateApiKey, isApiKeyExpired, validateApiKeyFormat } from '@/utils/apiKey';
@@ -1,4 +1,4 @@
1
- import { and, eq, inArray, lt } from 'drizzle-orm/expressions';
1
+ import { and, eq, inArray, lt } from 'drizzle-orm';
2
2
 
3
3
  import { LobeChatDatabase } from '@/database/type';
4
4
  import {
@@ -1,5 +1,4 @@
1
- import { cosineDistance, count, sql } from 'drizzle-orm';
2
- import { and, asc, desc, eq, inArray, isNull } from 'drizzle-orm/expressions';
1
+ import { and, asc, cosineDistance, count, desc, eq, inArray, isNull, sql } from 'drizzle-orm';
3
2
  import { chunk } from 'lodash-es';
4
3
 
5
4
  import { LobeChatDatabase } from '@/database/type';
@@ -1,4 +1,4 @@
1
- import { and, desc, eq } from 'drizzle-orm/expressions';
1
+ import { and, desc, eq } from 'drizzle-orm';
2
2
 
3
3
  import { LobeChatDatabase } from '@/database/type';
4
4
 
@@ -1,5 +1,4 @@
1
- import { count } from 'drizzle-orm';
2
- import { and, eq } from 'drizzle-orm/expressions';
1
+ import { and, count, eq } from 'drizzle-orm';
3
2
 
4
3
  import { LobeChatDatabase } from '@/database/type';
5
4
 
@@ -1,5 +1,4 @@
1
- import { count, sum } from 'drizzle-orm';
2
- import { and, asc, desc, eq, ilike, inArray, like, notExists, or } from 'drizzle-orm/expressions';
1
+ import { and, asc, count, desc, eq, ilike, inArray, like, notExists, or, sum } from 'drizzle-orm';
3
2
  import type { PgTransaction } from 'drizzle-orm/pg-core';
4
3
 
5
4
  import { LobeChatDatabase, Transaction } from '@/database/type';
@@ -1,4 +1,4 @@
1
- import { and, desc, eq } from 'drizzle-orm/expressions';
1
+ import { and, desc, eq } from 'drizzle-orm';
2
2
 
3
3
  import { LobeChatDatabase } from '@/database/type';
4
4
  import { FileService } from '@/server/services/file';
@@ -1,4 +1,4 @@
1
- import { and, desc, eq, inArray } from 'drizzle-orm/expressions';
1
+ import { and, desc, eq, inArray } from 'drizzle-orm';
2
2
 
3
3
  import { LobeChatDatabase } from '@/database/type';
4
4
  import { KnowledgeBaseItem } from '@/types/knowledgeBase';
@@ -1,7 +1,6 @@
1
1
  import type { HeatmapsProps } from '@lobehub/charts';
2
2
  import dayjs from 'dayjs';
3
- import { count, sql } from 'drizzle-orm';
4
- import { and, asc, desc, eq, gt, inArray, isNotNull, isNull, like } from 'drizzle-orm/expressions';
3
+ import { and, asc, count, desc, eq, gt, inArray, isNotNull, isNull, like, sql } from 'drizzle-orm';
5
4
 
6
5
  import { LobeChatDatabase } from '@/database/type';
7
6
  import {
@@ -1,4 +1,4 @@
1
- import { and, desc, eq } from 'drizzle-orm/expressions';
1
+ import { and, desc, eq } from 'drizzle-orm';
2
2
 
3
3
  import { LobeChatDatabase } from '@/database/type';
4
4
  import { LobeTool } from '@/types/tool';
@@ -1,5 +1,18 @@
1
- import { Column, count, sql } from 'drizzle-orm';
2
- import { and, asc, desc, eq, gt, inArray, isNull, like, not, or } from 'drizzle-orm/expressions';
1
+ import {
2
+ Column,
3
+ and,
4
+ asc,
5
+ count,
6
+ desc,
7
+ eq,
8
+ gt,
9
+ inArray,
10
+ isNull,
11
+ like,
12
+ not,
13
+ or,
14
+ sql,
15
+ } from 'drizzle-orm';
3
16
  import type { PartialDeep } from 'type-fest';
4
17
 
5
18
  import { DEFAULT_INBOX_AVATAR } from '@/const/meta';
@@ -1,4 +1,4 @@
1
- import { and, asc, desc, eq } from 'drizzle-orm/expressions';
1
+ import { and, asc, desc, eq } from 'drizzle-orm';
2
2
 
3
3
  import { LobeChatDatabase } from '@/database/type';
4
4
  import { idGenerator } from '@/database/utils/idGenerator';