@lobehub/lobehub 2.0.0-next.287 → 2.0.0-next.289
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/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/locales/en-US/plugin.json +3 -5
- package/locales/zh-CN/plugin.json +3 -5
- package/locales/zh-CN/tool.json +2 -0
- package/package.json +1 -1
- package/packages/builtin-agents/src/agents/group-supervisor/index.ts +12 -1
- package/packages/builtin-agents/src/agents/group-supervisor/systemRole.ts +0 -7
- package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/EditLocalFile/index.tsx +93 -0
- package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/GlobLocalFiles/index.tsx +73 -0
- package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/GrepContent/index.tsx +69 -0
- package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/ListLocalFiles/index.tsx +68 -0
- package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/ReadLocalFile/index.tsx +74 -0
- package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/SearchLocalFiles/index.tsx +70 -0
- package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/WriteLocalFile/index.tsx +57 -0
- package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/index.ts +14 -0
- package/packages/builtin-tool-cloud-sandbox/src/client/Render/WriteFile/index.tsx +54 -35
- package/packages/builtin-tool-cloud-sandbox/src/client/components/FilePathDisplay.tsx +52 -0
- package/packages/builtin-tool-group-management/src/client/Inspector/ExecuteTasks/index.tsx +90 -0
- package/packages/builtin-tool-group-management/src/client/Inspector/index.ts +2 -0
- package/packages/builtin-tool-group-management/src/client/Intervention/ExecuteTasks.tsx +237 -0
- package/packages/builtin-tool-group-management/src/client/Intervention/index.ts +4 -1
- package/packages/builtin-tool-group-management/src/client/Render/index.ts +1 -1
- package/packages/builtin-tool-group-management/src/client/Streaming/ExecuteTask/index.tsx +69 -0
- package/packages/builtin-tool-group-management/src/client/Streaming/ExecuteTasks/index.tsx +87 -0
- package/packages/builtin-tool-group-management/src/client/Streaming/index.ts +4 -0
- package/packages/builtin-tool-group-management/src/executor.test.ts +8 -311
- package/packages/builtin-tool-group-management/src/executor.ts +5 -160
- package/packages/builtin-tool-group-management/src/manifest.ts +50 -94
- package/packages/builtin-tool-group-management/src/systemRole.ts +251 -172
- package/packages/builtin-tool-group-management/src/types.ts +29 -40
- package/packages/context-engine/src/engine/messages/MessagesEngine.ts +22 -4
- package/packages/context-engine/src/engine/messages/types.ts +4 -4
- package/packages/context-engine/src/processors/GroupOrchestrationFilter.ts +211 -0
- package/packages/context-engine/src/processors/GroupRoleTransform.ts +261 -0
- package/packages/context-engine/src/processors/__tests__/GroupOrchestrationFilter.test.ts +770 -0
- package/packages/context-engine/src/processors/__tests__/GroupRoleTransform.test.ts +553 -0
- package/packages/context-engine/src/processors/index.ts +7 -2
- package/packages/context-engine/src/providers/__tests__/GroupContextInjector.test.ts +4 -16
- package/packages/context-engine/src/providers/__tests__/__snapshots__/GroupContextInjector.test.ts.snap +23 -28
- package/packages/prompts/src/prompts/agentGroup/__snapshots__/index.test.ts.snap +0 -7
- package/packages/prompts/src/prompts/agentGroup/groupContext.ts +0 -7
- package/src/app/[variants]/(main)/group/features/Conversation/AgentWelcome/OpeningQuestions.tsx +4 -8
- package/src/app/[variants]/(main)/group/features/Conversation/MainChatInput/GroupChat.tsx +0 -3
- package/src/app/[variants]/(main)/group/features/Conversation/useGroupContext.ts +3 -0
- package/src/features/ChatInput/Desktop/index.tsx +1 -3
- package/src/features/Conversation/store/slices/message/action/crud.ts +2 -2
- package/src/locales/default/plugin.ts +3 -5
- package/src/locales/default/tool.ts +3 -0
- package/src/services/chat/mecha/agentConfigResolver.test.ts +160 -0
- package/src/services/chat/mecha/agentConfigResolver.ts +15 -3
- package/src/services/chat/mecha/contextEngineering.ts +2 -1
- package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +4 -2
- package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +2 -0
- package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +1 -18
- package/src/store/chat/slices/message/selectors/displayMessage.test.ts +24 -0
- package/src/store/chat/slices/message/selectors/displayMessage.ts +6 -1
- package/src/store/chat/slices/topic/action.test.ts +10 -4
- package/src/store/chat/slices/topic/action.ts +3 -2
- package/src/store/document/slices/document/action.ts +8 -0
- package/packages/context-engine/src/processors/GroupMessageSender.ts +0 -138
- package/packages/context-engine/src/processors/__tests__/GroupMessageSender.test.ts +0 -274
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import debug from 'debug';
|
|
2
|
-
|
|
3
|
-
import { BaseProcessor } from '../base/BaseProcessor';
|
|
4
|
-
import type { Message, PipelineContext, ProcessorOptions } from '../types';
|
|
5
|
-
|
|
6
|
-
const log = debug('context-engine:processor:GroupMessageSenderProcessor');
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Agent info for message sender identification
|
|
10
|
-
*/
|
|
11
|
-
export interface AgentInfo {
|
|
12
|
-
name: string;
|
|
13
|
-
role: 'supervisor' | 'participant';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Configuration for GroupMessageSenderProcessor
|
|
18
|
-
*/
|
|
19
|
-
export interface GroupMessageSenderConfig {
|
|
20
|
-
/**
|
|
21
|
-
* Mapping from agentId to agent info
|
|
22
|
-
* Used to look up agent name and role for each message
|
|
23
|
-
*/
|
|
24
|
-
agentMap: Record<string, AgentInfo>;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Group Message Sender Processor
|
|
29
|
-
*
|
|
30
|
-
* Responsible for injecting sender identity information into assistant messages
|
|
31
|
-
* in group chat scenarios. This helps the model understand which agent sent
|
|
32
|
-
* each message in a multi-agent conversation.
|
|
33
|
-
*
|
|
34
|
-
* The processor appends a system context block at the end of each assistant
|
|
35
|
-
* message that has an agentId, containing:
|
|
36
|
-
* - Agent name
|
|
37
|
-
* - Agent role (supervisor or agent)
|
|
38
|
-
* - Agent ID (with instruction not to expose it in responses)
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* ```typescript
|
|
42
|
-
* const processor = new GroupMessageSenderProcessor({
|
|
43
|
-
* agentMap: {
|
|
44
|
-
* 'agt_xxx': { name: 'Weather Expert', role: 'agent' },
|
|
45
|
-
* 'agt_yyy': { name: 'Supervisor', role: 'supervisor' },
|
|
46
|
-
* }
|
|
47
|
-
* });
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
export class GroupMessageSenderProcessor extends BaseProcessor {
|
|
51
|
-
readonly name = 'GroupMessageSenderProcessor';
|
|
52
|
-
|
|
53
|
-
constructor(
|
|
54
|
-
private config: GroupMessageSenderConfig,
|
|
55
|
-
options: ProcessorOptions = {},
|
|
56
|
-
) {
|
|
57
|
-
super(options);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
protected async doProcess(context: PipelineContext): Promise<PipelineContext> {
|
|
61
|
-
const clonedContext = this.cloneContext(context);
|
|
62
|
-
|
|
63
|
-
// Skip if no agentMap provided
|
|
64
|
-
if (!this.config.agentMap || Object.keys(this.config.agentMap).length === 0) {
|
|
65
|
-
log('No agentMap provided, skipping processing');
|
|
66
|
-
return this.markAsExecuted(clonedContext);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
let processedCount = 0;
|
|
70
|
-
|
|
71
|
-
clonedContext.messages = clonedContext.messages.map((msg: Message) => {
|
|
72
|
-
// Only process assistant messages with agentId
|
|
73
|
-
if (msg.role === 'assistant' && msg.agentId) {
|
|
74
|
-
const agentInfo = this.config.agentMap[msg.agentId];
|
|
75
|
-
|
|
76
|
-
if (agentInfo) {
|
|
77
|
-
// Build the sender tag
|
|
78
|
-
const senderTag = this.buildSenderContext(msg.agentId, agentInfo);
|
|
79
|
-
|
|
80
|
-
// Prepend to message content (at the beginning)
|
|
81
|
-
if (typeof msg.content === 'string') {
|
|
82
|
-
processedCount++;
|
|
83
|
-
log(
|
|
84
|
-
`Injecting sender info for message from agent: ${agentInfo.name} (${agentInfo.role})`,
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
...msg,
|
|
89
|
-
content: senderTag + msg.content,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
// Handle array content (multimodal messages)
|
|
93
|
-
else if (Array.isArray(msg.content)) {
|
|
94
|
-
const firstTextIndex = msg.content.findIndex((part: any) => part.type === 'text');
|
|
95
|
-
|
|
96
|
-
if (firstTextIndex !== -1) {
|
|
97
|
-
processedCount++;
|
|
98
|
-
log(
|
|
99
|
-
`Injecting sender info for multimodal message from agent: ${agentInfo.name} (${agentInfo.role})`,
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
const newContent = [...msg.content];
|
|
103
|
-
newContent[firstTextIndex] = {
|
|
104
|
-
...newContent[firstTextIndex],
|
|
105
|
-
text: senderTag + newContent[firstTextIndex].text,
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
return {
|
|
109
|
-
...msg,
|
|
110
|
-
content: newContent,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return msg;
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
// Update metadata
|
|
121
|
-
clonedContext.metadata.groupMessageSenderProcessed = processedCount;
|
|
122
|
-
|
|
123
|
-
log(`Group message sender processing completed: ${processedCount} messages processed`);
|
|
124
|
-
|
|
125
|
-
return this.markAsExecuted(clonedContext);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Build the sender tag to prepend to assistant messages.
|
|
130
|
-
*
|
|
131
|
-
* Uses a self-closing XML tag at the beginning:
|
|
132
|
-
* - Placed at start so model sees "who is speaking" before the content
|
|
133
|
-
* - Self-closing tag is less likely to be reproduced as it's not a "wrapper"
|
|
134
|
-
*/
|
|
135
|
-
private buildSenderContext(_agentId: string, agentInfo: AgentInfo): string {
|
|
136
|
-
return `<speaker name="${agentInfo.name}" />\n`;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { PipelineContext } from '../../types';
|
|
4
|
-
import { GroupMessageSenderProcessor } from '../GroupMessageSender';
|
|
5
|
-
|
|
6
|
-
describe('GroupMessageSenderProcessor', () => {
|
|
7
|
-
const createContext = (messages: any[]): PipelineContext => ({
|
|
8
|
-
initialState: { messages: [] },
|
|
9
|
-
isAborted: false,
|
|
10
|
-
messages,
|
|
11
|
-
metadata: {},
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
describe('Basic Scenarios', () => {
|
|
15
|
-
it('should inject sender info into assistant message with agentId', async () => {
|
|
16
|
-
const processor = new GroupMessageSenderProcessor({
|
|
17
|
-
agentMap: {
|
|
18
|
-
agt_weather: { name: 'Weather Expert', role: 'participant' },
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const input: any[] = [
|
|
23
|
-
{ role: 'user', content: 'What is the weather?' },
|
|
24
|
-
{ role: 'assistant', content: 'The weather is sunny.', agentId: 'agt_weather' },
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
const context = createContext(input);
|
|
28
|
-
const result = await processor.process(context);
|
|
29
|
-
|
|
30
|
-
expect(result.messages).toHaveLength(2);
|
|
31
|
-
|
|
32
|
-
// User message should be unchanged
|
|
33
|
-
expect(result.messages[0].content).toBe('What is the weather?');
|
|
34
|
-
|
|
35
|
-
// Assistant message should have speaker tag prepended
|
|
36
|
-
const assistantContent = result.messages[1].content;
|
|
37
|
-
expect(assistantContent).toMatch(/^<speaker name="Weather Expert" \/>/);
|
|
38
|
-
expect(assistantContent).toContain('The weather is sunny.');
|
|
39
|
-
|
|
40
|
-
// Check metadata
|
|
41
|
-
expect(result.metadata.groupMessageSenderProcessed).toBe(1);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('should inject sender info for supervisor role', async () => {
|
|
45
|
-
const processor = new GroupMessageSenderProcessor({
|
|
46
|
-
agentMap: {
|
|
47
|
-
agt_supervisor: { name: 'Group Supervisor', role: 'supervisor' },
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
const input: any[] = [
|
|
52
|
-
{ role: 'assistant', content: 'I will coordinate the agents.', agentId: 'agt_supervisor' },
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
const context = createContext(input);
|
|
56
|
-
const result = await processor.process(context);
|
|
57
|
-
|
|
58
|
-
const assistantContent = result.messages[0].content;
|
|
59
|
-
expect(assistantContent).toMatch(/^<speaker name="Group Supervisor" \/>/);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should not modify assistant message without agentId', async () => {
|
|
63
|
-
const processor = new GroupMessageSenderProcessor({
|
|
64
|
-
agentMap: {
|
|
65
|
-
agt_weather: { name: 'Weather Expert', role: 'participant' },
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const input: any[] = [{ role: 'assistant', content: 'Hello from assistant.' }];
|
|
70
|
-
|
|
71
|
-
const context = createContext(input);
|
|
72
|
-
const result = await processor.process(context);
|
|
73
|
-
|
|
74
|
-
// Should be unchanged
|
|
75
|
-
expect(result.messages[0].content).toBe('Hello from assistant.');
|
|
76
|
-
expect(result.metadata.groupMessageSenderProcessed).toBe(0);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('should not modify assistant message with unknown agentId', async () => {
|
|
80
|
-
const processor = new GroupMessageSenderProcessor({
|
|
81
|
-
agentMap: {
|
|
82
|
-
agt_weather: { name: 'Weather Expert', role: 'participant' },
|
|
83
|
-
},
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
const input: any[] = [{ role: 'assistant', content: 'Hello.', agentId: 'agt_unknown' }];
|
|
87
|
-
|
|
88
|
-
const context = createContext(input);
|
|
89
|
-
const result = await processor.process(context);
|
|
90
|
-
|
|
91
|
-
// Should be unchanged because agentId not in map
|
|
92
|
-
expect(result.messages[0].content).toBe('Hello.');
|
|
93
|
-
expect(result.metadata.groupMessageSenderProcessed).toBe(0);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('should not modify user or tool messages', async () => {
|
|
97
|
-
const processor = new GroupMessageSenderProcessor({
|
|
98
|
-
agentMap: {
|
|
99
|
-
agt_weather: { name: 'Weather Expert', role: 'participant' },
|
|
100
|
-
},
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
const input: any[] = [
|
|
104
|
-
{ role: 'user', content: 'Hello', agentId: 'agt_weather' },
|
|
105
|
-
{ role: 'tool', content: 'Tool result', agentId: 'agt_weather' },
|
|
106
|
-
];
|
|
107
|
-
|
|
108
|
-
const context = createContext(input);
|
|
109
|
-
const result = await processor.process(context);
|
|
110
|
-
|
|
111
|
-
expect(result.messages[0].content).toBe('Hello');
|
|
112
|
-
expect(result.messages[1].content).toBe('Tool result');
|
|
113
|
-
expect(result.metadata.groupMessageSenderProcessed).toBe(0);
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
describe('Multiple Messages', () => {
|
|
118
|
-
it('should process multiple assistant messages from different agents', async () => {
|
|
119
|
-
const processor = new GroupMessageSenderProcessor({
|
|
120
|
-
agentMap: {
|
|
121
|
-
agt_weather: { name: 'Weather Expert', role: 'participant' },
|
|
122
|
-
agt_news: { name: 'News Reporter', role: 'participant' },
|
|
123
|
-
agt_supervisor: { name: 'Supervisor', role: 'supervisor' },
|
|
124
|
-
},
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
const input: any[] = [
|
|
128
|
-
{ role: 'user', content: 'Give me updates' },
|
|
129
|
-
{ role: 'assistant', content: 'Weather is sunny.', agentId: 'agt_weather' },
|
|
130
|
-
{ role: 'assistant', content: 'Top news today.', agentId: 'agt_news' },
|
|
131
|
-
{ role: 'assistant', content: 'Summary complete.', agentId: 'agt_supervisor' },
|
|
132
|
-
];
|
|
133
|
-
|
|
134
|
-
const context = createContext(input);
|
|
135
|
-
const result = await processor.process(context);
|
|
136
|
-
|
|
137
|
-
expect(result.messages).toHaveLength(4);
|
|
138
|
-
|
|
139
|
-
// Check each assistant message has correct speaker tag prepended
|
|
140
|
-
expect(result.messages[1].content).toMatch(/^<speaker name="Weather Expert" \/>/);
|
|
141
|
-
expect(result.messages[2].content).toMatch(/^<speaker name="News Reporter" \/>/);
|
|
142
|
-
expect(result.messages[3].content).toMatch(/^<speaker name="Supervisor" \/>/);
|
|
143
|
-
|
|
144
|
-
expect(result.metadata.groupMessageSenderProcessed).toBe(3);
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
describe('Multimodal Messages', () => {
|
|
149
|
-
it('should handle array content (multimodal messages)', async () => {
|
|
150
|
-
const processor = new GroupMessageSenderProcessor({
|
|
151
|
-
agentMap: {
|
|
152
|
-
agt_weather: { name: 'Weather Expert', role: 'participant' },
|
|
153
|
-
},
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
const input: any[] = [
|
|
157
|
-
{
|
|
158
|
-
role: 'assistant',
|
|
159
|
-
content: [
|
|
160
|
-
{ type: 'text', text: 'Here is the weather chart.' },
|
|
161
|
-
{ type: 'image_url', image_url: { url: 'https://example.com/chart.png' } },
|
|
162
|
-
],
|
|
163
|
-
agentId: 'agt_weather',
|
|
164
|
-
},
|
|
165
|
-
];
|
|
166
|
-
|
|
167
|
-
const context = createContext(input);
|
|
168
|
-
const result = await processor.process(context);
|
|
169
|
-
|
|
170
|
-
const content = result.messages[0].content as any[];
|
|
171
|
-
expect(Array.isArray(content)).toBe(true);
|
|
172
|
-
|
|
173
|
-
// The first text part should have speaker tag prepended
|
|
174
|
-
const textPart = content.find((p: any) => p.type === 'text');
|
|
175
|
-
expect(textPart.text).toMatch(/^<speaker name="Weather Expert" \/>/);
|
|
176
|
-
expect(textPart.text).toContain('Here is the weather chart.');
|
|
177
|
-
|
|
178
|
-
// Image part should be unchanged
|
|
179
|
-
const imagePart = content.find((p: any) => p.type === 'image_url');
|
|
180
|
-
expect(imagePart.image_url.url).toBe('https://example.com/chart.png');
|
|
181
|
-
|
|
182
|
-
expect(result.metadata.groupMessageSenderProcessed).toBe(1);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it('should append to the last text part in multimodal content', async () => {
|
|
186
|
-
const processor = new GroupMessageSenderProcessor({
|
|
187
|
-
agentMap: {
|
|
188
|
-
agt_weather: { name: 'Weather Expert', role: 'participant' },
|
|
189
|
-
},
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
const input: any[] = [
|
|
193
|
-
{
|
|
194
|
-
role: 'assistant',
|
|
195
|
-
content: [
|
|
196
|
-
{ type: 'text', text: 'First text.' },
|
|
197
|
-
{ type: 'image_url', image_url: { url: 'https://example.com/img.png' } },
|
|
198
|
-
{ type: 'text', text: 'Last text.' },
|
|
199
|
-
],
|
|
200
|
-
agentId: 'agt_weather',
|
|
201
|
-
},
|
|
202
|
-
];
|
|
203
|
-
|
|
204
|
-
const context = createContext(input);
|
|
205
|
-
const result = await processor.process(context);
|
|
206
|
-
|
|
207
|
-
const content = result.messages[0].content;
|
|
208
|
-
|
|
209
|
-
// First text part should have speaker tag prepended
|
|
210
|
-
expect(content[0].text).toMatch(/^<speaker name="Weather Expert" \/>/);
|
|
211
|
-
expect(content[0].text).toContain('First text.');
|
|
212
|
-
|
|
213
|
-
// Last text should be unchanged
|
|
214
|
-
expect(content[2].text).toBe('Last text.');
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
describe('Edge Cases', () => {
|
|
219
|
-
it('should skip processing with empty agentMap', async () => {
|
|
220
|
-
const processor = new GroupMessageSenderProcessor({
|
|
221
|
-
agentMap: {},
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
const input: any[] = [{ role: 'assistant', content: 'Hello', agentId: 'agt_weather' }];
|
|
225
|
-
|
|
226
|
-
const context = createContext(input);
|
|
227
|
-
const result = await processor.process(context);
|
|
228
|
-
|
|
229
|
-
expect(result.messages[0].content).toBe('Hello');
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it('should handle empty messages array', async () => {
|
|
233
|
-
const processor = new GroupMessageSenderProcessor({
|
|
234
|
-
agentMap: {
|
|
235
|
-
agt_weather: { name: 'Weather Expert', role: 'participant' },
|
|
236
|
-
},
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
const context = createContext([]);
|
|
240
|
-
const result = await processor.process(context);
|
|
241
|
-
|
|
242
|
-
expect(result.messages).toHaveLength(0);
|
|
243
|
-
expect(result.metadata.groupMessageSenderProcessed).toBe(0);
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
it('should preserve original message properties', async () => {
|
|
247
|
-
const processor = new GroupMessageSenderProcessor({
|
|
248
|
-
agentMap: {
|
|
249
|
-
agt_weather: { name: 'Weather Expert', role: 'participant' },
|
|
250
|
-
},
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
const input: any[] = [
|
|
254
|
-
{
|
|
255
|
-
role: 'assistant',
|
|
256
|
-
content: 'Weather info.',
|
|
257
|
-
agentId: 'agt_weather',
|
|
258
|
-
id: 'msg-123',
|
|
259
|
-
createdAt: '2025-01-01T00:00:00Z',
|
|
260
|
-
customField: 'custom value',
|
|
261
|
-
},
|
|
262
|
-
];
|
|
263
|
-
|
|
264
|
-
const context = createContext(input);
|
|
265
|
-
const result = await processor.process(context);
|
|
266
|
-
|
|
267
|
-
const msg = result.messages[0];
|
|
268
|
-
expect(msg.id).toBe('msg-123');
|
|
269
|
-
expect(msg.createdAt).toBe('2025-01-01T00:00:00Z');
|
|
270
|
-
expect(msg.customField).toBe('custom value');
|
|
271
|
-
expect(msg.agentId).toBe('agt_weather');
|
|
272
|
-
});
|
|
273
|
-
});
|
|
274
|
-
});
|