@lobehub/chat 1.111.4 → 1.111.6

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.
@@ -0,0 +1,78 @@
1
+ name: Claude Code Review
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize]
6
+ # Optional: Only run on specific file changes
7
+ # paths:
8
+ # - "src/**/*.ts"
9
+ # - "src/**/*.tsx"
10
+ # - "src/**/*.js"
11
+ # - "src/**/*.jsx"
12
+
13
+ jobs:
14
+ claude-review:
15
+ # Optional: Filter by PR author
16
+ # if: |
17
+ # github.event.pull_request.user.login == 'external-contributor' ||
18
+ # github.event.pull_request.user.login == 'new-developer' ||
19
+ # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
20
+
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: read
24
+ pull-requests: read
25
+ issues: read
26
+ id-token: write
27
+
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v4
31
+ with:
32
+ fetch-depth: 1
33
+
34
+ - name: Run Claude Code Review
35
+ id: claude-review
36
+ uses: anthropics/claude-code-action@beta
37
+ with:
38
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
39
+
40
+ # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
41
+ # model: "claude-opus-4-20250514"
42
+
43
+ # Direct prompt for automated review (no @claude mention needed)
44
+ direct_prompt: |
45
+ Please review this pull request and provide feedback on:
46
+ - Code quality and best practices
47
+ - Potential bugs or issues
48
+ - Performance considerations
49
+ - Security concerns
50
+ - Test coverage
51
+
52
+ Be constructive and helpful in your feedback.
53
+
54
+ # Optional: Use sticky comments to make Claude reuse the same comment on subsequent pushes to the same PR
55
+ # use_sticky_comment: true
56
+
57
+ # Optional: Customize review based on file types
58
+ # direct_prompt: |
59
+ # Review this PR focusing on:
60
+ # - For TypeScript files: Type safety and proper interface usage
61
+ # - For API endpoints: Security, input validation, and error handling
62
+ # - For React components: Performance, accessibility, and best practices
63
+ # - For tests: Coverage, edge cases, and test quality
64
+
65
+ # Optional: Different prompts for different authors
66
+ # direct_prompt: |
67
+ # ${{ github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' &&
68
+ # 'Welcome! Please review this PR from a first-time contributor. Be encouraging and provide detailed explanations for any suggestions.' ||
69
+ # 'Please provide a thorough code review focusing on our coding standards and best practices.' }}
70
+
71
+ # Optional: Add specific tools for running tests or linting
72
+ # allowed_tools: "Bash(npm run test),Bash(npm run lint),Bash(npm run typecheck)"
73
+
74
+ # Optional: Skip review for certain conditions
75
+ # if: |
76
+ # !contains(github.event.pull_request.title, '[skip-review]') &&
77
+ # !contains(github.event.pull_request.title, '[WIP]')
78
+
@@ -0,0 +1,64 @@
1
+ name: Claude Code
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+ pull_request_review_comment:
7
+ types: [created]
8
+ issues:
9
+ types: [opened, assigned]
10
+ pull_request_review:
11
+ types: [submitted]
12
+
13
+ jobs:
14
+ claude:
15
+ if: |
16
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: read
23
+ pull-requests: read
24
+ issues: read
25
+ id-token: write
26
+ actions: read # Required for Claude to read CI results on PRs
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@v4
30
+ with:
31
+ fetch-depth: 1
32
+
33
+ - name: Run Claude Code
34
+ id: claude
35
+ uses: anthropics/claude-code-action@beta
36
+ with:
37
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38
+
39
+ # This is an optional setting that allows Claude to read CI results on PRs
40
+ additional_permissions: |
41
+ actions: read
42
+
43
+ # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
44
+ # model: "claude-opus-4-20250514"
45
+
46
+ # Optional: Customize the trigger phrase (default: @claude)
47
+ # trigger_phrase: "/claude"
48
+
49
+ # Optional: Trigger when specific user is assigned to an issue
50
+ # assignee_trigger: "claude-bot"
51
+
52
+ # Optional: Allow Claude to run specific commands
53
+ # allowed_tools: "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)"
54
+
55
+ # Optional: Add custom instructions for Claude to customize its behavior for your project
56
+ # custom_instructions: |
57
+ # Follow our coding standards
58
+ # Ensure all new code has tests
59
+ # Use TypeScript for new files
60
+
61
+ # Optional: Custom environment variables for Claude
62
+ # claude_env: |
63
+ # NODE_ENV: test
64
+
@@ -35,7 +35,7 @@ jobs:
35
35
  - name: Setup pnpm
36
36
  uses: pnpm/action-setup@v2
37
37
  with:
38
- version: 9
38
+ version: 10
39
39
 
40
40
  - name: Install deps
41
41
  run: pnpm install
@@ -107,7 +107,7 @@ jobs:
107
107
  - name: Setup pnpm
108
108
  uses: pnpm/action-setup@v2
109
109
  with:
110
- version: 9
110
+ version: 10
111
111
 
112
112
  # node-linker=hoisted 模式将可以确保 asar 压缩可用
113
113
  - name: Install deps
@@ -31,7 +31,7 @@ jobs:
31
31
  - name: Setup pnpm
32
32
  uses: pnpm/action-setup@v2
33
33
  with:
34
- version: 9
34
+ version: 10
35
35
 
36
36
  - name: Install deps
37
37
  run: pnpm install
@@ -94,7 +94,7 @@ jobs:
94
94
  - name: Setup pnpm
95
95
  uses: pnpm/action-setup@v2
96
96
  with:
97
- version: 9
97
+ version: 10
98
98
 
99
99
  # node-linker=hoisted 模式将可以确保 asar 压缩可用
100
100
  - name: Install deps
package/CHANGELOG.md CHANGED
@@ -2,6 +2,57 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.111.6](https://github.com/lobehub/lobe-chat/compare/v1.111.5...v1.111.6)
6
+
7
+ <sup>Released on **2025-08-11**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Solve the cache problem caused by the same dom id when sharing pictures.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Solve the cache problem caused by the same dom id when sharing pictures, closes [#8704](https://github.com/lobehub/lobe-chat/issues/8704) ([68aad95](https://github.com/lobehub/lobe-chat/commit/68aad95))
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.111.5](https://github.com/lobehub/lobe-chat/compare/v1.111.4...v1.111.5)
31
+
32
+ <sup>Released on **2025-08-10**</sup>
33
+
34
+ #### 💄 Styles
35
+
36
+ - **misc**: Add mask effect to thinking scroll, update i18n.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### Styles
44
+
45
+ - **misc**: Add mask effect to thinking scroll, closes [#8729](https://github.com/lobehub/lobe-chat/issues/8729) ([4cefafd](https://github.com/lobehub/lobe-chat/commit/4cefafd))
46
+ - **misc**: Update i18n, closes [#8734](https://github.com/lobehub/lobe-chat/issues/8734) ([327a564](https://github.com/lobehub/lobe-chat/commit/327a564))
47
+
48
+ </details>
49
+
50
+ <div align="right">
51
+
52
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
53
+
54
+ </div>
55
+
5
56
  ### [Version 1.111.4](https://github.com/lobehub/lobe-chat/compare/v1.111.3...v1.111.4)
6
57
 
7
58
  <sup>Released on **2025-08-09**</sup>
package/README.md CHANGED
@@ -385,11 +385,11 @@ In addition, these plugins are not limited to news aggregation, but can also ext
385
385
  | Recent Submits | Description |
386
386
  | ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
387
387
  | [PortfolioMeta](https://lobechat.com/discover/plugin/StockData)<br/><sup>By **portfoliometa** on **2025-07-21**</sup> | Analyze stocks and get comprehensive real-time investment data and analytics.<br/>`stock` |
388
- | [Speak](https://lobechat.com/discover/plugin/speak)<br/><sup>By **speak** on **2025-07-18**</sup> | Learn how to say anything in another language with Speak, your AI-powered language tutor.<br/>`education` `language` |
389
388
  | [Web](https://lobechat.com/discover/plugin/web)<br/><sup>By **Proghit** on **2025-01-24**</sup> | Smart web search that reads and analyzes pages to deliver comprehensive answers from Google results.<br/>`web` `search` |
390
389
  | [Bing_websearch](https://lobechat.com/discover/plugin/Bingsearch-identifier)<br/><sup>By **FineHow** on **2024-12-22**</sup> | Search for information from the internet base BingApi<br/>`bingsearch` |
390
+ | [Google CSE](https://lobechat.com/discover/plugin/google-cse)<br/><sup>By **vsnthdev** on **2024-12-02**</sup> | Searches Google through their official CSE API.<br/>`web` `search` |
391
391
 
392
- > 📊 Total plugins: [<kbd>**43**</kbd>](https://lobechat.com/discover/plugins)
392
+ > 📊 Total plugins: [<kbd>**42**</kbd>](https://lobechat.com/discover/plugins)
393
393
 
394
394
  <!-- PLUGIN LIST -->
395
395
 
package/README.zh-CN.md CHANGED
@@ -378,11 +378,11 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
378
378
  | 最近新增 | 描述 |
379
379
  | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
380
380
  | [PortfolioMeta](https://lobechat.com/discover/plugin/StockData)<br/><sup>By **portfoliometa** on **2025-07-21**</sup> | 分析股票并获取全面的实时投资数据和分析。<br/>`股票` |
381
- | [Speak](https://lobechat.com/discover/plugin/speak)<br/><sup>By **speak** on **2025-07-18**</sup> | 使用 Speak,您的 AI 语言导师,学习如何用另一种语言说任何事情。<br/>`教育` `语言` |
382
381
  | [网页](https://lobechat.com/discover/plugin/web)<br/><sup>By **Proghit** on **2025-01-24**</sup> | 智能网页搜索,读取和分析页面,以提供来自 Google 结果的全面答案。<br/>`网页` `搜索` |
383
382
  | [必应网页搜索](https://lobechat.com/discover/plugin/Bingsearch-identifier)<br/><sup>By **FineHow** on **2024-12-22**</sup> | 通过 BingApi 搜索互联网上的信息<br/>`bingsearch` |
383
+ | [谷歌自定义搜索引擎](https://lobechat.com/discover/plugin/google-cse)<br/><sup>By **vsnthdev** on **2024-12-02**</sup> | 通过他们的官方自定义搜索引擎 API 搜索谷歌。<br/>`网络` `搜索` |
384
384
 
385
- > 📊 Total plugins: [<kbd>**43**</kbd>](https://lobechat.com/discover/plugins)
385
+ > 📊 Total plugins: [<kbd>**42**</kbd>](https://lobechat.com/discover/plugins)
386
386
 
387
387
  <!-- PLUGIN LIST -->
388
388
 
package/changelog/v1.json CHANGED
@@ -1,4 +1,22 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "fixes": [
5
+ "Solve the cache problem caused by the same dom id when sharing pictures."
6
+ ]
7
+ },
8
+ "date": "2025-08-11",
9
+ "version": "1.111.6"
10
+ },
11
+ {
12
+ "children": {
13
+ "improvements": [
14
+ "Add mask effect to thinking scroll, update i18n."
15
+ ]
16
+ },
17
+ "date": "2025-08-10",
18
+ "version": "1.111.5"
19
+ },
2
20
  {
3
21
  "children": {},
4
22
  "date": "2025-08-09",
@@ -21,6 +21,10 @@
21
21
  "desc": "الدخول إلى وضع التحرير عن طريق الضغط على مفتاح Alt والنقر المزدوج على الرسالة",
22
22
  "title": "تحرير الرسالة"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "التبديل إلى علامة تبويب المحادثة والدخول إلى دردشة عشوائية",
26
+ "title": "التبديل إلى المحادثة الافتراضية"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "عرض وتعديل إعدادات المحادثة الحالية",
26
30
  "title": "فتح إعدادات المحادثة"
@@ -21,6 +21,10 @@
21
21
  "desc": "Влезте в режим на редактиране, като задържите Alt и два пъти кликнете върху съобщението",
22
22
  "title": "Редактиране на съобщение"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "Превключване към раздела за разговори и влизане в случайна беседа",
26
+ "title": "Превключване към стандартния разговор"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "Прегледайте и променете настройките на текущия разговор",
26
30
  "title": "Отворете настройките на чата"
@@ -21,6 +21,10 @@
21
21
  "desc": "Treten Sie in den Bearbeitungsmodus, indem Sie die Alt-Taste gedrückt halten und auf die Nachricht doppelklicken",
22
22
  "title": "Nachricht bearbeiten"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "Zum Chat-Tab wechseln und einfach plaudern",
26
+ "title": "Zum Standard-Chat wechseln"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "Aktuelle Sitzungseinstellungen anzeigen und ändern",
26
30
  "title": "Chat-Einstellungen öffnen"
@@ -21,6 +21,10 @@
21
21
  "desc": "Enter edit mode by holding Alt and double-clicking the message",
22
22
  "title": "Edit Message"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "Switch to the chat tab and start a casual conversation",
26
+ "title": "Switch to Default Chat"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "View and modify the settings for the current conversation",
26
30
  "title": "Open Chat Settings"
@@ -21,6 +21,10 @@
21
21
  "desc": "Entrar en modo de edición manteniendo presionada la tecla Alt y haciendo doble clic en el mensaje",
22
22
  "title": "Editar mensaje"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "Cambiar a la pestaña de conversación y entrar en charla casual",
26
+ "title": "Cambiar a la conversación predeterminada"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "Ver y modificar la configuración de la conversación actual",
26
30
  "title": "Abrir configuración de la conversación"
@@ -21,6 +21,10 @@
21
21
  "desc": "با نگه داشتن کلید Alt و دوبار کلیک بر روی پیام وارد حالت ویرایش شوید",
22
22
  "title": "ویرایش پیام"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "تغییر به برگه گفتگو و ورود به چت آزاد",
26
+ "title": "تغییر به گفتگو پیش‌فرض"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "مشاهده و ویرایش تنظیمات کنونی گفتگو",
26
30
  "title": "باز کردن تنظیمات گفتگو"
@@ -21,6 +21,10 @@
21
21
  "desc": "Entrez en mode édition en maintenant la touche Alt enfoncée et en double-cliquant sur le message",
22
22
  "title": "Éditer le message"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "Basculer vers l'onglet de conversation et commencer une discussion libre",
26
+ "title": "Passer à la conversation par défaut"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "Voir et modifier les paramètres de la conversation actuelle",
26
30
  "title": "Ouvrir les paramètres de la conversation"
@@ -21,6 +21,10 @@
21
21
  "desc": "Entra in modalità di modifica tenendo premuto Alt e facendo doppio clic sul messaggio",
22
22
  "title": "Modifica messaggio"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "Passa alla scheda della conversazione e inizia una chiacchierata casuale",
26
+ "title": "Passa alla conversazione predefinita"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "Visualizza e modifica le impostazioni della conversazione attuale",
26
30
  "title": "Apri impostazioni chat"
@@ -21,6 +21,10 @@
21
21
  "desc": "Altキーを押しながらメッセージをダブルクリックして編集モードに入ります",
22
22
  "title": "メッセージを編集"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "チャットタブに切り替えて気軽に会話を始める",
26
+ "title": "デフォルトの会話に切り替え"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "現在の会話の設定を表示および変更する",
26
30
  "title": "チャット設定を開く"
@@ -21,6 +21,10 @@
21
21
  "desc": "Alt 키를 누른 채로 메시지를 더블 클릭하여 편집 모드로 들어갑니다",
22
22
  "title": "메시지 편집"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "대화 탭으로 전환하여 자유롭게 대화하기",
26
+ "title": "기본 대화로 전환"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "현재 대화의 설정을 확인하고 수정합니다.",
26
30
  "title": "채팅 설정 열기"
@@ -21,6 +21,10 @@
21
21
  "desc": "Ga naar de bewerkingsmodus door Alt ingedrukt te houden en op het bericht te dubbelklikken",
22
22
  "title": "Bewerk bericht"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "Schakel over naar het gesprekstabblad en begin een willekeurig gesprek",
26
+ "title": "Schakel over naar het standaardgesprek"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "Bekijk en wijzig de instellingen van de huidige sessie",
26
30
  "title": "Open gespreksinstellingen"
@@ -21,6 +21,10 @@
21
21
  "desc": "Wejdź w tryb edycji, przytrzymując klawisz Alt i podwójnie klikając wiadomość",
22
22
  "title": "Edytuj wiadomość"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "Przełącz na kartę rozmowy i rozpocznij swobodną rozmowę",
26
+ "title": "Przełącz na domyślną rozmowę"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "Zobacz i zmodyfikuj ustawienia bieżącej rozmowy",
26
30
  "title": "Otwórz ustawienia czatu"
@@ -21,6 +21,10 @@
21
21
  "desc": "Entre no modo de edição pressionando Alt e clicando duas vezes na mensagem",
22
22
  "title": "Editar mensagem"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "Mudar para a aba de conversas e entrar em bate-papo casual",
26
+ "title": "Mudar para a conversa padrão"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "Ver e modificar as configurações da conversa atual",
26
30
  "title": "Abrir configurações de conversa"
@@ -21,6 +21,10 @@
21
21
  "desc": "Войти в режим редактирования, удерживая Alt и дважды щелкнув по сообщению",
22
22
  "title": "Редактировать сообщение"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "Переключиться на вкладку чата и начать свободное общение",
26
+ "title": "Переключиться на стандартный чат"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "Просмотреть и изменить настройки текущего чата",
26
30
  "title": "Открыть настройки чата"
@@ -21,6 +21,10 @@
21
21
  "desc": "Mesaja çift tıklayıp Alt tuşuna basarak düzenleme moduna geçin",
22
22
  "title": "Mesajı düzenle"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "Sohbet sekmesine geç ve rastgele sohbet et",
26
+ "title": "Varsayılan sohbete geç"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "Mevcut oturumun ayarlarını görüntüle ve değiştir",
26
30
  "title": "Sohbet ayarlarını aç"
@@ -21,6 +21,10 @@
21
21
  "desc": "Vào chế độ chỉnh sửa bằng cách giữ phím Alt và nhấp đúp vào tin nhắn",
22
22
  "title": "Chỉnh sửa tin nhắn"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "Chuyển sang tab trò chuyện và bắt đầu cuộc trò chuyện ngẫu nhiên",
26
+ "title": "Chuyển sang cuộc trò chuyện mặc định"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "Xem và chỉnh sửa cài đặt của cuộc trò chuyện hiện tại",
26
30
  "title": "Mở cài đặt cuộc trò chuyện"
@@ -21,6 +21,10 @@
21
21
  "desc": "通过按住 Alt 并双击消息进入编辑模式",
22
22
  "title": "编辑消息"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "切换至会话标签并进入随便聊聊",
26
+ "title": "切换至默认会话"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "查看和修改当前会话的设置",
26
30
  "title": "打开会话设置"
@@ -21,6 +21,10 @@
21
21
  "desc": "通過按住 Alt 並雙擊消息進入編輯模式",
22
22
  "title": "編輯消息"
23
23
  },
24
+ "navigateToChat": {
25
+ "desc": "切換至會話標籤並進入隨便聊聊",
26
+ "title": "切換至預設會話"
27
+ },
24
28
  "openChatSettings": {
25
29
  "desc": "查看和修改當前會話的設定",
26
30
  "title": "打開會話設定"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.111.4",
3
+ "version": "1.111.6",
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",
@@ -204,7 +204,7 @@
204
204
  "langfuse": "^3.38.4",
205
205
  "langfuse-core": "^3.38.4",
206
206
  "lodash-es": "^4.17.21",
207
- "lucide-react": "^0.536.0",
207
+ "lucide-react": "^0.539.0",
208
208
  "mammoth": "^1.10.0",
209
209
  "markdown-to-txt": "^2.0.1",
210
210
  "mdast-util-to-markdown": "^2.1.2",
@@ -245,7 +245,7 @@
245
245
  "react-lazy-load": "^4.0.1",
246
246
  "react-pdf": "^9.2.1",
247
247
  "react-rnd": "^10.5.2",
248
- "react-scan": "^0.3.6",
248
+ "react-scan": "^0.4.0",
249
249
  "react-virtuoso": "^4.13.0",
250
250
  "react-wrap-balancer": "^1.1.1",
251
251
  "remark": "^15.0.1",
@@ -260,7 +260,7 @@
260
260
  "stripe": "^17.7.0",
261
261
  "superjson": "^2.2.2",
262
262
  "svix": "^1.70.1",
263
- "swr": "^2.3.4",
263
+ "swr": "2.3.4",
264
264
  "systemjs": "^6.15.1",
265
265
  "tokenx": "^0.4.1",
266
266
  "ts-md5": "^1.3.1",
@@ -363,7 +363,7 @@
363
363
  "vitest": "^3.2.4",
364
364
  "vitest-canvas-mock": "^0.3.3"
365
365
  },
366
- "packageManager": "pnpm@10.10.0",
366
+ "packageManager": "pnpm@10.14.0",
367
367
  "publishConfig": {
368
368
  "access": "public",
369
369
  "registry": "https://registry.npmjs.org"
@@ -1,4 +1,4 @@
1
- import { ActionIcon, CopyButton, Icon, Markdown } from '@lobehub/ui';
1
+ import { ActionIcon, CopyButton, Icon, Markdown, ScrollShadow } from '@lobehub/ui';
2
2
  import { createStyles } from 'antd-style';
3
3
  import { AnimatePresence, motion } from 'framer-motion';
4
4
  import { AtomIcon, ChevronDown, ChevronRight } from 'lucide-react';
@@ -17,14 +17,9 @@ const useStyles = createStyles(({ css, token }) => ({
17
17
  transition: all 0.2s ${token.motionEaseOut};
18
18
  `,
19
19
  contentScroll: css`
20
- scroll-behavior: auto;
21
-
22
- overflow-y: auto;
23
- overscroll-behavior: contain;
24
-
25
- max-height: 40vh;
26
- padding-block-end: 12px;
27
- padding-inline: 12px;
20
+ max-height: min(40vh, 320px);
21
+ padding-block-end: 8px;
22
+ padding-inline: 8px;
28
23
  `,
29
24
  expand: css`
30
25
  color: ${token.colorTextTertiary};
@@ -190,18 +185,26 @@ const Thinking = memo<ThinkingProps>((props) => {
190
185
  open: { opacity: 1, width: 'auto' },
191
186
  }}
192
187
  >
193
- <div
188
+ <ScrollShadow
194
189
  className={styles.contentScroll}
195
190
  ref={contentRef as unknown as RefObject<HTMLDivElement>}
191
+ size={12}
196
192
  >
197
193
  {typeof content === 'string' ? (
198
- <Markdown animated={thinkingAnimated} citations={citations} variant={'chat'}>
194
+ <Markdown
195
+ animated={thinkingAnimated}
196
+ citations={citations}
197
+ style={{
198
+ overflow: 'unset',
199
+ }}
200
+ variant={'chat'}
201
+ >
199
202
  {content}
200
203
  </Markdown>
201
204
  ) : (
202
205
  content
203
206
  )}
204
- </div>
207
+ </ScrollShadow>
205
208
  </motion.div>
206
209
  )}
207
210
  </AnimatePresence>
@@ -21,63 +21,70 @@ import { FieldType } from './type';
21
21
 
22
22
  interface PreviewProps extends FieldType {
23
23
  message: ChatMessage;
24
+ previewId?: string;
24
25
  title?: string;
25
26
  }
26
27
 
27
- const Preview = memo<PreviewProps>(({ title, withBackground, withFooter, message }) => {
28
- const [model, plugins] = useAgentStore((s) => [
29
- agentSelectors.currentAgentModel(s),
30
- agentSelectors.currentAgentPlugins(s),
31
- ]);
28
+ const Preview = memo<PreviewProps>(
29
+ ({ title, withBackground, withFooter, message, previewId = 'preview' }) => {
30
+ const [model, plugins] = useAgentStore((s) => [
31
+ agentSelectors.currentAgentModel(s),
32
+ agentSelectors.currentAgentPlugins(s),
33
+ ]);
32
34
 
33
- const [isInbox, description, avatar, backgroundColor] = useSessionStore((s) => [
34
- sessionSelectors.isInboxSession(s),
35
- sessionMetaSelectors.currentAgentDescription(s),
36
- sessionMetaSelectors.currentAgentAvatar(s),
37
- sessionMetaSelectors.currentAgentBackgroundColor(s),
38
- ]);
35
+ const [isInbox, description, avatar, backgroundColor] = useSessionStore((s) => [
36
+ sessionSelectors.isInboxSession(s),
37
+ sessionMetaSelectors.currentAgentDescription(s),
38
+ sessionMetaSelectors.currentAgentAvatar(s),
39
+ sessionMetaSelectors.currentAgentBackgroundColor(s),
40
+ ]);
39
41
 
40
- const { t } = useTranslation('chat');
41
- const { styles } = useStyles(withBackground);
42
- const { styles: containerStyles } = useContainerStyles();
42
+ const { t } = useTranslation('chat');
43
+ const { styles } = useStyles(withBackground);
44
+ const { styles: containerStyles } = useContainerStyles();
43
45
 
44
- const displayTitle = isInbox ? t('inbox.title') : title;
45
- const displayDesc = isInbox ? t('inbox.desc') : description;
46
+ const displayTitle = isInbox ? t('inbox.title') : title;
47
+ const displayDesc = isInbox ? t('inbox.desc') : description;
46
48
 
47
- return (
48
- <div className={containerStyles.preview}>
49
- <div className={withBackground ? styles.background : undefined} id={'preview'}>
50
- <Flexbox className={styles.container} gap={16}>
51
- <div className={styles.header}>
52
- <Flexbox align={'flex-start'} gap={12} horizontal>
53
- <Avatar avatar={avatar} background={backgroundColor} size={40} title={title} />
54
- <ChatHeaderTitle
55
- desc={displayDesc}
56
- tag={
57
- <Flexbox gap={4} horizontal>
58
- <ModelTag model={model} />
59
- {plugins?.length > 0 && <PluginTag plugins={plugins} />}
60
- </Flexbox>
61
- }
62
- title={displayTitle}
63
- />
49
+ return (
50
+ <div className={containerStyles.preview}>
51
+ <div className={withBackground ? styles.background : undefined} id={previewId}>
52
+ <Flexbox className={styles.container} gap={16}>
53
+ <div className={styles.header}>
54
+ <Flexbox align={'flex-start'} gap={12} horizontal>
55
+ <Avatar avatar={avatar} background={backgroundColor} size={40} title={title} />
56
+ <ChatHeaderTitle
57
+ desc={displayDesc}
58
+ tag={
59
+ <Flexbox gap={4} horizontal>
60
+ <ModelTag model={model} />
61
+ {plugins?.length > 0 && <PluginTag plugins={plugins} />}
62
+ </Flexbox>
63
+ }
64
+ title={displayTitle}
65
+ />
66
+ </Flexbox>
67
+ </div>
68
+ <Flexbox
69
+ height={'100%'}
70
+ style={{ paddingTop: 24, position: 'relative' }}
71
+ width={'100%'}
72
+ >
73
+ <ChatItem id={message.id} index={0} />
64
74
  </Flexbox>
65
- </div>
66
- <Flexbox height={'100%'} style={{ paddingTop: 24, position: 'relative' }} width={'100%'}>
67
- <ChatItem id={message.id} index={0} />
75
+ {withFooter ? (
76
+ <Flexbox align={'center'} className={styles.footer} gap={4}>
77
+ <ProductLogo type={'combine'} />
78
+ <div className={styles.url}>{pkg.homepage}</div>
79
+ </Flexbox>
80
+ ) : (
81
+ <div />
82
+ )}
68
83
  </Flexbox>
69
- {withFooter ? (
70
- <Flexbox align={'center'} className={styles.footer} gap={4}>
71
- <ProductLogo type={'combine'} />
72
- <div className={styles.url}>{pkg.homepage}</div>
73
- </Flexbox>
74
- ) : (
75
- <div />
76
- )}
77
- </Flexbox>
84
+ </div>
78
85
  </div>
79
- </div>
80
- );
81
- });
86
+ );
87
+ },
88
+ );
82
89
 
83
90
  export default Preview;
@@ -23,84 +23,91 @@ const DEFAULT_FIELD_VALUE: FieldType = {
23
23
  withFooter: true,
24
24
  };
25
25
 
26
- const ShareImage = memo<{ message: ChatMessage; mobile?: boolean }>(({ message }) => {
27
- const currentAgentTitle = useSessionStore(sessionMetaSelectors.currentAgentTitle);
28
- const [fieldValue, setFieldValue] = useState<FieldType>(DEFAULT_FIELD_VALUE);
29
- const { t } = useTranslation(['chat', 'common']);
30
- const { styles } = useStyles();
31
- const { loading, onDownload, title } = useScreenshot({
32
- imageType: fieldValue.imageType,
33
- title: currentAgentTitle,
34
- });
35
- const { loading: copyLoading, onCopy } = useImgToClipboard();
36
- const settings: FormItemProps[] = [
37
- {
38
- children: <Switch />,
39
- label: t('shareModal.withBackground'),
40
- layout: 'horizontal',
41
- minWidth: undefined,
42
- name: 'withBackground',
43
- valuePropName: 'checked',
44
- },
45
- {
46
- children: <Switch />,
47
- label: t('shareModal.withFooter'),
48
- layout: 'horizontal',
49
- minWidth: undefined,
50
- name: 'withFooter',
51
- valuePropName: 'checked',
52
- },
53
- {
54
- children: <Segmented options={imageTypeOptions} />,
55
- label: t('shareModal.imageType'),
56
- layout: 'horizontal',
57
- minWidth: undefined,
58
- name: 'imageType',
59
- },
60
- ];
26
+ const ShareImage = memo<{ message: ChatMessage; mobile?: boolean; uniqueId?: string }>(
27
+ ({ message, uniqueId }) => {
28
+ const currentAgentTitle = useSessionStore(sessionMetaSelectors.currentAgentTitle);
29
+ const [fieldValue, setFieldValue] = useState<FieldType>(DEFAULT_FIELD_VALUE);
30
+ const { t } = useTranslation(['chat', 'common']);
31
+ const { styles } = useStyles();
61
32
 
62
- const isMobile = useIsMobile();
33
+ // 生成唯一的预览ID,避免DOM冲突
34
+ const previewId = uniqueId ? `preview-${uniqueId}` : 'preview';
63
35
 
64
- const button = (
65
- <>
66
- <Button
67
- block
68
- icon={CopyIcon}
69
- loading={copyLoading}
70
- onClick={() => onCopy()}
71
- size={isMobile ? undefined : 'large'}
72
- type={'primary'}
73
- >
74
- {t('copy', { ns: 'common' })}
75
- </Button>
76
- <Button block loading={loading} onClick={onDownload} size={isMobile ? undefined : 'large'}>
77
- {t('shareModal.download')}
78
- </Button>
79
- </>
80
- );
36
+ const { loading, onDownload, title } = useScreenshot({
37
+ id: `#${previewId}`,
38
+ imageType: fieldValue.imageType,
39
+ title: currentAgentTitle,
40
+ });
41
+ const { loading: copyLoading, onCopy } = useImgToClipboard({ id: `#${previewId}` });
42
+ const settings: FormItemProps[] = [
43
+ {
44
+ children: <Switch />,
45
+ label: t('shareModal.withBackground'),
46
+ layout: 'horizontal',
47
+ minWidth: undefined,
48
+ name: 'withBackground',
49
+ valuePropName: 'checked',
50
+ },
51
+ {
52
+ children: <Switch />,
53
+ label: t('shareModal.withFooter'),
54
+ layout: 'horizontal',
55
+ minWidth: undefined,
56
+ name: 'withFooter',
57
+ valuePropName: 'checked',
58
+ },
59
+ {
60
+ children: <Segmented options={imageTypeOptions} />,
61
+ label: t('shareModal.imageType'),
62
+ layout: 'horizontal',
63
+ minWidth: undefined,
64
+ name: 'imageType',
65
+ },
66
+ ];
81
67
 
82
- return (
83
- <>
84
- <Flexbox className={styles.body} gap={16} horizontal={!isMobile}>
85
- <Preview title={title} {...fieldValue} message={message} />
86
- <Flexbox className={styles.sidebar} gap={12}>
87
- <Form
88
- initialValues={DEFAULT_FIELD_VALUE}
89
- items={settings}
90
- itemsType={'flat'}
91
- onValuesChange={(_, v) => setFieldValue(v)}
92
- {...FORM_STYLE}
93
- />
94
- {!isMobile && button}
95
- </Flexbox>
96
- </Flexbox>
97
- {isMobile && (
98
- <Flexbox className={styles.footer} gap={8} horizontal>
99
- {button}
68
+ const isMobile = useIsMobile();
69
+
70
+ const button = (
71
+ <>
72
+ <Button
73
+ block
74
+ icon={CopyIcon}
75
+ loading={copyLoading}
76
+ onClick={() => onCopy()}
77
+ size={isMobile ? undefined : 'large'}
78
+ type={'primary'}
79
+ >
80
+ {t('copy', { ns: 'common' })}
81
+ </Button>
82
+ <Button block loading={loading} onClick={onDownload} size={isMobile ? undefined : 'large'}>
83
+ {t('shareModal.download')}
84
+ </Button>
85
+ </>
86
+ );
87
+
88
+ return (
89
+ <>
90
+ <Flexbox className={styles.body} gap={16} horizontal={!isMobile}>
91
+ <Preview title={title} {...fieldValue} message={message} previewId={previewId} />
92
+ <Flexbox className={styles.sidebar} gap={12}>
93
+ <Form
94
+ initialValues={DEFAULT_FIELD_VALUE}
95
+ items={settings}
96
+ itemsType={'flat'}
97
+ onValuesChange={(_, v) => setFieldValue(v)}
98
+ {...FORM_STYLE}
99
+ />
100
+ {!isMobile && button}
101
+ </Flexbox>
100
102
  </Flexbox>
101
- )}
102
- </>
103
- );
104
- });
103
+ {isMobile && (
104
+ <Flexbox className={styles.footer} gap={8} horizontal>
105
+ {button}
106
+ </Flexbox>
107
+ )}
108
+ </>
109
+ );
110
+ },
111
+ );
105
112
 
106
113
  export default ShareImage;
@@ -1,5 +1,5 @@
1
1
  import { Modal, Segmented, type SegmentedProps } from '@lobehub/ui';
2
- import { memo, useMemo, useState } from 'react';
2
+ import { memo, useId, useMemo, useState } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { Flexbox } from 'react-layout-kit';
5
5
 
@@ -23,6 +23,7 @@ interface ShareModalProps {
23
23
  const ShareModal = memo<ShareModalProps>(({ onCancel, open, message }) => {
24
24
  const [tab, setTab] = useState<Tab>(Tab.Screenshot);
25
25
  const { t } = useTranslation('chat');
26
+ const uniqueId = useId();
26
27
 
27
28
  const options: SegmentedProps['options'] = useMemo(
28
29
  () => [
@@ -58,7 +59,9 @@ const ShareModal = memo<ShareModalProps>(({ onCancel, open, message }) => {
58
59
  value={tab}
59
60
  variant={'filled'}
60
61
  />
61
- {tab === Tab.Screenshot && <ShareImage message={message} mobile={isMobile} />}
62
+ {tab === Tab.Screenshot && (
63
+ <ShareImage message={message} mobile={isMobile} uniqueId={uniqueId} />
64
+ )}
62
65
  {tab === Tab.Text && <ShareText item={message} />}
63
66
  </Flexbox>
64
67
  </Modal>