@lobehub/lobehub 2.0.0-next.335 → 2.0.0-next.337

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 (53) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/changelog/v1.json +21 -0
  3. package/package.json +1 -1
  4. package/packages/builtin-tool-agent-builder/src/manifest.ts +0 -2
  5. package/packages/builtin-tool-group-management/src/manifest.ts +54 -53
  6. package/packages/builtin-tool-group-management/src/systemRole.ts +43 -111
  7. package/packages/builtin-tool-memory/src/client/Render/AddPreferenceMemory/index.tsx +17 -0
  8. package/packages/builtin-tool-memory/src/client/Render/index.ts +2 -0
  9. package/packages/builtin-tool-memory/src/client/Streaming/AddPreferenceMemory/index.tsx +17 -0
  10. package/packages/builtin-tool-memory/src/client/Streaming/index.ts +4 -3
  11. package/packages/builtin-tool-memory/src/client/components/PreferenceMemoryCard.tsx +357 -0
  12. package/packages/builtin-tool-memory/src/client/components/index.ts +1 -0
  13. package/packages/builtin-tool-memory/src/executor/index.ts +3 -3
  14. package/packages/builtin-tool-memory/src/systemRole.ts +1 -0
  15. package/packages/context-engine/src/engine/tools/ToolArgumentsRepairer.ts +129 -0
  16. package/packages/context-engine/src/engine/tools/__tests__/ToolArgumentsRepairer.test.ts +186 -0
  17. package/packages/context-engine/src/engine/tools/index.ts +3 -0
  18. package/packages/conversation-flow/src/__tests__/fixtures/inputs/tasks/index.ts +2 -0
  19. package/packages/conversation-flow/src/__tests__/fixtures/inputs/tasks/with-assistant-group.json +156 -0
  20. package/packages/conversation-flow/src/__tests__/parse.test.ts +22 -0
  21. package/packages/conversation-flow/src/transformation/FlatListBuilder.ts +88 -11
  22. package/packages/database/src/models/userMemory/model.ts +1 -1
  23. package/packages/memory-user-memory/src/extractors/context.test.ts +0 -1
  24. package/packages/memory-user-memory/src/extractors/experience.test.ts +0 -1
  25. package/packages/memory-user-memory/src/extractors/identity.test.ts +0 -1
  26. package/packages/memory-user-memory/src/extractors/preference.test.ts +0 -1
  27. package/packages/memory-user-memory/src/schemas/context.ts +0 -2
  28. package/packages/memory-user-memory/src/schemas/experience.ts +0 -2
  29. package/packages/memory-user-memory/src/schemas/identity.ts +1 -2
  30. package/packages/memory-user-memory/src/schemas/preference.ts +0 -2
  31. package/packages/types/src/openai/chat.ts +0 -4
  32. package/src/app/[variants]/(main)/community/(detail)/user/features/DetailProvider.tsx +5 -1
  33. package/src/app/[variants]/(main)/community/(detail)/user/features/UserAgentCard.tsx +8 -8
  34. package/src/app/[variants]/(main)/community/(detail)/user/features/UserGroupCard.tsx +142 -15
  35. package/src/app/[variants]/(main)/community/(detail)/user/features/useUserDetail.ts +45 -20
  36. package/src/server/routers/lambda/market/agentGroup.ts +179 -1
  37. package/src/server/routers/lambda/userMemories/tools.ts +5 -4
  38. package/src/server/routers/lambda/userMemories.ts +4 -4
  39. package/src/server/services/discover/index.ts +4 -0
  40. package/src/server/services/memory/userMemory/extract.ts +3 -3
  41. package/src/services/chat/chat.test.ts +109 -104
  42. package/src/services/chat/index.ts +13 -32
  43. package/src/services/chat/mecha/agentConfigResolver.test.ts +113 -0
  44. package/src/services/chat/mecha/agentConfigResolver.ts +15 -5
  45. package/src/services/marketApi.ts +14 -0
  46. package/src/store/chat/agents/__tests__/createAgentExecutors/helpers/testExecutor.ts +13 -0
  47. package/src/store/chat/agents/createAgentExecutors.ts +13 -1
  48. package/src/store/chat/slices/aiChat/actions/__tests__/conversationControl.test.ts +5 -1
  49. package/src/store/chat/slices/aiChat/actions/__tests__/fixtures.ts +14 -0
  50. package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +131 -7
  51. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +61 -62
  52. package/src/store/chat/slices/plugin/action.test.ts +71 -0
  53. package/src/store/chat/slices/plugin/actions/internals.ts +14 -5
@@ -0,0 +1,186 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { ToolArgumentsRepairer } from '../ToolArgumentsRepairer';
4
+ import type { LobeToolManifest } from '../types';
5
+
6
+ describe('ToolArgumentsRepairer', () => {
7
+ describe('repair - basic functionality', () => {
8
+ it('should return original parsed data when no schema provided', () => {
9
+ const repairer = new ToolArgumentsRepairer();
10
+ const parsed = { foo: 'bar' };
11
+
12
+ const result = repairer.repair(parsed);
13
+
14
+ expect(result).toEqual(parsed);
15
+ });
16
+
17
+ it('should return original parsed data when schema has no required fields', () => {
18
+ const repairer = new ToolArgumentsRepairer();
19
+ const parsed = { foo: 'bar' };
20
+ const schema = { type: 'object', properties: { foo: { type: 'string' } } };
21
+
22
+ const result = repairer.repair(parsed, schema);
23
+
24
+ expect(result).toEqual(parsed);
25
+ });
26
+
27
+ it('should return original parsed data when all required fields are present', () => {
28
+ const repairer = new ToolArgumentsRepairer();
29
+ const parsed = { description: 'test', instruction: 'do something' };
30
+ const schema = {
31
+ type: 'object',
32
+ required: ['description', 'instruction'],
33
+ properties: {
34
+ description: { type: 'string' },
35
+ instruction: { type: 'string' },
36
+ },
37
+ };
38
+
39
+ const result = repairer.repair(parsed, schema);
40
+
41
+ expect(result).toEqual(parsed);
42
+ });
43
+ });
44
+
45
+ describe('repair - malformed JSON from LLM', () => {
46
+ it('should repair malformed JSON with escaped string issue', () => {
47
+ const repairer = new ToolArgumentsRepairer();
48
+
49
+ // This is the malformed data from haiku-4.5 model
50
+ // The entire JSON got stuffed into the "description" field with escaped quotes
51
+ const malformedParsed = {
52
+ description:
53
+ 'Synthesize all 10 batch analyses into 10 most important themes for product builders", "instruction": "You have access to 10 batch analysis files", "runInClient": true, "timeout": 120000}',
54
+ };
55
+
56
+ const schema = {
57
+ type: 'object',
58
+ required: ['description', 'instruction'],
59
+ properties: {
60
+ description: { type: 'string' },
61
+ instruction: { type: 'string' },
62
+ runInClient: { type: 'boolean' },
63
+ timeout: { type: 'number' },
64
+ },
65
+ };
66
+
67
+ const result = repairer.repair(malformedParsed, schema);
68
+
69
+ expect(result).toHaveProperty('description');
70
+ expect(result).toHaveProperty('instruction');
71
+ expect(result).toHaveProperty('runInClient', true);
72
+ expect(result).toHaveProperty('timeout', 120000);
73
+ expect(result.description).toBe(
74
+ 'Synthesize all 10 batch analyses into 10 most important themes for product builders',
75
+ );
76
+ expect(result.instruction).toBe('You have access to 10 batch analysis files');
77
+ });
78
+
79
+ it('should return original data if repair fails', () => {
80
+ const repairer = new ToolArgumentsRepairer();
81
+
82
+ // Invalid malformed data that cannot be repaired
83
+ const malformedParsed = {
84
+ description: 'some text without proper escape pattern',
85
+ };
86
+
87
+ const schema = {
88
+ type: 'object',
89
+ required: ['description', 'instruction'],
90
+ properties: {
91
+ description: { type: 'string' },
92
+ instruction: { type: 'string' },
93
+ },
94
+ };
95
+
96
+ const result = repairer.repair(malformedParsed, schema);
97
+
98
+ // Should return original since pattern doesn't match
99
+ expect(result).toEqual(malformedParsed);
100
+ });
101
+ });
102
+
103
+ describe('parse - integrated parsing and repair', () => {
104
+ it('should parse and repair arguments using manifest schema', () => {
105
+ const manifest: LobeToolManifest = {
106
+ identifier: 'lobe-gtd',
107
+ api: [
108
+ {
109
+ name: 'execTask',
110
+ description: 'Execute async task',
111
+ parameters: {
112
+ type: 'object',
113
+ required: ['description', 'instruction'],
114
+ properties: {
115
+ description: { type: 'string' },
116
+ instruction: { type: 'string' },
117
+ runInClient: { type: 'boolean' },
118
+ timeout: { type: 'number' },
119
+ },
120
+ },
121
+ },
122
+ ],
123
+ type: 'builtin',
124
+ } as unknown as LobeToolManifest;
125
+
126
+ const repairer = new ToolArgumentsRepairer(manifest);
127
+
128
+ // Malformed arguments string
129
+ const malformedArguments = JSON.stringify({
130
+ description:
131
+ 'Test task", "instruction": "Do something important", "runInClient": true, "timeout": 60000}',
132
+ });
133
+
134
+ const result = repairer.parse('execTask', malformedArguments);
135
+
136
+ expect(result).toHaveProperty('description', 'Test task');
137
+ expect(result).toHaveProperty('instruction', 'Do something important');
138
+ expect(result).toHaveProperty('runInClient', true);
139
+ expect(result).toHaveProperty('timeout', 60000);
140
+ });
141
+
142
+ it('should handle normal arguments without repair needed', () => {
143
+ const manifest: LobeToolManifest = {
144
+ identifier: 'test-tool',
145
+ api: [
146
+ {
147
+ name: 'testApi',
148
+ description: 'Test API',
149
+ parameters: {
150
+ type: 'object',
151
+ required: ['name'],
152
+ properties: {
153
+ name: { type: 'string' },
154
+ },
155
+ },
156
+ },
157
+ ],
158
+ type: 'default',
159
+ } as unknown as LobeToolManifest;
160
+
161
+ const repairer = new ToolArgumentsRepairer(manifest);
162
+ const normalArguments = JSON.stringify({ name: 'test value' });
163
+
164
+ const result = repairer.parse('testApi', normalArguments);
165
+
166
+ expect(result).toEqual({ name: 'test value' });
167
+ });
168
+
169
+ it('should handle no manifest gracefully', () => {
170
+ const repairer = new ToolArgumentsRepairer();
171
+ const arguments_ = JSON.stringify({ foo: 'bar' });
172
+
173
+ const result = repairer.parse('unknownApi', arguments_);
174
+
175
+ expect(result).toEqual({ foo: 'bar' });
176
+ });
177
+
178
+ it('should handle invalid JSON gracefully', () => {
179
+ const repairer = new ToolArgumentsRepairer();
180
+
181
+ const result = repairer.parse('test', 'invalid json');
182
+
183
+ expect(result).toEqual({});
184
+ });
185
+ });
186
+ });
@@ -4,6 +4,9 @@ export { ToolsEngine } from './ToolsEngine';
4
4
  // Tool Name Resolver
5
5
  export { ToolNameResolver } from './ToolNameResolver';
6
6
 
7
+ // Tool Arguments Repairer
8
+ export { ToolArgumentsRepairer, type ToolParameterSchema } from './ToolArgumentsRepairer';
9
+
7
10
  // Types and interfaces
8
11
  export type {
9
12
  FunctionCallChecker,
@@ -1,10 +1,12 @@
1
1
  import type { Message } from '../../../../types';
2
2
  import multiTasksWithSummary from './multi-tasks-with-summary.json';
3
3
  import simple from './simple.json';
4
+ import withAssistantGroup from './with-assistant-group.json';
4
5
  import withSummary from './with-summary.json';
5
6
 
6
7
  export const tasks = {
7
8
  multiTasksWithSummary: multiTasksWithSummary as Message[],
8
9
  simple: simple as Message[],
10
+ withAssistantGroup: withAssistantGroup as Message[],
9
11
  withSummary: withSummary as Message[],
10
12
  };
@@ -0,0 +1,156 @@
1
+ [
2
+ {
3
+ "id": "msg-user-1",
4
+ "role": "user",
5
+ "content": "Create three parallel tasks to research AI topics.",
6
+ "parentId": null,
7
+ "createdAt": 1735526559382,
8
+ "updatedAt": 1735526559382
9
+ },
10
+ {
11
+ "id": "msg-assistant-1",
12
+ "role": "assistant",
13
+ "content": "Creating three parallel research tasks.",
14
+ "parentId": "msg-user-1",
15
+ "createdAt": 1735526560163,
16
+ "updatedAt": 1735526585550,
17
+ "model": "gpt-4",
18
+ "provider": "openai",
19
+ "tools": [
20
+ {
21
+ "id": "call_exec_tasks_1",
22
+ "type": "builtin",
23
+ "apiName": "execTasks",
24
+ "arguments": "{\"tasks\": [{\"description\": \"Research LLM architectures\"}, {\"description\": \"Research AI agents\"}, {\"description\": \"Research RAG systems\"}]}",
25
+ "identifier": "lobe-gtd"
26
+ }
27
+ ]
28
+ },
29
+ {
30
+ "id": "msg-tool-1",
31
+ "role": "tool",
32
+ "content": "Triggered 3 async tasks",
33
+ "parentId": "msg-assistant-1",
34
+ "tool_call_id": "call_exec_tasks_1",
35
+ "createdAt": 1735526588116,
36
+ "updatedAt": 1735526591337,
37
+ "pluginState": {
38
+ "type": "execTasks",
39
+ "tasks": [
40
+ { "description": "Research LLM architectures" },
41
+ { "description": "Research AI agents" },
42
+ { "description": "Research RAG systems" }
43
+ ],
44
+ "parentMessageId": "msg-tool-1"
45
+ }
46
+ },
47
+ {
48
+ "id": "msg-task-llm",
49
+ "role": "task",
50
+ "content": "# LLM Architectures\n\nTransformer-based models dominate...",
51
+ "parentId": "msg-tool-1",
52
+ "createdAt": 1735526594643,
53
+ "updatedAt": 1735526756262,
54
+ "taskDetail": {
55
+ "duration": 120000,
56
+ "status": "completed",
57
+ "threadId": "thd_llm",
58
+ "title": "Research LLM architectures",
59
+ "totalCost": 0.015,
60
+ "totalMessages": 15,
61
+ "totalTokens": 100000
62
+ }
63
+ },
64
+ {
65
+ "id": "msg-task-agents",
66
+ "role": "task",
67
+ "content": "# AI Agents\n\nAutonomous agents using LLMs...",
68
+ "parentId": "msg-tool-1",
69
+ "createdAt": 1735526595647,
70
+ "updatedAt": 1735526792430,
71
+ "taskDetail": {
72
+ "duration": 150000,
73
+ "status": "completed",
74
+ "threadId": "thd_agents",
75
+ "title": "Research AI agents",
76
+ "totalCost": 0.018,
77
+ "totalMessages": 20,
78
+ "totalTokens": 120000
79
+ }
80
+ },
81
+ {
82
+ "id": "msg-task-rag",
83
+ "role": "task",
84
+ "content": "# RAG Systems\n\nRetrieval Augmented Generation combines...",
85
+ "parentId": "msg-tool-1",
86
+ "createdAt": 1735526596000,
87
+ "updatedAt": 1735526800000,
88
+ "taskDetail": {
89
+ "duration": 130000,
90
+ "status": "completed",
91
+ "threadId": "thd_rag",
92
+ "title": "Research RAG systems",
93
+ "totalCost": 0.016,
94
+ "totalMessages": 18,
95
+ "totalTokens": 110000
96
+ }
97
+ },
98
+ {
99
+ "id": "msg-assistant-after-task",
100
+ "role": "assistant",
101
+ "content": "All tasks completed. Let me check the analysis files created.",
102
+ "parentId": "msg-task-rag",
103
+ "createdAt": 1735526810000,
104
+ "updatedAt": 1735526815000,
105
+ "agentId": "agent-main",
106
+ "model": "gpt-4",
107
+ "provider": "openai",
108
+ "tools": [
109
+ {
110
+ "id": "call_list_files",
111
+ "type": "builtin",
112
+ "apiName": "listFiles",
113
+ "arguments": "{\"path\": \"/analysis\"}",
114
+ "identifier": "lobe-local-system"
115
+ }
116
+ ],
117
+ "metadata": {
118
+ "totalInputTokens": 100,
119
+ "totalOutputTokens": 50,
120
+ "totalTokens": 150,
121
+ "cost": 0.001
122
+ }
123
+ },
124
+ {
125
+ "id": "msg-tool-list-files",
126
+ "role": "tool",
127
+ "content": "./ANALYSIS_1.md\n./ANALYSIS_2.md\n./ANALYSIS_3.md",
128
+ "parentId": "msg-assistant-after-task",
129
+ "tool_call_id": "call_list_files",
130
+ "createdAt": 1735526816000,
131
+ "updatedAt": 1735526817000,
132
+ "pluginState": {
133
+ "result": {
134
+ "output": "./ANALYSIS_1.md\n./ANALYSIS_2.md\n./ANALYSIS_3.md",
135
+ "success": true
136
+ }
137
+ }
138
+ },
139
+ {
140
+ "id": "msg-assistant-final",
141
+ "role": "assistant",
142
+ "content": "I found 3 analysis files. Let me summarize the findings for you.",
143
+ "parentId": "msg-tool-list-files",
144
+ "createdAt": 1735526820000,
145
+ "updatedAt": 1735526825000,
146
+ "agentId": "agent-main",
147
+ "model": "gpt-4",
148
+ "provider": "openai",
149
+ "metadata": {
150
+ "totalInputTokens": 200,
151
+ "totalOutputTokens": 80,
152
+ "totalTokens": 280,
153
+ "cost": 0.002
154
+ }
155
+ }
156
+ ]
@@ -219,6 +219,28 @@ describe('parse', () => {
219
219
  expect(result.flatList[3].id).toBe('msg-assistant-summary');
220
220
  expect(result.flatList[3].content).toContain('All 10 tasks completed');
221
221
  });
222
+
223
+ it('should merge assistant with tools after task into AssistantGroup', () => {
224
+ const result = parse(inputs.tasks.withAssistantGroup);
225
+
226
+ // The critical assertions:
227
+ // 1. flatList should have 4 items: user, assistantGroup(+tool), tasks(3 tasks), assistantGroup(with tool chain)
228
+ expect(result.flatList).toHaveLength(4);
229
+ expect(result.flatList[0].role).toBe('user');
230
+ expect(result.flatList[1].role).toBe('assistantGroup');
231
+ expect(result.flatList[2].role).toBe('tasks');
232
+ expect(result.flatList[3].role).toBe('assistantGroup');
233
+
234
+ // 2. The last assistantGroup should contain the full chain:
235
+ // - msg-assistant-after-task (with tool)
236
+ // - msg-assistant-final (without tool)
237
+ const lastGroup = result.flatList[3] as any;
238
+ expect(lastGroup.children).toHaveLength(2);
239
+ expect(lastGroup.children[0].id).toBe('msg-assistant-after-task');
240
+ expect(lastGroup.children[0].tools).toBeDefined();
241
+ expect(lastGroup.children[0].tools[0].result_msg_id).toBe('msg-tool-list-files');
242
+ expect(lastGroup.children[1].id).toBe('msg-assistant-final');
243
+ });
222
244
  });
223
245
 
224
246
  describe('Performance', () => {
@@ -107,9 +107,18 @@ export class FlatListBuilder {
107
107
  if (!processedIds.has(nonTaskChildId)) {
108
108
  const nonTaskChild = this.messageMap.get(nonTaskChildId);
109
109
  if (nonTaskChild) {
110
- flatList.push(nonTaskChild);
111
- processedIds.add(nonTaskChildId);
112
- this.buildFlatListRecursive(nonTaskChildId, flatList, processedIds, allMessages);
110
+ // Check if it's an AssistantGroup (assistant with tools)
111
+ if (
112
+ nonTaskChild.role === 'assistant' &&
113
+ nonTaskChild.tools &&
114
+ nonTaskChild.tools.length > 0
115
+ ) {
116
+ this.processAssistantGroup(nonTaskChild, flatList, processedIds, allMessages);
117
+ } else {
118
+ flatList.push(nonTaskChild);
119
+ processedIds.add(nonTaskChildId);
120
+ this.buildFlatListRecursive(nonTaskChildId, flatList, processedIds, allMessages);
121
+ }
113
122
  }
114
123
  }
115
124
  }
@@ -121,14 +130,28 @@ export class FlatListBuilder {
121
130
  if (!processedIds.has(taskGrandchildId)) {
122
131
  const taskGrandchild = this.messageMap.get(taskGrandchildId);
123
132
  if (taskGrandchild && taskGrandchild.role !== 'task') {
124
- flatList.push(taskGrandchild);
125
- processedIds.add(taskGrandchildId);
126
- this.buildFlatListRecursive(
127
- taskGrandchildId,
128
- flatList,
129
- processedIds,
130
- allMessages,
131
- );
133
+ // Check if it's an AssistantGroup (assistant with tools)
134
+ if (
135
+ taskGrandchild.role === 'assistant' &&
136
+ taskGrandchild.tools &&
137
+ taskGrandchild.tools.length > 0
138
+ ) {
139
+ this.processAssistantGroup(
140
+ taskGrandchild,
141
+ flatList,
142
+ processedIds,
143
+ allMessages,
144
+ );
145
+ } else {
146
+ flatList.push(taskGrandchild);
147
+ processedIds.add(taskGrandchildId);
148
+ this.buildFlatListRecursive(
149
+ taskGrandchildId,
150
+ flatList,
151
+ processedIds,
152
+ allMessages,
153
+ );
154
+ }
132
155
  }
133
156
  }
134
157
  }
@@ -427,6 +450,60 @@ export class FlatListBuilder {
427
450
  }
428
451
  }
429
452
 
453
+ /**
454
+ * Process an assistant message with tools into an AssistantGroup
455
+ * Extracted to avoid code duplication in task children handling
456
+ */
457
+ private processAssistantGroup(
458
+ message: Message,
459
+ flatList: Message[],
460
+ processedIds: Set<string>,
461
+ allMessages: Message[],
462
+ ): void {
463
+ // Collect the entire assistant group chain
464
+ const assistantChain: Message[] = [];
465
+ const allToolMessages: Message[] = [];
466
+ this.messageCollector.collectAssistantChain(
467
+ message,
468
+ allMessages,
469
+ assistantChain,
470
+ allToolMessages,
471
+ processedIds,
472
+ );
473
+
474
+ // Create assistantGroup virtual message
475
+ const groupMessage = this.createAssistantGroupMessage(
476
+ assistantChain[0],
477
+ assistantChain,
478
+ allToolMessages,
479
+ );
480
+ flatList.push(groupMessage);
481
+
482
+ // Mark all as processed
483
+ assistantChain.forEach((m) => processedIds.add(m.id));
484
+ allToolMessages.forEach((m) => processedIds.add(m.id));
485
+
486
+ // Continue after the assistant chain
487
+ // Priority 1: If last assistant has non-tool children, continue from it
488
+ // Priority 2: Otherwise continue from tools (for cases where user replies to tool)
489
+ const lastAssistant = assistantChain.at(-1);
490
+ const toolIds = new Set(allToolMessages.map((t) => t.id));
491
+
492
+ const lastAssistantNonToolChildren = lastAssistant
493
+ ? this.childrenMap.get(lastAssistant.id)?.filter((childId) => !toolIds.has(childId))
494
+ : undefined;
495
+
496
+ if (lastAssistantNonToolChildren && lastAssistantNonToolChildren.length > 0 && lastAssistant) {
497
+ // Follow-up messages exist after the last assistant (not tools)
498
+ this.buildFlatListRecursive(lastAssistant.id, flatList, processedIds, allMessages);
499
+ } else {
500
+ // No non-tool children of last assistant, check tools for children
501
+ for (const toolMsg of allToolMessages) {
502
+ this.buildFlatListRecursive(toolMsg.id, flatList, processedIds, allMessages);
503
+ }
504
+ }
505
+ }
506
+
430
507
  /**
431
508
  * Check if message has compare mode in metadata
432
509
  */
@@ -86,7 +86,7 @@ export interface BaseCreateUserMemoryParams {
86
86
  details: string;
87
87
  detailsEmbedding?: number[];
88
88
  memoryCategory: string;
89
- memoryLayer: LayersEnum;
89
+ memoryLayer?: LayersEnum;
90
90
  memoryType: TypesEnum;
91
91
  summary: string;
92
92
  summaryEmbedding?: number[];
@@ -39,7 +39,6 @@ describe('ContextExtractor', () => {
39
39
  const memoryItem = memories.items;
40
40
 
41
41
  expect(memories.type).toBe('array');
42
- expect(memoryItem.properties.memoryLayer.const).toBe('context');
43
42
  // memoryCategory is a plain string in schema, not an enum
44
43
  expect(memoryItem.properties.memoryCategory.type).toBe('string');
45
44
  expect(memoryItem.properties.memoryType.enum).toEqual(memoryTypeValues);
@@ -39,7 +39,6 @@ describe('ExperienceExtractor', () => {
39
39
  const memoryItem = memories.items;
40
40
 
41
41
  expect(memories.type).toBe('array');
42
- expect(memoryItem.properties.memoryLayer.const).toBe('experience');
43
42
  // memoryCategory is a plain string in schema, not an enum
44
43
  expect(memoryItem.properties.memoryCategory.type).toBe('string');
45
44
  expect(memoryItem.properties.memoryType.enum).toEqual(memoryTypeValues);
@@ -46,7 +46,6 @@ describe('IdentityExtractor', () => {
46
46
  {
47
47
  details: null,
48
48
  memoryCategory: 'personal',
49
- memoryLayer: 'identity',
50
49
  memoryType: 'fact',
51
50
  summary: 'New identity summary',
52
51
  tags: ['tag'],
@@ -39,7 +39,6 @@ describe('PreferenceExtractor', () => {
39
39
  const memoryItem = memories.items;
40
40
 
41
41
  expect(memories.type).toBe('array');
42
- expect(memoryItem.properties.memoryLayer.const).toBe('preference');
43
42
  // memoryCategory is a plain string in schema, not an enum
44
43
  expect(memoryItem.properties.memoryCategory.type).toBe('string');
45
44
  expect(memoryItem.properties.memoryType.enum).toEqual(memoryTypeValues);
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  ContextStatusEnum,
3
- LayersEnum,
4
3
  UserMemoryContextObjectType,
5
4
  UserMemoryContextSubjectType,
6
5
  } from '@lobechat/types';
@@ -79,7 +78,6 @@ export const WithContextSchema = z.object({
79
78
  export const ContextMemoryItemSchema = z.object({
80
79
  details: z.string().describe('Optional detailed information'),
81
80
  memoryCategory: z.string().describe('Memory category'),
82
- memoryLayer: z.literal(LayersEnum.Context).describe('Memory layer'),
83
81
  memoryType: MemoryTypeSchema.describe('Memory type'),
84
82
  summary: z.string().describe('Concise overview of this specific memory'),
85
83
  tags: z.array(z.string()).describe('User defined tags that summarize the context facets'),
@@ -1,4 +1,3 @@
1
- import { LayersEnum } from '@lobechat/types';
2
1
  import { z } from 'zod';
3
2
 
4
3
  import { MemoryTypeSchema } from './common';
@@ -37,7 +36,6 @@ export const WithExperienceSchema = z.object({
37
36
  export const ExperienceMemoryItemSchema = z.object({
38
37
  details: z.string().describe('Optional detailed information'),
39
38
  memoryCategory: z.string().describe('Memory category'),
40
- memoryLayer: z.literal(LayersEnum.Experience).describe('Memory layer'),
41
39
  memoryType: MemoryTypeSchema.describe('Memory type'),
42
40
  summary: z.string().describe('Concise overview of this specific memory'),
43
41
  tags: z.array(z.string()).describe('Model generated tags that summarize the experience facets'),
@@ -1,4 +1,4 @@
1
- import { LayersEnum, MergeStrategyEnum } from '@lobechat/types';
1
+ import { MergeStrategyEnum } from '@lobechat/types';
2
2
  import { z } from 'zod';
3
3
 
4
4
  import { MemoryTypeSchema } from './common';
@@ -43,7 +43,6 @@ export const AddIdentityActionSchema = z
43
43
  .object({
44
44
  details: z.union([z.string(), z.null()]).describe('Optional detailed information'),
45
45
  memoryCategory: z.string().describe('Memory category'),
46
- memoryLayer: z.literal(LayersEnum.Identity).describe('Memory layer'),
47
46
  memoryType: MemoryTypeSchema.describe('Memory type'),
48
47
  summary: z.string().describe('Concise overview of this specific memory'),
49
48
  tags: z.array(z.string()).describe('Model generated tags that summarize the identity facets'),
@@ -1,4 +1,3 @@
1
- import { LayersEnum } from '@lobechat/types';
2
1
  import { z } from 'zod';
3
2
 
4
3
  import { MemoryTypeSchema } from './common';
@@ -66,7 +65,6 @@ export const WithPreferenceSchema = z.object({
66
65
  export const PreferenceMemoryItemSchema = z.object({
67
66
  details: z.string().describe('Optional detailed information'),
68
67
  memoryCategory: z.string().describe('Memory category'),
69
- memoryLayer: z.literal(LayersEnum.Preference).describe('Memory layer'),
70
68
  memoryType: MemoryTypeSchema.describe('Memory type'),
71
69
  summary: z.string().describe('Concise overview of this specific memory'),
72
70
  tags: z.array(z.string()).describe('Model generated tags that summarize the preference facets'),
@@ -86,10 +86,6 @@ export interface ChatStreamPayload {
86
86
  * @title Number of texts to return
87
87
  */
88
88
  n?: number;
89
- /**
90
- * List of enabled plugins
91
- */
92
- plugins?: string[];
93
89
  /**
94
90
  * @title Penalty coefficient in generated text to reduce topic changes
95
91
  * @default 0
@@ -19,7 +19,11 @@ export interface UserDetailContextConfig {
19
19
  isOwner: boolean;
20
20
  mobile?: boolean;
21
21
  onEditProfile?: (onSuccess?: (profile: MarketUserProfile) => void) => void;
22
- onStatusChange?: (identifier: string, action: 'publish' | 'unpublish' | 'deprecate') => void;
22
+ onStatusChange?: (
23
+ identifier: string,
24
+ action: 'publish' | 'unpublish' | 'deprecate',
25
+ type?: 'agent' | 'group',
26
+ ) => void;
23
27
  totalInstalls: number;
24
28
  user: DiscoverUserInfo;
25
29
  }