@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
package/src/types/rag.ts
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
import { z } from 'zod';
|
2
|
+
import type { LLMProvider } from './llm';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* 向量存储配置
|
6
|
+
*/
|
7
|
+
export const VectorStoreConfigSchema = z.object({
|
8
|
+
/** 服务器URL */
|
9
|
+
url: z.string(),
|
10
|
+
/** 集合名称 */
|
11
|
+
collectionName: z.string(),
|
12
|
+
/** 向量维度 */
|
13
|
+
dimension: z.number(),
|
14
|
+
/** 距离度量方式 */
|
15
|
+
distance: z.enum(['Cosine', 'Euclidean', 'Dot']),
|
16
|
+
/** API密钥 */
|
17
|
+
apiKey: z.string().optional(),
|
18
|
+
});
|
19
|
+
|
20
|
+
export type VectorStoreConfig = z.infer<typeof VectorStoreConfigSchema>;
|
21
|
+
|
22
|
+
/**
|
23
|
+
* RAG系统配置
|
24
|
+
*/
|
25
|
+
export const RAGConfigSchema = z.object({
|
26
|
+
/** LLM提供商 */
|
27
|
+
llm: z.any(), // LLMProvider
|
28
|
+
/** 向量存储配置 */
|
29
|
+
vectorStore: VectorStoreConfigSchema,
|
30
|
+
/** 分块大小 */
|
31
|
+
chunkSize: z.number().default(1000),
|
32
|
+
/** 分块重叠大小 */
|
33
|
+
chunkOverlap: z.number().default(200),
|
34
|
+
/** 检索结果数量 */
|
35
|
+
topK: z.number().default(5),
|
36
|
+
/** 最小相似度分数 */
|
37
|
+
minScore: z.number().default(0.7),
|
38
|
+
});
|
39
|
+
|
40
|
+
export type RAGConfig = z.infer<typeof RAGConfigSchema>;
|
41
|
+
|
42
|
+
/**
|
43
|
+
* 文档块结构
|
44
|
+
*/
|
45
|
+
export const ChunkSchema = z.object({
|
46
|
+
/** 块ID */
|
47
|
+
id: z.string(),
|
48
|
+
/** 块内容 */
|
49
|
+
content: z.string(),
|
50
|
+
/** 块向量 */
|
51
|
+
embedding: z.array(z.number()),
|
52
|
+
/** 块元数据 */
|
53
|
+
metadata: z.record(z.any()),
|
54
|
+
});
|
55
|
+
|
56
|
+
export type Chunk = z.infer<typeof ChunkSchema>;
|
57
|
+
|
58
|
+
/**
|
59
|
+
* 搜索结果结构
|
60
|
+
*/
|
61
|
+
export const SearchResultSchema = z.object({
|
62
|
+
/** 匹配的文档块 */
|
63
|
+
chunk: ChunkSchema,
|
64
|
+
/** 相似度分数 */
|
65
|
+
score: z.number(),
|
66
|
+
/** 结果元数据 */
|
67
|
+
metadata: z.record(z.any()),
|
68
|
+
});
|
69
|
+
|
70
|
+
export type SearchResult = z.infer<typeof SearchResultSchema>;
|
71
|
+
|
72
|
+
/**
|
73
|
+
* RAG系统接口
|
74
|
+
*/
|
75
|
+
export interface RAGSystem {
|
76
|
+
/** 添加文档 */
|
77
|
+
addDocument(content: string, metadata?: Record<string, any>): Promise<Chunk[]>;
|
78
|
+
/** 删除文档块 */
|
79
|
+
deleteChunks(ids: string[]): Promise<void>;
|
80
|
+
/** 更新文档块 */
|
81
|
+
updateChunk(chunk: Chunk): Promise<void>;
|
82
|
+
/** 搜索相关文档 */
|
83
|
+
search(query: string, topK?: number): Promise<SearchResult[]>;
|
84
|
+
/** 生成回答 */
|
85
|
+
generate(query: string): Promise<string>;
|
86
|
+
}
|
@@ -0,0 +1,67 @@
|
|
1
|
+
import { z } from 'zod';
|
2
|
+
import type { Message } from './message';
|
3
|
+
import type { Action } from './action';
|
4
|
+
import { createMachine } from 'xstate';
|
5
|
+
|
6
|
+
export const RoleContextSchema = z.object({
|
7
|
+
memory: z.any(), // TODO: Define Memory type
|
8
|
+
workingMemory: z.any(), // TODO: Define Memory type
|
9
|
+
state: z.number(),
|
10
|
+
todo: z.any().nullable(), // TODO: Define Action type
|
11
|
+
watch: z.set(z.string()),
|
12
|
+
reactMode: z.enum(['react', 'by_order', 'plan_and_act']),
|
13
|
+
});
|
14
|
+
|
15
|
+
export type RoleContext = z.infer<typeof RoleContextSchema>;
|
16
|
+
|
17
|
+
export const RoleSchema = z.object({
|
18
|
+
name: z.string(),
|
19
|
+
profile: z.string(),
|
20
|
+
goal: z.string(),
|
21
|
+
constraints: z.string(),
|
22
|
+
actions: z.array(z.any()), // TODO: Define Action type
|
23
|
+
});
|
24
|
+
|
25
|
+
export type Role = z.infer<typeof RoleSchema> & {
|
26
|
+
observe(): Promise<number>;
|
27
|
+
think(): Promise<boolean>;
|
28
|
+
act(): Promise<Message>;
|
29
|
+
react(): Promise<Message>;
|
30
|
+
state: number;
|
31
|
+
context: RoleContext;
|
32
|
+
};
|
33
|
+
|
34
|
+
// 角色状态机定义
|
35
|
+
export const roleStateMachine = createMachine({
|
36
|
+
id: 'role',
|
37
|
+
initial: 'idle',
|
38
|
+
states: {
|
39
|
+
idle: {
|
40
|
+
on: { OBSERVE: 'observing' }
|
41
|
+
},
|
42
|
+
observing: {
|
43
|
+
on: {
|
44
|
+
THINK: 'thinking',
|
45
|
+
COMPLETE: 'idle'
|
46
|
+
}
|
47
|
+
},
|
48
|
+
thinking: {
|
49
|
+
on: {
|
50
|
+
ACT: 'acting',
|
51
|
+
COMPLETE: 'idle'
|
52
|
+
}
|
53
|
+
},
|
54
|
+
acting: {
|
55
|
+
on: {
|
56
|
+
REACT: 'reacting',
|
57
|
+
COMPLETE: 'idle'
|
58
|
+
}
|
59
|
+
},
|
60
|
+
reacting: {
|
61
|
+
on: {
|
62
|
+
OBSERVE: 'observing',
|
63
|
+
COMPLETE: 'idle'
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
});
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import { z } from 'zod';
|
2
|
+
import type { Action } from './action';
|
3
|
+
import type { LLMProvider } from './llm';
|
4
|
+
|
5
|
+
/**
|
6
|
+
* 技能配置结构
|
7
|
+
*/
|
8
|
+
export const SkillConfigSchema = z.object({
|
9
|
+
name: z.string(), // 技能名称
|
10
|
+
description: z.string(), // 技能描述
|
11
|
+
llm: z.any(), // LLM 提供商
|
12
|
+
actions: z.array(z.any()).optional(), // 技能包含的动作
|
13
|
+
args: z.record(z.any()).optional(), // 技能参数
|
14
|
+
});
|
15
|
+
|
16
|
+
export type SkillConfig = z.infer<typeof SkillConfigSchema>;
|
17
|
+
|
18
|
+
/**
|
19
|
+
* 技能上下文结构
|
20
|
+
*/
|
21
|
+
export const SkillContextSchema = z.object({
|
22
|
+
name: z.string(),
|
23
|
+
description: z.string(),
|
24
|
+
actions: z.array(z.any()),
|
25
|
+
args: z.record(z.any()).optional(),
|
26
|
+
llm: z.any(),
|
27
|
+
});
|
28
|
+
|
29
|
+
export type SkillContext = z.infer<typeof SkillContextSchema>;
|
30
|
+
|
31
|
+
/**
|
32
|
+
* 技能执行结果结构
|
33
|
+
*/
|
34
|
+
export const SkillResultSchema = z.object({
|
35
|
+
success: z.boolean(), // 执行是否成功
|
36
|
+
message: z.string(), // 结果消息
|
37
|
+
data: z.any().optional(), // 执行结果数据
|
38
|
+
error: z.any().optional(), // 错误信息
|
39
|
+
});
|
40
|
+
|
41
|
+
export type SkillResult = z.infer<typeof SkillResultSchema>;
|
42
|
+
|
43
|
+
/**
|
44
|
+
* 技能接口
|
45
|
+
*/
|
46
|
+
export interface Skill {
|
47
|
+
name: string; // 技能名称
|
48
|
+
description: string; // 技能描述
|
49
|
+
context: SkillContext; // 技能上下文
|
50
|
+
llm: LLMProvider; // LLM 提供商
|
51
|
+
actions: Action[]; // 技能包含的动作
|
52
|
+
|
53
|
+
/**
|
54
|
+
* 执行技能
|
55
|
+
* @param args 执行参数
|
56
|
+
* @returns 执行结果
|
57
|
+
*/
|
58
|
+
execute(args?: Record<string, any>): Promise<SkillResult>;
|
59
|
+
|
60
|
+
/**
|
61
|
+
* 验证技能是否可用
|
62
|
+
* @returns 验证结果
|
63
|
+
*/
|
64
|
+
validate(): Promise<boolean>;
|
65
|
+
|
66
|
+
/**
|
67
|
+
* 处理技能执行异常
|
68
|
+
* @param error 错误对象
|
69
|
+
*/
|
70
|
+
handleError(error: Error): Promise<void>;
|
71
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
/**
|
2
|
+
* 任务类型枚举
|
3
|
+
*/
|
4
|
+
export enum TaskType {
|
5
|
+
DATA_ANALYSIS = 'DATA_ANALYSIS',
|
6
|
+
DATA_PREPROCESS = 'DATA_PREPROCESS',
|
7
|
+
FEATURE_ENGINEERING = 'FEATURE_ENGINEERING',
|
8
|
+
MODEL_TRAIN = 'MODEL_TRAIN',
|
9
|
+
MODEL_EVALUATION = 'MODEL_EVALUATION',
|
10
|
+
VISUALIZATION = 'VISUALIZATION',
|
11
|
+
RECOMMENDATION = 'RECOMMENDATION',
|
12
|
+
}
|
13
|
+
|
14
|
+
/**
|
15
|
+
* 任务接口
|
16
|
+
*/
|
17
|
+
export interface Task {
|
18
|
+
id: string;
|
19
|
+
title: string;
|
20
|
+
description: string;
|
21
|
+
task_type: string;
|
22
|
+
status: 'pending' | 'in_progress' | 'completed' | 'failed';
|
23
|
+
}
|
24
|
+
|
25
|
+
/**
|
26
|
+
* 任务结果接口
|
27
|
+
*/
|
28
|
+
export interface TaskResult {
|
29
|
+
code: string;
|
30
|
+
result: string;
|
31
|
+
isSuccess: boolean;
|
32
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import { z } from 'zod';
|
2
|
+
import { Role } from './role';
|
3
|
+
import { Environment } from '../environment/environment';
|
4
|
+
import { Context } from '../context/context';
|
5
|
+
import { Message } from './message';
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Team configuration schema
|
9
|
+
*/
|
10
|
+
export const TeamConfigSchema = z.object({
|
11
|
+
/** Environment for team communication and state management */
|
12
|
+
environment: z.instanceof(Environment).optional(),
|
13
|
+
/** Initial investment amount */
|
14
|
+
investment: z.number().default(10.0),
|
15
|
+
/** Project idea or requirement */
|
16
|
+
idea: z.string().default(''),
|
17
|
+
/** Team context */
|
18
|
+
context: z.instanceof(Context).optional(),
|
19
|
+
/** Team roles */
|
20
|
+
roles: z.array(z.instanceof(Role)).optional(),
|
21
|
+
/** Environment description */
|
22
|
+
envDesc: z.string().optional(),
|
23
|
+
});
|
24
|
+
|
25
|
+
export type TeamConfig = z.infer<typeof TeamConfigSchema>;
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Team state schema
|
29
|
+
*/
|
30
|
+
export const TeamStateSchema = z.object({
|
31
|
+
/** Current round number */
|
32
|
+
currentRound: z.number().default(0),
|
33
|
+
/** Whether team is running */
|
34
|
+
isRunning: z.boolean().default(false),
|
35
|
+
/** Whether team is archived */
|
36
|
+
isArchived: z.boolean().default(false),
|
37
|
+
/** Team history */
|
38
|
+
history: z.array(z.instanceof(Message)).default([]),
|
39
|
+
});
|
40
|
+
|
41
|
+
export type TeamState = z.infer<typeof TeamStateSchema>;
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Team storage schema for serialization
|
45
|
+
*/
|
46
|
+
export const TeamStorageSchema = z.object({
|
47
|
+
/** Team configuration */
|
48
|
+
config: TeamConfigSchema,
|
49
|
+
/** Team state */
|
50
|
+
state: TeamStateSchema,
|
51
|
+
/** Storage path */
|
52
|
+
storagePath: z.string().optional(),
|
53
|
+
});
|
54
|
+
|
55
|
+
export type TeamStorage = z.infer<typeof TeamStorageSchema>;
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import { z } from 'zod';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* 工具配置结构
|
5
|
+
*/
|
6
|
+
export const ToolConfigSchema = z.object({
|
7
|
+
name: z.string(), // 工具名称
|
8
|
+
description: z.string(), // 工具描述
|
9
|
+
version: z.string(), // 工具版本
|
10
|
+
category: z.string(), // 工具类别
|
11
|
+
args: z.record(z.any()).optional(), // 工具参数
|
12
|
+
metadata: z.record(z.any()).optional(), // 元数据
|
13
|
+
});
|
14
|
+
|
15
|
+
export type ToolConfig = z.infer<typeof ToolConfigSchema>;
|
16
|
+
|
17
|
+
/**
|
18
|
+
* 工具上下文结构
|
19
|
+
*/
|
20
|
+
export const ToolContextSchema = z.object({
|
21
|
+
name: z.string(),
|
22
|
+
description: z.string(),
|
23
|
+
args: z.record(z.any()).optional(),
|
24
|
+
metadata: z.record(z.any()).optional(),
|
25
|
+
state: z.record(z.any()).optional(),
|
26
|
+
});
|
27
|
+
|
28
|
+
export type ToolContext = z.infer<typeof ToolContextSchema>;
|
29
|
+
|
30
|
+
/**
|
31
|
+
* 工具执行结果结构
|
32
|
+
*/
|
33
|
+
export const ToolResultSchema = z.object({
|
34
|
+
success: z.boolean(), // 执行是否成功
|
35
|
+
message: z.string(), // 结果消息
|
36
|
+
data: z.any().optional(), // 执行结果数据
|
37
|
+
error: z.any().optional(), // 错误信息
|
38
|
+
metadata: z.record(z.any()).optional(), // 结果元数据
|
39
|
+
});
|
40
|
+
|
41
|
+
export type ToolResult = z.infer<typeof ToolResultSchema>;
|
42
|
+
|
43
|
+
/**
|
44
|
+
* 工具接口
|
45
|
+
*/
|
46
|
+
export interface Tool {
|
47
|
+
name: string; // 工具名称
|
48
|
+
description: string; // 工具描述
|
49
|
+
version: string; // 工具版本
|
50
|
+
category: string; // 工具类别
|
51
|
+
context: ToolContext; // 工具上下文
|
52
|
+
|
53
|
+
/**
|
54
|
+
* 执行工具
|
55
|
+
* @param args 执行参数
|
56
|
+
* @returns 执行结果
|
57
|
+
*/
|
58
|
+
execute(args?: Record<string, any>): Promise<ToolResult>;
|
59
|
+
|
60
|
+
/**
|
61
|
+
* 验证工具是否可用
|
62
|
+
* @returns 验证结果
|
63
|
+
*/
|
64
|
+
validate(): Promise<boolean>;
|
65
|
+
|
66
|
+
/**
|
67
|
+
* 处理工具执行异常
|
68
|
+
* @param error 错误对象
|
69
|
+
*/
|
70
|
+
handleError(error: Error): Promise<void>;
|
71
|
+
|
72
|
+
/**
|
73
|
+
* 获取工具帮助信息
|
74
|
+
* @returns 帮助信息
|
75
|
+
*/
|
76
|
+
getHelp(): string;
|
77
|
+
}
|
@@ -0,0 +1,133 @@
|
|
1
|
+
import { z } from 'zod';
|
2
|
+
import type { Role } from './role';
|
3
|
+
import type { Action } from './action';
|
4
|
+
import type { Message } from './message';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* 工作流节点类型
|
8
|
+
*/
|
9
|
+
export const WorkflowNodeSchema = z.object({
|
10
|
+
/** 节点ID */
|
11
|
+
id: z.string(),
|
12
|
+
/** 节点名称 */
|
13
|
+
name: z.string(),
|
14
|
+
/** 节点类型 */
|
15
|
+
type: z.enum(['action', 'role', 'condition', 'parallel', 'sequence']),
|
16
|
+
/** 节点配置 */
|
17
|
+
config: z.record(z.any()).optional(),
|
18
|
+
/** 节点状态 */
|
19
|
+
status: z.enum(['pending', 'running', 'completed', 'failed']).default('pending'),
|
20
|
+
/** 节点执行结果 */
|
21
|
+
result: z.any().optional(),
|
22
|
+
/** 父节点ID */
|
23
|
+
parentId: z.string().optional(),
|
24
|
+
/** 子节点ID列表 */
|
25
|
+
childIds: z.array(z.string()).default([]),
|
26
|
+
});
|
27
|
+
|
28
|
+
export type WorkflowNode = z.infer<typeof WorkflowNodeSchema>;
|
29
|
+
|
30
|
+
/**
|
31
|
+
* 工作流配置
|
32
|
+
*/
|
33
|
+
export const WorkflowConfigSchema = z.object({
|
34
|
+
/** 工作流ID */
|
35
|
+
id: z.string(),
|
36
|
+
/** 工作流名称 */
|
37
|
+
name: z.string(),
|
38
|
+
/** 工作流描述 */
|
39
|
+
description: z.string().optional(),
|
40
|
+
/** 工作流版本 */
|
41
|
+
version: z.string().default('1.0.0'),
|
42
|
+
/** 工作流节点列表 */
|
43
|
+
nodes: z.array(WorkflowNodeSchema),
|
44
|
+
/** 工作流配置 */
|
45
|
+
config: z.record(z.any()).optional(),
|
46
|
+
/** 工作流元数据 */
|
47
|
+
metadata: z.record(z.any()).optional(),
|
48
|
+
});
|
49
|
+
|
50
|
+
export type WorkflowConfig = z.infer<typeof WorkflowConfigSchema>;
|
51
|
+
|
52
|
+
/**
|
53
|
+
* 工作流状态
|
54
|
+
*/
|
55
|
+
export const WorkflowStateSchema = z.object({
|
56
|
+
/** 工作流ID */
|
57
|
+
id: z.string(),
|
58
|
+
/** 工作流状态 */
|
59
|
+
status: z.enum(['pending', 'running', 'completed', 'failed']).default('pending'),
|
60
|
+
/** 当前执行的节点ID */
|
61
|
+
currentNodeId: z.string().optional(),
|
62
|
+
/** 已完成的节点ID列表 */
|
63
|
+
completedNodeIds: z.array(z.string()).default([]),
|
64
|
+
/** 失败的节点ID列表 */
|
65
|
+
failedNodeIds: z.array(z.string()).default([]),
|
66
|
+
/** 工作流执行历史 */
|
67
|
+
history: z.array(z.object({
|
68
|
+
timestamp: z.number(),
|
69
|
+
nodeId: z.string(),
|
70
|
+
status: z.string(),
|
71
|
+
message: z.string().optional(),
|
72
|
+
})).default([]),
|
73
|
+
});
|
74
|
+
|
75
|
+
export type WorkflowState = z.infer<typeof WorkflowStateSchema>;
|
76
|
+
|
77
|
+
/**
|
78
|
+
* 工作流执行器接口
|
79
|
+
*/
|
80
|
+
export interface WorkflowExecutor {
|
81
|
+
/** 执行工作流 */
|
82
|
+
execute(config: WorkflowConfig): Promise<void>;
|
83
|
+
/** 暂停工作流 */
|
84
|
+
pause(): Promise<void>;
|
85
|
+
/** 恢复工作流 */
|
86
|
+
resume(): Promise<void>;
|
87
|
+
/** 停止工作流 */
|
88
|
+
stop(): Promise<void>;
|
89
|
+
/** 获取工作流状态 */
|
90
|
+
getState(): WorkflowState;
|
91
|
+
}
|
92
|
+
|
93
|
+
/**
|
94
|
+
* 工作流节点执行器接口
|
95
|
+
*/
|
96
|
+
export interface NodeExecutor {
|
97
|
+
/** 执行节点 */
|
98
|
+
execute(node: WorkflowNode, context: any): Promise<any>;
|
99
|
+
/** 验证节点配置 */
|
100
|
+
validate(node: WorkflowNode): boolean;
|
101
|
+
/** 获取节点状态 */
|
102
|
+
getStatus(): string;
|
103
|
+
/** 获取节点结果 */
|
104
|
+
getResult(): any;
|
105
|
+
}
|
106
|
+
|
107
|
+
/**
|
108
|
+
* 工作流事件类型
|
109
|
+
*/
|
110
|
+
export const WorkflowEventSchema = z.object({
|
111
|
+
/** 事件类型 */
|
112
|
+
type: z.enum([
|
113
|
+
'workflow:start',
|
114
|
+
'workflow:complete',
|
115
|
+
'workflow:fail',
|
116
|
+
'node:start',
|
117
|
+
'node:complete',
|
118
|
+
'node:fail',
|
119
|
+
'error'
|
120
|
+
]),
|
121
|
+
/** 事件时间戳 */
|
122
|
+
timestamp: z.number(),
|
123
|
+
/** 工作流ID */
|
124
|
+
workflowId: z.string(),
|
125
|
+
/** 节点ID */
|
126
|
+
nodeId: z.string().optional(),
|
127
|
+
/** 事件数据 */
|
128
|
+
data: z.any().optional(),
|
129
|
+
/** 错误信息 */
|
130
|
+
error: z.any().optional(),
|
131
|
+
});
|
132
|
+
|
133
|
+
export type WorkflowEvent = z.infer<typeof WorkflowEventSchema>;
|
@@ -0,0 +1,73 @@
|
|
1
|
+
/**
|
2
|
+
* 将任意值转换为字符串
|
3
|
+
* @param value 要转换的值
|
4
|
+
* @returns 字符串表示
|
5
|
+
*/
|
6
|
+
export function anyToString(value: any): string {
|
7
|
+
if (typeof value === 'string') return value;
|
8
|
+
if (value === null) return 'null';
|
9
|
+
if (value === undefined) return 'undefined';
|
10
|
+
if (typeof value === 'function') return 'function: ' + (value.name || '(anonymous)');
|
11
|
+
if (typeof value === 'object') {
|
12
|
+
if (value instanceof Date) return 'Date: ' + value.toString();
|
13
|
+
try {
|
14
|
+
return value.toString() || JSON.stringify(value);
|
15
|
+
} catch (e) {
|
16
|
+
return Object.prototype.toString.call(value);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
return String(value);
|
20
|
+
}
|
21
|
+
|
22
|
+
/**
|
23
|
+
* 将任意值转换为字符串集合
|
24
|
+
* @param value 要转换的值
|
25
|
+
* @returns 字符串集合
|
26
|
+
*/
|
27
|
+
export function anyToStringSet(value: any): Set<string> {
|
28
|
+
if (value instanceof Set) {
|
29
|
+
return new Set([...value].map(anyToString));
|
30
|
+
}
|
31
|
+
if (Array.isArray(value)) {
|
32
|
+
return new Set(value.map(anyToString));
|
33
|
+
}
|
34
|
+
return new Set([anyToString(value)]);
|
35
|
+
}
|
36
|
+
|
37
|
+
/**
|
38
|
+
* 生成唯一ID
|
39
|
+
* @returns UUID字符串
|
40
|
+
*/
|
41
|
+
export function generateId(): string {
|
42
|
+
return crypto.randomUUID();
|
43
|
+
}
|
44
|
+
|
45
|
+
/**
|
46
|
+
* 延迟执行
|
47
|
+
* @param ms 延迟毫秒数
|
48
|
+
* @returns Promise
|
49
|
+
*/
|
50
|
+
export function delay(ms: number): Promise<void> {
|
51
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
52
|
+
}
|
53
|
+
|
54
|
+
/**
|
55
|
+
* 重试函数执行
|
56
|
+
* @param fn 要执行的函数
|
57
|
+
* @param retries 重试次数
|
58
|
+
* @param delay 重试延迟(ms)
|
59
|
+
* @returns Promise
|
60
|
+
*/
|
61
|
+
export async function retry<T>(
|
62
|
+
fn: () => Promise<T>,
|
63
|
+
retries: number = 3,
|
64
|
+
delayMs: number = 1000
|
65
|
+
): Promise<T> {
|
66
|
+
try {
|
67
|
+
return await fn();
|
68
|
+
} catch (error) {
|
69
|
+
if (retries <= 0) throw error;
|
70
|
+
await delay(delayMs);
|
71
|
+
return retry(fn, retries - 1, delayMs);
|
72
|
+
}
|
73
|
+
}
|
@@ -0,0 +1,67 @@
|
|
1
|
+
import * as yaml from 'js-yaml';
|
2
|
+
import * as fs from 'fs/promises';
|
3
|
+
import { stringify } from 'yaml';
|
4
|
+
|
5
|
+
/**
|
6
|
+
* YAML model utility class for handling YAML configuration files
|
7
|
+
*/
|
8
|
+
export class YamlModel {
|
9
|
+
/**
|
10
|
+
* Parse YAML string to object
|
11
|
+
* @param data - YAML string to parse
|
12
|
+
* @returns Parsed object
|
13
|
+
*/
|
14
|
+
public static parse(data: string): any {
|
15
|
+
try {
|
16
|
+
return yaml.load(data);
|
17
|
+
} catch (error: unknown) {
|
18
|
+
throw new Error(`Failed to parse YAML string: ${error instanceof Error ? error.message : String(error)}`);
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
/**
|
23
|
+
* Convert object to YAML string
|
24
|
+
* @param obj - Object to convert
|
25
|
+
* @returns YAML string
|
26
|
+
*/
|
27
|
+
public static stringify(obj: any): string {
|
28
|
+
try {
|
29
|
+
// Test for circular references
|
30
|
+
JSON.stringify(obj);
|
31
|
+
return yaml.dump(obj);
|
32
|
+
} catch (error: unknown) {
|
33
|
+
if (error instanceof TypeError && error.message.includes('circular')) {
|
34
|
+
throw new Error('Cannot stringify object with circular references');
|
35
|
+
}
|
36
|
+
throw error;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Load and parse YAML file
|
42
|
+
* @param path - Path to YAML file
|
43
|
+
* @returns Parsed object
|
44
|
+
*/
|
45
|
+
public static async fromFile(path: string): Promise<any> {
|
46
|
+
try {
|
47
|
+
const data = await fs.readFile(path, 'utf-8');
|
48
|
+
return YamlModel.parse(data);
|
49
|
+
} catch (error: unknown) {
|
50
|
+
throw new Error(`Failed to load YAML file: ${error instanceof Error ? error.message : String(error)}`);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Save object as YAML file
|
56
|
+
* @param obj - Object to save
|
57
|
+
* @param path - Path to save to
|
58
|
+
*/
|
59
|
+
public static async toFile(obj: any, path: string): Promise<void> {
|
60
|
+
try {
|
61
|
+
const yaml = YamlModel.stringify(obj);
|
62
|
+
await fs.writeFile(path, yaml);
|
63
|
+
} catch (error: unknown) {
|
64
|
+
throw new Error(`Failed to save YAML file: ${error instanceof Error ? error.message : String(error)}`);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|