@lobehub/lobehub 2.0.0-next.267 → 2.0.0-next.269
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/microcopy-cn.mdc +75 -63
- package/.cursor/rules/microcopy-en.mdc +4 -8
- package/CHANGELOG.md +50 -0
- package/README.md +8 -8
- package/README.zh-CN.md +8 -8
- package/apps/desktop/src/main/core/browser/Browser.ts +6 -0
- package/apps/desktop/src/main/locales/default/common.ts +2 -2
- package/changelog/v1.json +10 -0
- package/docs/development/database-schema.dbml +4 -0
- package/e2e/CLAUDE.md +9 -8
- package/e2e/cucumber.config.js +1 -0
- package/e2e/src/features/page/README.md +118 -0
- package/e2e/src/features/page/crud.feature +62 -0
- package/e2e/src/features/page/editor-content.feature +93 -0
- package/e2e/src/features/page/editor-meta.feature +60 -0
- package/e2e/src/steps/agent/conversation.steps.ts +4 -4
- package/e2e/src/steps/home/sidebarAgent.steps.ts +91 -94
- package/e2e/src/steps/home/sidebarGroup.steps.ts +4 -4
- package/e2e/src/steps/hooks.ts +2 -0
- package/e2e/src/steps/page/editor-content.steps.ts +344 -0
- package/e2e/src/steps/page/editor-meta.steps.ts +410 -0
- package/e2e/src/steps/page/page-crud.steps.ts +363 -0
- package/e2e/src/support/world.ts +12 -0
- package/locales/ar/file.json +2 -0
- package/locales/bg-BG/file.json +2 -0
- package/locales/de-DE/file.json +2 -0
- package/locales/en-US/auth.json +1 -1
- package/locales/en-US/file.json +2 -0
- package/locales/en-US/metadata.json +2 -2
- package/locales/es-ES/file.json +2 -0
- package/locales/fa-IR/file.json +2 -0
- package/locales/fr-FR/file.json +2 -0
- package/locales/it-IT/file.json +2 -0
- package/locales/ja-JP/file.json +2 -0
- package/locales/ko-KR/file.json +2 -0
- package/locales/nl-NL/file.json +2 -0
- package/locales/pl-PL/file.json +2 -0
- package/locales/pt-BR/file.json +2 -0
- package/locales/ru-RU/file.json +2 -0
- package/locales/tr-TR/file.json +2 -0
- package/locales/vi-VN/file.json +2 -0
- package/locales/zh-CN/file.json +2 -0
- package/locales/zh-TW/file.json +2 -0
- package/package.json +1 -1
- package/packages/builtin-agents/src/agents/agent-builder/index.ts +1 -1
- package/packages/builtin-agents/src/agents/group-agent-builder/index.ts +1 -1
- package/packages/builtin-agents/src/agents/page-agent/index.ts +1 -1
- package/packages/const/src/settings/group.ts +0 -10
- package/packages/database/migrations/0068_update_group_data.sql +4 -0
- package/packages/database/migrations/meta/0068_snapshot.json +9588 -0
- package/packages/database/migrations/meta/_journal.json +7 -0
- package/packages/database/src/models/__tests__/chatGroup.test.ts +5 -7
- package/packages/database/src/models/__tests__/knowledgeBase.test.ts +185 -0
- package/packages/database/src/models/knowledgeBase.ts +67 -3
- package/packages/database/src/repositories/agentGroup/index.test.ts +23 -29
- package/packages/database/src/repositories/agentGroup/index.ts +4 -9
- package/packages/database/src/repositories/knowledge/index.ts +3 -3
- package/packages/database/src/schemas/chatGroup.ts +4 -3
- package/packages/database/src/types/chatGroup.ts +0 -7
- package/packages/types/src/agentGroup/index.ts +30 -9
- package/packages/utils/src/index.ts +1 -0
- package/packages/utils/src/platform.ts +35 -3
- package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/index.tsx +30 -22
- package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/style.ts +8 -5
- package/src/app/[variants]/(main)/_layout/DesktopLayoutContainer.tsx +2 -3
- package/src/app/[variants]/(main)/home/_layout/Body/Agent/ModalProvider.tsx +9 -32
- package/src/app/[variants]/(main)/home/_layout/hooks/useCreateMenuItems.tsx +3 -37
- package/src/app/[variants]/(main)/home/_layout/hooks/useSessionGroupMenuItems.tsx +7 -53
- package/src/app/[variants]/(main)/home/features/RecentPage/List.tsx +2 -1
- package/src/app/[variants]/(main)/resource/features/DndContextWrapper.tsx +1 -1
- package/src/app/[variants]/(main)/resource/library/_layout/Sidebar.tsx +2 -2
- package/src/app/[variants]/(main)/resource/library/features/LibraryMenu.tsx +2 -2
- package/src/app/[variants]/(mobile)/chat/settings/features/SettingButton.tsx +2 -12
- package/src/components/ChatGroupWizard/ChatGroupWizard.tsx +5 -27
- package/src/components/DragUpload/index.tsx +24 -27
- package/src/components/MemberSelectionModal/MemberSelectionModal.tsx +2 -11
- package/src/features/CommandMenu/useCommandMenu.ts +4 -14
- package/src/features/ElectronTitlebar/SimpleTitleBar.tsx +31 -0
- package/src/features/ElectronTitlebar/index.tsx +1 -0
- package/src/features/ResourceManager/components/Editor/index.tsx +2 -3
- package/src/features/ResourceManager/components/Explorer/Header/index.tsx +13 -17
- package/src/features/ResourceManager/components/Explorer/ItemDropdown/useFileItemDropdown.tsx +1 -1
- package/src/features/ResourceManager/components/Explorer/ListView/ListItem/TruncatedFileName.tsx +130 -0
- package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +36 -4
- package/src/features/ResourceManager/components/Explorer/ListView/Skeleton.tsx +4 -3
- package/src/features/ResourceManager/components/Explorer/ListView/index.tsx +58 -2
- package/src/features/ResourceManager/components/Explorer/MasonryView/index.tsx +58 -6
- package/src/features/ResourceManager/components/Explorer/MoveToFolderModal.tsx +2 -5
- package/src/features/ResourceManager/components/Explorer/ToolBar/BatchActionsDropdown.tsx +9 -5
- package/src/features/ResourceManager/components/Explorer/index.tsx +11 -56
- package/src/features/ResourceManager/components/Header/AddButton.tsx +5 -6
- package/src/features/ResourceManager/components/LibraryHierarchy/HierarchyNode.tsx +382 -0
- package/src/features/ResourceManager/components/LibraryHierarchy/index.tsx +396 -0
- package/src/features/ResourceManager/components/LibraryHierarchy/styles.ts +19 -0
- package/src/features/ResourceManager/components/LibraryHierarchy/treeState.ts +178 -0
- package/src/features/ResourceManager/components/LibraryHierarchy/types.ts +10 -0
- package/src/features/ResourceManager/index.tsx +3 -0
- package/src/layout/GlobalProvider/GroupWizardProvider.tsx +6 -29
- package/src/locales/default/auth.ts +1 -1
- package/src/locales/default/file.ts +2 -0
- package/src/locales/default/metadata.ts +2 -2
- package/src/server/modules/AgentRuntime/AgentRuntimeCoordinator.ts +30 -30
- package/src/server/modules/AgentRuntime/AgentStateManager.ts +23 -23
- package/src/server/modules/AgentRuntime/InMemoryAgentStateManager.ts +16 -16
- package/src/server/modules/AgentRuntime/InMemoryStreamEventManager.ts +13 -13
- package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +2 -2
- package/src/server/modules/AgentRuntime/StreamEventManager.ts +18 -18
- package/src/server/modules/AgentRuntime/types.ts +21 -21
- package/src/server/routers/lambda/__tests__/agentGroup.test.ts +8 -8
- package/src/server/routers/lambda/agentGroup.ts +10 -12
- package/src/server/services/document/index.ts +1 -0
- package/src/store/agentGroup/slices/curd.test.ts +4 -4
- package/src/store/file/slices/fileManager/action.ts +12 -4
- package/src/store/home/slices/homeInput/action.ts +0 -3
- package/src/store/session/slices/session/action.ts +5 -9
- package/src/utils/platform.ts +2 -0
- package/src/app/[variants]/(mobile)/chat/settings/features/AgentTeamSettings/index.tsx +0 -95
- package/src/features/GroupChatSettings/AgentCard.tsx +0 -154
- package/src/features/GroupChatSettings/AgentTeamChatSettings.tsx +0 -179
- package/src/features/GroupChatSettings/AgentTeamMembersSettings.tsx +0 -244
- package/src/features/GroupChatSettings/AgentTeamMetaSettings.tsx +0 -94
- package/src/features/GroupChatSettings/AgentTeamSettings.tsx +0 -54
- package/src/features/GroupChatSettings/GroupCategory/index.tsx +0 -30
- package/src/features/GroupChatSettings/GroupCategory/useGroupCategory.tsx +0 -42
- package/src/features/GroupChatSettings/GroupChatSettingsProvider.tsx +0 -19
- package/src/features/GroupChatSettings/HostMemberCard.tsx +0 -113
- package/src/features/GroupChatSettings/StoreUpdater.tsx +0 -34
- package/src/features/GroupChatSettings/hooks/useGroupChatSettings.ts +0 -25
- package/src/features/GroupChatSettings/index.ts +0 -16
- package/src/features/GroupChatSettings/store/action.ts +0 -105
- package/src/features/GroupChatSettings/store/index.ts +0 -18
- package/src/features/GroupChatSettings/store/initialState.ts +0 -23
- package/src/features/GroupChatSettings/store/selectors.ts +0 -13
- package/src/features/ResourceManager/components/Tree/index.tsx +0 -883
- /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
|
-
*
|
|
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
|
-
'*', //
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
//
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
64
|
+
* Load Agent state
|
|
65
65
|
*/
|
|
66
66
|
loadAgentState(operationId: string): Promise<AgentState | null>;
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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: {
|
|
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,
|
|
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: {
|
|
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,
|
|
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,
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
228
|
+
value: InsertChatGroupSchema.partial(),
|
|
231
229
|
}),
|
|
232
230
|
)
|
|
233
231
|
.mutation(async ({ input, ctx }) => {
|
|
@@ -87,13 +87,13 @@ describe('ChatGroupCurdSlice', () => {
|
|
|
87
87
|
const { result } = renderHook(() => useAgentGroupStore());
|
|
88
88
|
|
|
89
89
|
await act(async () => {
|
|
90
|
-
await result.current.updateGroupConfig({
|
|
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
|
-
|
|
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({
|
|
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({
|
|
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>(
|
|
547
|
-
|
|
548
|
-
|
|
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',
|
|
@@ -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
|
-
|
|
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;
|