@lobehub/chat 1.141.6 → 1.141.8

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 (119) hide show
  1. package/.github/PULL_REQUEST_TEMPLATE.md +26 -0
  2. package/.github/workflows/e2e.yml +6 -6
  3. package/CHANGELOG.md +50 -0
  4. package/changelog/v1.json +18 -0
  5. package/docs/usage/features/{group-chat.mdx → agent-team.mdx} +14 -14
  6. package/docs/usage/features/agent-team.zh-CN.mdx +52 -0
  7. package/e2e/README.md +143 -0
  8. package/e2e/cucumber.config.js +20 -0
  9. package/e2e/package.json +24 -0
  10. package/e2e/src/features/discover/smoke.feature +11 -0
  11. package/e2e/src/features/routes/core-routes.feature +43 -0
  12. package/e2e/src/steps/common/navigation.steps.ts +36 -0
  13. package/e2e/src/steps/discover/smoke.steps.ts +34 -0
  14. package/e2e/src/steps/hooks.ts +69 -0
  15. package/e2e/src/steps/routes/routes.steps.ts +41 -0
  16. package/e2e/src/support/webServer.ts +96 -0
  17. package/e2e/src/support/world.ts +76 -0
  18. package/e2e/tsconfig.json +19 -0
  19. package/locales/ar/chat.json +17 -17
  20. package/locales/ar/setting.json +15 -19
  21. package/locales/ar/welcome.json +1 -1
  22. package/locales/bg-BG/chat.json +17 -17
  23. package/locales/bg-BG/setting.json +15 -19
  24. package/locales/de-DE/chat.json +17 -17
  25. package/locales/de-DE/setting.json +15 -19
  26. package/locales/de-DE/welcome.json +1 -1
  27. package/locales/en-US/chat.json +17 -17
  28. package/locales/en-US/setting.json +15 -19
  29. package/locales/en-US/welcome.json +1 -1
  30. package/locales/es-ES/chat.json +17 -17
  31. package/locales/es-ES/setting.json +15 -19
  32. package/locales/es-ES/welcome.json +1 -1
  33. package/locales/fa-IR/chat.json +17 -17
  34. package/locales/fa-IR/setting.json +15 -19
  35. package/locales/fa-IR/welcome.json +1 -1
  36. package/locales/fr-FR/chat.json +16 -16
  37. package/locales/fr-FR/setting.json +15 -19
  38. package/locales/fr-FR/welcome.json +1 -1
  39. package/locales/it-IT/chat.json +17 -17
  40. package/locales/it-IT/setting.json +15 -19
  41. package/locales/it-IT/welcome.json +1 -1
  42. package/locales/ja-JP/chat.json +17 -17
  43. package/locales/ja-JP/setting.json +15 -19
  44. package/locales/ja-JP/welcome.json +1 -1
  45. package/locales/ko-KR/chat.json +17 -17
  46. package/locales/ko-KR/setting.json +15 -19
  47. package/locales/ko-KR/welcome.json +1 -1
  48. package/locales/nl-NL/chat.json +17 -17
  49. package/locales/nl-NL/setting.json +15 -19
  50. package/locales/nl-NL/welcome.json +1 -1
  51. package/locales/pl-PL/chat.json +17 -17
  52. package/locales/pl-PL/setting.json +15 -19
  53. package/locales/pt-BR/chat.json +17 -17
  54. package/locales/pt-BR/setting.json +15 -19
  55. package/locales/pt-BR/welcome.json +1 -1
  56. package/locales/ru-RU/chat.json +17 -17
  57. package/locales/ru-RU/setting.json +15 -19
  58. package/locales/ru-RU/welcome.json +1 -1
  59. package/locales/tr-TR/chat.json +17 -17
  60. package/locales/tr-TR/setting.json +15 -19
  61. package/locales/vi-VN/chat.json +15 -15
  62. package/locales/vi-VN/setting.json +15 -19
  63. package/locales/zh-CN/chat.json +17 -17
  64. package/locales/zh-CN/setting.json +15 -19
  65. package/locales/zh-CN/welcome.json +1 -1
  66. package/locales/zh-TW/chat.json +17 -17
  67. package/locales/zh-TW/setting.json +15 -19
  68. package/locales/zh-TW/welcome.json +1 -1
  69. package/package.json +6 -3
  70. package/packages/const/src/layoutTokens.ts +1 -1
  71. package/packages/const/src/settings/systemAgent.ts +0 -1
  72. package/packages/database/src/models/__tests__/session.test.ts +108 -0
  73. package/packages/database/src/models/session.ts +41 -1
  74. package/packages/model-bank/src/aiModels/groq.ts +0 -17
  75. package/packages/model-bank/src/aiModels/novita.ts +2 -60
  76. package/packages/model-bank/src/aiModels/siliconcloud.ts +116 -17
  77. package/packages/types/src/user/settings/systemAgent.ts +0 -1
  78. package/pnpm-workspace.yaml +1 -0
  79. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatList/ChatItem/OrchestratorThinking.tsx +2 -3
  80. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatList/ChatItem/index.tsx +2 -2
  81. package/src/app/[variants]/(main)/chat/(workspace)/@topic/features/GroupConfig/GroupMember.tsx +34 -2
  82. package/src/app/[variants]/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/Main.tsx +1 -1
  83. package/src/app/[variants]/(main)/chat/(workspace)/features/{GroupChatSettings → AgentTeamSettings}/index.tsx +4 -5
  84. package/src/app/[variants]/(main)/chat/(workspace)/features/SettingButton.tsx +2 -2
  85. package/src/app/[variants]/(main)/chat/@session/_layout/Desktop/SessionHeader.tsx +2 -0
  86. package/src/app/[variants]/(main)/chat/@session/features/SessionListContent/CollapseGroup/Actions.tsx +18 -1
  87. package/src/app/[variants]/(main)/discover/(list)/assistant/features/List/Item.tsx +1 -0
  88. package/src/app/[variants]/(main)/discover/DiscoverRouter.tsx +12 -10
  89. package/src/app/[variants]/(main)/discover/[[...path]]/page.tsx +7 -6
  90. package/src/app/[variants]/(main)/discover/features/Search.tsx +1 -0
  91. package/src/components/ChatGroupWizard/ChatGroupWizard.tsx +33 -5
  92. package/src/components/Loading/index.ts +1 -0
  93. package/src/components/MemberSelectionModal/MemberSelectionModal.tsx +170 -26
  94. package/src/features/AgentSetting/AgentModal/index.tsx +262 -35
  95. package/src/features/ChatInput/ActionBar/Params/Controls.tsx +261 -50
  96. package/src/features/Conversation/Messages/Assistant/Actions/index.tsx +7 -2
  97. package/src/features/Conversation/Messages/User/Actions.tsx +8 -2
  98. package/src/features/GroupChatSettings/{ChatGroupSettings.tsx → AgentTeamChatSettings.tsx} +6 -5
  99. package/src/features/GroupChatSettings/{GroupMembers.tsx → AgentTeamMembersSettings.tsx} +64 -19
  100. package/src/features/GroupChatSettings/{ChatGroupMeta.tsx → AgentTeamMetaSettings.tsx} +2 -2
  101. package/src/features/GroupChatSettings/AgentTeamSettings.tsx +54 -0
  102. package/src/features/GroupChatSettings/index.ts +4 -5
  103. package/src/features/ModelParamsControl/FrequencyPenalty.tsx +8 -3
  104. package/src/features/ModelParamsControl/PresencePenalty.tsx +8 -3
  105. package/src/features/ModelParamsControl/Temperature.tsx +8 -5
  106. package/src/features/ModelParamsControl/TopP.tsx +8 -3
  107. package/src/locales/default/chat.ts +17 -17
  108. package/src/locales/default/setting.ts +15 -19
  109. package/src/locales/default/welcome.ts +1 -1
  110. package/src/services/chat/index.ts +6 -0
  111. package/src/store/chat/slices/aiChat/actions/generateAIGroupChat.ts +2 -1
  112. package/src/store/chatGroup/action.ts +36 -1
  113. package/src/store/user/slices/settings/selectors/__snapshots__/settings.test.ts.snap +0 -4
  114. package/src/store/user/slices/settings/selectors/systemAgent.ts +0 -2
  115. package/docs/usage/features/group-chat.zh-CN.mdx +0 -52
  116. package/e2e/routes.spec.ts +0 -73
  117. package/playwright.config.ts +0 -35
  118. package/src/features/GroupChatSettings/GroupSettings.tsx +0 -30
  119. package/src/features/GroupChatSettings/GroupSettingsContent.tsx +0 -24
@@ -12,10 +12,36 @@
12
12
  - [ ] 📝 docs
13
13
  - [ ] 🔨 chore
14
14
 
15
+ #### 🔗 Related Issue
16
+
17
+ <!-- Link to the issue that is fixed by this PR -->
18
+
19
+ <!-- Example: Fixes #123, Closes #456, Related to #789 -->
20
+
15
21
  #### 🔀 Description of Change
16
22
 
17
23
  <!-- Thank you for your Pull Request. Please provide a description above. -->
18
24
 
25
+ #### 🧪 How to Test
26
+
27
+ <!-- Please describe how you tested your changes -->
28
+
29
+ <!-- For AI features, please include test prompts or scenarios -->
30
+
31
+ - [ ] Tested locally
32
+ - [ ] Added/updated tests
33
+ - [ ] No tests needed
34
+
35
+ #### 📸 Screenshots / Videos
36
+
37
+ <!-- If this PR includes UI changes, please provide screenshots or videos -->
38
+
39
+ | Before | After |
40
+ | ------ | ----- |
41
+ | ... | ... |
42
+
19
43
  #### 📝 Additional Information
20
44
 
21
45
  <!-- Add any other context about the Pull Request here. -->
46
+
47
+ <!-- Breaking changes? Migration guide? Performance impact? -->
@@ -35,18 +35,18 @@ jobs:
35
35
  PORT: 3010
36
36
  run: bun run e2e
37
37
 
38
- - name: Upload Playwright HTML report (on failure)
38
+ - name: Upload Cucumber HTML report (on failure)
39
39
  if: failure()
40
40
  uses: actions/upload-artifact@v4
41
41
  with:
42
- name: playwright-report
43
- path: playwright-report
42
+ name: cucumber-report
43
+ path: e2e/reports
44
44
  if-no-files-found: ignore
45
45
 
46
- - name: Upload Playwright traces (on failure)
46
+ - name: Upload screenshots (on failure)
47
47
  if: failure()
48
48
  uses: actions/upload-artifact@v4
49
49
  with:
50
- name: test-results
51
- path: test-results
50
+ name: test-screenshots
51
+ path: e2e/screenshots
52
52
  if-no-files-found: ignore
package/CHANGELOG.md CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.141.8](https://github.com/lobehub/lobe-chat/compare/v1.141.7...v1.141.8)
6
+
7
+ <sup>Released on **2025-10-23**</sup>
8
+
9
+ #### 💄 Styles
10
+
11
+ - **misc**: Improvement for Agent Team After Alpha Launch \[LOB-517].
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Styles
19
+
20
+ - **misc**: Improvement for Agent Team After Alpha Launch \[LOB-517], closes [#9748](https://github.com/lobehub/lobe-chat/issues/9748) ([28245be](https://github.com/lobehub/lobe-chat/commit/28245be))
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.141.7](https://github.com/lobehub/lobe-chat/compare/v1.141.6...v1.141.7)
31
+
32
+ <sup>Released on **2025-10-23**</sup>
33
+
34
+ #### 💄 Styles
35
+
36
+ - **misc**: Allow removal of `top_p` and similar request parameters.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### Styles
44
+
45
+ - **misc**: Allow removal of `top_p` and similar request parameters, closes [#9498](https://github.com/lobehub/lobe-chat/issues/9498) ([4c313ce](https://github.com/lobehub/lobe-chat/commit/4c313ce))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ### [Version 1.141.6](https://github.com/lobehub/lobe-chat/compare/v1.141.5...v1.141.6)
6
56
 
7
57
  <sup>Released on **2025-10-22**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,22 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Improvement for Agent Team After Alpha Launch [LOB-517]."
6
+ ]
7
+ },
8
+ "date": "2025-10-23",
9
+ "version": "1.141.8"
10
+ },
11
+ {
12
+ "children": {
13
+ "improvements": [
14
+ "Allow removal of top_p and similar request parameters."
15
+ ]
16
+ },
17
+ "date": "2025-10-23",
18
+ "version": "1.141.7"
19
+ },
2
20
  {
3
21
  "children": {},
4
22
  "date": "2025-10-22",
@@ -1,26 +1,26 @@
1
1
  ---
2
- title: Group Chat
2
+ title: Agent Team
3
3
  description: Turn any conversation into a team effort. Multiple AI agents collaborate naturally to give you richer, more insightful responses.
4
4
  tags:
5
- - Group Chat
5
+ - Agent Team
6
6
  - Multi-Agent
7
7
  - AI Orchestration
8
8
  - Agent Coordination
9
9
  ---
10
10
 
11
- # Group Chat
11
+ # Agent Team
12
12
 
13
- <Image alt={'Group Chat'} cover src={'https://github.com/user-attachments/assets/6e5599f6-1e39-4b14-a218-4f5ffa2c306a'} />
13
+ <Image alt={'Agent Team'} cover src={'https://github.com/user-attachments/assets/6e5599f6-1e39-4b14-a218-4f5ffa2c306a'} />
14
14
 
15
- Sometimes one perspective isn't enough. Group Chat brings together multiple AI agents, each with their own expertise, to collaborate on your conversations. Richer discussions, diverse viewpoints, and solutions you wouldn't get from any single agent.
15
+ Sometimes one perspective isn't enough. Agent Team brings together multiple AI agents, each with their own expertise, to collaborate on your conversations. Richer discussions, diverse viewpoints, and solutions you wouldn't get from any single agent.
16
16
 
17
17
  ## Highlights
18
18
 
19
19
  - Multiple assistants with specialized knowledge work together, each contributing their strengths
20
- - A built-in host ensures the group chat runs smoothly and organized
20
+ - A built-in host ensures the agent team conversation runs smoothly and organized
21
21
  - Private messaging allows seamless coordination between assistants
22
22
  - You get comprehensive answers from multiple perspectives
23
- - Ready to use with your own assistants or rich group chat team templates
23
+ - Ready to use with your own assistants or rich agent team templates
24
24
 
25
25
  ## Use Cases
26
26
 
@@ -30,23 +30,23 @@ Sometimes one perspective isn't enough. Group Chat brings together multiple AI a
30
30
 
31
31
  **Brainstorming**: Diverse perspectives spark better ideas.
32
32
 
33
- **Problem Solving**: Benefit from insights across different professional fields, with different tools and MCPs, group chat allows you to have the perfect AI team.
33
+ **Problem Solving**: Benefit from insights across different professional fields, with different tools and MCPs, agent team allows you to have the perfect AI team.
34
34
 
35
35
  ## Quick Start
36
36
 
37
- Click the "Create Group Chat" button, you can choose to create directly from preset group chat templates, or select your own assistants to form a group chat.
37
+ Click the "Create Agent Team" button, you can choose to create directly from preset agent team templates, or select your own assistants to form an agent team.
38
38
 
39
- You can use @ to mention a group member in the group chat, or click their avatar to send them a private message. Everything works just like in a real chat room.
39
+ You can use @ to mention a team member in the agent team, or click their avatar to send them a private message. Everything works just like in a real chat room.
40
40
 
41
- ### Interrupt and Resume Group Chat
41
+ ### Interrupt and Resume Agent Team
42
42
 
43
- You can interrupt the host's thinking at any time, and the group chat will "pause" after interruption. You can start the moderator at any time, and the group chat will continue.
43
+ You can interrupt the host's thinking at any time, and the agent team will "pause" after interruption. You can start the moderator at any time, and the agent team will continue.
44
44
 
45
45
  Of course, conversations may also stop naturally.
46
46
 
47
47
  ### Advanced Options
48
48
 
49
- - Group Chat Speed: Customize the response speed of the group chat
49
+ - Agent Team Speed: Customize the response speed of the agent team
50
50
  - Custom Moderator: Guide the moderator's behavior according to specific needs
51
51
 
52
- Group Chat transforms how you interact with AI. Instead of getting one answer, you participate in a conversation—complete with different viewpoints, collaborative problem-solving, and profound insights that emerge when AI agents work together.
52
+ Agent Team transforms how you interact with AI. Instead of getting one answer, you participate in a conversation—complete with different viewpoints, collaborative problem-solving, and profound insights that emerge when AI agents work together.
@@ -0,0 +1,52 @@
1
+ ---
2
+ title: Agent 团队
3
+ description: 让对话变成团队协作。多个 AI 智能体自然配合,为你提供更丰富、更有洞察力的回答。
4
+ tags:
5
+ - 群组对话
6
+ - 多智能体
7
+ - AI 编排
8
+ - 智能体协调
9
+ ---
10
+
11
+ # Agent 团队
12
+
13
+ <Image alt={'Agent 团队'} cover src={'https://github.com/user-attachments/assets/6e5599f6-1e39-4b14-a218-4f5ffa2c306a'} />
14
+
15
+ 有时候,一个视角远远不够。Agent 团队功能让多个拥有不同知识和技能的 AI 智能体聚在一起,协作参与你的对话。更丰富的讨论、多元的观点,以及任何单一智能体都无法提供的解决方案。
16
+
17
+ ## 亮点
18
+
19
+ - 多个具有专业知识的助手协同工作,各取所长
20
+ - 团队内置的主持人将确保整个团队聊天有条不紊的进行
21
+ - 私信功能让助手间无缝协调配合
22
+ - 你将从多个视角获得全面的答案
23
+ - 开箱即用,由你自己的助手组成,或者使用丰富的团队模版
24
+
25
+ ## 适用场景
26
+
27
+ **学习研究**:不同的助手通过不同的工具收集不同的资料,汇聚一处并自发讨论。
28
+
29
+ **娱乐**:狼人杀、模拟联合国、海龟汤等多人语聊游戏。
30
+
31
+ **头脑风暴**:多元观点激发更好的想法。
32
+
33
+ **问题解决**:受益于不同专业领域的见解,以及不同的工具和 MCP,Agent 团队允许你拥有完美的 AI 团队。
34
+
35
+ ## 快速开始
36
+
37
+ 点击「创建 Agent 团队」按钮,你可以选择直接从预设的团队模版创建,或选择你自己的助手组成团队。
38
+
39
+ 你可以在团队聊天中输入 @ 来提及某个成员,或者点击他们的头像对其私聊。一切就像是在真实的聊天室中一样。
40
+
41
+ ### 中断与继续团队聊天
42
+
43
+ 你可以随时打断主持人的思考,打断后团队聊天将会「暂停」。你可以随时开启主持人,团队聊天便会继续。
44
+
45
+ 当然,对话也有可能自然地停止。
46
+
47
+ ### 高级选项
48
+
49
+ - 团队速度:自定义团队的回答速度
50
+ - 自定义主持人:根据特定需要指导主持人的行为
51
+
52
+ Agent 团队改变了你与 AI 的互动方式。不再是获得一个答案,而是参与一场对话 —— 包含不同观点、协作解决问题,以及 AI 智能体协同工作时产生的深刻洞察。
package/e2e/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # E2E Tests for LobeChat
2
+
3
+ This directory contains end-to-end (E2E) tests for LobeChat using Cucumber (BDD) and Playwright.
4
+
5
+ ## Directory Structure
6
+
7
+ ````
8
+ e2e/
9
+ ├── src/ # Source files
10
+ │ ├── features/ # Gherkin feature files
11
+ │ │ └── discover/ # Discover page tests
12
+ │ ├── steps/ # Step definitions
13
+ │ │ ├── common/ # Reusable step definitions
14
+ │ │ └── discover/ # Discover-specific steps
15
+ │ └── support/ # Test support files
16
+ │ └── world.ts # Custom World context
17
+ ├── reports/ # Test reports (generated)
18
+ ├── cucumber.config.js # Cucumber configuration
19
+ ├── tsconfig.json # TypeScript configuration
20
+ └── package.json # Dependencies and scripts
21
+
22
+ ## Prerequisites
23
+
24
+ - Node.js 20, 22, or >=24
25
+ - Dev server running on `http://localhost:3010` (or set `BASE_URL` env var)
26
+
27
+ ## Installation
28
+
29
+ Install dependencies:
30
+
31
+ ```bash
32
+ cd e2e
33
+ pnpm install
34
+ ````
35
+
36
+ Install Playwright browsers:
37
+
38
+ ```bash
39
+ npx playwright install chromium
40
+ ```
41
+
42
+ ## Running Tests
43
+
44
+ Run all tests:
45
+
46
+ ```bash
47
+ npm test
48
+ ```
49
+
50
+ Run tests in headed mode (see browser):
51
+
52
+ ```bash
53
+ npm run test:headed
54
+ ```
55
+
56
+ Run only smoke tests:
57
+
58
+ ```bash
59
+ npm run test:smoke
60
+ ```
61
+
62
+ Run discover tests:
63
+
64
+ ```bash
65
+ npm run test:discover
66
+ ```
67
+
68
+ ## Environment Variables
69
+
70
+ - `BASE_URL`: Base URL for the application (default: `http://localhost:3010`)
71
+ - `PORT`: Port number (default: `3010`)
72
+ - `HEADLESS`: Run browser in headless mode (default: `true`, set to `false` to see browser)
73
+
74
+ Example:
75
+
76
+ ```bash
77
+ HEADLESS=false BASE_URL=http://localhost:3000 npm run test:smoke
78
+ ```
79
+
80
+ ## Writing Tests
81
+
82
+ ### Feature Files
83
+
84
+ Feature files are written in Gherkin syntax and placed in the `src/features/` directory:
85
+
86
+ ```gherkin
87
+ @discover @smoke
88
+ Feature: Discover Smoke Tests
89
+ Critical path tests to ensure the discover module is functional
90
+
91
+ @DISCOVER-SMOKE-001 @P0
92
+ Scenario: Load discover assistant list page
93
+ Given I navigate to "/discover/assistant"
94
+ Then the page should load without errors
95
+ And I should see the page body
96
+ And I should see the search bar
97
+ And I should see assistant cards
98
+ ```
99
+
100
+ ### Step Definitions
101
+
102
+ Step definitions are TypeScript files in the `src/steps/` directory that implement the steps from feature files:
103
+
104
+ ```typescript
105
+ import { Given, Then } from '@cucumber/cucumber';
106
+ import { expect } from '@playwright/test';
107
+
108
+ import { CustomWorld } from '../../support/world';
109
+
110
+ Given('I navigate to {string}', async function (this: CustomWorld, path: string) {
111
+ await this.page.goto(path);
112
+ await this.page.waitForLoadState('domcontentloaded');
113
+ });
114
+ ```
115
+
116
+ ## Test Reports
117
+
118
+ After running tests, HTML and JSON reports are generated in the `reports/` directory:
119
+
120
+ - `reports/cucumber-report.html` - Human-readable HTML report
121
+ - `reports/cucumber-report.json` - Machine-readable JSON report
122
+
123
+ ## Troubleshooting
124
+
125
+ ### Browser not found
126
+
127
+ If you see errors about missing browser executables:
128
+
129
+ ```bash
130
+ npx playwright install chromium
131
+ ```
132
+
133
+ ### Port already in use
134
+
135
+ Make sure the dev server is running on the expected port (3010 by default), or set `PORT` or `BASE_URL` environment variable.
136
+
137
+ ### Test timeout
138
+
139
+ Increase timeout in `cucumber.config.js` or `src/steps/hooks.ts`:
140
+
141
+ ```typescript
142
+ setDefaultTimeout(120000); // 2 minutes
143
+ ```
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @type {import('@cucumber/cucumber').IConfiguration}
3
+ */
4
+ export default {
5
+ format: [
6
+ 'progress-bar',
7
+ 'html:reports/cucumber-report.html',
8
+ 'json:reports/cucumber-report.json',
9
+ ],
10
+ formatOptions: {
11
+ snippetInterface: 'async-await',
12
+ },
13
+ parallel: process.env.CI ? 1 : 4,
14
+ paths: ['src/features/**/*.feature'],
15
+ publishQuiet: true,
16
+ require: ['src/steps/**/*.ts', 'src/support/**/*.ts'],
17
+ requireModule: ['tsx/cjs'],
18
+ retry: 0,
19
+ timeout: 120_000,
20
+ };
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@lobechat/e2e-tests",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "description": "E2E tests for LobeChat using Cucumber and Playwright",
6
+ "scripts": {
7
+ "test": "cucumber-js --config cucumber.config.js",
8
+ "test:discover": "cucumber-js --config cucumber.config.js src/features/discover/",
9
+ "test:headed": "HEADLESS=false cucumber-js --config cucumber.config.js",
10
+ "test:routes": "cucumber-js --config cucumber.config.js --tags '@routes'",
11
+ "test:routes:ci": "cucumber-js --config cucumber.config.js --tags '@routes and not @ci-skip'",
12
+ "test:smoke": "cucumber-js --config cucumber.config.js --tags '@smoke'"
13
+ },
14
+ "dependencies": {
15
+ "@cucumber/cucumber": "^12.2.0",
16
+ "@playwright/test": "^1.56.1",
17
+ "playwright": "^1.56.1"
18
+ },
19
+ "devDependencies": {
20
+ "@types/node": "^22.10.5",
21
+ "tsx": "^4.20.6",
22
+ "typescript": "^5.7.3"
23
+ }
24
+ }
@@ -0,0 +1,11 @@
1
+ @discover @smoke
2
+ Feature: Discover Smoke Tests
3
+ Critical path tests to ensure the discover module is functional
4
+
5
+ @DISCOVER-SMOKE-001 @P0
6
+ Scenario: Load discover assistant list page
7
+ Given I navigate to "/discover/assistant"
8
+ Then the page should load without errors
9
+ And I should see the page body
10
+ And I should see the search bar
11
+ And I should see assistant cards
@@ -0,0 +1,43 @@
1
+ @routes @smoke
2
+ Feature: Core Routes Accessibility
3
+ As a user
4
+ I want all core application routes to be accessible
5
+ So that I can navigate the application without errors
6
+
7
+ Background:
8
+ Given the application is running
9
+
10
+ @ROUTES-001 @P0
11
+ Scenario Outline: Access core routes without errors
12
+ When I navigate to "<route>"
13
+ Then the response status should be less than 400
14
+ And the page should load without errors
15
+ And I should see the page body
16
+ And the page title should not contain "error" or "not found"
17
+
18
+ Examples:
19
+ | route |
20
+ | / |
21
+ | /chat |
22
+ | /discover |
23
+ | /files |
24
+ | /repos |
25
+
26
+ @ROUTES-002 @P0
27
+ Scenario Outline: Access settings routes without errors
28
+ When I navigate to "/settings?active=<tab>"
29
+ Then the response status should be less than 400
30
+ And the page should load without errors
31
+ And I should see the page body
32
+ And the page title should not contain "error" or "not found"
33
+
34
+ Examples:
35
+ | tab |
36
+ | about |
37
+ | agent |
38
+ | hotkey |
39
+ | provider |
40
+ | proxy |
41
+ | storage |
42
+ | system-agent |
43
+ | tts |
@@ -0,0 +1,36 @@
1
+ import { Given, Then } from '@cucumber/cucumber';
2
+ import { expect } from '@playwright/test';
3
+
4
+ import { CustomWorld } from '../../support/world';
5
+
6
+ // ============================================
7
+ // Given Steps (Preconditions)
8
+ // ============================================
9
+
10
+ Given('I navigate to {string}', async function (this: CustomWorld, path: string) {
11
+ const response = await this.page.goto(path, { waitUntil: 'commit' });
12
+ this.testContext.lastResponse = response;
13
+ await this.page.waitForLoadState('domcontentloaded');
14
+ });
15
+
16
+ // ============================================
17
+ // Then Steps (Assertions)
18
+ // ============================================
19
+
20
+ Then('the page should load without errors', async function (this: CustomWorld) {
21
+ // Check for no JavaScript errors
22
+ expect(this.testContext.jsErrors).toHaveLength(0);
23
+
24
+ // Check page didn't navigate to error page
25
+ const url = this.page.url();
26
+ expect(url).not.toMatch(/\/404|\/error|not-found/i);
27
+
28
+ // Check no error title
29
+ const title = await this.page.title();
30
+ expect(title).not.toMatch(/not found|error/i);
31
+ });
32
+
33
+ Then('I should see the page body', async function (this: CustomWorld) {
34
+ const body = this.page.locator('body');
35
+ await expect(body).toBeVisible();
36
+ });
@@ -0,0 +1,34 @@
1
+ import { Then } from '@cucumber/cucumber';
2
+ import { expect } from '@playwright/test';
3
+
4
+ import { CustomWorld } from '../../support/world';
5
+
6
+ // ============================================
7
+ // Then Steps (Assertions)
8
+ // ============================================
9
+
10
+ Then('I should see the search bar', async function (this: CustomWorld) {
11
+ // Wait for network to be idle to ensure Suspense components are loaded
12
+ await this.page.waitForLoadState('networkidle', { timeout: 120_000 });
13
+
14
+ // The SearchBar component from @lobehub/ui may not pass through data-testid
15
+ // Try to find the input element within the search component
16
+ const searchBar = this.page.locator('input[type="text"]').first();
17
+ await expect(searchBar).toBeVisible({ timeout: 120_000 });
18
+ });
19
+
20
+ Then('I should see assistant cards', async function (this: CustomWorld) {
21
+ // Wait for content to load
22
+ await this.page.waitForLoadState('networkidle', { timeout: 120_000 });
23
+
24
+ // After migrating to SPA (react-router), links use relative paths like /assistant/:id
25
+ // Look for assistant items by data-testid instead of href
26
+ const assistantItems = this.page.locator('[data-testid="assistant-item"]');
27
+
28
+ // Wait for at least one item to be visible
29
+ await expect(assistantItems.first()).toBeVisible({ timeout: 120_000 });
30
+
31
+ // Check we have multiple items
32
+ const count = await assistantItems.count();
33
+ expect(count).toBeGreaterThan(0);
34
+ });
@@ -0,0 +1,69 @@
1
+ import { After, AfterAll, Before, BeforeAll, Status, setDefaultTimeout } from '@cucumber/cucumber';
2
+
3
+ import { startWebServer, stopWebServer } from '../support/webServer';
4
+ import { CustomWorld } from '../support/world';
5
+
6
+ // Set default timeout for all steps to 120 seconds
7
+ setDefaultTimeout(120_000);
8
+
9
+ BeforeAll({ timeout: 120_000 }, async function () {
10
+ console.log('🚀 Starting E2E test suite...');
11
+
12
+ const PORT = process.env.PORT ? Number(process.env.PORT) : 3010;
13
+ const BASE_URL = process.env.BASE_URL || `http://localhost:${PORT}`;
14
+
15
+ console.log(`Base URL: ${BASE_URL}`);
16
+
17
+ // Start web server if not using external BASE_URL
18
+ if (!process.env.BASE_URL) {
19
+ await startWebServer({
20
+ command: 'npm run dev',
21
+ port: PORT,
22
+ reuseExistingServer: !process.env.CI,
23
+ });
24
+ }
25
+ });
26
+
27
+ Before(async function (this: CustomWorld, { pickle }) {
28
+ await this.init();
29
+
30
+ const testId = pickle.tags.find((tag) => tag.name.startsWith('@DISCOVER-'));
31
+ console.log(`\n📝 Running: ${pickle.name}${testId ? ` (${testId.name.replace('@', '')})` : ''}`);
32
+ });
33
+
34
+ After(async function (this: CustomWorld, { pickle, result }) {
35
+ const testId = pickle.tags
36
+ .find((tag) => tag.name.startsWith('@DISCOVER-'))
37
+ ?.name.replace('@', '');
38
+
39
+ if (result?.status === Status.FAILED) {
40
+ const screenshot = await this.takeScreenshot(`${testId || 'failure'}-${Date.now()}`);
41
+ this.attach(screenshot, 'image/png');
42
+
43
+ const html = await this.page.content();
44
+ this.attach(html, 'text/html');
45
+
46
+ if (this.testContext.jsErrors.length > 0) {
47
+ const errors = this.testContext.jsErrors.map((e) => e.message).join('\n');
48
+ this.attach(`JavaScript Errors:\n${errors}`, 'text/plain');
49
+ }
50
+
51
+ console.log(`❌ Failed: ${pickle.name}`);
52
+ if (result.message) {
53
+ console.log(` Error: ${result.message}`);
54
+ }
55
+ } else if (result?.status === Status.PASSED) {
56
+ console.log(`✅ Passed: ${pickle.name}`);
57
+ }
58
+
59
+ await this.cleanup();
60
+ });
61
+
62
+ AfterAll(async function () {
63
+ console.log('\n🏁 Test suite completed');
64
+
65
+ // Stop web server if we started it
66
+ if (!process.env.BASE_URL && process.env.CI) {
67
+ await stopWebServer();
68
+ }
69
+ });