@lobehub/lobehub 2.0.0-next.266 → 2.0.0-next.268

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 (136) hide show
  1. package/.cursor/rules/microcopy-cn.mdc +75 -63
  2. package/.cursor/rules/microcopy-en.mdc +4 -8
  3. package/CHANGELOG.md +50 -0
  4. package/README.md +8 -8
  5. package/README.zh-CN.md +8 -8
  6. package/apps/desktop/src/main/locales/default/common.ts +2 -2
  7. package/changelog/v1.json +10 -0
  8. package/docs/development/database-schema.dbml +4 -0
  9. package/e2e/CLAUDE.md +43 -81
  10. package/e2e/cucumber.config.js +1 -0
  11. package/e2e/docs/local-setup.md +67 -219
  12. package/e2e/scripts/setup.ts +529 -0
  13. package/e2e/src/features/home/sidebarAgent.feature +62 -0
  14. package/e2e/src/features/home/sidebarGroup.feature +62 -0
  15. package/e2e/src/features/page/README.md +118 -0
  16. package/e2e/src/features/page/crud.feature +62 -0
  17. package/e2e/src/features/page/editor-content.feature +93 -0
  18. package/e2e/src/features/page/editor-meta.feature +60 -0
  19. package/e2e/src/steps/agent/conversation.steps.ts +4 -4
  20. package/e2e/src/steps/home/sidebarAgent.steps.ts +370 -0
  21. package/e2e/src/steps/home/sidebarGroup.steps.ts +168 -0
  22. package/e2e/src/steps/hooks.ts +4 -0
  23. package/e2e/src/steps/page/editor-content.steps.ts +344 -0
  24. package/e2e/src/steps/page/editor-meta.steps.ts +410 -0
  25. package/e2e/src/steps/page/page-crud.steps.ts +363 -0
  26. package/e2e/src/support/world.ts +12 -0
  27. package/locales/ar/file.json +2 -0
  28. package/locales/bg-BG/file.json +2 -0
  29. package/locales/de-DE/file.json +2 -0
  30. package/locales/en-US/auth.json +1 -1
  31. package/locales/en-US/file.json +2 -0
  32. package/locales/en-US/metadata.json +2 -2
  33. package/locales/es-ES/file.json +2 -0
  34. package/locales/fa-IR/file.json +2 -0
  35. package/locales/fr-FR/file.json +2 -0
  36. package/locales/it-IT/file.json +2 -0
  37. package/locales/ja-JP/file.json +2 -0
  38. package/locales/ko-KR/file.json +2 -0
  39. package/locales/nl-NL/file.json +2 -0
  40. package/locales/pl-PL/file.json +2 -0
  41. package/locales/pt-BR/file.json +2 -0
  42. package/locales/ru-RU/file.json +2 -0
  43. package/locales/tr-TR/file.json +2 -0
  44. package/locales/vi-VN/file.json +2 -0
  45. package/locales/zh-CN/file.json +2 -0
  46. package/locales/zh-TW/file.json +2 -0
  47. package/package.json +3 -3
  48. package/packages/builtin-agents/src/agents/agent-builder/index.ts +1 -1
  49. package/packages/builtin-agents/src/agents/group-agent-builder/index.ts +1 -1
  50. package/packages/builtin-agents/src/agents/page-agent/index.ts +1 -1
  51. package/packages/const/src/settings/group.ts +0 -10
  52. package/packages/database/migrations/0068_update_group_data.sql +4 -0
  53. package/packages/database/migrations/meta/0068_snapshot.json +9588 -0
  54. package/packages/database/migrations/meta/_journal.json +7 -0
  55. package/packages/database/src/models/__tests__/chatGroup.test.ts +5 -7
  56. package/packages/database/src/models/__tests__/knowledgeBase.test.ts +185 -0
  57. package/packages/database/src/models/knowledgeBase.ts +67 -3
  58. package/packages/database/src/repositories/agentGroup/index.test.ts +23 -29
  59. package/packages/database/src/repositories/agentGroup/index.ts +4 -9
  60. package/packages/database/src/repositories/knowledge/index.ts +3 -3
  61. package/packages/database/src/schemas/chatGroup.ts +4 -3
  62. package/packages/database/src/types/chatGroup.ts +0 -7
  63. package/packages/types/src/agentGroup/index.ts +30 -9
  64. package/packages/utils/src/multimodalContent.test.ts +302 -0
  65. package/packages/utils/src/server/__tests__/sse.test.ts +353 -0
  66. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentGroupItem/Editing.tsx +4 -11
  67. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentGroupItem/index.tsx +3 -3
  68. package/src/app/[variants]/(main)/home/_layout/Body/Agent/ModalProvider.tsx +9 -32
  69. package/src/app/[variants]/(main)/home/_layout/hooks/useCreateMenuItems.tsx +3 -37
  70. package/src/app/[variants]/(main)/home/_layout/hooks/useSessionGroupMenuItems.tsx +7 -53
  71. package/src/app/[variants]/(main)/home/features/RecentPage/List.tsx +2 -1
  72. package/src/app/[variants]/(main)/resource/features/DndContextWrapper.tsx +1 -1
  73. package/src/app/[variants]/(main)/resource/library/_layout/Sidebar.tsx +2 -2
  74. package/src/app/[variants]/(main)/resource/library/features/LibraryMenu.tsx +2 -2
  75. package/src/app/[variants]/(mobile)/chat/settings/features/SettingButton.tsx +2 -12
  76. package/src/components/ChatGroupWizard/ChatGroupWizard.tsx +5 -27
  77. package/src/components/DragUpload/index.tsx +24 -27
  78. package/src/components/MemberSelectionModal/MemberSelectionModal.tsx +2 -11
  79. package/src/features/ChatInput/ActionBar/Params/Controls.tsx +42 -7
  80. package/src/features/CommandMenu/useCommandMenu.ts +4 -14
  81. package/src/features/ResourceManager/components/Editor/index.tsx +2 -3
  82. package/src/features/ResourceManager/components/Explorer/Header/index.tsx +13 -17
  83. package/src/features/ResourceManager/components/Explorer/ItemDropdown/useFileItemDropdown.tsx +1 -1
  84. package/src/features/ResourceManager/components/Explorer/ListView/ListItem/TruncatedFileName.tsx +130 -0
  85. package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +36 -4
  86. package/src/features/ResourceManager/components/Explorer/ListView/Skeleton.tsx +4 -3
  87. package/src/features/ResourceManager/components/Explorer/ListView/index.tsx +58 -2
  88. package/src/features/ResourceManager/components/Explorer/MasonryView/index.tsx +58 -6
  89. package/src/features/ResourceManager/components/Explorer/MoveToFolderModal.tsx +2 -5
  90. package/src/features/ResourceManager/components/Explorer/ToolBar/BatchActionsDropdown.tsx +9 -5
  91. package/src/features/ResourceManager/components/Explorer/index.tsx +11 -56
  92. package/src/features/ResourceManager/components/Header/AddButton.tsx +5 -6
  93. package/src/features/ResourceManager/components/LibraryHierarchy/HierarchyNode.tsx +382 -0
  94. package/src/features/ResourceManager/components/LibraryHierarchy/index.tsx +396 -0
  95. package/src/features/ResourceManager/components/LibraryHierarchy/styles.ts +19 -0
  96. package/src/features/ResourceManager/components/LibraryHierarchy/treeState.ts +178 -0
  97. package/src/features/ResourceManager/components/LibraryHierarchy/types.ts +10 -0
  98. package/src/features/ResourceManager/index.tsx +3 -0
  99. package/src/layout/GlobalProvider/GroupWizardProvider.tsx +6 -29
  100. package/src/locales/default/auth.ts +1 -1
  101. package/src/locales/default/file.ts +2 -0
  102. package/src/locales/default/metadata.ts +2 -2
  103. package/src/server/modules/AgentRuntime/AgentRuntimeCoordinator.ts +30 -30
  104. package/src/server/modules/AgentRuntime/AgentStateManager.ts +23 -23
  105. package/src/server/modules/AgentRuntime/InMemoryAgentStateManager.ts +16 -16
  106. package/src/server/modules/AgentRuntime/InMemoryStreamEventManager.ts +13 -13
  107. package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +2 -2
  108. package/src/server/modules/AgentRuntime/StreamEventManager.ts +18 -18
  109. package/src/server/modules/AgentRuntime/types.ts +21 -21
  110. package/src/server/routers/lambda/__tests__/agentGroup.test.ts +8 -8
  111. package/src/server/routers/lambda/agentGroup.ts +10 -12
  112. package/src/server/services/document/index.ts +1 -0
  113. package/src/store/agentGroup/slices/curd.test.ts +4 -4
  114. package/src/store/file/slices/fileManager/action.ts +12 -4
  115. package/src/store/home/slices/homeInput/action.ts +0 -3
  116. package/src/store/home/slices/sidebarUI/action.ts +9 -0
  117. package/src/store/session/slices/session/action.ts +5 -9
  118. package/src/app/[variants]/(mobile)/chat/settings/features/AgentTeamSettings/index.tsx +0 -95
  119. package/src/features/GroupChatSettings/AgentCard.tsx +0 -154
  120. package/src/features/GroupChatSettings/AgentTeamChatSettings.tsx +0 -179
  121. package/src/features/GroupChatSettings/AgentTeamMembersSettings.tsx +0 -244
  122. package/src/features/GroupChatSettings/AgentTeamMetaSettings.tsx +0 -94
  123. package/src/features/GroupChatSettings/AgentTeamSettings.tsx +0 -54
  124. package/src/features/GroupChatSettings/GroupCategory/index.tsx +0 -30
  125. package/src/features/GroupChatSettings/GroupCategory/useGroupCategory.tsx +0 -42
  126. package/src/features/GroupChatSettings/GroupChatSettingsProvider.tsx +0 -19
  127. package/src/features/GroupChatSettings/HostMemberCard.tsx +0 -113
  128. package/src/features/GroupChatSettings/StoreUpdater.tsx +0 -34
  129. package/src/features/GroupChatSettings/hooks/useGroupChatSettings.ts +0 -25
  130. package/src/features/GroupChatSettings/index.ts +0 -16
  131. package/src/features/GroupChatSettings/store/action.ts +0 -105
  132. package/src/features/GroupChatSettings/store/index.ts +0 -18
  133. package/src/features/GroupChatSettings/store/initialState.ts +0 -23
  134. package/src/features/GroupChatSettings/store/selectors.ts +0 -13
  135. package/src/features/ResourceManager/components/Tree/index.tsx +0 -883
  136. /package/src/features/ResourceManager/components/{Tree → LibraryHierarchy}/TreeSkeleton.tsx +0 -0
@@ -53,7 +53,7 @@ export interface StreamChunkData {
53
53
  export class StreamEventManager {
54
54
  private redis: Redis;
55
55
  private readonly STREAM_PREFIX = 'agent_runtime_stream';
56
- private readonly STREAM_RETENTION = 2 * 3600; // 2小时
56
+ private readonly STREAM_RETENTION = 2 * 3600; // 2 hours
57
57
 
58
58
  constructor() {
59
59
  const redisClient = getAgentRuntimeRedisClient();
@@ -64,7 +64,7 @@ export class StreamEventManager {
64
64
  }
65
65
 
66
66
  /**
67
- * 发布流式事件到 Redis Stream
67
+ * Publish stream event to Redis Stream
68
68
  */
69
69
  async publishStreamEvent(
70
70
  operationId: string,
@@ -84,8 +84,8 @@ export class StreamEventManager {
84
84
  streamKey,
85
85
  'MAXLEN',
86
86
  '~',
87
- '1000', // 限制流长度,防止内存溢出
88
- '*', // 自动生成 ID
87
+ '1000', // Limit stream length to prevent memory overflow
88
+ '*', // Auto-generate ID
89
89
  'type',
90
90
  eventData.type,
91
91
  'stepIndex',
@@ -99,7 +99,7 @@ export class StreamEventManager {
99
99
  );
100
100
  const xaddEnd = Date.now();
101
101
 
102
- // 设置过期时间
102
+ // Set expiration time
103
103
  await this.redis.expire(streamKey, this.STREAM_RETENTION);
104
104
 
105
105
  log(
@@ -126,7 +126,7 @@ export class StreamEventManager {
126
126
  }
127
127
 
128
128
  /**
129
- * 发布流式内容块
129
+ * Publish stream content chunk
130
130
  */
131
131
  async publishStreamChunk(
132
132
  operationId: string,
@@ -141,7 +141,7 @@ export class StreamEventManager {
141
141
  }
142
142
 
143
143
  /**
144
- * 发布 Agent 运行时初始化事件
144
+ * Publish Agent runtime initialization event
145
145
  */
146
146
  async publishAgentRuntimeInit(operationId: string, initialState: any): Promise<string> {
147
147
  return this.publishStreamEvent(operationId, {
@@ -152,7 +152,7 @@ export class StreamEventManager {
152
152
  }
153
153
 
154
154
  /**
155
- * 发布 Agent 运行时结束事件
155
+ * Publish Agent runtime end event
156
156
  */
157
157
  async publishAgentRuntimeEnd(
158
158
  operationId: string,
@@ -175,7 +175,7 @@ export class StreamEventManager {
175
175
  }
176
176
 
177
177
  /**
178
- * 订阅流式事件(用于 WebSocket/SSE
178
+ * Subscribe to stream events (for WebSocket/SSE)
179
179
  */
180
180
  async subscribeStreamEvents(
181
181
  operationId: string,
@@ -193,7 +193,7 @@ export class StreamEventManager {
193
193
  const xreadStart = Date.now();
194
194
  const results = await this.redis.xread(
195
195
  'BLOCK',
196
- 1000, // 1秒超时
196
+ 1000, // 1 second timeout
197
197
  'STREAMS',
198
198
  streamKey,
199
199
  currentLastId,
@@ -207,7 +207,7 @@ export class StreamEventManager {
207
207
  for (const [id, fields] of messages) {
208
208
  const eventData: any = {};
209
209
 
210
- // 解析 Redis Stream 字段
210
+ // Parse Redis Stream fields
211
211
  for (let i = 0; i < fields.length; i += 2) {
212
212
  const key = fields[i];
213
213
  const value = fields[i + 1];
@@ -223,7 +223,7 @@ export class StreamEventManager {
223
223
 
224
224
  events.push({
225
225
  ...eventData,
226
- id, // Redis Stream 事件 ID
226
+ id, // Redis Stream event ID
227
227
  } as StreamEvent);
228
228
 
229
229
  currentLastId = id;
@@ -231,7 +231,7 @@ export class StreamEventManager {
231
231
 
232
232
  if (events.length > 0) {
233
233
  const now = Date.now();
234
- // 计算事件从发布到被读取的延迟
234
+ // Calculate latency from event publication to read
235
235
  for (const event of events) {
236
236
  const latency = now - event.timestamp;
237
237
  timing(
@@ -254,7 +254,7 @@ export class StreamEventManager {
254
254
  }
255
255
 
256
256
  console.error('[StreamEventManager] Stream subscription error:', error);
257
- // 短暂延迟后重试
257
+ // Retry after brief delay
258
258
  await new Promise((resolve) => {
259
259
  setTimeout(resolve, 1000);
260
260
  });
@@ -265,7 +265,7 @@ export class StreamEventManager {
265
265
  }
266
266
 
267
267
  /**
268
- * 获取流式事件历史
268
+ * Get stream event history
269
269
  */
270
270
  async getStreamHistory(operationId: string, count: number = 100): Promise<StreamEvent[]> {
271
271
  const streamKey = `${this.STREAM_PREFIX}:${operationId}`;
@@ -298,7 +298,7 @@ export class StreamEventManager {
298
298
  }
299
299
 
300
300
  /**
301
- * 清理操作的流式数据
301
+ * Clean up stream data for operation
302
302
  */
303
303
  async cleanupOperation(operationId: string): Promise<void> {
304
304
  const streamKey = `${this.STREAM_PREFIX}:${operationId}`;
@@ -312,7 +312,7 @@ export class StreamEventManager {
312
312
  }
313
313
 
314
314
  /**
315
- * 获取活跃操作数量
315
+ * Get count of active operations
316
316
  */
317
317
  async getActiveOperationsCount(): Promise<number> {
318
318
  try {
@@ -326,7 +326,7 @@ export class StreamEventManager {
326
326
  }
327
327
 
328
328
  /**
329
- * 关闭 Redis 连接
329
+ * Close Redis connection
330
330
  */
331
331
  async disconnect(): Promise<void> {
332
332
  await this.redis.quit();
@@ -5,16 +5,16 @@ import type { StreamChunkData, StreamEvent } from './StreamEventManager';
5
5
 
6
6
  /**
7
7
  * Agent State Manager Interface
8
- * 用于状态持久化的抽象接口,支持 Redis 和内存实现
8
+ * Abstract interface for state persistence, supports Redis and in-memory implementations
9
9
  */
10
10
  export interface IAgentStateManager {
11
11
  /**
12
- * 清理过期的操作数据
12
+ * Clean up expired operation data
13
13
  */
14
14
  cleanupExpiredOperations(): Promise<number>;
15
15
 
16
16
  /**
17
- * 创建新的操作元数据
17
+ * Create new operation metadata
18
18
  */
19
19
  createOperationMetadata(
20
20
  operationId: string,
@@ -26,32 +26,32 @@ export interface IAgentStateManager {
26
26
  ): Promise<void>;
27
27
 
28
28
  /**
29
- * 删除 Agent 操作的所有数据
29
+ * Delete all data for Agent operation
30
30
  */
31
31
  deleteAgentOperation(operationId: string): Promise<void>;
32
32
 
33
33
  /**
34
- * 关闭连接
34
+ * Close connections
35
35
  */
36
36
  disconnect(): Promise<void>;
37
37
 
38
38
  /**
39
- * 获取所有活跃操作
39
+ * Get all active operations
40
40
  */
41
41
  getActiveOperations(): Promise<string[]>;
42
42
 
43
43
  /**
44
- * 获取执行历史
44
+ * Get execution history
45
45
  */
46
46
  getExecutionHistory(operationId: string, limit?: number): Promise<any[]>;
47
47
 
48
48
  /**
49
- * 获取操作元数据
49
+ * Get operation metadata
50
50
  */
51
51
  getOperationMetadata(operationId: string): Promise<AgentOperationMetadata | null>;
52
52
 
53
53
  /**
54
- * 获取统计信息
54
+ * Get statistics
55
55
  */
56
56
  getStats(): Promise<{
57
57
  activeOperations: number;
@@ -61,48 +61,48 @@ export interface IAgentStateManager {
61
61
  }>;
62
62
 
63
63
  /**
64
- * 加载 Agent 状态
64
+ * Load Agent state
65
65
  */
66
66
  loadAgentState(operationId: string): Promise<AgentState | null>;
67
67
 
68
68
  /**
69
- * 保存 Agent 状态
69
+ * Save Agent state
70
70
  */
71
71
  saveAgentState(operationId: string, state: AgentState): Promise<void>;
72
72
 
73
73
  /**
74
- * 保存步骤执行结果
74
+ * Save step execution result
75
75
  */
76
76
  saveStepResult(operationId: string, stepResult: StepResult): Promise<void>;
77
77
  }
78
78
 
79
79
  /**
80
80
  * Stream Event Manager Interface
81
- * 用于流式事件发布的抽象接口,支持 Redis 和内存实现
81
+ * Abstract interface for stream event publishing, supports Redis and in-memory implementations
82
82
  */
83
83
  export interface IStreamEventManager {
84
84
  /**
85
- * 清理操作的流式数据
85
+ * Clean up stream data for operation
86
86
  */
87
87
  cleanupOperation(operationId: string): Promise<void>;
88
88
 
89
89
  /**
90
- * 关闭连接
90
+ * Close connections
91
91
  */
92
92
  disconnect(): Promise<void>;
93
93
 
94
94
  /**
95
- * 获取活跃操作数量
95
+ * Get count of active operations
96
96
  */
97
97
  getActiveOperationsCount(): Promise<number>;
98
98
 
99
99
  /**
100
- * 获取流式事件历史
100
+ * Get stream event history
101
101
  */
102
102
  getStreamHistory(operationId: string, count?: number): Promise<StreamEvent[]>;
103
103
 
104
104
  /**
105
- * 发布 Agent 运行时结束事件
105
+ * Publish Agent runtime end event
106
106
  */
107
107
  publishAgentRuntimeEnd(
108
108
  operationId: string,
@@ -113,12 +113,12 @@ export interface IStreamEventManager {
113
113
  ): Promise<string>;
114
114
 
115
115
  /**
116
- * 发布 Agent 运行时初始化事件
116
+ * Publish Agent runtime initialization event
117
117
  */
118
118
  publishAgentRuntimeInit(operationId: string, initialState: any): Promise<string>;
119
119
 
120
120
  /**
121
- * 发布流式内容块
121
+ * Publish stream content chunk
122
122
  */
123
123
  publishStreamChunk(
124
124
  operationId: string,
@@ -127,7 +127,7 @@ export interface IStreamEventManager {
127
127
  ): Promise<string>;
128
128
 
129
129
  /**
130
- * 发布流式事件
130
+ * Publish stream event
131
131
  */
132
132
  publishStreamEvent(
133
133
  operationId: string,
@@ -84,7 +84,7 @@ describe('agentGroupRouter', () => {
84
84
  title: 'Test Group',
85
85
  description: 'Test Description',
86
86
  config: {
87
- enableSupervisor: true,
87
+ allowDM: true,
88
88
  },
89
89
  };
90
90
 
@@ -92,7 +92,7 @@ describe('agentGroupRouter', () => {
92
92
  id: 'group-1',
93
93
  title: 'Test Group',
94
94
  description: 'Test Description',
95
- config: { ...DEFAULT_CHAT_GROUP_CHAT_CONFIG, enableSupervisor: true },
95
+ config: { ...DEFAULT_CHAT_GROUP_CHAT_CONFIG, allowDM: true },
96
96
  };
97
97
 
98
98
  agentGroupRepoMock.createGroupWithSupervisor.mockResolvedValue({
@@ -105,7 +105,7 @@ describe('agentGroupRouter', () => {
105
105
 
106
106
  expect(agentGroupRepoMock.createGroupWithSupervisor).toHaveBeenCalledWith({
107
107
  ...mockInput,
108
- config: { ...DEFAULT_CHAT_GROUP_CHAT_CONFIG, enableSupervisor: true },
108
+ config: { ...DEFAULT_CHAT_GROUP_CHAT_CONFIG, allowDM: true },
109
109
  });
110
110
  expect(result).toEqual({ group: mockCreatedGroup, supervisorAgentId: 'supervisor-1' });
111
111
  });
@@ -141,7 +141,7 @@ describe('agentGroupRouter', () => {
141
141
  const mockInput = {
142
142
  groupConfig: {
143
143
  title: 'Team Group',
144
- config: { enableSupervisor: true },
144
+ config: { allowDM: true },
145
145
  },
146
146
  members: [
147
147
  { title: 'Agent 1', systemRole: 'Helper' },
@@ -168,7 +168,7 @@ describe('agentGroupRouter', () => {
168
168
  expect(agentGroupRepoMock.createGroupWithSupervisor).toHaveBeenCalledWith(
169
169
  {
170
170
  title: 'Team Group',
171
- config: { ...DEFAULT_CHAT_GROUP_CHAT_CONFIG, enableSupervisor: true },
171
+ config: { ...DEFAULT_CHAT_GROUP_CHAT_CONFIG, allowDM: true },
172
172
  },
173
173
  ['agent-1', 'agent-2'],
174
174
  );
@@ -388,14 +388,14 @@ describe('agentGroupRouter', () => {
388
388
  id: 'group-1',
389
389
  value: {
390
390
  title: 'Updated Title',
391
- config: { enableSupervisor: false },
391
+ config: { allowDM: false },
392
392
  },
393
393
  };
394
394
 
395
395
  const mockUpdatedGroup = {
396
396
  id: 'group-1',
397
397
  title: 'Updated Title',
398
- config: { ...DEFAULT_CHAT_GROUP_CHAT_CONFIG, enableSupervisor: false },
398
+ config: { ...DEFAULT_CHAT_GROUP_CHAT_CONFIG, allowDM: false },
399
399
  };
400
400
 
401
401
  chatGroupModelMock.update.mockResolvedValue(mockUpdatedGroup);
@@ -405,7 +405,7 @@ describe('agentGroupRouter', () => {
405
405
 
406
406
  expect(chatGroupModelMock.update).toHaveBeenCalledWith('group-1', {
407
407
  title: 'Updated Title',
408
- config: { ...DEFAULT_CHAT_GROUP_CHAT_CONFIG, enableSupervisor: false },
408
+ config: { ...DEFAULT_CHAT_GROUP_CHAT_CONFIG, allowDM: false },
409
409
  });
410
410
  expect(result).toEqual(mockUpdatedGroup);
411
411
  });
@@ -1,3 +1,4 @@
1
+ import { InsertChatGroupSchema } from '@lobechat/types';
1
2
  import { z } from 'zod';
2
3
 
3
4
  import { AgentModel } from '@/database/models/agent';
@@ -5,7 +6,6 @@ import { ChatGroupModel } from '@/database/models/chatGroup';
5
6
  import { UserModel } from '@/database/models/user';
6
7
  import { AgentGroupRepository } from '@/database/repositories/agentGroup';
7
8
  import { insertAgentSchema } from '@/database/schemas';
8
- import { insertChatGroupSchema } from '@/database/schemas/chatGroup';
9
9
  import { type ChatGroupConfig } from '@/database/types/chatGroup';
10
10
  import { authedProcedure, router } from '@/libs/trpc/lambda';
11
11
  import { serverDatabase } from '@/libs/trpc/lambda/middleware';
@@ -57,16 +57,14 @@ export const agentGroupRouter = router({
57
57
  * The supervisor agent is automatically created as a virtual agent.
58
58
  * Returns the groupId and supervisorAgentId.
59
59
  */
60
- createGroup: agentGroupProcedure
61
- .input(insertChatGroupSchema.omit({ userId: true }))
62
- .mutation(async ({ input, ctx }) => {
63
- const { group, supervisorAgentId } = await ctx.agentGroupRepo.createGroupWithSupervisor({
64
- ...input,
65
- config: ctx.agentGroupService.normalizeGroupConfig(input.config as ChatGroupConfig | null),
66
- });
60
+ createGroup: agentGroupProcedure.input(InsertChatGroupSchema).mutation(async ({ input, ctx }) => {
61
+ const { group, supervisorAgentId } = await ctx.agentGroupRepo.createGroupWithSupervisor({
62
+ ...input,
63
+ config: ctx.agentGroupService.normalizeGroupConfig(input.config as ChatGroupConfig | null),
64
+ });
67
65
 
68
- return { group, supervisorAgentId };
69
- }),
66
+ return { group, supervisorAgentId };
67
+ }),
70
68
 
71
69
  /**
72
70
  * Create a group with virtual member agents in one request.
@@ -80,7 +78,7 @@ export const agentGroupRouter = router({
80
78
  createGroupWithMembers: agentGroupProcedure
81
79
  .input(
82
80
  z.object({
83
- groupConfig: insertChatGroupSchema.omit({ userId: true }),
81
+ groupConfig: InsertChatGroupSchema,
84
82
  members: z.array(
85
83
  insertAgentSchema
86
84
  .omit({
@@ -227,7 +225,7 @@ export const agentGroupRouter = router({
227
225
  .input(
228
226
  z.object({
229
227
  id: z.string(),
230
- value: insertChatGroupSchema.partial(),
228
+ value: InsertChatGroupSchema.partial(),
231
229
  }),
232
230
  )
233
231
  .mutation(async ({ input, ctx }) => {
@@ -86,6 +86,7 @@ export class DocumentService {
86
86
  fileId,
87
87
  fileType,
88
88
  filename: title,
89
+ knowledgeBaseId, // Set knowledge_base_id column for all document types
89
90
  metadata: finalMetadata,
90
91
  pages: undefined,
91
92
  parentId,
@@ -87,13 +87,13 @@ describe('ChatGroupCurdSlice', () => {
87
87
  const { result } = renderHook(() => useAgentGroupStore());
88
88
 
89
89
  await act(async () => {
90
- await result.current.updateGroupConfig({ enableSupervisor: false });
90
+ await result.current.updateGroupConfig({ allowDM: false });
91
91
  });
92
92
 
93
93
  expect(chatGroupService.updateGroup).toHaveBeenCalledWith('group-1', {
94
94
  config: expect.objectContaining({
95
95
  ...DEFAULT_CHAT_GROUP_CHAT_CONFIG,
96
- enableSupervisor: false,
96
+ allowDM: false,
97
97
  }),
98
98
  });
99
99
  });
@@ -109,7 +109,7 @@ describe('ChatGroupCurdSlice', () => {
109
109
  const { result } = renderHook(() => useAgentGroupStore());
110
110
 
111
111
  await act(async () => {
112
- await result.current.updateGroupConfig({ enableSupervisor: false });
112
+ await result.current.updateGroupConfig({ allowDM: false });
113
113
  });
114
114
 
115
115
  expect(chatGroupService.updateGroup).not.toHaveBeenCalled();
@@ -121,7 +121,7 @@ describe('ChatGroupCurdSlice', () => {
121
121
  const { result } = renderHook(() => useAgentGroupStore());
122
122
 
123
123
  await act(async () => {
124
- await result.current.updateGroupConfig({ scene: 'casual' });
124
+ await result.current.updateGroupConfig({ revealDM: true });
125
125
  });
126
126
 
127
127
  expect(mutate).toHaveBeenCalledWith(['fetchGroupDetail', 'group-1']);
@@ -307,6 +307,11 @@ export const createFileManageSlice: StateCreator<
307
307
  revalidate: true,
308
308
  },
309
309
  );
310
+
311
+ // Also revalidate the ResourceManager resource list cache (SWR_RESOURCES)
312
+ // so uploaded files appear immediately in the Explorer without a full refresh.
313
+ const { revalidateResources } = await import('../resource/hooks');
314
+ await revalidateResources();
310
315
  },
311
316
  removeAllFiles: async () => {
312
317
  await fileService.removeAllFiles();
@@ -543,10 +548,13 @@ export const createFileManageSlice: StateCreator<
543
548
  }),
544
549
 
545
550
  useFetchKnowledgeItem: (id) =>
546
- useClientDataSWR<FileListItem | undefined>(!id ? null : ['useFetchKnowledgeItem', id], async () => {
547
- const response = await serverFileService.getKnowledgeItem(id!);
548
- return response ?? undefined;
549
- }),
551
+ useClientDataSWR<FileListItem | undefined>(
552
+ !id ? null : ['useFetchKnowledgeItem', id],
553
+ async () => {
554
+ const response = await serverFileService.getKnowledgeItem(id!);
555
+ return response ?? undefined;
556
+ },
557
+ ),
550
558
 
551
559
  useFetchKnowledgeItems: (params) =>
552
560
  useClientDataSWR<FileListItem[]>([FETCH_ALL_KNOWLEDGE_KEY, params], async () => {
@@ -110,9 +110,6 @@ export const createHomeInputSlice: StateCreator<
110
110
  // 2. Create new Group with inherited model/provider for orchestrator
111
111
  const { group } = await chatGroupService.createGroup({
112
112
  config: {
113
- orchestratorModel: model,
114
- orchestratorProvider: provider,
115
- scene: 'productive',
116
113
  systemPrompt: message,
117
114
  },
118
115
  title: message?.slice(0, 50) || 'New Group',
@@ -40,6 +40,10 @@ export interface SidebarUIAction {
40
40
  * Remove an agent group (group chat)
41
41
  */
42
42
  removeAgentGroup: (groupId: string) => Promise<void>;
43
+ /**
44
+ * Rename an agent group (group chat)
45
+ */
46
+ renameAgentGroup: (groupId: string, title: string) => Promise<void>;
43
47
  /**
44
48
  * Update agent's group
45
49
  */
@@ -162,6 +166,11 @@ export const createSidebarUISlice: StateCreator<
162
166
  await get().refreshAgentList();
163
167
  },
164
168
 
169
+ renameAgentGroup: async (groupId, title) => {
170
+ await chatGroupService.updateGroup(groupId, { title });
171
+ await get().refreshAgentList();
172
+ },
173
+
165
174
  updateAgentGroup: async (agentId, groupId) => {
166
175
  await homeService.updateAgentSessionGroupId(agentId, groupId === 'default' ? null : groupId);
167
176
  await get().refreshAgentList();
@@ -7,7 +7,6 @@ import { type StateCreator } from 'zustand/vanilla';
7
7
 
8
8
  import { message } from '@/components/AntdStaticMethods';
9
9
  import { DEFAULT_AGENT_LOBE_SESSION, INBOX_SESSION_ID } from '@/const/session';
10
- import { DEFAULT_CHAT_GROUP_CHAT_CONFIG } from '@/const/settings';
11
10
  import { mutate, useClientDataSWR } from '@/libs/swr';
12
11
  import { chatGroupService } from '@/services/chatGroup';
13
12
  import { sessionService } from '@/services/session';
@@ -281,17 +280,14 @@ export const createSessionSlice: StateCreator<
281
280
  const chatGroupStore = getChatGroupStoreState();
282
281
  const chatGroups = groupSessions.map((session) => ({
283
282
  accessedAt: session.updatedAt,
283
+ avatar: null,
284
+ backgroundColor: null,
284
285
  clientId: null,
285
- config: {
286
- maxResponseInRow: 3,
287
- orchestratorModel: 'gpt-4',
288
- orchestratorProvider: 'openai',
289
- responseOrder: 'sequential' as const,
290
- responseSpeed: 'medium' as const,
291
- scene: DEFAULT_CHAT_GROUP_CHAT_CONFIG.scene,
292
- },
286
+ config: null,
287
+ content: null,
293
288
  createdAt: session.createdAt,
294
289
  description: session.meta?.description || '',
290
+ editorData: null,
295
291
 
296
292
  groupId: session.group || null,
297
293
  id: session.id, // Add the missing groupId property
@@ -1,95 +0,0 @@
1
- 'use client';
2
-
3
- import { Drawer, Flexbox } from '@lobehub/ui';
4
- import isEqual from 'fast-deep-equal';
5
- import { memo, useState } from 'react';
6
- import { useTranslation } from 'react-i18next';
7
-
8
- import BrandWatermark from '@/components/BrandWatermark';
9
- import PanelTitle from '@/components/PanelTitle';
10
- import { isDesktop } from '@/const/version';
11
- import { TITLE_BAR_HEIGHT } from '@/features/ElectronTitlebar';
12
- import {
13
- AgentTeamSettings,
14
- GroupCategory,
15
- GroupChatSettingsProvider,
16
- } from '@/features/GroupChatSettings';
17
- import Footer from '@/features/Setting/Footer';
18
- import { useInitGroupConfig } from '@/hooks/useInitGroupConfig';
19
- import { useAgentGroupStore } from '@/store/agentGroup';
20
- import { agentGroupSelectors } from '@/store/agentGroup/selectors';
21
- import { GroupSettingsTabs } from '@/store/global/initialState';
22
- import { useSessionStore } from '@/store/session';
23
-
24
- const AgentTeamSettingsWrapper = memo(() => {
25
- const { t } = useTranslation('setting');
26
- const id = useSessionStore((s) => s.activeId);
27
- const config = useAgentGroupStore(agentGroupSelectors.currentGroupConfig, isEqual);
28
- const meta = useAgentGroupStore(agentGroupSelectors.currentGroupMeta, isEqual);
29
- const { isLoading } = useInitGroupConfig();
30
-
31
- const [showGroupSetting, updateGroupConfig, updateGroupMeta] = useAgentGroupStore((s) => [
32
- s.showGroupSetting,
33
- s.updateGroupConfig,
34
- s.updateGroupMeta,
35
- ]);
36
-
37
- const [tab, setTab] = useState(GroupSettingsTabs.Settings);
38
-
39
- return (
40
- <GroupChatSettingsProvider
41
- config={config}
42
- id={id}
43
- loading={isLoading}
44
- meta={meta}
45
- onConfigChange={updateGroupConfig}
46
- onMetaChange={updateGroupMeta}
47
- >
48
- <Drawer
49
- containerMaxWidth={1280}
50
- height={isDesktop ? `calc(100vh - ${TITLE_BAR_HEIGHT}px)` : '100vh'}
51
- noHeader
52
- onClose={() => useAgentGroupStore.setState({ showGroupSetting: false })}
53
- open={showGroupSetting}
54
- placement={'bottom'}
55
- sidebar={
56
- <Flexbox
57
- gap={20}
58
- style={{
59
- height: 'calc(100vh - 28px)',
60
- }}
61
- >
62
- <PanelTitle desc={meta?.title} title={t('header.group')} />
63
- <Flexbox flex={1} width={'100%'}>
64
- <GroupCategory setTab={setTab} tab={tab} />
65
- </Flexbox>
66
- <BrandWatermark paddingInline={12} />
67
- </Flexbox>
68
- }
69
- sidebarWidth={280}
70
- styles={{
71
- sidebarContent: {
72
- gap: 48,
73
- justifyContent: 'space-between',
74
- minHeight: isDesktop ? `calc(100% - ${TITLE_BAR_HEIGHT}px)` : '100%',
75
- paddingBlock: 24,
76
- paddingInline: 48,
77
- },
78
- }}
79
- >
80
- <AgentTeamSettings
81
- config={config}
82
- id={id}
83
- loading={isLoading}
84
- meta={meta}
85
- onConfigChange={updateGroupConfig}
86
- onMetaChange={updateGroupMeta}
87
- tab={tab}
88
- />
89
- <Footer />
90
- </Drawer>
91
- </GroupChatSettingsProvider>
92
- );
93
- });
94
-
95
- export default AgentTeamSettingsWrapper;