@lobehub/lobehub 2.0.0-next.277 → 2.0.0-next.278

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 (73) hide show
  1. package/.cursor/rules/db-migrations.mdc +1 -1
  2. package/.cursor/rules/debug-usage.mdc +7 -5
  3. package/.cursor/rules/desktop-controller-tests.mdc +2 -1
  4. package/.cursor/rules/desktop-feature-implementation.mdc +9 -5
  5. package/.cursor/rules/desktop-local-tools-implement.mdc +67 -66
  6. package/.cursor/rules/desktop-menu-configuration.mdc +21 -9
  7. package/.cursor/rules/desktop-window-management.mdc +17 -2
  8. package/.cursor/rules/drizzle-schema-style-guide.mdc +6 -6
  9. package/.cursor/rules/hotkey.mdc +1 -0
  10. package/.cursor/rules/i18n.mdc +1 -0
  11. package/.cursor/rules/project-structure.mdc +16 -3
  12. package/.cursor/rules/react.mdc +17 -5
  13. package/.cursor/rules/recent-data-usage.mdc +2 -1
  14. package/.cursor/rules/testing-guide/testing-guide.mdc +262 -238
  15. package/.cursor/rules/testing-guide/zustand-store-action-test.mdc +1 -1
  16. package/.cursor/rules/zustand-action-patterns.mdc +1 -1
  17. package/.cursor/rules/zustand-slice-organization.mdc +4 -4
  18. package/CHANGELOG.md +25 -0
  19. package/CLAUDE.md +1 -1
  20. package/GEMINI.md +1 -1
  21. package/changelog/v1.json +5 -0
  22. package/docs/development/database-schema.dbml +16 -0
  23. package/locales/en-US/chat.json +24 -0
  24. package/locales/zh-CN/chat.json +24 -0
  25. package/package.json +1 -1
  26. package/packages/business/const/src/index.ts +3 -0
  27. package/packages/database/migrations/0069_add_topic_shares_table.sql +22 -0
  28. package/packages/database/migrations/meta/0069_snapshot.json +9704 -0
  29. package/packages/database/migrations/meta/_journal.json +7 -0
  30. package/packages/database/src/models/__tests__/topicShare.test.ts +318 -0
  31. package/packages/database/src/models/topicShare.ts +177 -0
  32. package/packages/database/src/schemas/topic.ts +44 -2
  33. package/packages/types/src/conversation.ts +5 -0
  34. package/packages/types/src/topic/topic.ts +46 -0
  35. package/src/app/[variants]/(main)/agent/features/Conversation/Header/ShareButton/index.tsx +24 -9
  36. package/src/app/[variants]/(main)/group/features/Conversation/Header/ShareButton/index.tsx +26 -9
  37. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/AspectRatioSelect/index.tsx +1 -2
  38. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/ImageNum.tsx +54 -173
  39. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/ResolutionSelect.tsx +22 -67
  40. package/src/app/[variants]/(mobile)/router/mobileRouter.config.tsx +18 -0
  41. package/src/app/[variants]/router/desktopRouter.config.tsx +18 -0
  42. package/src/app/[variants]/share/t/[id]/SharedMessageList.tsx +54 -0
  43. package/src/app/[variants]/share/t/[id]/_layout/index.tsx +170 -0
  44. package/src/app/[variants]/share/t/[id]/features/Portal/index.tsx +66 -0
  45. package/src/app/[variants]/share/t/[id]/index.tsx +112 -0
  46. package/src/app/robots.tsx +1 -1
  47. package/src/business/client/BusinessMobileRoutes.tsx +1 -1
  48. package/src/features/Conversation/ChatList/index.tsx +12 -5
  49. package/src/features/Conversation/Messages/AssistantGroup/Tool/Render/index.tsx +8 -4
  50. package/src/features/Conversation/Messages/AssistantGroup/Tool/index.tsx +15 -10
  51. package/src/features/Conversation/Messages/AssistantGroup/Tools.tsx +3 -1
  52. package/src/features/Conversation/Messages/AssistantGroup/components/ContentBlock.tsx +3 -2
  53. package/src/features/Conversation/Messages/AssistantGroup/components/GroupItem.tsx +2 -2
  54. package/src/features/Conversation/Messages/Supervisor/components/ContentBlock.tsx +25 -26
  55. package/src/features/Conversation/Messages/Supervisor/components/Group.tsx +4 -2
  56. package/src/features/Conversation/Messages/Tool/Tool/index.tsx +16 -12
  57. package/src/features/Conversation/Messages/Tool/index.tsx +20 -11
  58. package/src/features/Conversation/Messages/index.tsx +1 -1
  59. package/src/features/Conversation/store/slices/data/action.ts +2 -1
  60. package/src/features/SharePopover/index.tsx +215 -0
  61. package/src/features/SharePopover/style.ts +10 -0
  62. package/src/libs/next/proxy/define-config.ts +4 -1
  63. package/src/locales/default/chat.ts +26 -0
  64. package/src/proxy.ts +1 -0
  65. package/src/server/routers/lambda/__tests__/message.test.ts +152 -0
  66. package/src/server/routers/lambda/__tests__/share.test.ts +227 -0
  67. package/src/server/routers/lambda/__tests__/topic.test.ts +174 -0
  68. package/src/server/routers/lambda/index.ts +2 -0
  69. package/src/server/routers/lambda/message.ts +37 -4
  70. package/src/server/routers/lambda/share.ts +55 -0
  71. package/src/server/routers/lambda/topic.ts +45 -0
  72. package/src/services/message/index.ts +1 -0
  73. package/src/services/topic/index.ts +16 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Best practices for testing Zustand store actions
3
- globs: 'src/store/**/*.test.ts'
3
+ globs: src/store/**/*.test.ts
4
4
  alwaysApply: false
5
5
  ---
6
6
 
@@ -16,7 +16,7 @@ Main interfaces exposed for UI component consumption:
16
16
 
17
17
  - Naming: Verb form (`createTopic`, `sendMessage`, `updateTopicTitle`)
18
18
  - Responsibilities: Parameter validation, flow orchestration, calling internal actions
19
- - Example: [src/store/chat/slices/topic/action.ts](mdc:src/store/chat/slices/topic/action.ts)
19
+ - Example: `src/store/chat/slices/topic/action.ts`
20
20
 
21
21
  ```typescript
22
22
  // Public Action example
@@ -105,7 +105,7 @@ export const initialTopicState: ChatTopicState = {
105
105
  };
106
106
  ```
107
107
 
108
- 2. `reducer.ts` (复杂状态使用):
108
+ 1. `reducer.ts` (复杂状态使用):
109
109
  - 定义纯函数 reducer,处理同步状态转换
110
110
  - 使用 `immer` 确保不可变更新
111
111
 
@@ -151,7 +151,7 @@ export const topicReducer = (state: ChatTopic[] = [], payload: ChatTopicDispatch
151
151
  };
152
152
  ```
153
153
 
154
- 3. `selectors.ts`:
154
+ 1. `selectors.ts`:
155
155
  - 提供状态查询和计算函数
156
156
  - 供 UI 组件使用的状态订阅接口
157
157
  - 重要: 使用 `export const xxxSelectors` 模式聚合所有 selectors
@@ -186,7 +186,7 @@ export const topicSelectors = {
186
186
 
187
187
  当 slice 的 actions 过于复杂时,可以拆分到子目录:
188
188
 
189
- ```
189
+ ```plaintext
190
190
  src/store/chat/slices/aiChat/
191
191
  ├── actions/
192
192
  │ ├── generateAIChat.ts # AI 对话生成
@@ -204,7 +204,7 @@ src/store/chat/slices/aiChat/
204
204
 
205
205
  管理多种内置工具的状态:
206
206
 
207
- ```
207
+ ```plaintext
208
208
  src/store/chat/slices/builtinTool/
209
209
  ├── actions/
210
210
  │ ├── dalle.ts # DALL-E 图像生成
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.278](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.277...v2.0.0-next.278)
6
+
7
+ <sup>Released on **2026-01-13**</sup>
8
+
9
+ #### ✨ Features
10
+
11
+ - **share**: Add topic sharing functionality.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's improved
19
+
20
+ - **share**: Add topic sharing functionality, closes [#11448](https://github.com/lobehub/lobe-chat/issues/11448) ([ddca165](https://github.com/lobehub/lobe-chat/commit/ddca165))
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
+
5
30
  ## [Version 2.0.0-next.277](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.276...v2.0.0-next.277)
6
31
 
7
32
  <sup>Released on **2026-01-13**</sup>
package/CLAUDE.md CHANGED
@@ -34,7 +34,7 @@ see @.cursor/rules/typescript.mdc
34
34
 
35
35
  ### Testing
36
36
 
37
- - **Required Rule**: read `@.cursor/rules/testing-guide/testing-guide.mdc` before writing tests
37
+ - **Required Rule**: read `.cursor/rules/testing-guide/testing-guide.mdc` before writing tests
38
38
  - **Command**:
39
39
  - web: `bunx vitest run --silent='passed-only' '[file-path-pattern]'`
40
40
  - packages(eg: database): `cd packages/database && bunx vitest run --silent='passed-only' '[file-path-pattern]'`
package/GEMINI.md CHANGED
@@ -34,7 +34,7 @@ see @.cursor/rules/typescript.mdc
34
34
 
35
35
  ### Testing
36
36
 
37
- - **Required Rule**: read `@.cursor/rules/testing-guide/testing-guide.mdc` before writing tests
37
+ - **Required Rule**: read `.cursor/rules/testing-guide/testing-guide.mdc` before writing tests
38
38
  - **Command**:
39
39
  - web: `bunx vitest run --silent='passed-only' '[file-path-pattern]'`
40
40
  - packages(eg: database): `cd packages/database && bunx vitest run --silent='passed-only' '[file-path-pattern]'`
package/changelog/v1.json CHANGED
@@ -1,4 +1,9 @@
1
1
  [
2
+ {
3
+ "children": {},
4
+ "date": "2026-01-13",
5
+ "version": "2.0.0-next.278"
6
+ },
2
7
  {
3
8
  "children": {
4
9
  "features": [
@@ -1093,6 +1093,22 @@ table topic_documents {
1093
1093
  }
1094
1094
  }
1095
1095
 
1096
+ table topic_shares {
1097
+ id text [pk, not null]
1098
+ topic_id text [not null]
1099
+ user_id text [not null]
1100
+ visibility text [not null, default: 'private']
1101
+ page_view_count integer [not null, default: 0]
1102
+ accessed_at "timestamp with time zone" [not null, default: `now()`]
1103
+ created_at "timestamp with time zone" [not null, default: `now()`]
1104
+ updated_at "timestamp with time zone" [not null, default: `now()`]
1105
+
1106
+ indexes {
1107
+ topic_id [name: 'topic_shares_topic_id_unique', unique]
1108
+ user_id [name: 'topic_shares_user_id_idx']
1109
+ }
1110
+ }
1111
+
1096
1112
  table topics {
1097
1113
  id text [pk, not null]
1098
1114
  title text
@@ -253,6 +253,8 @@
253
253
  "sessionGroup.sorting": "Group sorting updating...",
254
254
  "sessionGroup.tooLong": "Group name length should be between 1-20",
255
255
  "shareModal.copy": "Copy",
256
+ "shareModal.copyLink": "Copy Link",
257
+ "shareModal.copyLinkSuccess": "Link copied",
256
258
  "shareModal.download": "Download Screenshot",
257
259
  "shareModal.downloadError": "Download failed",
258
260
  "shareModal.downloadFile": "Download File",
@@ -268,12 +270,26 @@
268
270
  "shareModal.imageType": "Image Format",
269
271
  "shareModal.includeTool": "Include Skill messages",
270
272
  "shareModal.includeUser": "Include User Messages",
273
+ "shareModal.link": "Link",
274
+ "shareModal.link.linkHint": "Anyone with the link can view this topic",
275
+ "shareModal.link.noTopic": "Start a conversation first to share",
276
+ "shareModal.link.permissionLink": "Anyone with the link",
277
+ "shareModal.link.permissionPrivate": "Private",
278
+ "shareModal.link.privateHint": "Only you can access this link",
279
+ "shareModal.link.updateError": "Failed to update sharing settings",
280
+ "shareModal.link.visibilityUpdated": "Visibility updated",
271
281
  "shareModal.loadingPdf": "Loading PDF...",
272
282
  "shareModal.noPdfData": "No PDF data available",
273
283
  "shareModal.pdf": "PDF",
274
284
  "shareModal.pdfErrorDescription": "An error occurred while generating the PDF, please try again",
275
285
  "shareModal.pdfGenerationError": "PDF generation failed",
276
286
  "shareModal.pdfReady": "PDF is ready",
287
+ "shareModal.popover.moreOptions": "More share options",
288
+ "shareModal.popover.privacyWarning.confirm": "I understand, continue",
289
+ "shareModal.popover.privacyWarning.content": "Please ensure the conversation does not contain any private or sensitive information before sharing. LobeHub is not responsible for any security issues that may arise from sharing.",
290
+ "shareModal.popover.privacyWarning.title": "Privacy Notice",
291
+ "shareModal.popover.title": "Share Topic",
292
+ "shareModal.popover.visibility": "Visibility",
277
293
  "shareModal.regeneratePdf": "Regenerate PDF",
278
294
  "shareModal.screenshot": "Screenshot",
279
295
  "shareModal.settings": "Export Settings",
@@ -286,6 +302,14 @@
286
302
  "shareModal.withPluginInfo": "Include Skill Information",
287
303
  "shareModal.withRole": "Include Message Role",
288
304
  "shareModal.withSystemRole": "Include Agent Profile",
305
+ "sharePage.error.forbidden.subtitle": "This share is private and not accessible.",
306
+ "sharePage.error.forbidden.title": "Access Denied",
307
+ "sharePage.error.notFound.subtitle": "This topic does not exist or has been removed.",
308
+ "sharePage.error.notFound.title": "Topic Not Found",
309
+ "sharePage.error.unauthorized.action": "Sign In",
310
+ "sharePage.error.unauthorized.subtitle": "Please sign in to view this shared topic.",
311
+ "sharePage.error.unauthorized.title": "Sign In Required",
312
+ "sharePageDisclaimer": "This content is shared by a user and does not represent the views of LobeHub. LobeHub is not responsible for any consequences arising from this shared content.",
289
313
  "stt.action": "Voice Input",
290
314
  "stt.loading": "Recognizing...",
291
315
  "stt.prettifying": "Polishing...",
@@ -253,6 +253,8 @@
253
253
  "sessionGroup.sorting": "正在更新排序…",
254
254
  "sessionGroup.tooLong": "分组名称长度需为 1–20 个字符",
255
255
  "shareModal.copy": "复制",
256
+ "shareModal.copyLink": "复制链接",
257
+ "shareModal.copyLinkSuccess": "链接已复制",
256
258
  "shareModal.download": "下载截图",
257
259
  "shareModal.downloadError": "下载失败,请检查网络后重试",
258
260
  "shareModal.downloadFile": "下载文件",
@@ -268,12 +270,26 @@
268
270
  "shareModal.imageType": "图片格式",
269
271
  "shareModal.includeTool": "包含技能消息",
270
272
  "shareModal.includeUser": "包含用户消息",
273
+ "shareModal.link": "链接",
274
+ "shareModal.link.linkHint": "任何拿到链接的人都可以查看此话题",
275
+ "shareModal.link.noTopic": "先开始对话,才能分享",
276
+ "shareModal.link.permissionLink": "有链接即可访问",
277
+ "shareModal.link.permissionPrivate": "私密",
278
+ "shareModal.link.privateHint": "仅你自己可以访问此链接",
279
+ "shareModal.link.updateError": "更新分享设置失败",
280
+ "shareModal.link.visibilityUpdated": "可见性已更新",
271
281
  "shareModal.loadingPdf": "正在加载 PDF…",
272
282
  "shareModal.noPdfData": "暂无 PDF 数据",
273
283
  "shareModal.pdf": "PDF",
274
284
  "shareModal.pdfErrorDescription": "生成 PDF 时出错,请重试或联系支持",
275
285
  "shareModal.pdfGenerationError": "PDF 生成失败",
276
286
  "shareModal.pdfReady": "PDF 已准备就绪",
287
+ "shareModal.popover.moreOptions": "更多分享方式",
288
+ "shareModal.popover.privacyWarning.confirm": "我已了解,继续",
289
+ "shareModal.popover.privacyWarning.content": "分享前请确保对话中不包含任何隐私或敏感信息。因分享而可能产生的任何安全问题,LobeHub 概不负责。",
290
+ "shareModal.popover.privacyWarning.title": "隐私提醒",
291
+ "shareModal.popover.title": "分享话题",
292
+ "shareModal.popover.visibility": "可见性",
277
293
  "shareModal.regeneratePdf": "重新生成 PDF",
278
294
  "shareModal.screenshot": "截图",
279
295
  "shareModal.settings": "导出设置",
@@ -286,6 +302,14 @@
286
302
  "shareModal.withPluginInfo": "包含技能信息",
287
303
  "shareModal.withRole": "包含消息角色",
288
304
  "shareModal.withSystemRole": "包含助理档案",
305
+ "sharePage.error.forbidden.subtitle": "此分享为私密状态,无法访问。",
306
+ "sharePage.error.forbidden.title": "无权访问",
307
+ "sharePage.error.notFound.subtitle": "该话题不存在或已被删除。",
308
+ "sharePage.error.notFound.title": "话题不存在",
309
+ "sharePage.error.unauthorized.action": "登录",
310
+ "sharePage.error.unauthorized.subtitle": "请登录后查看此分享话题。",
311
+ "sharePage.error.unauthorized.title": "需要登录",
312
+ "sharePageDisclaimer": "此内容由用户分享,不代表 LobeHub 观点。LobeHub 不对该分享内容产生的任何后果承担责任。",
289
313
  "stt.action": "语音输入",
290
314
  "stt.loading": "识别中…",
291
315
  "stt.prettifying": "润色中…",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.0.0-next.277",
3
+ "version": "2.0.0-next.278",
4
4
  "description": "LobeHub - an open-source,comprehensive AI Agent 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",
@@ -4,3 +4,6 @@ export * from './llm';
4
4
  export * from './url';
5
5
 
6
6
  export const ENABLE_BUSINESS_FEATURES = false;
7
+ export const ENABLE_TOPIC_LINK_SHARE =
8
+ ENABLE_BUSINESS_FEATURES ||
9
+ (process.env.NODE_ENV === 'development' && !!process.env.NEXT_PUBLIC_ENABLE_TOPIC_LINK_SHARE);
@@ -0,0 +1,22 @@
1
+ CREATE TABLE IF NOT EXISTS "topic_shares" (
2
+ "id" text PRIMARY KEY NOT NULL,
3
+ "topic_id" text NOT NULL,
4
+ "user_id" text NOT NULL,
5
+ "visibility" text DEFAULT 'private' NOT NULL,
6
+ "page_view_count" integer DEFAULT 0 NOT NULL,
7
+ "accessed_at" timestamp with time zone DEFAULT now() NOT NULL,
8
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
9
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
10
+ );
11
+ --> statement-breakpoint
12
+ DO $$ BEGIN
13
+ ALTER TABLE "topic_shares" ADD CONSTRAINT "topic_shares_topic_id_topics_id_fk" FOREIGN KEY ("topic_id") REFERENCES "public"."topics"("id") ON DELETE cascade ON UPDATE no action;
14
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;
15
+ --> statement-breakpoint
16
+ DO $$ BEGIN
17
+ ALTER TABLE "topic_shares" ADD CONSTRAINT "topic_shares_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;
18
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;
19
+ --> statement-breakpoint
20
+ CREATE UNIQUE INDEX IF NOT EXISTS "topic_shares_topic_id_unique" ON "topic_shares" USING btree ("topic_id");
21
+ --> statement-breakpoint
22
+ CREATE INDEX IF NOT EXISTS "topic_shares_user_id_idx" ON "topic_shares" USING btree ("user_id");