@lobehub/chat 1.98.2 → 1.99.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.
- package/.cursor/rules/backend-architecture.mdc +93 -17
- package/.cursor/rules/cursor-ux.mdc +45 -35
- package/.cursor/rules/project-introduce.mdc +72 -6
- package/.cursor/rules/rules-attach.mdc +16 -7
- package/.eslintrc.js +10 -0
- package/CHANGELOG.md +27 -0
- package/apps/desktop/README.md +7 -0
- package/apps/desktop/electron-builder.js +5 -0
- package/apps/desktop/package.json +2 -1
- package/apps/desktop/src/main/const/dir.ts +3 -0
- package/apps/desktop/src/main/controllers/UploadFileCtr.ts +13 -8
- package/apps/desktop/src/main/core/App.ts +8 -0
- package/apps/desktop/src/main/core/StaticFileServerManager.ts +221 -0
- package/apps/desktop/src/main/services/fileSrv.ts +231 -44
- package/apps/desktop/src/main/utils/next-electron-rsc.ts +36 -5
- package/changelog/v1.json +9 -0
- package/docs/development/database-schema.dbml +70 -0
- package/locales/ar/common.json +2 -0
- package/locales/ar/components.json +35 -0
- package/locales/ar/error.json +2 -0
- package/locales/ar/image.json +100 -0
- package/locales/ar/metadata.json +4 -0
- package/locales/ar/modelProvider.json +1 -0
- package/locales/ar/models.json +15 -0
- package/locales/ar/plugin.json +22 -0
- package/locales/ar/providers.json +3 -0
- package/locales/ar/setting.json +5 -0
- package/locales/bg-BG/common.json +2 -0
- package/locales/bg-BG/components.json +35 -0
- package/locales/bg-BG/error.json +2 -0
- package/locales/bg-BG/image.json +100 -0
- package/locales/bg-BG/metadata.json +4 -0
- package/locales/bg-BG/modelProvider.json +1 -0
- package/locales/bg-BG/models.json +15 -0
- package/locales/bg-BG/plugin.json +22 -0
- package/locales/bg-BG/providers.json +3 -0
- package/locales/bg-BG/setting.json +5 -0
- package/locales/de-DE/common.json +2 -0
- package/locales/de-DE/components.json +35 -0
- package/locales/de-DE/error.json +2 -0
- package/locales/de-DE/image.json +100 -0
- package/locales/de-DE/metadata.json +4 -0
- package/locales/de-DE/modelProvider.json +1 -0
- package/locales/de-DE/models.json +15 -0
- package/locales/de-DE/plugin.json +22 -0
- package/locales/de-DE/providers.json +3 -0
- package/locales/de-DE/setting.json +5 -0
- package/locales/en-US/common.json +2 -0
- package/locales/en-US/components.json +35 -0
- package/locales/en-US/error.json +2 -0
- package/locales/en-US/image.json +100 -0
- package/locales/en-US/metadata.json +4 -0
- package/locales/en-US/modelProvider.json +1 -0
- package/locales/en-US/models.json +15 -0
- package/locales/en-US/plugin.json +22 -0
- package/locales/en-US/providers.json +3 -0
- package/locales/en-US/setting.json +5 -0
- package/locales/es-ES/common.json +2 -0
- package/locales/es-ES/components.json +35 -0
- package/locales/es-ES/error.json +2 -0
- package/locales/es-ES/image.json +100 -0
- package/locales/es-ES/metadata.json +4 -0
- package/locales/es-ES/modelProvider.json +1 -0
- package/locales/es-ES/models.json +15 -0
- package/locales/es-ES/plugin.json +22 -0
- package/locales/es-ES/providers.json +3 -0
- package/locales/es-ES/setting.json +5 -0
- package/locales/fa-IR/common.json +2 -0
- package/locales/fa-IR/components.json +35 -0
- package/locales/fa-IR/error.json +2 -0
- package/locales/fa-IR/image.json +100 -0
- package/locales/fa-IR/metadata.json +4 -0
- package/locales/fa-IR/modelProvider.json +1 -0
- package/locales/fa-IR/models.json +15 -0
- package/locales/fa-IR/plugin.json +22 -0
- package/locales/fa-IR/providers.json +3 -0
- package/locales/fa-IR/setting.json +5 -0
- package/locales/fr-FR/common.json +2 -0
- package/locales/fr-FR/components.json +35 -0
- package/locales/fr-FR/error.json +2 -0
- package/locales/fr-FR/image.json +100 -0
- package/locales/fr-FR/metadata.json +4 -0
- package/locales/fr-FR/modelProvider.json +1 -0
- package/locales/fr-FR/models.json +15 -0
- package/locales/fr-FR/plugin.json +22 -0
- package/locales/fr-FR/providers.json +3 -0
- package/locales/fr-FR/setting.json +5 -0
- package/locales/it-IT/common.json +2 -0
- package/locales/it-IT/components.json +35 -0
- package/locales/it-IT/error.json +2 -0
- package/locales/it-IT/image.json +100 -0
- package/locales/it-IT/metadata.json +4 -0
- package/locales/it-IT/modelProvider.json +1 -0
- package/locales/it-IT/models.json +15 -0
- package/locales/it-IT/plugin.json +22 -0
- package/locales/it-IT/providers.json +3 -0
- package/locales/it-IT/setting.json +5 -0
- package/locales/ja-JP/common.json +2 -0
- package/locales/ja-JP/components.json +35 -0
- package/locales/ja-JP/error.json +2 -0
- package/locales/ja-JP/image.json +100 -0
- package/locales/ja-JP/metadata.json +4 -0
- package/locales/ja-JP/modelProvider.json +1 -0
- package/locales/ja-JP/models.json +15 -0
- package/locales/ja-JP/plugin.json +22 -0
- package/locales/ja-JP/providers.json +3 -0
- package/locales/ja-JP/setting.json +5 -0
- package/locales/ko-KR/common.json +2 -0
- package/locales/ko-KR/components.json +35 -0
- package/locales/ko-KR/error.json +2 -0
- package/locales/ko-KR/image.json +100 -0
- package/locales/ko-KR/metadata.json +4 -0
- package/locales/ko-KR/modelProvider.json +1 -0
- package/locales/ko-KR/models.json +15 -0
- package/locales/ko-KR/plugin.json +22 -0
- package/locales/ko-KR/providers.json +3 -0
- package/locales/ko-KR/setting.json +5 -0
- package/locales/nl-NL/common.json +2 -0
- package/locales/nl-NL/components.json +35 -0
- package/locales/nl-NL/error.json +2 -0
- package/locales/nl-NL/image.json +100 -0
- package/locales/nl-NL/metadata.json +4 -0
- package/locales/nl-NL/modelProvider.json +1 -0
- package/locales/nl-NL/models.json +15 -0
- package/locales/nl-NL/plugin.json +22 -0
- package/locales/nl-NL/providers.json +3 -0
- package/locales/nl-NL/setting.json +5 -0
- package/locales/pl-PL/common.json +2 -0
- package/locales/pl-PL/components.json +35 -0
- package/locales/pl-PL/error.json +2 -0
- package/locales/pl-PL/image.json +100 -0
- package/locales/pl-PL/metadata.json +4 -0
- package/locales/pl-PL/modelProvider.json +1 -0
- package/locales/pl-PL/models.json +15 -0
- package/locales/pl-PL/plugin.json +22 -0
- package/locales/pl-PL/providers.json +3 -0
- package/locales/pl-PL/setting.json +5 -0
- package/locales/pt-BR/common.json +2 -0
- package/locales/pt-BR/components.json +35 -0
- package/locales/pt-BR/error.json +2 -0
- package/locales/pt-BR/image.json +100 -0
- package/locales/pt-BR/metadata.json +4 -0
- package/locales/pt-BR/modelProvider.json +1 -0
- package/locales/pt-BR/models.json +15 -0
- package/locales/pt-BR/plugin.json +22 -0
- package/locales/pt-BR/providers.json +3 -0
- package/locales/pt-BR/setting.json +5 -0
- package/locales/ru-RU/common.json +2 -0
- package/locales/ru-RU/components.json +35 -0
- package/locales/ru-RU/error.json +2 -0
- package/locales/ru-RU/image.json +100 -0
- package/locales/ru-RU/metadata.json +4 -0
- package/locales/ru-RU/modelProvider.json +1 -0
- package/locales/ru-RU/models.json +15 -0
- package/locales/ru-RU/plugin.json +22 -0
- package/locales/ru-RU/providers.json +3 -0
- package/locales/ru-RU/setting.json +5 -0
- package/locales/tr-TR/common.json +2 -0
- package/locales/tr-TR/components.json +35 -0
- package/locales/tr-TR/error.json +2 -0
- package/locales/tr-TR/image.json +100 -0
- package/locales/tr-TR/metadata.json +4 -0
- package/locales/tr-TR/modelProvider.json +1 -0
- package/locales/tr-TR/models.json +15 -0
- package/locales/tr-TR/plugin.json +22 -0
- package/locales/tr-TR/providers.json +3 -0
- package/locales/tr-TR/setting.json +5 -0
- package/locales/vi-VN/common.json +2 -0
- package/locales/vi-VN/components.json +35 -0
- package/locales/vi-VN/error.json +2 -0
- package/locales/vi-VN/image.json +100 -0
- package/locales/vi-VN/metadata.json +4 -0
- package/locales/vi-VN/modelProvider.json +1 -0
- package/locales/vi-VN/models.json +15 -0
- package/locales/vi-VN/plugin.json +22 -0
- package/locales/vi-VN/providers.json +3 -0
- package/locales/vi-VN/setting.json +5 -0
- package/locales/zh-CN/common.json +2 -0
- package/locales/zh-CN/components.json +35 -0
- package/locales/zh-CN/error.json +2 -0
- package/locales/zh-CN/image.json +100 -0
- package/locales/zh-CN/metadata.json +4 -0
- package/locales/zh-CN/modelProvider.json +1 -0
- package/locales/zh-CN/models.json +15 -0
- package/locales/zh-CN/plugin.json +22 -0
- package/locales/zh-CN/providers.json +3 -0
- package/locales/zh-CN/setting.json +5 -0
- package/locales/zh-TW/common.json +2 -0
- package/locales/zh-TW/components.json +35 -0
- package/locales/zh-TW/error.json +2 -0
- package/locales/zh-TW/image.json +100 -0
- package/locales/zh-TW/metadata.json +4 -0
- package/locales/zh-TW/modelProvider.json +1 -0
- package/locales/zh-TW/models.json +15 -0
- package/locales/zh-TW/plugin.json +22 -0
- package/locales/zh-TW/providers.json +3 -0
- package/locales/zh-TW/setting.json +5 -0
- package/package.json +11 -4
- package/packages/electron-server-ipc/src/events/file.ts +3 -1
- package/packages/electron-server-ipc/src/types/file.ts +15 -0
- package/src/app/[variants]/(main)/_layout/Desktop/SideBar/TopActions.tsx +11 -1
- package/src/app/[variants]/(main)/image/@menu/components/AspectRatioSelect/index.tsx +73 -0
- package/src/app/[variants]/(main)/image/@menu/components/SeedNumberInput/index.tsx +39 -0
- package/src/app/[variants]/(main)/image/@menu/components/SizeSelect/index.tsx +89 -0
- package/src/app/[variants]/(main)/image/@menu/default.tsx +11 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/AspectRatioSelect.tsx +24 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/DimensionControlGroup.tsx +107 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/ImageNum.tsx +290 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/ImageUpload.tsx +504 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/ImageUrl.tsx +18 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/ImageUrlsUpload.tsx +19 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/ModelSelect.tsx +155 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/MultiImagesUpload/ImageManageModal.tsx +415 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/MultiImagesUpload/index.tsx +732 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/SeedNumberInput.tsx +24 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/SizeSelect.tsx +17 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/SizeSliderInput.tsx +15 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/StepsSliderInput.tsx +11 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/constants.ts +1 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/index.tsx +93 -0
- package/src/app/[variants]/(main)/image/@topic/default.tsx +17 -0
- package/src/app/[variants]/(main)/image/@topic/features/Topics/NewTopicButton.tsx +64 -0
- package/src/app/[variants]/(main)/image/@topic/features/Topics/SkeletonList.tsx +34 -0
- package/src/app/[variants]/(main)/image/@topic/features/Topics/TopicItem.tsx +136 -0
- package/src/app/[variants]/(main)/image/@topic/features/Topics/TopicItemContainer.tsx +91 -0
- package/src/app/[variants]/(main)/image/@topic/features/Topics/TopicList.tsx +57 -0
- package/src/app/[variants]/(main)/image/@topic/features/Topics/TopicUrlSync.tsx +37 -0
- package/src/app/[variants]/(main)/image/@topic/features/Topics/index.tsx +19 -0
- package/src/app/[variants]/(main)/image/NotSupportClient.tsx +153 -0
- package/src/app/[variants]/(main)/image/_layout/Desktop/Container.tsx +35 -0
- package/src/app/[variants]/(main)/image/_layout/Desktop/RegisterHotkeys.tsx +10 -0
- package/src/app/[variants]/(main)/image/_layout/Desktop/index.tsx +30 -0
- package/src/app/[variants]/(main)/image/_layout/Mobile/index.tsx +14 -0
- package/src/app/[variants]/(main)/image/_layout/type.ts +7 -0
- package/src/app/[variants]/(main)/image/features/GenerationFeed/BatchItem.tsx +196 -0
- package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/ActionButtons.tsx +60 -0
- package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/ElapsedTime.tsx +90 -0
- package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/ErrorState.tsx +65 -0
- package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/LoadingState.tsx +43 -0
- package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/SuccessState.tsx +49 -0
- package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/index.tsx +156 -0
- package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/styles.ts +51 -0
- package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/types.ts +39 -0
- package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/utils.ts +11 -0
- package/src/app/[variants]/(main)/image/features/GenerationFeed/index.tsx +97 -0
- package/src/app/[variants]/(main)/image/features/ImageWorkspace/Content.tsx +48 -0
- package/src/app/[variants]/(main)/image/features/ImageWorkspace/EmptyState.tsx +37 -0
- package/src/app/[variants]/(main)/image/features/ImageWorkspace/SkeletonList.tsx +50 -0
- package/src/app/[variants]/(main)/image/features/ImageWorkspace/index.tsx +23 -0
- package/src/app/[variants]/(main)/image/features/PromptInput/Title.tsx +38 -0
- package/src/app/[variants]/(main)/image/features/PromptInput/index.tsx +114 -0
- package/src/app/[variants]/(main)/image/layout.tsx +19 -0
- package/src/app/[variants]/(main)/image/loading.tsx +3 -0
- package/src/app/[variants]/(main)/image/page.tsx +47 -0
- package/src/app/[variants]/(main)/settings/system-agent/index.tsx +2 -1
- package/src/chains/summaryGenerationTitle.ts +25 -0
- package/src/components/ImageItem/index.tsx +9 -6
- package/src/{features/Conversation/Error → components/InvalidAPIKey}/APIKeyForm/Bedrock.tsx +3 -4
- package/src/{features/Conversation/Error → components/InvalidAPIKey}/APIKeyForm/ProviderApiKeyForm.tsx +5 -4
- package/src/components/InvalidAPIKey/APIKeyForm/index.tsx +108 -0
- package/src/{features/Conversation/Error → components/InvalidAPIKey}/APIKeyForm/useApiKey.ts +2 -1
- package/src/components/InvalidAPIKey/index.tsx +30 -0
- package/src/components/KeyValueEditor/index.tsx +203 -0
- package/src/components/KeyValueEditor/utils.ts +42 -0
- package/src/config/aiModels/fal.ts +52 -0
- package/src/config/aiModels/index.ts +3 -0
- package/src/config/aiModels/openai.ts +20 -6
- package/src/config/llm.ts +6 -0
- package/src/config/modelProviders/fal.ts +21 -0
- package/src/config/modelProviders/index.ts +3 -0
- package/src/config/paramsSchemas/fal/flux-kontext-dev.ts +8 -0
- package/src/config/paramsSchemas/fal/flux-pro-kontext.ts +11 -0
- package/src/config/paramsSchemas/fal/flux-schnell.ts +9 -0
- package/src/config/paramsSchemas/fal/imagen4.ts +10 -0
- package/src/config/paramsSchemas/openai/gpt-image-1.ts +10 -0
- package/src/const/hotkeys.ts +2 -2
- package/src/const/image.ts +6 -0
- package/src/const/settings/systemAgent.ts +1 -0
- package/src/database/client/migrations.json +27 -0
- package/src/database/migrations/0026_add_autovacuum_tuning.sql +2 -0
- package/src/database/migrations/0027_ai_image.sql +47 -0
- package/src/database/migrations/meta/0027_snapshot.json +6003 -0
- package/src/database/migrations/meta/_journal.json +7 -0
- package/src/database/models/__tests__/asyncTask.test.ts +7 -5
- package/src/database/models/__tests__/file.test.ts +287 -0
- package/src/database/models/__tests__/generation.test.ts +786 -0
- package/src/database/models/__tests__/generationBatch.test.ts +614 -0
- package/src/database/models/__tests__/generationTopic.test.ts +411 -0
- package/src/database/models/aiModel.ts +2 -0
- package/src/database/models/asyncTask.ts +1 -1
- package/src/database/models/file.ts +28 -20
- package/src/database/models/generation.ts +197 -0
- package/src/database/models/generationBatch.ts +212 -0
- package/src/database/models/generationTopic.ts +131 -0
- package/src/database/repositories/aiInfra/index.test.ts +151 -1
- package/src/database/repositories/aiInfra/index.ts +28 -19
- package/src/database/repositories/tableViewer/index.test.ts +1 -1
- package/src/database/schemas/file.ts +8 -0
- package/src/database/schemas/generation.ts +127 -0
- package/src/database/schemas/index.ts +1 -0
- package/src/database/schemas/relations.ts +45 -1
- package/src/database/type.ts +2 -0
- package/src/database/utils/idGenerator.ts +3 -0
- package/src/features/Conversation/Error/ChatInvalidApiKey.tsx +39 -0
- package/src/features/Conversation/Error/InvalidAccessCode.tsx +2 -2
- package/src/features/Conversation/Error/index.tsx +3 -3
- package/src/features/ImageSidePanel/index.tsx +83 -0
- package/src/features/ImageTopicPanel/index.tsx +79 -0
- package/src/features/PluginDevModal/MCPManifestForm/CollapsibleSection.tsx +62 -0
- package/src/features/PluginDevModal/MCPManifestForm/QuickImportSection.tsx +158 -0
- package/src/features/PluginDevModal/MCPManifestForm/index.tsx +99 -155
- package/src/features/PluginStore/McpList/Detail/Settings/index.tsx +5 -2
- package/src/hooks/useDownloadImage.ts +31 -0
- package/src/hooks/useFetchGenerationTopics.ts +13 -0
- package/src/hooks/useHotkeys/imageScope.ts +48 -0
- package/src/libs/mcp/client.ts +55 -22
- package/src/libs/mcp/types.ts +42 -6
- package/src/libs/model-runtime/BaseAI.ts +3 -1
- package/src/libs/model-runtime/ModelRuntime.test.ts +80 -0
- package/src/libs/model-runtime/ModelRuntime.ts +15 -1
- package/src/libs/model-runtime/UniformRuntime/index.ts +4 -1
- package/src/libs/model-runtime/fal/index.test.ts +442 -0
- package/src/libs/model-runtime/fal/index.ts +88 -0
- package/src/libs/model-runtime/openai/index.test.ts +396 -2
- package/src/libs/model-runtime/openai/index.ts +129 -3
- package/src/libs/model-runtime/runtimeMap.ts +2 -0
- package/src/libs/model-runtime/types/image.ts +25 -0
- package/src/libs/model-runtime/types/type.ts +1 -0
- package/src/libs/model-runtime/utils/openaiCompatibleFactory/index.ts +10 -0
- package/src/libs/standard-parameters/index.ts +1 -0
- package/src/libs/standard-parameters/meta-schema.test.ts +214 -0
- package/src/libs/standard-parameters/meta-schema.ts +147 -0
- package/src/libs/swr/index.ts +1 -0
- package/src/libs/trpc/async/asyncAuth.ts +29 -8
- package/src/libs/trpc/async/context.ts +42 -4
- package/src/libs/trpc/async/index.ts +17 -4
- package/src/libs/trpc/async/init.ts +8 -0
- package/src/libs/trpc/client/lambda.ts +19 -2
- package/src/locales/default/common.ts +2 -0
- package/src/locales/default/components.ts +35 -0
- package/src/locales/default/error.ts +2 -0
- package/src/locales/default/image.ts +100 -0
- package/src/locales/default/index.ts +2 -0
- package/src/locales/default/metadata.ts +4 -0
- package/src/locales/default/modelProvider.ts +2 -0
- package/src/locales/default/plugin.ts +22 -0
- package/src/locales/default/setting.ts +5 -0
- package/src/middleware.ts +1 -0
- package/src/server/modules/ElectronIPCClient/index.ts +9 -1
- package/src/server/modules/S3/index.ts +15 -0
- package/src/server/routers/async/caller.ts +9 -1
- package/src/server/routers/async/image.ts +253 -0
- package/src/server/routers/async/index.ts +2 -0
- package/src/server/routers/lambda/aiProvider.test.ts +1 -0
- package/src/server/routers/lambda/generation.test.ts +267 -0
- package/src/server/routers/lambda/generation.ts +86 -0
- package/src/server/routers/lambda/generationBatch.test.ts +376 -0
- package/src/server/routers/lambda/generationBatch.ts +56 -0
- package/src/server/routers/lambda/generationTopic.test.ts +508 -0
- package/src/server/routers/lambda/generationTopic.ts +93 -0
- package/src/server/routers/lambda/image.ts +248 -0
- package/src/server/routers/lambda/index.ts +8 -0
- package/src/server/routers/tools/mcp.ts +15 -0
- package/src/server/services/file/__tests__/index.test.ts +135 -0
- package/src/server/services/file/impls/local.test.ts +153 -52
- package/src/server/services/file/impls/local.ts +70 -46
- package/src/server/services/file/impls/s3.test.ts +114 -0
- package/src/server/services/file/impls/s3.ts +40 -0
- package/src/server/services/file/impls/type.ts +10 -0
- package/src/server/services/file/index.ts +14 -0
- package/src/server/services/generation/index.ts +239 -0
- package/src/server/services/mcp/index.ts +20 -2
- package/src/services/__tests__/generation.test.ts +40 -0
- package/src/services/__tests__/generationBatch.test.ts +36 -0
- package/src/services/__tests__/generationTopic.test.ts +72 -0
- package/src/services/electron/file.ts +3 -1
- package/src/services/generation.ts +16 -0
- package/src/services/generationBatch.ts +25 -0
- package/src/services/generationTopic.ts +28 -0
- package/src/services/image.ts +33 -0
- package/src/services/mcp.ts +12 -7
- package/src/services/upload.ts +43 -9
- package/src/store/aiInfra/slices/aiProvider/action.ts +25 -5
- package/src/store/aiInfra/slices/aiProvider/initialState.ts +1 -0
- package/src/store/aiInfra/slices/aiProvider/selectors.ts +3 -0
- package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +5 -5
- package/src/store/chat/slices/message/action.ts +2 -2
- package/src/store/chat/slices/translate/action.ts +1 -1
- package/src/store/global/initialState.ts +9 -0
- package/src/store/global/selectors/systemStatus.ts +8 -0
- package/src/store/image/index.ts +2 -0
- package/src/store/image/initialState.ts +25 -0
- package/src/store/image/selectors.ts +4 -0
- package/src/store/image/slices/createImage/action.test.ts +330 -0
- package/src/store/image/slices/createImage/action.ts +134 -0
- package/src/store/image/slices/createImage/initialState.ts +9 -0
- package/src/store/image/slices/createImage/selectors.test.ts +114 -0
- package/src/store/image/slices/createImage/selectors.ts +9 -0
- package/src/store/image/slices/generationBatch/action.test.ts +495 -0
- package/src/store/image/slices/generationBatch/action.ts +303 -0
- package/src/store/image/slices/generationBatch/initialState.ts +13 -0
- package/src/store/image/slices/generationBatch/reducer.test.ts +568 -0
- package/src/store/image/slices/generationBatch/reducer.ts +101 -0
- package/src/store/image/slices/generationBatch/selectors.test.ts +307 -0
- package/src/store/image/slices/generationBatch/selectors.ts +36 -0
- package/src/store/image/slices/generationConfig/action.test.ts +351 -0
- package/src/store/image/slices/generationConfig/action.ts +295 -0
- package/src/store/image/slices/generationConfig/hooks.test.ts +304 -0
- package/src/store/image/slices/generationConfig/hooks.ts +118 -0
- package/src/store/image/slices/generationConfig/index.ts +1 -0
- package/src/store/image/slices/generationConfig/initialState.ts +37 -0
- package/src/store/image/slices/generationConfig/selectors.test.ts +204 -0
- package/src/store/image/slices/generationConfig/selectors.ts +25 -0
- package/src/store/image/slices/generationTopic/action.test.ts +687 -0
- package/src/store/image/slices/generationTopic/action.ts +319 -0
- package/src/store/image/slices/generationTopic/index.ts +2 -0
- package/src/store/image/slices/generationTopic/initialState.ts +14 -0
- package/src/store/image/slices/generationTopic/reducer.test.ts +198 -0
- package/src/store/image/slices/generationTopic/reducer.ts +66 -0
- package/src/store/image/slices/generationTopic/selectors.test.ts +103 -0
- package/src/store/image/slices/generationTopic/selectors.ts +15 -0
- package/src/store/image/store.ts +42 -0
- package/src/store/image/utils/size.ts +51 -0
- package/src/store/tool/slices/customPlugin/action.ts +10 -1
- package/src/store/tool/slices/mcpStore/action.ts +6 -4
- package/src/store/user/slices/settings/selectors/__snapshots__/settings.test.ts.snap +4 -0
- package/src/store/user/slices/settings/selectors/systemAgent.ts +2 -0
- package/src/types/aiModel.ts +8 -3
- package/src/types/aiProvider.ts +1 -0
- package/src/types/asyncTask.ts +2 -0
- package/src/types/files/index.ts +5 -0
- package/src/types/generation/index.ts +80 -0
- package/src/types/hotkey.ts +2 -0
- package/src/types/plugins/mcp.ts +2 -6
- package/src/types/tool/plugin.ts +8 -0
- package/src/types/user/settings/keyVaults.ts +5 -0
- package/src/types/user/settings/systemAgent.ts +1 -0
- package/src/utils/client/downloadFile.ts +33 -4
- package/src/utils/number.test.ts +105 -0
- package/src/utils/number.ts +25 -0
- package/src/utils/server/__tests__/geo.test.ts +6 -3
- package/src/utils/storeDebug.test.ts +152 -0
- package/src/utils/storeDebug.ts +16 -7
- package/src/utils/time.test.ts +259 -0
- package/src/utils/time.ts +18 -0
- package/src/utils/units.ts +61 -0
- package/src/utils/url.test.ts +358 -9
- package/src/utils/url.ts +105 -3
- package/{vitest.server.config.ts → vitest.config.server.ts} +3 -0
- package/.cursor/rules/i18n/i18n-auto-attached.mdc +0 -6
- package/src/features/Conversation/Error/APIKeyForm/index.tsx +0 -105
- package/src/features/Conversation/Error/InvalidAPIKey.tsx +0 -16
- package/src/features/PluginDevModal/MCPManifestForm/EnvEditor.tsx +0 -227
- /package/.cursor/rules/{i18n/i18n.mdc → i18n.mdc} +0 -0
- /package/src/app/[variants]/(main)/settings/system-agent/features/{createForm.tsx → SystemAgentForm.tsx} +0 -0
- /package/src/{features/Conversation/Error → components/InvalidAPIKey}/APIKeyForm/LoadingContext.ts +0 -0
@@ -1,8 +1,9 @@
|
|
1
1
|
---
|
2
|
-
description:
|
2
|
+
description:
|
3
3
|
globs: src/services/**/*,src/database/**/*,src/server/**/*
|
4
4
|
alwaysApply: false
|
5
5
|
---
|
6
|
+
|
6
7
|
# LobeChat 后端技术架构指南
|
7
8
|
|
8
9
|
本指南旨在阐述 LobeChat 项目的后端分层架构,重点介绍各核心目录的职责以及它们之间的协作方式。
|
@@ -29,24 +30,21 @@ LobeChat 的后端设计注重模块化、可测试性和灵活性,以适应
|
|
29
30
|
其主要分层如下:
|
30
31
|
|
31
32
|
1. 客户端服务层 (`src/services`):
|
32
|
-
|
33
33
|
- 位于 src/services/。
|
34
34
|
- 这是客户端业务逻辑的核心层,负责封装各种业务操作和数据处理逻辑。
|
35
35
|
- 环境适配: 根据不同的运行环境,服务层会选择合适的数据访问方式:
|
36
|
-
|
37
|
-
|
36
|
+
- 本地数据库模式: 直接调用 `Model` 层进行数据操作,适用于浏览器 PGLite 和本地 Electron 应用。
|
37
|
+
- 远程数据库模式: 通过 `tRPC` 客户端调用服务端 API,适用于需要云同步的场景。
|
38
38
|
- 类型转换: 对于简单的数据类型转换,直接在此层进行类型断言,如 `this.pluginModel.query() as Promise<LobeTool[]>`
|
39
39
|
- 每个服务模块通常包含 `client.ts`(本地模式)、`server.ts`(远程模式)和 `type.ts`(接口定义)文件,在实现时应该确保本地模式和远程模式业务逻辑实现一致,只是数据库不同。
|
40
40
|
|
41
41
|
2. API 接口层 (`TRPC`):
|
42
|
-
|
43
42
|
- 位于 src/server/routers/
|
44
43
|
- 使用 `tRPC` 构建类型安全的 API。Router 根据运行时环境(如 Edge Functions, Node.js Lambda)进行组织。
|
45
44
|
- 负责接收客户端请求,并将其路由到相应的 `Service` 层进行处理。
|
46
45
|
- 新建 lambda 端点时可以参考 src/server/routers/lambda/\_template.ts
|
47
46
|
|
48
47
|
3. 仓库层 (`Repositories`):
|
49
|
-
|
50
48
|
- 位于 src/database/repositories/。
|
51
49
|
- 主要处理复杂的跨表查询和数据聚合逻辑,特别是当需要从多个 `Model` 获取数据并进行组合时。
|
52
50
|
- 与 `Model` 层不同,`Repository` 层专注于复杂的业务查询场景,而不涉及简单的领域模型转换。
|
@@ -54,7 +52,6 @@ LobeChat 的后端设计注重模块化、可测试性和灵活性,以适应
|
|
54
52
|
- 如果数据操作简单(仅涉及单个 `Model`),则通常直接在 `src/services` 层调用 `Model` 并进行简单的类型断言。
|
55
53
|
|
56
54
|
4. 模型层 (`Models`):
|
57
|
-
|
58
55
|
- 位于 src/database/models/ (例如 src/database/models/plugin.ts 和 src/database/models/document.ts)。
|
59
56
|
- 提供对数据库中各个表(由 src/database/schemas/ 中的 Drizzle ORM schema 定义)的基本 CRUD (创建、读取、更新、删除) 操作和简单的查询能力。
|
60
57
|
- `Model` 类专注于单个数据表的直接操作,不涉及复杂的领域模型转换,这些转换通常在上层的 `src/services` 中通过类型断言完成。
|
@@ -65,11 +62,11 @@ LobeChat 的后端设计注重模块化、可测试性和灵活性,以适应
|
|
65
62
|
- 客户端模式 (浏览器/PWA): 使用 PGLite (基于 WASM 的 PostgreSQL),数据存储在用户浏览器本地。
|
66
63
|
- 服务端模式 (云部署): 使用远程 PostgreSQL 数据库。
|
67
64
|
- Electron 桌面应用:
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
65
|
+
- Electron 客户端会启动一个本地 Node.js 服务。
|
66
|
+
- 本地服务通过 `tRPC` 与 Electron 的渲染进程通信。
|
67
|
+
- 数据库选择依赖于是否开启云同步功能:
|
68
|
+
- 云同步开启: 连接到远程 PostgreSQL 数据库。
|
69
|
+
- 云同步关闭: 使用 PGLite (通过 Node.js 的 WASM 实现) 在本地存储数据。
|
73
70
|
|
74
71
|
## 数据流向说明
|
75
72
|
|
@@ -93,8 +90,87 @@ UI (Electron Renderer) → Zustand action → Client Service -> TRPC Client →
|
|
93
90
|
|
94
91
|
## 服务层 (Server Services)
|
95
92
|
|
96
|
-
-
|
97
|
-
-
|
98
|
-
-
|
99
|
-
-
|
100
|
-
-
|
93
|
+
- 位于 src/server/services/。
|
94
|
+
- 核心职责是封装独立的、可复用的业务逻辑单元。这些服务应易于测试。
|
95
|
+
- 平台差异抽象: 一个关键特性是通过其内部的 `impls` 子目录(例如 src/server/services/file/impls 包含 s3.ts 和 local.ts)来抹平不同运行环境带来的差异(例如云端使用 S3 存储,桌面版使用本地文件系统)。这使得上层(如 `tRPC` routers)无需关心底层具体实现。
|
96
|
+
- 目标是使 `tRPC` router 层的逻辑尽可能纯粹,专注于请求处理和业务流程编排。
|
97
|
+
- 服务可能会调用 `Repository` 层或直接调用 `Model` 层进行数据持久化和检索,也可能调用其他服务。
|
98
|
+
|
99
|
+
## 最佳实践 (Best Practices)
|
100
|
+
|
101
|
+
### 数据库操作封装原则
|
102
|
+
|
103
|
+
**连续的数据库操作应该封装到 Model 层**
|
104
|
+
|
105
|
+
当业务逻辑涉及多个相关的数据库操作时,建议将这些操作封装到 Model 层中,而不是在上层(Service 或 Router 层)中进行多次数据库调用。
|
106
|
+
|
107
|
+
**优势:**
|
108
|
+
|
109
|
+
- **代码复用**: Client DB 环境的 service 实现和 Server DB 的 lambda 层实现可以复用相同的 Model 方法
|
110
|
+
- **事务一致性**: 相关的数据库操作可以在同一个方法中管理,便于维护数据一致性
|
111
|
+
- **性能优化**: 减少数据库连接次数,提高查询效率
|
112
|
+
- **职责清晰**: Model 层专注数据访问,上层专注业务协调
|
113
|
+
|
114
|
+
**示例:**
|
115
|
+
|
116
|
+
```typescript
|
117
|
+
// ✅ 推荐:在 Model 层封装连续的数据库操作
|
118
|
+
class GenerationBatchModel {
|
119
|
+
async delete(id: string): Promise<{ deletedBatch: BatchItem; thumbnailUrls: string[] }> {
|
120
|
+
// 1. 查询相关数据
|
121
|
+
const batchWithGenerations = await this.db.query.generationBatches.findFirst({...});
|
122
|
+
|
123
|
+
// 2. 收集需要处理的数据
|
124
|
+
const thumbnailUrls = [...];
|
125
|
+
|
126
|
+
// 3. 执行删除操作
|
127
|
+
const [deletedBatch] = await this.db.delete(generationBatches)...;
|
128
|
+
|
129
|
+
return { deletedBatch, thumbnailUrls };
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
// ✅ 上层使用简洁
|
134
|
+
const { thumbnailUrls } = await model.delete(id);
|
135
|
+
await fileService.deleteFiles(thumbnailUrls);
|
136
|
+
```
|
137
|
+
|
138
|
+
### 文件操作与数据库操作的执行顺序
|
139
|
+
|
140
|
+
**删除操作原则:数据库删除在前,文件删除在后**
|
141
|
+
|
142
|
+
当业务逻辑同时涉及数据库记录和文件系统操作时,应该遵循"数据库优先"的原则。
|
143
|
+
|
144
|
+
**原因:**
|
145
|
+
|
146
|
+
- **用户体验优先**: 如果先删除文件再删除数据库记录,可能出现文件已删除但数据库记录仍存在的情况,用户访问时会遇到文件不存在的错误
|
147
|
+
- **影响程度较小**: 如果先删除数据库记录再删除文件,即使文件删除失败,用户也看不到这个记录,只是造成一些存储空间浪费,对用户体验影响更小
|
148
|
+
- **数据一致性**: 数据库记录是业务逻辑的核心,应该优先保证其一致性
|
149
|
+
|
150
|
+
**示例:**
|
151
|
+
|
152
|
+
```typescript
|
153
|
+
// ✅ 推荐:先删除数据库记录,再删除文件
|
154
|
+
async deleteGeneration(id: string) {
|
155
|
+
// 1. 先删除数据库记录
|
156
|
+
const deletedGeneration = await generationModel.delete(id);
|
157
|
+
|
158
|
+
// 2. 再删除相关文件
|
159
|
+
if (deletedGeneration.asset?.thumbnailUrl) {
|
160
|
+
await fileService.deleteFile(deletedGeneration.asset.thumbnailUrl);
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
// ❌ 不推荐:先删除文件
|
165
|
+
async deleteGeneration(id: string) {
|
166
|
+
const generation = await generationModel.findById(id);
|
167
|
+
|
168
|
+
// 如果这里删除成功,但后面数据库删除失败,用户会遇到访问错误
|
169
|
+
await fileService.deleteFile(generation.asset.thumbnailUrl);
|
170
|
+
await generationModel.delete(id); // 可能失败
|
171
|
+
}
|
172
|
+
```
|
173
|
+
|
174
|
+
**创建操作原则:数据库创建在前,文件操作在后**
|
175
|
+
|
176
|
+
创建操作同样应该优先处理数据库记录,确保数据的一致性和完整性。
|
@@ -1,21 +1,25 @@
|
|
1
1
|
---
|
2
|
-
description:
|
3
|
-
globs:
|
2
|
+
description:
|
3
|
+
globs:
|
4
4
|
alwaysApply: true
|
5
5
|
---
|
6
|
+
|
6
7
|
# Guide to Optimize Output(Response) Rendering
|
7
8
|
|
8
9
|
## File Path and Code Symbol Rendering
|
9
10
|
|
10
11
|
- When rendering file paths, use backtick wrapping instead of markdown links so they can be parsed as clickable links in Cursor IDE.
|
12
|
+
- Good: `src/components/Button.tsx`
|
13
|
+
- Bad: [src/components/Button.tsx](src/components/Button.tsx)
|
11
14
|
|
12
|
-
|
13
|
-
|
15
|
+
- Don't use line and column number in file path, this will make file path not clickable in Cursor IDE.
|
16
|
+
- Good: `src/components/Button.tsx` `10:20` (add a space between the file path and the line and column number)
|
17
|
+
- Bad: `src/components/Button.tsx:10:20`
|
14
18
|
|
15
19
|
- When rendering functions, variables, or other code symbols, use backtick wrapping so they can be parsed as navigable links in Cursor IDE
|
16
|
-
|
17
|
-
|
18
|
-
|
20
|
+
- Good: The `useState` hook in `MyComponent`
|
21
|
+
- Bad: The useState hook in MyComponent
|
22
|
+
|
19
23
|
## Markdown Render
|
20
24
|
|
21
25
|
- don't use br tag to wrap in table cell
|
@@ -23,9 +27,9 @@ alwaysApply: true
|
|
23
27
|
## Terminal Command Output
|
24
28
|
|
25
29
|
- If terminal commands don't produce output, it's likely due to paging issues. Try piping the command to `cat` to ensure full output is displayed.
|
26
|
-
|
27
|
-
|
28
|
-
|
30
|
+
- Good: `git show commit_hash -- file.txt | cat`
|
31
|
+
- Good: `git log --oneline | cat`
|
32
|
+
- Reason: Some git commands use pagers by default, which may prevent output from being captured properly
|
29
33
|
|
30
34
|
## Mermaid Diagram Generation: Strict Syntax Validation Checklist
|
31
35
|
|
@@ -44,50 +48,56 @@ Before producing any Mermaid diagram, you **must** compare your final code line-
|
|
44
48
|
|
45
49
|
### Checklist Details
|
46
50
|
|
47
|
-
#### Rule 1: Edge Labels – Must Be Plain Text Only
|
51
|
+
#### Rule 1: Edge Labels – Must Be Plain Text Only
|
52
|
+
|
48
53
|
> **Essence:** Anything inside `|...|` must contain pure, unformatted text. Absolutely NO Markdown, list markers, or parentheses/brackets allowed—these often cause rendering failures.
|
49
54
|
|
50
|
-
-
|
51
|
-
-
|
52
|
-
-
|
53
|
-
-
|
54
|
-
-
|
55
|
-
-
|
55
|
+
- **✅ Do:** `A -->|Process plain text data| B`
|
56
|
+
- **❌ Don't:** `A -->|1. Ordered list item| B` (No numbered lists)
|
57
|
+
- **❌ Don't:** `CC --"1. fetch('/api/...')"--> API` (No square brackets)
|
58
|
+
- **❌ Don't:** `A -->|- Unordered list item| B` (No hyphen lists)
|
59
|
+
- **❌ Don't:** `A -->|Transform (important)| B` (No parentheses)
|
60
|
+
- **❌ Don't:** `A -->|Transform [important]| B` (No square brackets)
|
61
|
+
|
62
|
+
#### Rule 2: Node Definition – Handle Special Characters with Care
|
56
63
|
|
57
|
-
#### Rule 2: Node Definition – Handle Special Characters with Care
|
58
64
|
> **Essence:** When node text or subgraph titles contain special characters like `()` or `[]`, wrap the text in quotes to avoid conflicts with Mermaid shape syntax.
|
59
65
|
|
60
|
-
-
|
61
|
-
|
62
|
-
|
63
|
-
|
66
|
+
- **When your node text includes parentheses (e.g., 'React (JSX)'):**
|
67
|
+
- **✅ Do:** `I_REACT["<b>React component (JSX)</b>"]` (Quotes wrap all text)
|
68
|
+
- **❌ Don't:** `I_REACT(<b>React component (JSX)</b>)` (Wrong, Mermaid parses this as a shape)
|
69
|
+
- **❌ Don't:** `subgraph Plugin Features (Plugins)` (Wrong, subgraph titles with parentheses must also be wrapped in quotes)
|
70
|
+
|
71
|
+
#### Rule 3: Double Quotes in Text – Must Be Escaped
|
64
72
|
|
65
|
-
#### Rule 3: Double Quotes in Text – Must Be Escaped
|
66
73
|
> **Essence:** Use `"` for double quotes **inside node text**.
|
67
74
|
|
68
|
-
-
|
69
|
-
-
|
75
|
+
- **✅ Do:** `A[This node contains "quotes"]`
|
76
|
+
- **❌ Don't:** `A[This node contains "quotes"]`
|
77
|
+
|
78
|
+
#### Rule 4: All Formatting Must Use HTML Tags (NOT Markdown!)
|
70
79
|
|
71
|
-
#### Rule 4: All Formatting Must Use HTML Tags (NOT Markdown!)
|
72
80
|
> **Essence:** For newlines, bold, and other text formatting in nodes, use HTML tags only. Markdown is not supported.
|
73
81
|
|
74
|
-
-
|
75
|
-
-
|
76
|
-
-
|
77
|
-
-
|
82
|
+
- **✅ Do (robust):** `A["<b>Bold</b> and <code>code</code><br>This is a new line"]`
|
83
|
+
- **❌ Don't (not rendered):** `C["# This is a heading"]`
|
84
|
+
- **❌ Don't (not rendered):** ``C["`const` means constant"]``
|
85
|
+
- **⚠️ Warning (unreliable):** `B["Markdown **bold** might sometimes work but DON'T rely on it"]`
|
86
|
+
|
87
|
+
#### Rule 5: No HTML Tags for Participants and Message Labels (Sequence Diagrams)
|
78
88
|
|
79
|
-
#### Rule 5: No HTML Tags for Participants and Message Labels (Sequence Diagrams)
|
80
89
|
> **Important Addition:**
|
81
90
|
> In Mermaid sequence diagrams, you MUST NOT use any HTML tags (such as `<b>`, `<code>`, etc.) in:
|
91
|
+
>
|
82
92
|
> - `participant` display names (`as` part)
|
83
93
|
> - Message labels (the text after `:` in diagram flows)
|
84
94
|
>
|
85
95
|
> These tags are generally not rendered—they may appear as-is or cause compatibility issues.
|
86
96
|
|
87
|
-
-
|
88
|
-
-
|
89
|
-
-
|
90
|
-
-
|
97
|
+
- **✅ Do:** `participant A as Client`
|
98
|
+
- **❌ Don't:** `participant A as <b>Client</b>`
|
99
|
+
- **✅ Do:** `A->>B: 1. Establish connection`
|
100
|
+
- **❌ Don't:** `A->>B: 1. <code>Establish connection</code>`
|
91
101
|
|
92
102
|
---
|
93
103
|
|
@@ -1,19 +1,71 @@
|
|
1
1
|
---
|
2
|
-
description:
|
3
|
-
globs:
|
4
2
|
alwaysApply: true
|
5
3
|
---
|
4
|
+
|
6
5
|
## Project Description
|
7
6
|
|
8
|
-
You are developing an open-source, modern-design AI chat framework: lobe chat.
|
7
|
+
You are developing an open-source, modern-design AI chat framework: lobe chat.
|
8
|
+
|
9
|
+
Emoji logo: 🤯
|
10
|
+
|
11
|
+
## Project Technologies Stack
|
12
|
+
|
13
|
+
read [package.json](mdc:package.json) to know all npm packages you can use. read [folder-structure.mdx](mdc:docs/development/basic/folder-structure.mdx) to learn project structure.
|
14
|
+
|
15
|
+
The project uses the following technologies:
|
16
|
+
|
17
|
+
- pnpm as package manager
|
18
|
+
- Next.js 15 for frontend and backend, using app router instead of pages router
|
19
|
+
- react 19, using hooks, functional components, react server components
|
20
|
+
- TypeScript programming language
|
21
|
+
- antd, @lobehub/ui for component framework
|
22
|
+
- antd-style for css-in-js framework
|
23
|
+
- react-layout-kit for flex layout
|
24
|
+
- react-i18next for i18n
|
25
|
+
- lucide-react, @ant-design/icons for icons
|
26
|
+
- @lobehub/icons for AI provider/model logo icon
|
27
|
+
- @formkit/auto-animate for react list animation
|
28
|
+
- zustand for global state management
|
29
|
+
- nuqs for type-safe search params state manager
|
30
|
+
- SWR for react data fetch
|
31
|
+
- aHooks for react hooks library
|
32
|
+
- dayjs for date and time library
|
33
|
+
- lodash-es for utility library
|
34
|
+
- fast-deep-equal for deep comparison of JavaScript objects
|
35
|
+
- zod for data validation
|
36
|
+
- TRPC for type safe backend
|
37
|
+
- PGLite for client DB and PostgreSQL for backend DB
|
38
|
+
- Drizzle ORM
|
39
|
+
- Vitest for testing, testing-library for react component test
|
40
|
+
- Prettier for code formatting
|
41
|
+
- ESLint for code linting
|
42
|
+
- Cursor AI for code editing and AI coding assistance
|
43
|
+
|
44
|
+
Note: All tools and libraries used are the latest versions. The application only needs to be compatible with the latest browsers;
|
45
|
+
|
46
|
+
## Often used npm scripts
|
47
|
+
|
48
|
+
```bash
|
49
|
+
# type check
|
50
|
+
bun type-check
|
51
|
+
|
52
|
+
# install dependencies
|
53
|
+
pnpm install
|
54
|
+
|
55
|
+
# !: don't any build script to check weather code can work after modify
|
56
|
+
```
|
57
|
+
|
58
|
+
check [testing guide](./testing-guide.mdc) to learn test scripts.
|
59
|
+
|
60
|
+
## Project Description
|
9
61
|
|
10
|
-
|
62
|
+
You are developing an open-source, modern-design AI chat framework: lobe chat.
|
11
63
|
|
64
|
+
Emoji logo: 🤯
|
12
65
|
|
13
66
|
## Project Technologies Stack
|
14
67
|
|
15
|
-
read [package.json](mdc:package.json) to know all npm packages you can use.
|
16
|
-
read [folder-structure.mdx](mdc:docs/development/basic/folder-structure.mdx) to learn project structure.
|
68
|
+
read [package.json](mdc:package.json) to know all npm packages you can use. read [folder-structure.mdx](mdc:docs/development/basic/folder-structure.mdx) to learn project structure.
|
17
69
|
|
18
70
|
The project uses the following technologies:
|
19
71
|
|
@@ -45,3 +97,17 @@ The project uses the following technologies:
|
|
45
97
|
- Cursor AI for code editing and AI coding assistance
|
46
98
|
|
47
99
|
Note: All tools and libraries used are the latest versions. The application only needs to be compatible with the latest browsers;
|
100
|
+
|
101
|
+
## Often used npm scripts
|
102
|
+
|
103
|
+
```bash
|
104
|
+
# type check
|
105
|
+
bun type-check
|
106
|
+
|
107
|
+
# install dependencies
|
108
|
+
pnpm install
|
109
|
+
|
110
|
+
# !: don't any build script to check weather code can work after modify
|
111
|
+
```
|
112
|
+
|
113
|
+
check [testing guide](./testing-guide.mdc) to learn test scripts.
|
@@ -1,8 +1,9 @@
|
|
1
1
|
---
|
2
|
-
description:
|
3
|
-
globs:
|
2
|
+
description:
|
3
|
+
globs:
|
4
4
|
alwaysApply: true
|
5
5
|
---
|
6
|
+
|
6
7
|
# LobeChat Cursor Rules System Guide
|
7
8
|
|
8
9
|
This document explains how the LobeChat project's Cursor rules system works and serves as an index for manually accessible rules.
|
@@ -14,22 +15,26 @@ This document explains how the LobeChat project's Cursor rules system works and
|
|
14
15
|
## 📚 Four Ways to Access Rules
|
15
16
|
|
16
17
|
### 1. **Always Applied Rules** - `always_applied_workspace_rules`
|
18
|
+
|
17
19
|
- **What**: Core project guidelines that are always active
|
18
20
|
- **Content**: Project tech stack, basic coding standards, output formatting rules
|
19
21
|
- **Access**: No tools needed - automatically provided in every conversation
|
20
22
|
|
21
23
|
### 2. **Dynamic Context Rules** - `cursor_rules_context`
|
24
|
+
|
22
25
|
- **What**: Rules automatically matched based on files referenced in the conversation
|
23
26
|
- **Trigger**: Only when user **explicitly @ mentions files** or **opens files in Cursor**
|
24
27
|
- **Content**: May include brief descriptions or full rule content, depending on relevance
|
25
28
|
- **Access**: No tools needed - automatically updated when files are referenced
|
26
29
|
|
27
30
|
### 3. **Agent Requestable Rules** - `agent_requestable_workspace_rules`
|
31
|
+
|
28
32
|
- **What**: Detailed operational guides that can be requested on-demand
|
29
33
|
- **Access**: Use `fetch_rules` tool with rule names
|
30
34
|
- **Examples**: `debug`, `i18n/i18n`, `code-review`
|
31
35
|
|
32
36
|
### 4. **Manual Rules Index** - This file + `read_file`
|
37
|
+
|
33
38
|
- **What**: Additional rules not covered by the above mechanisms
|
34
39
|
- **Why needed**: Cursor's rule system only supports "agent request" or "auto attach" modes
|
35
40
|
- **Access**: Use `read_file` tool to read specific `.mdc` files
|
@@ -47,10 +52,13 @@ Use `read_file` to access rules from the index below when:
|
|
47
52
|
The following rules are available via `read_file` from the `.cursor/rules/` directory:
|
48
53
|
|
49
54
|
- `backend-architecture.mdc` – Backend layer architecture and design guidelines
|
50
|
-
- `
|
51
|
-
- `zustand-slice-organization.mdc` – Best practices for structuring Zustand slices
|
55
|
+
- `define-database-model.mdc` – Database model definition guidelines
|
52
56
|
- `drizzle-schema-style-guide.mdc` – Style guide for defining Drizzle ORM schemas
|
53
57
|
- `react-component.mdc` – React component style guide and conventions
|
58
|
+
- `testing-guide.mdc` – Comprehensive testing guide for Vitest environment
|
59
|
+
- `typescript.mdc` – TypeScript code style guide
|
60
|
+
- `zustand-action-patterns.mdc` – Recommended patterns for organizing Zustand actions
|
61
|
+
- `zustand-slice-organization.mdc` – Best practices for structuring Zustand slices
|
54
62
|
|
55
63
|
## ❌ Common Misunderstandings to Avoid
|
56
64
|
|
@@ -62,7 +70,7 @@ The following rules are available via `read_file` from the `.cursor/rules/` dire
|
|
62
70
|
|
63
71
|
```
|
64
72
|
1. Start with always_applied_workspace_rules (automatic)
|
65
|
-
2. Check cursor_rules_context for auto-matched rules (automatic)
|
73
|
+
2. Check cursor_rules_context for auto-matched rules (automatic)
|
66
74
|
3. If you need specific guides: fetch_rules (manual)
|
67
75
|
4. If you identify gaps: consult this index → read_file (manual)
|
68
76
|
```
|
@@ -70,7 +78,8 @@ The following rules are available via `read_file` from the `.cursor/rules/` dire
|
|
70
78
|
## Example Decision Flow
|
71
79
|
|
72
80
|
**Scenario**: Working on a new Zustand store slice
|
81
|
+
|
73
82
|
1. Follow always_applied_workspace_rules ✅
|
74
|
-
2. If store files were @ mentioned → use cursor_rules_context rules ✅
|
83
|
+
2. If store files were @ mentioned → use cursor_rules_context rules ✅
|
75
84
|
3. Need detailed Zustand guidance → `read_file('.cursor/rules/zustand-slice-organization.mdc')` ✅
|
76
|
-
4. All rules apply simultaneously - no conflicts ✅
|
85
|
+
4. All rules apply simultaneously - no conflicts ✅
|
package/.eslintrc.js
CHANGED
@@ -36,6 +36,16 @@ config.overrides = [
|
|
36
36
|
'mdx/code-blocks': false,
|
37
37
|
},
|
38
38
|
},
|
39
|
+
|
40
|
+
{
|
41
|
+
files: ['src/store/image/**/*', 'src/types/generation/**/*'],
|
42
|
+
rules: {
|
43
|
+
'@typescript-eslint/no-empty-interface': 0,
|
44
|
+
'sort-keys-fix/sort-keys-fix': 0,
|
45
|
+
'typescript-sort-keys/interface': 0,
|
46
|
+
'typescript-sort-keys/string-enum': 0,
|
47
|
+
},
|
48
|
+
},
|
39
49
|
];
|
40
50
|
|
41
51
|
module.exports = config;
|
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,33 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
## [Version 1.99.0](https://github.com/lobehub/lobe-chat/compare/v1.98.2...v1.99.0)
|
6
|
+
|
7
|
+
<sup>Released on **2025-07-14**</sup>
|
8
|
+
|
9
|
+
#### ✨ Features
|
10
|
+
|
11
|
+
- **plugin**: Support Streamable HTTP MCP Server Auth.
|
12
|
+
- **misc**: support AI Image.
|
13
|
+
|
14
|
+
<br/>
|
15
|
+
|
16
|
+
<details>
|
17
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
18
|
+
|
19
|
+
#### What's improved
|
20
|
+
|
21
|
+
- **plugin**: Support Streamable HTTP MCP Server Auth, closes [#8425](https://github.com/lobehub/lobe-chat/issues/8425) ([853a09a](https://github.com/lobehub/lobe-chat/commit/853a09a))
|
22
|
+
- **misc**: support AI Image, closes [#8312](https://github.com/lobehub/lobe-chat/issues/8312) ([095de57](https://github.com/lobehub/lobe-chat/commit/095de57))
|
23
|
+
|
24
|
+
</details>
|
25
|
+
|
26
|
+
<div align="right">
|
27
|
+
|
28
|
+
[](#readme-top)
|
29
|
+
|
30
|
+
</div>
|
31
|
+
|
5
32
|
### [Version 1.98.2](https://github.com/lobehub/lobe-chat/compare/v1.98.1...v1.98.2)
|
6
33
|
|
7
34
|
<sup>Released on **2025-07-14**</sup>
|
package/apps/desktop/README.md
CHANGED
@@ -25,6 +25,11 @@ const config = {
|
|
25
25
|
artifactName: '${productName}-${version}.${ext}',
|
26
26
|
},
|
27
27
|
asar: true,
|
28
|
+
asarUnpack: [
|
29
|
+
// https://github.com/electron-userland/electron-builder/issues/9001#issuecomment-2778802044
|
30
|
+
'**/node_modules/sharp/**/*',
|
31
|
+
'**/node_modules/@img/**/*',
|
32
|
+
],
|
28
33
|
detectUpdateChannel: true,
|
29
34
|
directories: {
|
30
35
|
buildResources: 'build',
|
@@ -14,12 +14,13 @@
|
|
14
14
|
"build-local": "npm run build && electron-builder --dir --config electron-builder.js --c.mac.notarize=false -c.mac.identity=null --c.asar=false",
|
15
15
|
"build:linux": "npm run build && electron-builder --linux --config electron-builder.js --publish never",
|
16
16
|
"build:mac": "npm run build && electron-builder --mac --config electron-builder.js --publish never",
|
17
|
+
"build:mac:local": "npm run build && UPDATE_CHANNEL=nightly electron-builder --mac --config electron-builder.js --publish never",
|
17
18
|
"build:win": "npm run build && electron-builder --win --config electron-builder.js --publish never",
|
18
19
|
"electron:dev": "electron-vite dev",
|
19
20
|
"electron:run-unpack": "electron .",
|
20
21
|
"format": "prettier --write ",
|
21
22
|
"i18n": "bun run scripts/i18nWorkflow/index.ts && lobe-i18n",
|
22
|
-
"postinstall": "electron-builder install-app-deps",
|
23
|
+
"postinstall": "electron-builder install-app-deps && pnpm rebuild sharp",
|
23
24
|
"install-isolated": "pnpm install",
|
24
25
|
"lint": "eslint --cache ",
|
25
26
|
"pg-server": "bun run scripts/pglite-server.ts",
|
@@ -1,15 +1,10 @@
|
|
1
|
+
import { UploadFileParams } from '@lobechat/electron-client-ipc';
|
2
|
+
import { CreateFileParams } from '@lobechat/electron-server-ipc';
|
3
|
+
|
1
4
|
import FileService from '@/services/fileSrv';
|
2
5
|
|
3
6
|
import { ControllerModule, ipcClientEvent, ipcServerEvent } from './index';
|
4
7
|
|
5
|
-
interface UploadFileParams {
|
6
|
-
content: ArrayBuffer;
|
7
|
-
filename: string;
|
8
|
-
hash: string;
|
9
|
-
path: string;
|
10
|
-
type: string;
|
11
|
-
}
|
12
|
-
|
13
8
|
export default class UploadFileCtr extends ControllerModule {
|
14
9
|
private get fileService() {
|
15
10
|
return this.app.getService(FileService);
|
@@ -27,8 +22,18 @@ export default class UploadFileCtr extends ControllerModule {
|
|
27
22
|
return this.fileService.getFilePath(id);
|
28
23
|
}
|
29
24
|
|
25
|
+
@ipcServerEvent('getFileHTTPURL')
|
26
|
+
async getFileHTTPURL(path: string) {
|
27
|
+
return this.fileService.getFileHTTPURL(path);
|
28
|
+
}
|
29
|
+
|
30
30
|
@ipcServerEvent('deleteFiles')
|
31
31
|
async deleteFiles(paths: string[]) {
|
32
32
|
return this.fileService.deleteFiles(paths);
|
33
33
|
}
|
34
|
+
|
35
|
+
@ipcServerEvent('createFile')
|
36
|
+
async createFile(params: CreateFileParams) {
|
37
|
+
return this.fileService.uploadFile(params);
|
38
|
+
}
|
34
39
|
}
|
@@ -9,6 +9,7 @@ import { buildDir, nextStandaloneDir } from '@/const/dir';
|
|
9
9
|
import { isDev } from '@/const/env';
|
10
10
|
import { IControlModule } from '@/controllers';
|
11
11
|
import { IServiceModule } from '@/services';
|
12
|
+
import FileService from '@/services/fileSrv';
|
12
13
|
import { IpcClientEventSender } from '@/types/ipcClientEvent';
|
13
14
|
import { createLogger } from '@/utils/logger';
|
14
15
|
import { CustomRequestHandler, createHandler } from '@/utils/next-electron-rsc';
|
@@ -18,6 +19,7 @@ import { I18nManager } from './I18nManager';
|
|
18
19
|
import { IoCContainer } from './IoCContainer';
|
19
20
|
import MenuManager from './MenuManager';
|
20
21
|
import { ShortcutManager } from './ShortcutManager';
|
22
|
+
import { StaticFileServerManager } from './StaticFileServerManager';
|
21
23
|
import { StoreManager } from './StoreManager';
|
22
24
|
import TrayManager from './TrayManager';
|
23
25
|
import { UpdaterManager } from './UpdaterManager';
|
@@ -41,6 +43,7 @@ export class App {
|
|
41
43
|
updaterManager: UpdaterManager;
|
42
44
|
shortcutManager: ShortcutManager;
|
43
45
|
trayManager: TrayManager;
|
46
|
+
staticFileServerManager: StaticFileServerManager;
|
44
47
|
chromeFlags: string[] = ['OverlayScrollbar', 'FluentOverlayScrollbar', 'FluentScrollbar'];
|
45
48
|
|
46
49
|
/**
|
@@ -97,6 +100,7 @@ export class App {
|
|
97
100
|
this.updaterManager = new UpdaterManager(this);
|
98
101
|
this.shortcutManager = new ShortcutManager(this);
|
99
102
|
this.trayManager = new TrayManager(this);
|
103
|
+
this.staticFileServerManager = new StaticFileServerManager(this);
|
100
104
|
|
101
105
|
// register the schema to interceptor url
|
102
106
|
// it should register before app ready
|
@@ -130,6 +134,9 @@ export class App {
|
|
130
134
|
await this.i18n.init();
|
131
135
|
this.menuManager.initialize();
|
132
136
|
|
137
|
+
// Initialize static file manager
|
138
|
+
await this.staticFileServerManager.initialize();
|
139
|
+
|
133
140
|
// Initialize global shortcuts: globalShortcut must be called after app.whenReady()
|
134
141
|
this.shortcutManager.initialize();
|
135
142
|
|
@@ -399,6 +406,7 @@ export class App {
|
|
399
406
|
}
|
400
407
|
|
401
408
|
// 执行清理操作
|
409
|
+
this.staticFileServerManager.destroy();
|
402
410
|
this.unregisterAllRequestHandlers();
|
403
411
|
};
|
404
412
|
}
|