@lobehub/lobehub 2.0.0-next.343 → 2.0.0-next.345
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/i18n.mdc +1 -1
- package/.cursor/rules/modal-imperative.mdc +162 -0
- package/.cursor/rules/rules-index.mdc +1 -0
- package/.env.example +0 -14
- package/.eslintrc.js +8 -1
- package/CHANGELOG.md +66 -0
- package/Dockerfile +3 -13
- package/README.md +3 -5
- package/README.zh-CN.md +3 -5
- package/changelog/v1.json +24 -0
- package/docs/self-hosting/advanced/auth/clerk-to-betterauth.mdx +11 -42
- package/docs/self-hosting/advanced/auth/clerk-to-betterauth.zh-CN.mdx +10 -41
- package/e2e/src/support/webServer.ts +2 -0
- package/locales/ar/error.json +0 -4
- package/locales/bg-BG/error.json +0 -4
- package/locales/de-DE/error.json +0 -4
- package/locales/en-US/error.json +0 -4
- package/locales/es-ES/error.json +0 -4
- package/locales/fa-IR/error.json +0 -4
- package/locales/fr-FR/error.json +0 -4
- package/locales/it-IT/error.json +0 -4
- package/locales/ja-JP/error.json +0 -4
- package/locales/ko-KR/error.json +0 -4
- package/locales/nl-NL/error.json +0 -4
- package/locales/pl-PL/error.json +0 -4
- package/locales/pt-BR/error.json +0 -4
- package/locales/ru-RU/error.json +0 -4
- package/locales/tr-TR/error.json +0 -4
- package/locales/vi-VN/error.json +0 -4
- package/locales/zh-CN/error.json +0 -4
- package/locales/zh-TW/error.json +0 -4
- package/package.json +7 -9
- package/packages/builtin-agents/package.json +2 -0
- package/packages/builtin-agents/src/agents/agent-builder/index.ts +4 -2
- package/packages/builtin-agents/src/agents/group-agent-builder/index.ts +4 -2
- package/packages/builtin-agents/src/agents/page-agent/index.ts +5 -2
- package/packages/builtin-tool-cloud-sandbox/src/ExecutionRuntime/index.ts +161 -12
- package/packages/context-engine/src/engine/messages/MessagesEngine.ts +9 -9
- package/packages/context-engine/src/providers/GroupContextInjector.ts +19 -33
- package/packages/context-engine/src/providers/__tests__/GroupContextInjector.test.ts +79 -43
- package/packages/context-engine/src/providers/__tests__/__snapshots__/GroupContextInjector.test.ts.snap +5 -15
- package/packages/database/src/repositories/userMemory/__tests__/UserMemoryTopicRepository.test.ts +24 -3
- package/packages/model-bank/src/modelProviders/comfyui.ts +0 -1
- package/packages/model-bank/src/modelProviders/fal.ts +0 -1
- package/packages/types/src/fetch.ts +1 -2
- package/packages/utils/src/server/__tests__/auth.test.ts +0 -47
- package/packages/utils/src/server/auth.ts +1 -9
- package/scripts/_shared/checkDeprecatedClerkEnv.js +42 -0
- package/scripts/changelogWorkflow/buildStaticChangelog.ts +2 -1
- package/scripts/clerk-to-betterauth/_internal/types.ts +53 -20
- package/scripts/clerk-to-betterauth/export-clerk-users-with-api.ts +43 -36
- package/scripts/countEnWord.ts +1 -1
- package/scripts/electronWorkflow/modifiers/appCode.mts +2 -131
- package/scripts/i18nWorkflow/protectedPatterns.ts +1 -2
- package/scripts/prebuild.mts +10 -8
- package/scripts/serverLauncher/startServer.js +23 -5
- package/src/app/(backend)/middleware/auth/index.test.ts +8 -4
- package/src/app/(backend)/middleware/auth/index.ts +0 -15
- package/src/app/(backend)/middleware/auth/utils.test.ts +0 -28
- package/src/app/(backend)/middleware/auth/utils.ts +2 -17
- package/src/app/(backend)/webapi/chat/[provider]/route.test.ts +3 -51
- package/src/app/(backend)/webapi/models/[provider]/route.test.ts +8 -4
- package/src/app/[variants]/(auth)/next-auth/signin/AuthSignInBox.tsx +7 -6
- package/src/app/[variants]/(auth)/signup/[[...signup]]/page.tsx +1 -16
- package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/index.tsx +1 -1
- package/src/app/[variants]/(main)/home/features/InputArea/SkillInstallBanner.tsx +13 -13
- package/src/app/[variants]/(main)/home/features/RecentPage/Item.tsx +2 -2
- package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +3 -21
- package/src/app/[variants]/(main)/settings/profile/features/AvatarRow.tsx +1 -2
- package/src/app/[variants]/(main)/settings/security/index.tsx +1 -22
- package/src/app/[variants]/(main)/settings/skill/features/KlavisSkillItem.tsx +12 -14
- package/src/app/[variants]/(main)/settings/skill/features/LobehubSkillItem.tsx +8 -14
- package/src/app/[variants]/(main)/settings/skill/index.tsx +7 -5
- package/src/app/[variants]/(mobile)/me/(home)/__tests__/UserBanner.test.tsx +2 -35
- package/src/app/[variants]/(mobile)/me/(home)/__tests__/useCategory.test.tsx +0 -20
- package/src/app/[variants]/(mobile)/me/(home)/features/UserBanner.tsx +1 -2
- package/src/app/[variants]/(mobile)/me/profile/features/Category.tsx +3 -13
- package/src/app/[variants]/(mobile)/settings/_layout/Header.tsx +2 -3
- package/src/app/[variants]/share/t/[id]/_layout/index.tsx +1 -1
- package/src/app/[variants]/share/t/[id]/index.tsx +1 -1
- package/src/app/robots.tsx +1 -1
- package/src/envs/auth.ts +2 -27
- package/src/envs/llm.ts +2 -2
- package/src/features/AgentSetting/AgentPlugin/index.tsx +9 -12
- package/src/features/ChatInput/ActionBar/Tools/index.tsx +7 -5
- package/src/features/ChatMiniMap/utils.ts +1 -1
- package/src/features/CommandMenu/SearchResults.tsx +1 -1
- package/src/features/Conversation/ChatList/components/AutoScroll/DebugInspector.tsx +166 -0
- package/src/features/Conversation/ChatList/components/AutoScroll/index.tsx +86 -0
- package/src/features/Conversation/ChatList/components/VirtualizedList.tsx +11 -17
- package/src/features/Conversation/Messages/AgentCouncil/components/AutoScrollShadow.tsx +25 -14
- package/src/features/Conversation/Messages/AgentCouncil/components/CouncilMember.tsx +1 -1
- package/src/features/IntegrationDetailModal/IntegrationDetailContent.tsx +305 -0
- package/src/features/IntegrationDetailModal/index.tsx +21 -283
- package/src/features/MCPPluginDetail/Deployment/index.tsx +1 -1
- package/src/features/MCPPluginDetail/Schema/Prompts.tsx +1 -1
- package/src/features/MCPPluginDetail/Schema/Tools.tsx +1 -1
- package/src/features/ProfileEditor/AgentTool.tsx +14 -20
- package/src/features/ResourceManager/components/Explorer/MasonryView/MasonryFileItem/NoteFileItem.tsx +1 -1
- package/src/features/SkillStore/LobeHubList/index.tsx +50 -87
- package/src/features/SkillStore/Search/index.tsx +1 -1
- package/src/features/SkillStore/{Content.tsx → SkillStoreContent.tsx} +3 -8
- package/src/features/SkillStore/index.tsx +15 -33
- package/src/features/User/UserPanel/PanelContent.tsx +0 -8
- package/src/features/User/__tests__/PanelContent.test.tsx +1 -35
- package/src/features/User/__tests__/UserAvatar.test.tsx +30 -57
- package/src/features/User/__tests__/useMenu.test.tsx +2 -43
- package/src/layout/AuthProvider/index.tsx +0 -5
- package/src/libs/next/config/define-config.ts +6 -0
- package/src/libs/next/proxy/createRouteMatcher.test.ts +121 -0
- package/src/libs/next/proxy/createRouteMatcher.ts +18 -0
- package/src/libs/next/proxy/define-config.ts +4 -53
- package/src/libs/next-auth/adapter/index.ts +1 -2
- package/src/libs/oidc-provider/provider.test.ts +5 -316
- package/src/libs/trpc/lambda/context.test.ts +0 -13
- package/src/libs/trpc/lambda/context.ts +3 -22
- package/src/libs/trpc/middleware/userAuth.ts +2 -4
- package/src/libs/trusted-client/getSessionUser.ts +2 -17
- package/src/locales/default/error.ts +0 -6
- package/src/locales/default/index.ts +0 -2
- package/src/proxy.ts +0 -1
- package/src/server/routers/lambda/__tests__/user.test.ts +0 -71
- package/src/server/routers/lambda/user.ts +6 -63
- package/src/server/services/changelog/index.test.ts +3 -2
- package/src/server/services/changelog/index.ts +1 -1
- package/src/server/services/user/index.ts +0 -83
- package/src/services/chat/index.ts +1 -2
- package/src/services/chat/mecha/agentConfigResolver.test.ts +43 -0
- package/src/services/chat/mecha/agentConfigResolver.ts +3 -1
- package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +58 -14
- package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +10 -2
- package/src/store/user/slices/auth/action.test.ts +1 -81
- package/src/store/user/slices/auth/action.ts +3 -28
- package/src/store/user/slices/auth/initialState.ts +1 -18
- package/src/store/user/slices/auth/selectors.test.ts +2 -127
- package/src/store/user/slices/auth/selectors.ts +1 -21
- package/src/utils/errorResponse.ts +1 -4
- package/src/utils/markdownToTxt.ts +20 -0
- package/locales/ar/clerk.json +0 -545
- package/locales/bg-BG/clerk.json +0 -545
- package/locales/de-DE/clerk.json +0 -545
- package/locales/en-US/clerk.json +0 -545
- package/locales/es-ES/clerk.json +0 -545
- package/locales/fa-IR/clerk.json +0 -545
- package/locales/fr-FR/clerk.json +0 -545
- package/locales/it-IT/clerk.json +0 -545
- package/locales/ja-JP/clerk.json +0 -545
- package/locales/ko-KR/clerk.json +0 -545
- package/locales/nl-NL/clerk.json +0 -545
- package/locales/pl-PL/clerk.json +0 -545
- package/locales/pt-BR/clerk.json +0 -545
- package/locales/ru-RU/clerk.json +0 -545
- package/locales/tr-TR/clerk.json +0 -545
- package/locales/vi-VN/clerk.json +0 -545
- package/locales/zh-CN/clerk.json +0 -545
- package/locales/zh-TW/clerk.json +0 -545
- package/src/app/(backend)/api/webhooks/clerk/__tests__/fixtures/createUser.json +0 -73
- package/src/app/(backend)/api/webhooks/clerk/route.ts +0 -95
- package/src/app/(backend)/api/webhooks/clerk/validateRequest.ts +0 -22
- package/src/app/[variants]/(auth)/login/[[...login]]/page.tsx +0 -27
- package/src/app/[variants]/(main)/settings/security/features/ClerkProfile.tsx +0 -67
- package/src/features/Conversation/ChatList/components/AutoScroll.tsx +0 -25
- package/src/layout/AuthProvider/Clerk/UserUpdater.tsx +0 -40
- package/src/layout/AuthProvider/Clerk/index.tsx +0 -54
- package/src/layout/AuthProvider/Clerk/useAppearance.ts +0 -133
- package/src/libs/clerk-auth/index.test.ts +0 -216
- package/src/libs/clerk-auth/index.ts +0 -80
- package/src/locales/default/clerk.ts +0 -677
- package/src/server/services/user/index.test.ts +0 -220
|
@@ -65,6 +65,14 @@ export class CloudSandboxExecutionRuntime {
|
|
|
65
65
|
try {
|
|
66
66
|
const result = await this.callTool('listLocalFiles', args);
|
|
67
67
|
|
|
68
|
+
if (!result.success) {
|
|
69
|
+
return {
|
|
70
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
71
|
+
state: { files: [] },
|
|
72
|
+
success: true,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
68
76
|
const files = result.result?.files || [];
|
|
69
77
|
const state: ListLocalFilesState = { files };
|
|
70
78
|
|
|
@@ -90,6 +98,19 @@ export class CloudSandboxExecutionRuntime {
|
|
|
90
98
|
try {
|
|
91
99
|
const result = await this.callTool('readLocalFile', args);
|
|
92
100
|
|
|
101
|
+
if (!result.success) {
|
|
102
|
+
return {
|
|
103
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
104
|
+
state: {
|
|
105
|
+
content: '',
|
|
106
|
+
endLine: args.endLine,
|
|
107
|
+
path: args.path,
|
|
108
|
+
startLine: args.startLine,
|
|
109
|
+
},
|
|
110
|
+
success: true,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
93
114
|
const state: ReadLocalFileState = {
|
|
94
115
|
content: result.result?.content || '',
|
|
95
116
|
endLine: args.endLine,
|
|
@@ -123,6 +144,17 @@ export class CloudSandboxExecutionRuntime {
|
|
|
123
144
|
try {
|
|
124
145
|
const result = await this.callTool('writeLocalFile', args);
|
|
125
146
|
|
|
147
|
+
if (!result.success) {
|
|
148
|
+
return {
|
|
149
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
150
|
+
state: {
|
|
151
|
+
path: args.path,
|
|
152
|
+
success: false,
|
|
153
|
+
},
|
|
154
|
+
success: true,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
126
158
|
const state: WriteLocalFileState = {
|
|
127
159
|
bytesWritten: result.result?.bytesWritten,
|
|
128
160
|
path: args.path,
|
|
@@ -148,6 +180,17 @@ export class CloudSandboxExecutionRuntime {
|
|
|
148
180
|
try {
|
|
149
181
|
const result = await this.callTool('editLocalFile', args);
|
|
150
182
|
|
|
183
|
+
if (!result.success) {
|
|
184
|
+
return {
|
|
185
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
186
|
+
state: {
|
|
187
|
+
path: args.path,
|
|
188
|
+
replacements: 0,
|
|
189
|
+
},
|
|
190
|
+
success: true,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
151
194
|
const state: EditLocalFileState = {
|
|
152
195
|
diffText: result.result?.diffText,
|
|
153
196
|
linesAdded: result.result?.linesAdded,
|
|
@@ -177,6 +220,17 @@ export class CloudSandboxExecutionRuntime {
|
|
|
177
220
|
try {
|
|
178
221
|
const result = await this.callTool('searchLocalFiles', args);
|
|
179
222
|
|
|
223
|
+
if (!result.success) {
|
|
224
|
+
return {
|
|
225
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
226
|
+
state: {
|
|
227
|
+
results: [],
|
|
228
|
+
totalCount: 0,
|
|
229
|
+
},
|
|
230
|
+
success: true,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
180
234
|
const results = result.result?.results || [];
|
|
181
235
|
const state: SearchLocalFilesState = {
|
|
182
236
|
results,
|
|
@@ -201,6 +255,18 @@ export class CloudSandboxExecutionRuntime {
|
|
|
201
255
|
try {
|
|
202
256
|
const result = await this.callTool('moveLocalFiles', args);
|
|
203
257
|
|
|
258
|
+
if (!result.success) {
|
|
259
|
+
return {
|
|
260
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
261
|
+
state: {
|
|
262
|
+
results: [],
|
|
263
|
+
successCount: 0,
|
|
264
|
+
totalCount: args.operations.length,
|
|
265
|
+
},
|
|
266
|
+
success: true,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
204
270
|
const results = result.result?.results || [];
|
|
205
271
|
const state: MoveLocalFilesState = {
|
|
206
272
|
results,
|
|
@@ -224,6 +290,19 @@ export class CloudSandboxExecutionRuntime {
|
|
|
224
290
|
try {
|
|
225
291
|
const result = await this.callTool('renameLocalFile', args);
|
|
226
292
|
|
|
293
|
+
if (!result.success) {
|
|
294
|
+
return {
|
|
295
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
296
|
+
state: {
|
|
297
|
+
error: result.error?.message,
|
|
298
|
+
newPath: '',
|
|
299
|
+
oldPath: args.oldPath,
|
|
300
|
+
success: false,
|
|
301
|
+
},
|
|
302
|
+
success: true,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
227
306
|
const state: RenameLocalFileState = {
|
|
228
307
|
error: result.result?.error,
|
|
229
308
|
newPath: result.result?.newPath || '',
|
|
@@ -241,7 +320,7 @@ export class CloudSandboxExecutionRuntime {
|
|
|
241
320
|
return {
|
|
242
321
|
content,
|
|
243
322
|
state,
|
|
244
|
-
success:
|
|
323
|
+
success: true,
|
|
245
324
|
};
|
|
246
325
|
} catch (error) {
|
|
247
326
|
return this.handleError(error);
|
|
@@ -264,15 +343,24 @@ export class CloudSandboxExecutionRuntime {
|
|
|
264
343
|
language,
|
|
265
344
|
output: result.result?.output,
|
|
266
345
|
stderr: result.result?.stderr,
|
|
267
|
-
success: result.success,
|
|
346
|
+
success: result.success || false,
|
|
268
347
|
};
|
|
269
348
|
|
|
349
|
+
if (!result.success) {
|
|
350
|
+
return {
|
|
351
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
352
|
+
state,
|
|
353
|
+
success: true,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
270
357
|
return {
|
|
271
358
|
content: JSON.stringify(result.result),
|
|
272
359
|
state,
|
|
273
|
-
success:
|
|
360
|
+
success: true,
|
|
274
361
|
};
|
|
275
362
|
} catch (error) {
|
|
363
|
+
console.log('executeCode error', error);
|
|
276
364
|
return this.handleError(error);
|
|
277
365
|
}
|
|
278
366
|
}
|
|
@@ -283,6 +371,18 @@ export class CloudSandboxExecutionRuntime {
|
|
|
283
371
|
try {
|
|
284
372
|
const result = await this.callTool('runCommand', args);
|
|
285
373
|
|
|
374
|
+
if (!result.success) {
|
|
375
|
+
return {
|
|
376
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
377
|
+
state: {
|
|
378
|
+
error: result.error?.message,
|
|
379
|
+
isBackground: args.background || false,
|
|
380
|
+
success: false,
|
|
381
|
+
},
|
|
382
|
+
success: true,
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
|
|
286
386
|
const state: RunCommandState = {
|
|
287
387
|
commandId: result.result?.commandId,
|
|
288
388
|
error: result.result?.error,
|
|
@@ -296,7 +396,7 @@ export class CloudSandboxExecutionRuntime {
|
|
|
296
396
|
return {
|
|
297
397
|
content: JSON.stringify(result.result),
|
|
298
398
|
state,
|
|
299
|
-
success:
|
|
399
|
+
success: true,
|
|
300
400
|
};
|
|
301
401
|
} catch (error) {
|
|
302
402
|
return this.handleError(error);
|
|
@@ -307,6 +407,18 @@ export class CloudSandboxExecutionRuntime {
|
|
|
307
407
|
try {
|
|
308
408
|
const result = await this.callTool('getCommandOutput', args);
|
|
309
409
|
|
|
410
|
+
if (!result.success) {
|
|
411
|
+
return {
|
|
412
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
413
|
+
state: {
|
|
414
|
+
error: result.error?.message,
|
|
415
|
+
running: false,
|
|
416
|
+
success: false,
|
|
417
|
+
},
|
|
418
|
+
success: true,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
|
|
310
422
|
const state: GetCommandOutputState = {
|
|
311
423
|
error: result.result?.error,
|
|
312
424
|
newOutput: result.result?.newOutput,
|
|
@@ -317,7 +429,7 @@ export class CloudSandboxExecutionRuntime {
|
|
|
317
429
|
return {
|
|
318
430
|
content: JSON.stringify(result.result),
|
|
319
431
|
state,
|
|
320
|
-
success:
|
|
432
|
+
success: true,
|
|
321
433
|
};
|
|
322
434
|
} catch (error) {
|
|
323
435
|
return this.handleError(error);
|
|
@@ -328,6 +440,18 @@ export class CloudSandboxExecutionRuntime {
|
|
|
328
440
|
try {
|
|
329
441
|
const result = await this.callTool('killCommand', args);
|
|
330
442
|
|
|
443
|
+
if (!result.success) {
|
|
444
|
+
return {
|
|
445
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
446
|
+
state: {
|
|
447
|
+
commandId: args.commandId,
|
|
448
|
+
error: result.error?.message,
|
|
449
|
+
success: false,
|
|
450
|
+
},
|
|
451
|
+
success: true,
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
|
|
331
455
|
const state: KillCommandState = {
|
|
332
456
|
commandId: args.commandId,
|
|
333
457
|
error: result.result?.error,
|
|
@@ -340,7 +464,7 @@ export class CloudSandboxExecutionRuntime {
|
|
|
340
464
|
success: true,
|
|
341
465
|
}),
|
|
342
466
|
state,
|
|
343
|
-
success:
|
|
467
|
+
success: true,
|
|
344
468
|
};
|
|
345
469
|
} catch (error) {
|
|
346
470
|
return this.handleError(error);
|
|
@@ -353,6 +477,18 @@ export class CloudSandboxExecutionRuntime {
|
|
|
353
477
|
try {
|
|
354
478
|
const result = await this.callTool('grepContent', args);
|
|
355
479
|
|
|
480
|
+
if (!result.success) {
|
|
481
|
+
return {
|
|
482
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
483
|
+
state: {
|
|
484
|
+
matches: [],
|
|
485
|
+
pattern: args.pattern,
|
|
486
|
+
totalMatches: 0,
|
|
487
|
+
},
|
|
488
|
+
success: true,
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
|
|
356
492
|
const state: GrepContentState = {
|
|
357
493
|
matches: result.result?.matches || [],
|
|
358
494
|
pattern: args.pattern,
|
|
@@ -373,6 +509,18 @@ export class CloudSandboxExecutionRuntime {
|
|
|
373
509
|
try {
|
|
374
510
|
const result = await this.callTool('globLocalFiles', args);
|
|
375
511
|
|
|
512
|
+
if (!result.success) {
|
|
513
|
+
return {
|
|
514
|
+
content: result.error?.message || JSON.stringify(result.error),
|
|
515
|
+
state: {
|
|
516
|
+
files: [],
|
|
517
|
+
pattern: args.pattern,
|
|
518
|
+
totalCount: 0,
|
|
519
|
+
},
|
|
520
|
+
success: true,
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
|
|
376
524
|
const files = result.result?.files || [];
|
|
377
525
|
const totalCount = result.result?.totalCount || 0;
|
|
378
526
|
|
|
@@ -433,7 +581,7 @@ export class CloudSandboxExecutionRuntime {
|
|
|
433
581
|
success: false,
|
|
434
582
|
}),
|
|
435
583
|
state,
|
|
436
|
-
success:
|
|
584
|
+
success: true,
|
|
437
585
|
};
|
|
438
586
|
}
|
|
439
587
|
|
|
@@ -455,13 +603,14 @@ export class CloudSandboxExecutionRuntime {
|
|
|
455
603
|
private async callTool(
|
|
456
604
|
toolName: string,
|
|
457
605
|
params: Record<string, any>,
|
|
458
|
-
): Promise<{
|
|
606
|
+
): Promise<{
|
|
607
|
+
error?: { message: string; name?: string };
|
|
608
|
+
result: any;
|
|
609
|
+
sessionExpiredAndRecreated?: boolean;
|
|
610
|
+
success: boolean;
|
|
611
|
+
}> {
|
|
459
612
|
const result = await this.sandboxService.callTool(toolName, params);
|
|
460
613
|
|
|
461
|
-
if (!result.success) {
|
|
462
|
-
throw new Error(result.error?.message || `Cloud Sandbox tool ${toolName} failed`);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
614
|
return result;
|
|
466
615
|
}
|
|
467
616
|
|
|
@@ -162,6 +162,15 @@ export class MessagesEngine {
|
|
|
162
162
|
// 2. System role injection (agent's system role)
|
|
163
163
|
new SystemRoleInjector({ systemRole }),
|
|
164
164
|
|
|
165
|
+
// =============================================
|
|
166
|
+
// Phase 2.5: First User Message Context Injection
|
|
167
|
+
// These providers inject content before the first user message
|
|
168
|
+
// Order matters: first executed = first in content
|
|
169
|
+
// =============================================
|
|
170
|
+
|
|
171
|
+
// 4. User memory injection (conditionally added, injected first)
|
|
172
|
+
...(isUserMemoryEnabled ? [new UserMemoryInjector(userMemory)] : []),
|
|
173
|
+
|
|
165
174
|
// 3. Group context injection (agent identity and group info for multi-agent chat)
|
|
166
175
|
new GroupContextInjector({
|
|
167
176
|
currentAgentId: agentGroup?.currentAgentId,
|
|
@@ -173,15 +182,6 @@ export class MessagesEngine {
|
|
|
173
182
|
systemPrompt: agentGroup?.systemPrompt,
|
|
174
183
|
}),
|
|
175
184
|
|
|
176
|
-
// =============================================
|
|
177
|
-
// Phase 2.5: First User Message Context Injection
|
|
178
|
-
// These providers inject content before the first user message
|
|
179
|
-
// Order matters: first executed = first in content
|
|
180
|
-
// =============================================
|
|
181
|
-
|
|
182
|
-
// 4. User memory injection (conditionally added, injected first)
|
|
183
|
-
...(isUserMemoryEnabled ? [new UserMemoryInjector(userMemory)] : []),
|
|
184
|
-
|
|
185
185
|
// 4.5. GTD Plan injection (conditionally added, after user memory, before knowledge)
|
|
186
186
|
...(isGTDPlanEnabled ? [new GTDPlanInjector({ enabled: true, plan: gtd.plan })] : []),
|
|
187
187
|
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from '@lobechat/prompts';
|
|
6
6
|
import debug from 'debug';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { BaseFirstUserContentProvider } from '../base/BaseFirstUserContentProvider';
|
|
9
9
|
import type { PipelineContext, ProcessorOptions } from '../types';
|
|
10
10
|
|
|
11
11
|
const log = debug('context-engine:provider:GroupContextInjector');
|
|
@@ -59,13 +59,13 @@ export interface GroupContextInjectorConfig {
|
|
|
59
59
|
/**
|
|
60
60
|
* Group Context Injector
|
|
61
61
|
*
|
|
62
|
-
* Responsible for injecting group context information
|
|
62
|
+
* Responsible for injecting group context information before the first user message
|
|
63
63
|
* for multi-agent group chat scenarios. This helps the model understand:
|
|
64
64
|
* - Its own identity within the group
|
|
65
65
|
* - The group composition and other members
|
|
66
66
|
* - Rules for handling system metadata
|
|
67
67
|
*
|
|
68
|
-
* The injector
|
|
68
|
+
* The injector creates a system injection message before the first user message,
|
|
69
69
|
* containing:
|
|
70
70
|
* - Agent's identity (name, role, ID)
|
|
71
71
|
* - Group info (name, member list)
|
|
@@ -87,7 +87,7 @@ export interface GroupContextInjectorConfig {
|
|
|
87
87
|
* });
|
|
88
88
|
* ```
|
|
89
89
|
*/
|
|
90
|
-
export class GroupContextInjector extends
|
|
90
|
+
export class GroupContextInjector extends BaseFirstUserContentProvider {
|
|
91
91
|
readonly name = 'GroupContextInjector';
|
|
92
92
|
|
|
93
93
|
constructor(
|
|
@@ -97,44 +97,32 @@ export class GroupContextInjector extends BaseProvider {
|
|
|
97
97
|
super(options);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
protected
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
// Skip if not enabled or missing required config
|
|
100
|
+
protected buildContent(): string | null {
|
|
101
|
+
// Skip if not enabled
|
|
104
102
|
if (!this.config.enabled) {
|
|
105
103
|
log('Group context injection disabled, skipping');
|
|
106
|
-
return
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Find the system message to append to
|
|
110
|
-
const systemMessageIndex = clonedContext.messages.findIndex((msg) => msg.role === 'system');
|
|
111
|
-
|
|
112
|
-
if (systemMessageIndex === -1) {
|
|
113
|
-
log('No system message found, skipping group context injection');
|
|
114
|
-
return this.markAsExecuted(clonedContext);
|
|
104
|
+
return null;
|
|
115
105
|
}
|
|
116
106
|
|
|
117
|
-
const
|
|
118
|
-
|
|
107
|
+
const content = this.buildGroupContextBlock();
|
|
108
|
+
log('Group context prepared for injection');
|
|
119
109
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
clonedContext.messages[systemMessageIndex] = {
|
|
123
|
-
...systemMessage,
|
|
124
|
-
content: systemMessage.content + groupContext,
|
|
125
|
-
};
|
|
110
|
+
return content;
|
|
111
|
+
}
|
|
126
112
|
|
|
127
|
-
|
|
128
|
-
|
|
113
|
+
protected async doProcess(context: PipelineContext): Promise<PipelineContext> {
|
|
114
|
+
const result = await super.doProcess(context);
|
|
129
115
|
|
|
130
116
|
// Update metadata
|
|
131
|
-
|
|
117
|
+
if (this.config.enabled) {
|
|
118
|
+
result.metadata.groupContextInjected = true;
|
|
119
|
+
}
|
|
132
120
|
|
|
133
|
-
return
|
|
121
|
+
return result;
|
|
134
122
|
}
|
|
135
123
|
|
|
136
124
|
/**
|
|
137
|
-
* Build the group context block
|
|
125
|
+
* Build the group context block
|
|
138
126
|
* Uses template from @lobechat/prompts with direct variable replacement
|
|
139
127
|
*/
|
|
140
128
|
private buildGroupContextBlock(): string {
|
|
@@ -159,9 +147,7 @@ export class GroupContextInjector extends BaseProvider {
|
|
|
159
147
|
.replace('{{SYSTEM_PROMPT}}', systemPrompt || '')
|
|
160
148
|
.replace('{{GROUP_MEMBERS}}', membersText);
|
|
161
149
|
|
|
162
|
-
return
|
|
163
|
-
|
|
164
|
-
<group_context>
|
|
150
|
+
return `<group_context>
|
|
165
151
|
${groupContextContent}
|
|
166
152
|
</group_context>`;
|
|
167
153
|
}
|
|
@@ -12,7 +12,7 @@ describe('GroupContextInjector', () => {
|
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
describe('Basic Scenarios', () => {
|
|
15
|
-
it('should inject group context
|
|
15
|
+
it('should inject group context before first user message', async () => {
|
|
16
16
|
const injector = new GroupContextInjector({
|
|
17
17
|
currentAgentId: 'agt_editor',
|
|
18
18
|
currentAgentName: 'Editor',
|
|
@@ -35,31 +35,39 @@ describe('GroupContextInjector', () => {
|
|
|
35
35
|
const context = createContext(input);
|
|
36
36
|
const result = await injector.process(context);
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
// System message should be unchanged
|
|
39
|
+
expect(result.messages[0].content).toBe('You are a helpful editor.');
|
|
40
|
+
|
|
41
|
+
// Should have 3 messages now (system, injected, user)
|
|
42
|
+
expect(result.messages).toHaveLength(3);
|
|
39
43
|
|
|
40
|
-
//
|
|
41
|
-
|
|
44
|
+
// Check injected message (second message)
|
|
45
|
+
const injectedContent = result.messages[1].content;
|
|
46
|
+
expect(result.messages[1].role).toBe('user');
|
|
42
47
|
|
|
43
48
|
// Agent identity (plain text, no wrapper)
|
|
44
|
-
expect(
|
|
45
|
-
expect(
|
|
46
|
-
expect(
|
|
47
|
-
expect(
|
|
48
|
-
expect(
|
|
49
|
+
expect(injectedContent).toContain('You are "Editor"');
|
|
50
|
+
expect(injectedContent).toContain('acting as a participant');
|
|
51
|
+
expect(injectedContent).toContain('"Writing Team"');
|
|
52
|
+
expect(injectedContent).toContain('agt_editor');
|
|
53
|
+
expect(injectedContent).not.toContain('<agent_identity>');
|
|
49
54
|
|
|
50
55
|
// Group context section with system prompt
|
|
51
|
-
expect(
|
|
52
|
-
expect(
|
|
56
|
+
expect(injectedContent).toContain('<group_context>');
|
|
57
|
+
expect(injectedContent).toContain('A team for collaborative writing');
|
|
53
58
|
|
|
54
59
|
// Participants section with XML format
|
|
55
|
-
expect(
|
|
56
|
-
expect(
|
|
57
|
-
expect(
|
|
58
|
-
expect(
|
|
60
|
+
expect(injectedContent).toContain('<group_participants>');
|
|
61
|
+
expect(injectedContent).toContain('<member name="Supervisor" id="agt_supervisor" />');
|
|
62
|
+
expect(injectedContent).toContain('<member name="Writer" id="agt_writer" />');
|
|
63
|
+
expect(injectedContent).toContain('<member name="Editor" id="agt_editor" you="true" />');
|
|
59
64
|
|
|
60
65
|
// Identity rules
|
|
61
|
-
expect(
|
|
62
|
-
expect(
|
|
66
|
+
expect(injectedContent).toContain('<identity_rules>');
|
|
67
|
+
expect(injectedContent).toContain('NEVER expose or display agent IDs');
|
|
68
|
+
|
|
69
|
+
// Original user message should be third
|
|
70
|
+
expect(result.messages[2].content).toBe('Please review this.');
|
|
63
71
|
|
|
64
72
|
// Metadata should be updated
|
|
65
73
|
expect(result.metadata.groupContextInjected).toBe(true);
|
|
@@ -72,35 +80,37 @@ describe('GroupContextInjector', () => {
|
|
|
72
80
|
enabled: false, // Disabled
|
|
73
81
|
});
|
|
74
82
|
|
|
75
|
-
const input: any[] = [
|
|
83
|
+
const input: any[] = [
|
|
84
|
+
{ role: 'system', content: 'You are a helpful editor.' },
|
|
85
|
+
{ role: 'user', content: 'Hello' },
|
|
86
|
+
];
|
|
76
87
|
|
|
77
88
|
const context = createContext(input);
|
|
78
89
|
const result = await injector.process(context);
|
|
79
90
|
|
|
80
|
-
// Should be unchanged
|
|
91
|
+
// Should be unchanged - no injection
|
|
92
|
+
expect(result.messages).toHaveLength(2);
|
|
81
93
|
expect(result.messages[0].content).toBe('You are a helpful editor.');
|
|
94
|
+
expect(result.messages[1].content).toBe('Hello');
|
|
82
95
|
expect(result.metadata.groupContextInjected).toBeUndefined();
|
|
83
96
|
});
|
|
84
97
|
|
|
85
|
-
it('should skip injection when no
|
|
98
|
+
it('should skip injection when no user message exists', async () => {
|
|
86
99
|
const injector = new GroupContextInjector({
|
|
87
100
|
currentAgentId: 'agt_editor',
|
|
88
101
|
currentAgentName: 'Editor',
|
|
89
102
|
enabled: true,
|
|
90
103
|
});
|
|
91
104
|
|
|
92
|
-
const input: any[] = [
|
|
93
|
-
{ role: 'user', content: 'Hello' },
|
|
94
|
-
{ role: 'assistant', content: 'Hi there!' },
|
|
95
|
-
];
|
|
105
|
+
const input: any[] = [{ role: 'system', content: 'You are a helpful editor.' }];
|
|
96
106
|
|
|
97
107
|
const context = createContext(input);
|
|
98
108
|
const result = await injector.process(context);
|
|
99
109
|
|
|
100
|
-
// Messages should be unchanged
|
|
101
|
-
expect(result.messages
|
|
102
|
-
expect(result.messages[
|
|
103
|
-
expect(result.metadata.groupContextInjected).
|
|
110
|
+
// Messages should be unchanged - no user message to inject before
|
|
111
|
+
expect(result.messages).toHaveLength(1);
|
|
112
|
+
expect(result.messages[0].content).toBe('You are a helpful editor.');
|
|
113
|
+
expect(result.metadata.groupContextInjected).toBe(true);
|
|
104
114
|
});
|
|
105
115
|
});
|
|
106
116
|
|
|
@@ -113,12 +123,16 @@ describe('GroupContextInjector', () => {
|
|
|
113
123
|
enabled: true,
|
|
114
124
|
});
|
|
115
125
|
|
|
116
|
-
const input: any[] = [
|
|
126
|
+
const input: any[] = [
|
|
127
|
+
{ content: 'You are an editor.', role: 'system' },
|
|
128
|
+
{ content: 'Hello', role: 'user' },
|
|
129
|
+
];
|
|
117
130
|
|
|
118
131
|
const context = createContext(input);
|
|
119
132
|
const result = await injector.process(context);
|
|
120
133
|
|
|
121
|
-
|
|
134
|
+
// Check injected message content
|
|
135
|
+
expect(result.messages[1].content).toMatchSnapshot();
|
|
122
136
|
});
|
|
123
137
|
|
|
124
138
|
it('should handle config with only group info', async () => {
|
|
@@ -129,12 +143,16 @@ describe('GroupContextInjector', () => {
|
|
|
129
143
|
systemPrompt: 'Test group description',
|
|
130
144
|
});
|
|
131
145
|
|
|
132
|
-
const input: any[] = [
|
|
146
|
+
const input: any[] = [
|
|
147
|
+
{ content: 'System prompt.', role: 'system' },
|
|
148
|
+
{ content: 'Hello', role: 'user' },
|
|
149
|
+
];
|
|
133
150
|
|
|
134
151
|
const context = createContext(input);
|
|
135
152
|
const result = await injector.process(context);
|
|
136
153
|
|
|
137
|
-
|
|
154
|
+
// Check injected message content
|
|
155
|
+
expect(result.messages[1].content).toMatchSnapshot();
|
|
138
156
|
});
|
|
139
157
|
|
|
140
158
|
it('should handle empty config', async () => {
|
|
@@ -142,12 +160,16 @@ describe('GroupContextInjector', () => {
|
|
|
142
160
|
enabled: true,
|
|
143
161
|
});
|
|
144
162
|
|
|
145
|
-
const input: any[] = [
|
|
163
|
+
const input: any[] = [
|
|
164
|
+
{ content: 'Base prompt.', role: 'system' },
|
|
165
|
+
{ content: 'Hello', role: 'user' },
|
|
166
|
+
];
|
|
146
167
|
|
|
147
168
|
const context = createContext(input);
|
|
148
169
|
const result = await injector.process(context);
|
|
149
170
|
|
|
150
|
-
|
|
171
|
+
// Check injected message content
|
|
172
|
+
expect(result.messages[1].content).toMatchSnapshot();
|
|
151
173
|
});
|
|
152
174
|
});
|
|
153
175
|
|
|
@@ -158,15 +180,19 @@ describe('GroupContextInjector', () => {
|
|
|
158
180
|
// Minimal config
|
|
159
181
|
});
|
|
160
182
|
|
|
161
|
-
const input: any[] = [
|
|
183
|
+
const input: any[] = [
|
|
184
|
+
{ role: 'system', content: 'Base prompt.' },
|
|
185
|
+
{ role: 'user', content: 'Hello' },
|
|
186
|
+
];
|
|
162
187
|
|
|
163
188
|
const context = createContext(input);
|
|
164
189
|
const result = await injector.process(context);
|
|
165
190
|
|
|
166
|
-
|
|
191
|
+
// Check injected message content
|
|
192
|
+
const injectedContent = result.messages[1].content;
|
|
167
193
|
|
|
168
194
|
// Even with minimal config, identity rules should be present
|
|
169
|
-
expect(
|
|
195
|
+
expect(injectedContent).toMatchSnapshot();
|
|
170
196
|
});
|
|
171
197
|
});
|
|
172
198
|
|
|
@@ -179,12 +205,16 @@ describe('GroupContextInjector', () => {
|
|
|
179
205
|
systemPrompt: 'Empty group description',
|
|
180
206
|
});
|
|
181
207
|
|
|
182
|
-
const input: any[] = [
|
|
208
|
+
const input: any[] = [
|
|
209
|
+
{ content: 'Prompt.', role: 'system' },
|
|
210
|
+
{ content: 'Hello', role: 'user' },
|
|
211
|
+
];
|
|
183
212
|
|
|
184
213
|
const context = createContext(input);
|
|
185
214
|
const result = await injector.process(context);
|
|
186
215
|
|
|
187
|
-
|
|
216
|
+
// Check injected message content
|
|
217
|
+
expect(result.messages[1].content).toMatchSnapshot();
|
|
188
218
|
});
|
|
189
219
|
|
|
190
220
|
it('should preserve other messages unchanged', async () => {
|
|
@@ -204,10 +234,16 @@ describe('GroupContextInjector', () => {
|
|
|
204
234
|
const context = createContext(input);
|
|
205
235
|
const result = await injector.process(context);
|
|
206
236
|
|
|
207
|
-
//
|
|
208
|
-
expect(result.messages[0].content).
|
|
209
|
-
|
|
210
|
-
|
|
237
|
+
// System message should be unchanged
|
|
238
|
+
expect(result.messages[0].content).toBe('System prompt.');
|
|
239
|
+
|
|
240
|
+
// Injected message should be second
|
|
241
|
+
expect(result.messages[1].role).toBe('user');
|
|
242
|
+
expect(result.messages[1].content).toContain('<group_context>');
|
|
243
|
+
|
|
244
|
+
// Original messages should be preserved
|
|
245
|
+
expect(result.messages[2].content).toBe('User message.');
|
|
246
|
+
expect(result.messages[3].content).toBe('Assistant response.');
|
|
211
247
|
});
|
|
212
248
|
});
|
|
213
249
|
});
|