@louloulinx/metagpt 0.1.3
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/.eslintrc.json +23 -0
- package/.prettierrc +7 -0
- package/LICENSE +21 -0
- package/README-CN.md +754 -0
- package/README.md +238 -0
- package/bun.lock +1023 -0
- package/doc/TutorialAssistant.md +114 -0
- package/doc/VercelLLMProvider.md +164 -0
- package/eslint.config.js +55 -0
- package/examples/data-interpreter-example.ts +173 -0
- package/examples/qwen-direct-example.ts +60 -0
- package/examples/qwen-example.ts +62 -0
- package/examples/tutorial-assistant-example.ts +97 -0
- package/jest.config.ts +22 -0
- package/output/tutorials/Go/350/257/255/350/250/200/347/274/226/347/250/213/346/225/231/347/250/213_2025-02-25T09-35-15-436Z.md +2208 -0
- package/output/tutorials/Rust/346/225/231/347/250/213_2025-02-25T08-27-27-632Z.md +1967 -0
- package/output/tutorials//345/246/202/344/275/225/344/275/277/347/224/250TypeScript/345/274/200/345/217/221Node.js/345/272/224/347/224/250_2025-02-25T08-14-39-605Z.md +1721 -0
- package/output/tutorials//346/225/260/345/255/227/347/273/217/346/265/216/345/255/246/346/225/231/347/250/213_2025-02-25T10-45-03-605Z.md +902 -0
- package/output/tutorials//346/232/250/345/215/227/345/244/247/345/255/246/346/225/260/345/255/227/347/273/217/346/265/216/345/255/246/345/244/215/350/257/225/350/265/204/346/226/231_2025-02-25T11-16-59-133Z.md +719 -0
- package/package.json +58 -0
- package/plan-cn.md +321 -0
- package/plan.md +154 -0
- package/src/actions/analyze-task.ts +65 -0
- package/src/actions/base-action.ts +103 -0
- package/src/actions/di/execute-nb-code.ts +247 -0
- package/src/actions/di/write-analysis-code.ts +234 -0
- package/src/actions/write-tutorial.ts +232 -0
- package/src/config/browser.ts +33 -0
- package/src/config/config.ts +345 -0
- package/src/config/embedding.ts +26 -0
- package/src/config/llm.ts +36 -0
- package/src/config/mermaid.ts +37 -0
- package/src/config/omniparse.ts +25 -0
- package/src/config/redis.ts +34 -0
- package/src/config/s3.ts +33 -0
- package/src/config/search.ts +30 -0
- package/src/config/workspace.ts +20 -0
- package/src/index.ts +40 -0
- package/src/management/team.ts +168 -0
- package/src/memory/longterm.ts +218 -0
- package/src/memory/manager.ts +160 -0
- package/src/memory/types.ts +100 -0
- package/src/memory/working.ts +154 -0
- package/src/monitoring/system.ts +413 -0
- package/src/monitoring/types.ts +230 -0
- package/src/plugin/manager.ts +79 -0
- package/src/plugin/types.ts +114 -0
- package/src/provider/vercel-llm.ts +314 -0
- package/src/rag/base-rag.ts +194 -0
- package/src/rag/document-qa.ts +102 -0
- package/src/roles/base-role.ts +155 -0
- package/src/roles/data-interpreter.ts +360 -0
- package/src/roles/engineer.ts +1 -0
- package/src/roles/tutorial-assistant.ts +217 -0
- package/src/skills/base-skill.ts +144 -0
- package/src/skills/code-review.ts +120 -0
- package/src/tools/base-tool.ts +155 -0
- package/src/tools/file-system.ts +204 -0
- package/src/tools/tool-recommend.d.ts +14 -0
- package/src/tools/tool-recommend.ts +31 -0
- package/src/types/action.ts +38 -0
- package/src/types/config.ts +129 -0
- package/src/types/document.ts +354 -0
- package/src/types/llm.ts +64 -0
- package/src/types/memory.ts +36 -0
- package/src/types/message.ts +193 -0
- package/src/types/rag.ts +86 -0
- package/src/types/role.ts +67 -0
- package/src/types/skill.ts +71 -0
- package/src/types/task.ts +32 -0
- package/src/types/team.ts +55 -0
- package/src/types/tool.ts +77 -0
- package/src/types/workflow.ts +133 -0
- package/src/utils/common.ts +73 -0
- package/src/utils/yaml.ts +67 -0
- package/src/websocket/browser-client.ts +187 -0
- package/src/websocket/client.ts +186 -0
- package/src/websocket/server.ts +169 -0
- package/src/websocket/types.ts +125 -0
- package/src/workflow/executor.ts +193 -0
- package/src/workflow/executors/action-executor.ts +72 -0
- package/src/workflow/executors/condition-executor.ts +118 -0
- package/src/workflow/executors/parallel-executor.ts +201 -0
- package/src/workflow/executors/role-executor.ts +76 -0
- package/src/workflow/executors/sequence-executor.ts +196 -0
- package/tests/actions.test.ts +105 -0
- package/tests/benchmark/performance.test.ts +147 -0
- package/tests/config/config.test.ts +115 -0
- package/tests/config.test.ts +106 -0
- package/tests/e2e/setup.ts +74 -0
- package/tests/e2e/workflow.test.ts +88 -0
- package/tests/llm.test.ts +84 -0
- package/tests/memory/memory.test.ts +164 -0
- package/tests/memory.test.ts +63 -0
- package/tests/monitoring/monitoring.test.ts +225 -0
- package/tests/plugin/plugin.test.ts +183 -0
- package/tests/provider/bailian-llm.test.ts +98 -0
- package/tests/rag.test.ts +162 -0
- package/tests/roles.test.ts +88 -0
- package/tests/skills.test.ts +166 -0
- package/tests/team.test.ts +143 -0
- package/tests/tools.test.ts +170 -0
- package/tests/types/document.test.ts +181 -0
- package/tests/types/message.test.ts +122 -0
- package/tests/utils/yaml.test.ts +110 -0
- package/tests/utils.test.ts +74 -0
- package/tests/websocket/browser-client.test.ts +1 -0
- package/tests/websocket/websocket.test.ts +42 -0
- package/tests/workflow/parallel-executor.test.ts +224 -0
- package/tests/workflow/sequence-executor.test.ts +207 -0
- package/tests/workflow.test.ts +290 -0
- package/tsconfig.json +27 -0
- package/typedoc.json +25 -0
@@ -0,0 +1,290 @@
|
|
1
|
+
import { describe, expect, test, mock, beforeEach } from 'bun:test';
|
2
|
+
import { BaseWorkflowExecutor } from '../src/workflow/executor';
|
3
|
+
import { ActionNodeExecutor } from '../src/workflow/executors/action-executor';
|
4
|
+
import { RoleNodeExecutor } from '../src/workflow/executors/role-executor';
|
5
|
+
import type {
|
6
|
+
WorkflowNode,
|
7
|
+
NodeExecutor,
|
8
|
+
WorkflowConfig,
|
9
|
+
WorkflowEvent
|
10
|
+
} from '../src/types/workflow';
|
11
|
+
import type { Action, ActionOutput } from '../src/types/action';
|
12
|
+
import type { Role } from '../src/types/role';
|
13
|
+
import type { Message } from '../src/types/message';
|
14
|
+
import { generateId } from '../src/utils/common';
|
15
|
+
|
16
|
+
describe('Workflow System', () => {
|
17
|
+
// 模拟动作
|
18
|
+
const mockAction: Action = {
|
19
|
+
name: 'test_action',
|
20
|
+
context: {} as any,
|
21
|
+
llm: {} as any,
|
22
|
+
run: mock(() => Promise.resolve({
|
23
|
+
content: 'Action completed',
|
24
|
+
status: 'completed' as const,
|
25
|
+
})),
|
26
|
+
handleException: mock(() => Promise.resolve()),
|
27
|
+
};
|
28
|
+
|
29
|
+
// 模拟角色
|
30
|
+
const mockRole: Role = {
|
31
|
+
name: 'test_role',
|
32
|
+
profile: 'Test profile',
|
33
|
+
goal: 'Test goal',
|
34
|
+
constraints: '',
|
35
|
+
actions: [],
|
36
|
+
state: 0,
|
37
|
+
context: {} as any,
|
38
|
+
observe: mock(() => Promise.resolve(0)),
|
39
|
+
think: mock(() => Promise.resolve(true)),
|
40
|
+
act: mock(() => Promise.resolve({
|
41
|
+
id: '1',
|
42
|
+
content: 'Role action completed',
|
43
|
+
role: 'test_role',
|
44
|
+
causedBy: 'test_action',
|
45
|
+
sentFrom: 'test_role',
|
46
|
+
sendTo: new Set(['*']),
|
47
|
+
})),
|
48
|
+
react: mock(() => Promise.resolve({} as Message)),
|
49
|
+
};
|
50
|
+
|
51
|
+
describe('Node Executors', () => {
|
52
|
+
test('should execute action node', async () => {
|
53
|
+
const executor = new ActionNodeExecutor();
|
54
|
+
const node: WorkflowNode = {
|
55
|
+
id: 'action1',
|
56
|
+
name: 'Test Action',
|
57
|
+
type: 'action',
|
58
|
+
status: 'pending',
|
59
|
+
config: { action: mockAction },
|
60
|
+
childIds: [],
|
61
|
+
};
|
62
|
+
|
63
|
+
const result = await executor.execute(node, {});
|
64
|
+
expect(result.content).toBe('Action completed');
|
65
|
+
expect(executor.getStatus()).toBe('completed');
|
66
|
+
expect(mockAction.run).toHaveBeenCalled();
|
67
|
+
});
|
68
|
+
|
69
|
+
test('should execute role node', async () => {
|
70
|
+
const executor = new RoleNodeExecutor();
|
71
|
+
const node: WorkflowNode = {
|
72
|
+
id: 'role1',
|
73
|
+
name: 'Test Role',
|
74
|
+
type: 'role',
|
75
|
+
status: 'pending',
|
76
|
+
config: { role: mockRole },
|
77
|
+
childIds: [],
|
78
|
+
};
|
79
|
+
|
80
|
+
const result = await executor.execute(node, {});
|
81
|
+
expect(result.content).toBe('Role action completed');
|
82
|
+
expect(executor.getStatus()).toBe('completed');
|
83
|
+
expect(mockRole.observe).toHaveBeenCalled();
|
84
|
+
expect(mockRole.think).toHaveBeenCalled();
|
85
|
+
expect(mockRole.act).toHaveBeenCalled();
|
86
|
+
});
|
87
|
+
|
88
|
+
test('should validate node configurations', () => {
|
89
|
+
const actionExecutor = new ActionNodeExecutor();
|
90
|
+
const roleExecutor = new RoleNodeExecutor();
|
91
|
+
|
92
|
+
const validActionNode: WorkflowNode = {
|
93
|
+
id: 'test',
|
94
|
+
name: 'test',
|
95
|
+
type: 'action',
|
96
|
+
status: 'pending',
|
97
|
+
config: { action: mockAction },
|
98
|
+
childIds: [],
|
99
|
+
};
|
100
|
+
|
101
|
+
const validRoleNode: WorkflowNode = {
|
102
|
+
id: 'test',
|
103
|
+
name: 'test',
|
104
|
+
type: 'role',
|
105
|
+
status: 'pending',
|
106
|
+
config: { role: mockRole },
|
107
|
+
childIds: [],
|
108
|
+
};
|
109
|
+
|
110
|
+
const invalidActionNode: WorkflowNode = {
|
111
|
+
id: 'test',
|
112
|
+
name: 'test',
|
113
|
+
type: 'action',
|
114
|
+
status: 'pending',
|
115
|
+
config: {},
|
116
|
+
childIds: [],
|
117
|
+
};
|
118
|
+
|
119
|
+
expect(actionExecutor.validate(validActionNode)).toBe(true);
|
120
|
+
expect(roleExecutor.validate(validRoleNode)).toBe(true);
|
121
|
+
expect(actionExecutor.validate(invalidActionNode)).toBe(false);
|
122
|
+
});
|
123
|
+
});
|
124
|
+
|
125
|
+
describe('Workflow Execution', () => {
|
126
|
+
let executor: BaseWorkflowExecutor;
|
127
|
+
let config: WorkflowConfig;
|
128
|
+
let events: WorkflowEvent[] = [];
|
129
|
+
|
130
|
+
beforeEach(() => {
|
131
|
+
executor = new BaseWorkflowExecutor();
|
132
|
+
events = [];
|
133
|
+
|
134
|
+
// 注册事件监听器
|
135
|
+
['workflow:start', 'workflow:complete', 'workflow:fail',
|
136
|
+
'node:start', 'node:complete', 'node:fail'].forEach(event => {
|
137
|
+
executor.on(event, (e: WorkflowEvent) => events.push(e));
|
138
|
+
});
|
139
|
+
|
140
|
+
// 创建测试工作流配置
|
141
|
+
config = {
|
142
|
+
id: generateId(),
|
143
|
+
name: 'Test Workflow',
|
144
|
+
version: '1.0.0',
|
145
|
+
nodes: [
|
146
|
+
{
|
147
|
+
id: 'action1',
|
148
|
+
name: 'Action Node',
|
149
|
+
type: 'action',
|
150
|
+
status: 'pending',
|
151
|
+
config: { action: mockAction },
|
152
|
+
childIds: ['role1'],
|
153
|
+
},
|
154
|
+
{
|
155
|
+
id: 'role1',
|
156
|
+
name: 'Role Node',
|
157
|
+
type: 'role',
|
158
|
+
status: 'pending',
|
159
|
+
config: { role: mockRole },
|
160
|
+
childIds: [],
|
161
|
+
parentId: 'action1',
|
162
|
+
},
|
163
|
+
],
|
164
|
+
};
|
165
|
+
|
166
|
+
// 注册执行器
|
167
|
+
executor.registerNodeExecutor('action', new ActionNodeExecutor());
|
168
|
+
executor.registerNodeExecutor('role', new RoleNodeExecutor());
|
169
|
+
});
|
170
|
+
|
171
|
+
test('should execute workflow with mixed nodes', async () => {
|
172
|
+
await executor.execute(config);
|
173
|
+
|
174
|
+
const state = executor.getState();
|
175
|
+
expect(state.status).toBe('completed');
|
176
|
+
expect(state.completedNodeIds).toContain('action1');
|
177
|
+
expect(state.completedNodeIds).toContain('role1');
|
178
|
+
expect(state.failedNodeIds).toHaveLength(0);
|
179
|
+
|
180
|
+
const eventTypes = events.map(e => e.type);
|
181
|
+
expect(eventTypes).toContain('workflow:start');
|
182
|
+
expect(eventTypes).toContain('node:start');
|
183
|
+
expect(eventTypes).toContain('node:complete');
|
184
|
+
expect(eventTypes).toContain('workflow:complete');
|
185
|
+
});
|
186
|
+
|
187
|
+
test('should execute workflow successfully', async () => {
|
188
|
+
await executor.execute(config);
|
189
|
+
|
190
|
+
const state = executor.getState();
|
191
|
+
expect(state.status).toBe('completed');
|
192
|
+
expect(state.completedNodeIds).toContain('action1');
|
193
|
+
expect(state.completedNodeIds).toContain('role1');
|
194
|
+
expect(state.failedNodeIds).toHaveLength(0);
|
195
|
+
});
|
196
|
+
|
197
|
+
test('should emit workflow events', async () => {
|
198
|
+
await executor.execute(config);
|
199
|
+
|
200
|
+
const eventTypes = events.map(e => e.type);
|
201
|
+
expect(eventTypes).toContain('workflow:start');
|
202
|
+
expect(eventTypes).toContain('node:start');
|
203
|
+
expect(eventTypes).toContain('node:complete');
|
204
|
+
expect(eventTypes).toContain('workflow:complete');
|
205
|
+
});
|
206
|
+
|
207
|
+
test('should handle node execution failure', async () => {
|
208
|
+
const failingExecutor: NodeExecutor = {
|
209
|
+
async execute() { throw new Error('Test error'); },
|
210
|
+
validate() { return true; },
|
211
|
+
getStatus() { return 'failed'; },
|
212
|
+
getResult() { return null; },
|
213
|
+
};
|
214
|
+
|
215
|
+
executor.registerNodeExecutor('action', failingExecutor);
|
216
|
+
|
217
|
+
await expect(executor.execute(config)).rejects.toThrow('Test error');
|
218
|
+
|
219
|
+
const state = executor.getState();
|
220
|
+
expect(state.status).toBe('failed');
|
221
|
+
expect(state.failedNodeIds).toContain('action1');
|
222
|
+
});
|
223
|
+
|
224
|
+
test('should pause and resume workflow', async () => {
|
225
|
+
const slowExecutor: NodeExecutor = {
|
226
|
+
async execute(node: WorkflowNode) {
|
227
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
228
|
+
return { nodeId: node.id, executed: true };
|
229
|
+
},
|
230
|
+
validate() { return true; },
|
231
|
+
getStatus() { return 'running'; },
|
232
|
+
getResult() { return null; },
|
233
|
+
};
|
234
|
+
|
235
|
+
executor.registerNodeExecutor('action', slowExecutor);
|
236
|
+
|
237
|
+
// 启动工作流
|
238
|
+
const execution = executor.execute(config);
|
239
|
+
|
240
|
+
// 暂停工作流
|
241
|
+
await executor.pause();
|
242
|
+
const pausedState = executor.getState();
|
243
|
+
expect(pausedState.status).toBe('running');
|
244
|
+
|
245
|
+
// 恢复工作流
|
246
|
+
await executor.resume();
|
247
|
+
await execution;
|
248
|
+
|
249
|
+
const finalState = executor.getState();
|
250
|
+
expect(finalState.status).toBe('completed');
|
251
|
+
});
|
252
|
+
|
253
|
+
test('should stop workflow', async () => {
|
254
|
+
const execution = executor.execute(config);
|
255
|
+
await executor.stop();
|
256
|
+
await execution;
|
257
|
+
|
258
|
+
const state = executor.getState();
|
259
|
+
expect(state.status).toBe('running');
|
260
|
+
expect(state.completedNodeIds.length).toBeLessThan(config.nodes.length);
|
261
|
+
});
|
262
|
+
|
263
|
+
test('should validate node configuration', async () => {
|
264
|
+
const validatingExecutor: NodeExecutor = {
|
265
|
+
async execute() { return null; },
|
266
|
+
validate(node: WorkflowNode) {
|
267
|
+
return !!node.name && !!node.type;
|
268
|
+
},
|
269
|
+
getStatus() { return 'pending'; },
|
270
|
+
getResult() { return null; },
|
271
|
+
};
|
272
|
+
|
273
|
+
executor.registerNodeExecutor('action', validatingExecutor);
|
274
|
+
|
275
|
+
// 测试无效节点配置
|
276
|
+
const invalidConfig: WorkflowConfig = {
|
277
|
+
...config,
|
278
|
+
nodes: [{
|
279
|
+
id: 'invalid',
|
280
|
+
name: '', // 无效的名称
|
281
|
+
type: 'action',
|
282
|
+
status: 'pending',
|
283
|
+
childIds: [],
|
284
|
+
}],
|
285
|
+
};
|
286
|
+
|
287
|
+
await expect(executor.execute(invalidConfig)).rejects.toThrow('Invalid node configuration');
|
288
|
+
});
|
289
|
+
});
|
290
|
+
});
|
package/tsconfig.json
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
// Enable latest features
|
4
|
+
"lib": ["ESNext", "DOM"],
|
5
|
+
"target": "ESNext",
|
6
|
+
"module": "ESNext",
|
7
|
+
"moduleDetection": "force",
|
8
|
+
"jsx": "react-jsx",
|
9
|
+
"allowJs": true,
|
10
|
+
|
11
|
+
// Bundler mode
|
12
|
+
"moduleResolution": "bundler",
|
13
|
+
"allowImportingTsExtensions": true,
|
14
|
+
"verbatimModuleSyntax": true,
|
15
|
+
"noEmit": true,
|
16
|
+
|
17
|
+
// Best practices
|
18
|
+
"strict": true,
|
19
|
+
"skipLibCheck": true,
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
21
|
+
|
22
|
+
// Some stricter flags (disabled by default)
|
23
|
+
"noUnusedLocals": false,
|
24
|
+
"noUnusedParameters": false,
|
25
|
+
"noPropertyAccessFromIndexSignature": false
|
26
|
+
}
|
27
|
+
}
|
package/typedoc.json
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
{
|
2
|
+
"entryPoints": ["src/index.ts"],
|
3
|
+
"out": "docs/api",
|
4
|
+
"exclude": ["**/node_modules/**", "**/tests/**"],
|
5
|
+
"theme": "default",
|
6
|
+
"name": "MetaGPT TypeScript API",
|
7
|
+
"excludePrivate": true,
|
8
|
+
"excludeProtected": false,
|
9
|
+
"excludeExternals": true,
|
10
|
+
"includeVersion": true,
|
11
|
+
"categorizeByGroup": true,
|
12
|
+
"categoryOrder": [
|
13
|
+
"Core",
|
14
|
+
"Role System",
|
15
|
+
"Action System",
|
16
|
+
"Memory",
|
17
|
+
"LLM",
|
18
|
+
"Tools",
|
19
|
+
"Skills",
|
20
|
+
"RAG",
|
21
|
+
"Team",
|
22
|
+
"Workflow",
|
23
|
+
"*"
|
24
|
+
]
|
25
|
+
}
|