agency-orchestrator 0.3.0 → 0.3.2
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/README.md +20 -3
- package/README.zh-CN.md +17 -0
- package/dist/agents/loader.js +1 -0
- package/dist/cli/compose.d.ts +43 -0
- package/dist/cli/compose.js +210 -0
- package/dist/cli/explain.js +6 -4
- package/dist/cli/init-workflow.js +20 -11
- package/dist/cli/watch.js +4 -2
- package/dist/cli.js +53 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/types.d.ts +1 -0
- package/integrations/antigravity/README.md +12 -5
- package/integrations/codex/README.md +12 -5
- package/integrations/cursor/README.md +13 -10
- package/integrations/deerflow/README.md +9 -3
- package/integrations/gemini-cli/README.md +12 -5
- package/integrations/kiro/README.md +9 -6
- package/integrations/trae/README.md +9 -6
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -150,6 +150,22 @@ analyze ──→ tech_review ──→ summary
|
|
|
150
150
|
|
|
151
151
|
## Features
|
|
152
152
|
|
|
153
|
+
### AI Workflow Composer
|
|
154
|
+
|
|
155
|
+
Describe your workflow in one sentence — AI selects the right roles, designs the DAG, and generates a ready-to-run YAML:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
ao compose "PR code review covering security and performance"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The AI will:
|
|
162
|
+
1. Select matching roles from 186 available (e.g., Code Reviewer, Security Engineer, Performance Benchmarker)
|
|
163
|
+
2. Design the DAG (3-way parallel → summary)
|
|
164
|
+
3. Generate complete YAML with variable passing and task descriptions
|
|
165
|
+
4. Save to `workflows/` — ready to `ao run`
|
|
166
|
+
|
|
167
|
+
Supports `--provider` and `--model` flags (default: DeepSeek).
|
|
168
|
+
|
|
153
169
|
### Condition Branching
|
|
154
170
|
|
|
155
171
|
```yaml
|
|
@@ -160,7 +176,7 @@ analyze ──→ tech_review ──→ summary
|
|
|
160
176
|
condition: "{{job_type}} contains technical"
|
|
161
177
|
|
|
162
178
|
- id: biz_path
|
|
163
|
-
role: "marketing/marketing-strategist"
|
|
179
|
+
role: "marketing/marketing-social-media-strategist"
|
|
164
180
|
task: "Business evaluation: {{requirements}}"
|
|
165
181
|
depends_on: [classify]
|
|
166
182
|
condition: "{{job_type}} contains business"
|
|
@@ -176,12 +192,12 @@ Supported operators: `contains`, `equals`, `not_contains`, `not_equals`.
|
|
|
176
192
|
|
|
177
193
|
```yaml
|
|
178
194
|
- id: write_draft
|
|
179
|
-
role: "
|
|
195
|
+
role: "marketing/marketing-content-creator"
|
|
180
196
|
task: "Write article: {{topic}}"
|
|
181
197
|
output: draft
|
|
182
198
|
|
|
183
199
|
- id: brand_review
|
|
184
|
-
role: "
|
|
200
|
+
role: "design/design-brand-guardian"
|
|
185
201
|
task: "Review brand compliance: {{draft}}"
|
|
186
202
|
output: review_result
|
|
187
203
|
depends_on: [write_draft]
|
|
@@ -238,6 +254,7 @@ All providers support custom `base_url` and `api_key`, compatible with any OpenA
|
|
|
238
254
|
```bash
|
|
239
255
|
ao init # Download 186 AI roles
|
|
240
256
|
ao init --workflow # Interactive workflow creator
|
|
257
|
+
ao compose "description" # AI-powered workflow generation
|
|
241
258
|
ao run <workflow.yaml> [options] # Execute workflow
|
|
242
259
|
ao validate <workflow.yaml> # Validate without running
|
|
243
260
|
ao plan <workflow.yaml> # Show execution plan (DAG)
|
package/README.zh-CN.md
CHANGED
|
@@ -200,6 +200,7 @@ analyze ──→ tech_review ──→ summary
|
|
|
200
200
|
```bash
|
|
201
201
|
ao init # 下载 186 个 AI 角色
|
|
202
202
|
ao init --workflow # 交互式创建工作流
|
|
203
|
+
ao compose "一句话描述" # AI 智能编排工作流
|
|
203
204
|
ao run <workflow.yaml> [选项] # 执行工作流
|
|
204
205
|
ao validate <workflow.yaml> # 校验(不执行)
|
|
205
206
|
ao plan <workflow.yaml> # 查看执行计划(DAG)
|
|
@@ -217,6 +218,22 @@ ao roles # 列出所有角色
|
|
|
217
218
|
| `--watch` | 实时终端进度显示 |
|
|
218
219
|
| `--quiet` | 静默模式 |
|
|
219
220
|
|
|
221
|
+
### AI 智能编排(Compose)
|
|
222
|
+
|
|
223
|
+
一句话描述需求,AI 自动从 186 个角色中选角色、设计 DAG、生成完整 workflow YAML:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
ao compose "PR 代码审查,要覆盖安全和性能"
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
AI 会自动:
|
|
230
|
+
1. 从 186 角色中匹配出 Code Reviewer、Security Engineer、Performance Benchmarker
|
|
231
|
+
2. 设计 DAG(三路并行 → 汇总)
|
|
232
|
+
3. 生成带 `depends_on`、变量串联的完整 YAML
|
|
233
|
+
4. 保存到 `workflows/` — 直接 `ao run` 就能跑
|
|
234
|
+
|
|
235
|
+
支持 `--provider` 和 `--model` 参数(默认使用 DeepSeek)。
|
|
236
|
+
|
|
220
237
|
### 迭代优化(Resume)
|
|
221
238
|
|
|
222
239
|
**问题**:`ao run` 跑完一轮后,所有步骤的输出都丢了。想基于叙事学家的结构重写小说,只能整个工作流从头跑。
|
package/dist/agents/loader.js
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { LLMConfig } from '../types.js';
|
|
2
|
+
/** 精简的角色摘要,供 LLM 选角色用 */
|
|
3
|
+
export interface RoleSummary {
|
|
4
|
+
path: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
category: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 从 agents 目录构建精简的角色目录
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildRoleCatalog(agentsDir: string): RoleSummary[];
|
|
13
|
+
/**
|
|
14
|
+
* 格式化角色目录为紧凑文本(给 LLM 看)
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatCatalogForPrompt(roles: RoleSummary[]): string;
|
|
17
|
+
/**
|
|
18
|
+
* 构建发给 LLM 的 system prompt
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildComposeSystemPrompt(catalog: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* 构建 user prompt
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildComposeUserPrompt(description: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* 从 LLM 回复中提取 YAML 内容
|
|
27
|
+
*/
|
|
28
|
+
export declare function extractYamlFromResponse(response: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* 根据描述生成文件名
|
|
31
|
+
*/
|
|
32
|
+
export declare function generateFileName(description: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* 执行 compose 流程
|
|
35
|
+
*/
|
|
36
|
+
export declare function composeWorkflow(options: {
|
|
37
|
+
description: string;
|
|
38
|
+
agentsDir: string;
|
|
39
|
+
llmConfig: LLMConfig;
|
|
40
|
+
}): Promise<{
|
|
41
|
+
yaml: string;
|
|
42
|
+
savedPath: string;
|
|
43
|
+
}>;
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ao compose — AI 智能编排工作流
|
|
3
|
+
*
|
|
4
|
+
* 用户用一句话描述需求,AI 从 186 个角色中选角色、设计 DAG、生成完整 workflow YAML。
|
|
5
|
+
*/
|
|
6
|
+
import { listAgents } from '../agents/loader.js';
|
|
7
|
+
import { existsSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
8
|
+
import { resolve } from 'node:path';
|
|
9
|
+
/**
|
|
10
|
+
* 从 agents 目录构建精简的角色目录
|
|
11
|
+
*/
|
|
12
|
+
export function buildRoleCatalog(agentsDir) {
|
|
13
|
+
const agents = listAgents(agentsDir);
|
|
14
|
+
return agents
|
|
15
|
+
.filter(a => a.rolePath) // 只保留有路径的
|
|
16
|
+
.map(a => ({
|
|
17
|
+
path: a.rolePath,
|
|
18
|
+
name: a.name,
|
|
19
|
+
description: a.description || '',
|
|
20
|
+
category: a.rolePath.split('/')[0],
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 格式化角色目录为紧凑文本(给 LLM 看)
|
|
25
|
+
*/
|
|
26
|
+
export function formatCatalogForPrompt(roles) {
|
|
27
|
+
const byCategory = new Map();
|
|
28
|
+
for (const r of roles) {
|
|
29
|
+
const list = byCategory.get(r.category) || [];
|
|
30
|
+
list.push(r);
|
|
31
|
+
byCategory.set(r.category, list);
|
|
32
|
+
}
|
|
33
|
+
const lines = [];
|
|
34
|
+
for (const [cat, list] of byCategory) {
|
|
35
|
+
lines.push(`## ${cat}`);
|
|
36
|
+
for (const r of list) {
|
|
37
|
+
lines.push(`- ${r.path} | ${r.name} | ${r.description}`);
|
|
38
|
+
}
|
|
39
|
+
lines.push('');
|
|
40
|
+
}
|
|
41
|
+
return lines.join('\n');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 构建发给 LLM 的 system prompt
|
|
45
|
+
*/
|
|
46
|
+
export function buildComposeSystemPrompt(catalog) {
|
|
47
|
+
return `你是一个 AI 工作流编排专家。用户会用一句话描述他想要的工作流,你需要:
|
|
48
|
+
|
|
49
|
+
1. 从下方角色目录中选择最合适的角色(通常 2-6 个)
|
|
50
|
+
2. 设计合理的 DAG 依赖关系(哪些步骤可以并行,哪些必须串行)
|
|
51
|
+
3. 为每个步骤编写详细的 task 描述
|
|
52
|
+
4. 设计合理的输入变量
|
|
53
|
+
5. 生成完整的 workflow YAML
|
|
54
|
+
|
|
55
|
+
## 输出格式
|
|
56
|
+
|
|
57
|
+
直接输出一个完整的 YAML 代码块,格式如下:
|
|
58
|
+
|
|
59
|
+
\`\`\`yaml
|
|
60
|
+
name: "工作流名称"
|
|
61
|
+
description: "一句话描述"
|
|
62
|
+
|
|
63
|
+
agents_dir: "agency-agents-zh"
|
|
64
|
+
|
|
65
|
+
llm:
|
|
66
|
+
provider: deepseek
|
|
67
|
+
model: deepseek-chat
|
|
68
|
+
max_tokens: 4096
|
|
69
|
+
|
|
70
|
+
concurrency: 2
|
|
71
|
+
|
|
72
|
+
inputs:
|
|
73
|
+
- name: variable_name
|
|
74
|
+
description: "变量描述"
|
|
75
|
+
required: true
|
|
76
|
+
|
|
77
|
+
steps:
|
|
78
|
+
- id: step_id
|
|
79
|
+
role: "category/role-name"
|
|
80
|
+
task: |
|
|
81
|
+
详细的任务描述...
|
|
82
|
+
使用 {{variable_name}} 引用输入变量
|
|
83
|
+
使用 {{previous_output}} 引用上游步骤的输出
|
|
84
|
+
output: output_variable_name
|
|
85
|
+
depends_on: [upstream_step_id] # 仅在有依赖时添加
|
|
86
|
+
\`\`\`
|
|
87
|
+
|
|
88
|
+
## 设计原则
|
|
89
|
+
|
|
90
|
+
- **并行优先**:没有数据依赖的步骤应该并行执行(不加 depends_on)
|
|
91
|
+
- **变量串联**:上游步骤的 output 变量名要和下游步骤 task 中的 {{变量}} 对应
|
|
92
|
+
- **角色匹配**:选择最专业的角色,不要用一个角色做所有事
|
|
93
|
+
- **任务详细**:task 描述要具体,告诉角色要做什么、输出什么格式
|
|
94
|
+
- **合理输入**:提取用户需求中的关键变量作为 inputs
|
|
95
|
+
- **最终汇总**:如果有多路并行,最后应该有一个汇总步骤
|
|
96
|
+
|
|
97
|
+
## 可用角色目录
|
|
98
|
+
|
|
99
|
+
${catalog}
|
|
100
|
+
|
|
101
|
+
## 注意
|
|
102
|
+
|
|
103
|
+
- role 的值必须严格使用角色目录中的 path(如 "engineering/engineering-code-reviewer"),不要自己编造
|
|
104
|
+
- 只输出 YAML 代码块,不要输出其他内容
|
|
105
|
+
- concurrency 设为并行步骤的最大数量`;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 构建 user prompt
|
|
109
|
+
*/
|
|
110
|
+
export function buildComposeUserPrompt(description) {
|
|
111
|
+
return `请为以下需求设计一个多智能体协作工作流:
|
|
112
|
+
|
|
113
|
+
${description}`;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 从 LLM 回复中提取 YAML 内容
|
|
117
|
+
*/
|
|
118
|
+
export function extractYamlFromResponse(response) {
|
|
119
|
+
// 尝试从 ```yaml ... ``` 代码块中提取
|
|
120
|
+
const yamlBlock = response.match(/```ya?ml\s*\n([\s\S]*?)```/);
|
|
121
|
+
if (yamlBlock)
|
|
122
|
+
return yamlBlock[1].trim();
|
|
123
|
+
// 尝试从 ``` ... ``` 代码块中提取
|
|
124
|
+
const codeBlock = response.match(/```\s*\n([\s\S]*?)```/);
|
|
125
|
+
if (codeBlock)
|
|
126
|
+
return codeBlock[1].trim();
|
|
127
|
+
// 没有代码块,整个回复当 YAML
|
|
128
|
+
return response.trim();
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* 根据描述生成文件名
|
|
132
|
+
*/
|
|
133
|
+
export function generateFileName(description) {
|
|
134
|
+
const cleaned = description
|
|
135
|
+
.replace(/[^\u4e00-\u9fffa-zA-Z0-9\s-]/g, '')
|
|
136
|
+
.trim()
|
|
137
|
+
.slice(0, 40)
|
|
138
|
+
.toLowerCase()
|
|
139
|
+
.replace(/\s+/g, '-')
|
|
140
|
+
.replace(/^-|-$/g, '');
|
|
141
|
+
return (cleaned || 'composed-workflow') + '.yaml';
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* 创建 LLM connector(动态导入)
|
|
145
|
+
*/
|
|
146
|
+
async function createConnector(config) {
|
|
147
|
+
switch (config.provider) {
|
|
148
|
+
case 'deepseek': {
|
|
149
|
+
const { OpenAICompatibleConnector } = await import('../connectors/openai-compatible.js');
|
|
150
|
+
return new OpenAICompatibleConnector({
|
|
151
|
+
apiKey: config.api_key || process.env.DEEPSEEK_API_KEY,
|
|
152
|
+
baseUrl: config.base_url || 'https://api.deepseek.com/v1',
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
case 'openai': {
|
|
156
|
+
const { OpenAICompatibleConnector } = await import('../connectors/openai-compatible.js');
|
|
157
|
+
return new OpenAICompatibleConnector({
|
|
158
|
+
apiKey: config.api_key || process.env.OPENAI_API_KEY,
|
|
159
|
+
baseUrl: config.base_url || 'https://api.openai.com/v1',
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
case 'claude': {
|
|
163
|
+
const { ClaudeConnector } = await import('../connectors/claude.js');
|
|
164
|
+
return new ClaudeConnector(config.api_key);
|
|
165
|
+
}
|
|
166
|
+
case 'ollama': {
|
|
167
|
+
const { OllamaConnector } = await import('../connectors/ollama.js');
|
|
168
|
+
return new OllamaConnector(config.base_url);
|
|
169
|
+
}
|
|
170
|
+
default:
|
|
171
|
+
throw new Error(`不支持的 provider: ${config.provider}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* 执行 compose 流程
|
|
176
|
+
*/
|
|
177
|
+
export async function composeWorkflow(options) {
|
|
178
|
+
const { description, agentsDir, llmConfig } = options;
|
|
179
|
+
// 1. 构建角色目录
|
|
180
|
+
const roles = buildRoleCatalog(agentsDir);
|
|
181
|
+
if (roles.length === 0) {
|
|
182
|
+
throw new Error(`角色目录为空: ${agentsDir}\n请先运行 ao init 下载角色定义`);
|
|
183
|
+
}
|
|
184
|
+
const catalog = formatCatalogForPrompt(roles);
|
|
185
|
+
// 2. 构建 prompt
|
|
186
|
+
const systemPrompt = buildComposeSystemPrompt(catalog);
|
|
187
|
+
const userPrompt = buildComposeUserPrompt(description);
|
|
188
|
+
// 3. 调用 LLM
|
|
189
|
+
console.log(` 正在用 AI 编排工作流...(${roles.length} 个角色可选)\n`);
|
|
190
|
+
const connector = await createConnector(llmConfig);
|
|
191
|
+
const result = await connector.chat(systemPrompt, userPrompt, {
|
|
192
|
+
...llmConfig,
|
|
193
|
+
max_tokens: llmConfig.max_tokens || 4096,
|
|
194
|
+
});
|
|
195
|
+
// 4. 提取 YAML
|
|
196
|
+
const yaml = extractYamlFromResponse(result.content);
|
|
197
|
+
if (!yaml || !yaml.includes('steps:')) {
|
|
198
|
+
throw new Error('AI 生成的内容不是有效的 workflow YAML,请重试或调整描述');
|
|
199
|
+
}
|
|
200
|
+
// 5. 保存
|
|
201
|
+
const fileName = generateFileName(description);
|
|
202
|
+
const workflowsDir = resolve('workflows');
|
|
203
|
+
if (!existsSync(workflowsDir)) {
|
|
204
|
+
mkdirSync(workflowsDir, { recursive: true });
|
|
205
|
+
}
|
|
206
|
+
const savedPath = resolve(workflowsDir, fileName);
|
|
207
|
+
writeFileSync(savedPath, yaml + '\n', 'utf-8');
|
|
208
|
+
console.log(` Token 用量: 输入 ${result.usage.input_tokens}, 输出 ${result.usage.output_tokens}`);
|
|
209
|
+
return { yaml, savedPath };
|
|
210
|
+
}
|
package/dist/cli/explain.js
CHANGED
|
@@ -34,7 +34,7 @@ function buildLayers(steps) {
|
|
|
34
34
|
remaining.delete(s.id);
|
|
35
35
|
for (const [id, depList] of deps) {
|
|
36
36
|
if (depList.includes(s.id)) {
|
|
37
|
-
inDegree.set(id, (inDegree.get(id)
|
|
37
|
+
inDegree.set(id, (inDegree.get(id) ?? 0) - 1);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -77,10 +77,12 @@ export function explainWorkflow(workflow) {
|
|
|
77
77
|
for (const step of layer.steps) {
|
|
78
78
|
const role = formatRole(step.role);
|
|
79
79
|
// 取 task 的第一行作为摘要
|
|
80
|
-
const
|
|
80
|
+
const firstLine = (step.task || '').split('\n')[0].trim();
|
|
81
|
+
const taskSummary = firstLine.slice(0, 60);
|
|
82
|
+
const truncated = firstLine.length > 60 || (step.task || '').includes('\n');
|
|
81
83
|
lines.push(` • ${step.id} (${role})`);
|
|
82
84
|
if (taskSummary) {
|
|
83
|
-
lines.push(` ${taskSummary}${
|
|
85
|
+
lines.push(` ${taskSummary}${truncated ? '...' : ''}`);
|
|
84
86
|
}
|
|
85
87
|
// 标注条件
|
|
86
88
|
if (step.condition) {
|
|
@@ -96,7 +98,7 @@ export function explainWorkflow(workflow) {
|
|
|
96
98
|
}
|
|
97
99
|
// 汇总
|
|
98
100
|
const totalSteps = workflow.steps.length;
|
|
99
|
-
const maxParallel = Math.max(...layers.map(l => l.steps.length));
|
|
101
|
+
const maxParallel = layers.length > 0 ? Math.max(...layers.map(l => l.steps.length)) : 0;
|
|
100
102
|
const hasLoop = workflow.steps.some(s => s.loop);
|
|
101
103
|
const hasCondition = workflow.steps.some(s => s.condition);
|
|
102
104
|
lines.push(`总计 ${totalSteps} 个步骤,${layers.length} 层执行,最大并行度 ${maxParallel}。`);
|
|
@@ -4,10 +4,14 @@
|
|
|
4
4
|
import { createInterface } from 'readline';
|
|
5
5
|
import { writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
6
6
|
import { resolve } from 'path';
|
|
7
|
+
/** Escape double quotes for YAML string values */
|
|
8
|
+
function yamlEscape(s) {
|
|
9
|
+
return s.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
10
|
+
}
|
|
7
11
|
export function generateWorkflowYaml(opts) {
|
|
8
12
|
const lines = [
|
|
9
|
-
`name: "${opts.name}"`,
|
|
10
|
-
`description: "${opts.description}"`,
|
|
13
|
+
`name: "${yamlEscape(opts.name)}"`,
|
|
14
|
+
`description: "${yamlEscape(opts.description)}"`,
|
|
11
15
|
'',
|
|
12
16
|
'agents_dir: "agency-agents-zh"',
|
|
13
17
|
'',
|
|
@@ -21,22 +25,27 @@ export function generateWorkflowYaml(opts) {
|
|
|
21
25
|
if (opts.hasInputs && opts.inputs.length > 0) {
|
|
22
26
|
lines.push('', 'inputs:');
|
|
23
27
|
for (const input of opts.inputs) {
|
|
24
|
-
lines.push(` - name: ${input.name}`);
|
|
25
|
-
lines.push(` description: "${input.description}"`);
|
|
28
|
+
lines.push(` - name: "${yamlEscape(input.name)}"`);
|
|
29
|
+
lines.push(` description: "${yamlEscape(input.description)}"`);
|
|
26
30
|
lines.push(` required: ${input.required}`);
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
lines.push('', 'steps:');
|
|
30
34
|
for (let i = 0; i < opts.roles.length; i++) {
|
|
31
35
|
const step = opts.roles[i];
|
|
32
|
-
lines.push(` - id: ${step.id}`);
|
|
33
|
-
lines.push(` role: "${step.role}"`);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
lines.push(` - id: "${yamlEscape(step.id)}"`);
|
|
37
|
+
lines.push(` role: "${yamlEscape(step.role)}"`);
|
|
38
|
+
// 单行 task 用引号,多行用 block scalar
|
|
39
|
+
if (step.task.includes('\n')) {
|
|
40
|
+
lines.push(` task: |`);
|
|
41
|
+
for (const taskLine of step.task.split('\n')) {
|
|
42
|
+
lines.push(` ${taskLine}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
lines.push(` task: "${yamlEscape(step.task)}"`);
|
|
38
47
|
}
|
|
39
|
-
lines.push(` output: ${step.output}`);
|
|
48
|
+
lines.push(` output: "${yamlEscape(step.output)}"`);
|
|
40
49
|
if (i > 0) {
|
|
41
50
|
lines.push(` depends_on: [${opts.roles[i - 1].id}]`);
|
|
42
51
|
}
|
package/dist/cli/watch.js
CHANGED
|
@@ -6,7 +6,7 @@ const ICONS = {
|
|
|
6
6
|
running: '🔄',
|
|
7
7
|
done: '✅',
|
|
8
8
|
error: '❌',
|
|
9
|
-
skipped: '
|
|
9
|
+
skipped: '⏩',
|
|
10
10
|
};
|
|
11
11
|
/**
|
|
12
12
|
* 创建 watch 渲染器,返回 ProgressCallback
|
|
@@ -50,7 +50,9 @@ export function createWatchRenderer(workflowName, stepIds, roles) {
|
|
|
50
50
|
lines.push(line);
|
|
51
51
|
}
|
|
52
52
|
lines.push(`│${''.padEnd(boxWidth - 2)}│`);
|
|
53
|
-
|
|
53
|
+
const progressContent = `Progress: ${bar} ${completed}/${total} ${elapsed}s`;
|
|
54
|
+
const progressPad = Math.max(0, boxWidth - 4 - progressContent.length);
|
|
55
|
+
lines.push(`│ ${progressContent}${''.padEnd(progressPad)} │`);
|
|
54
56
|
lines.push(`└${'─'.repeat(boxWidth - 2)}┘`);
|
|
55
57
|
// 写到 stderr 避免与正常输出混合
|
|
56
58
|
for (const line of lines) {
|
package/dist/cli.js
CHANGED
|
@@ -41,13 +41,16 @@ async function main() {
|
|
|
41
41
|
case 'explain':
|
|
42
42
|
await handleExplain();
|
|
43
43
|
break;
|
|
44
|
+
case 'compose':
|
|
45
|
+
await handleCompose();
|
|
46
|
+
break;
|
|
44
47
|
case '--version':
|
|
45
48
|
case '-v':
|
|
46
49
|
console.log(getVersion());
|
|
47
50
|
break;
|
|
48
51
|
default: {
|
|
49
52
|
// 容错:用户可能漏了空格,如 "planworkflows/x.yaml"
|
|
50
|
-
const knownCmds = ['run', 'validate', 'plan', 'explain', 'roles'];
|
|
53
|
+
const knownCmds = ['run', 'validate', 'plan', 'explain', 'compose', 'roles', 'init'];
|
|
51
54
|
const match = knownCmds.find(c => command.startsWith(c) && command.length > c.length);
|
|
52
55
|
if (match) {
|
|
53
56
|
console.error(`看起来少了个空格?试试:\n ao ${match} ${command.slice(match.length)}\n`);
|
|
@@ -166,6 +169,53 @@ async function handleExplain() {
|
|
|
166
169
|
process.exit(1);
|
|
167
170
|
}
|
|
168
171
|
}
|
|
172
|
+
async function handleCompose() {
|
|
173
|
+
const description = args[1];
|
|
174
|
+
if (!description) {
|
|
175
|
+
console.error('用法: ao compose "用一句话描述你想要的工作流"');
|
|
176
|
+
console.error('');
|
|
177
|
+
console.error('示例:');
|
|
178
|
+
console.error(' ao compose "PR 代码审查,要覆盖安全和性能"');
|
|
179
|
+
console.error(' ao compose "写一篇技术博客,需要调研、写稿、审校"');
|
|
180
|
+
console.error(' ao compose "用户反馈分析,分类后分别给产品和技术团队"');
|
|
181
|
+
console.error('');
|
|
182
|
+
console.error('选项:');
|
|
183
|
+
console.error(' --provider <name> LLM 提供商 (默认 deepseek)');
|
|
184
|
+
console.error(' --model <name> 模型名 (默认 deepseek-chat)');
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
const provider = (getArgValue('--provider') || 'deepseek');
|
|
188
|
+
const model = getArgValue('--model') || (provider === 'deepseek' ? 'deepseek-chat' : provider === 'claude' ? 'claude-sonnet-4-20250514' : 'gpt-4o');
|
|
189
|
+
const agentsDir = getArgValue('--agents-dir') || resolveAgentsDir();
|
|
190
|
+
try {
|
|
191
|
+
const { composeWorkflow } = await import('./cli/compose.js');
|
|
192
|
+
const { yaml, savedPath } = await composeWorkflow({
|
|
193
|
+
description,
|
|
194
|
+
agentsDir: resolve(agentsDir),
|
|
195
|
+
llmConfig: { provider, model },
|
|
196
|
+
});
|
|
197
|
+
console.log(`\n ✅ 工作流已生成: ${savedPath}\n`);
|
|
198
|
+
console.log(' 预览:');
|
|
199
|
+
// 显示前 30 行
|
|
200
|
+
const previewLines = yaml.split('\n').slice(0, 30);
|
|
201
|
+
for (const line of previewLines) {
|
|
202
|
+
console.log(` ${line}`);
|
|
203
|
+
}
|
|
204
|
+
if (yaml.split('\n').length > 30) {
|
|
205
|
+
console.log(' ...');
|
|
206
|
+
}
|
|
207
|
+
console.log('');
|
|
208
|
+
console.log(' 接下来可以:');
|
|
209
|
+
console.log(` ao plan ${savedPath} 查看执行计划`);
|
|
210
|
+
console.log(` ao validate ${savedPath} 校验工作流`);
|
|
211
|
+
console.log(` ao run ${savedPath} 运行工作流`);
|
|
212
|
+
console.log('');
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
console.error(`\n错误: ${err instanceof Error ? err.message : err}`);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
169
219
|
async function handleInit() {
|
|
170
220
|
// ao init --workflow: 交互式创建工作流
|
|
171
221
|
if (args.includes('--workflow')) {
|
|
@@ -302,6 +352,7 @@ function printHelp() {
|
|
|
302
352
|
Commands:
|
|
303
353
|
init 下载/更新 agency-agents-zh
|
|
304
354
|
init --workflow 交互式创建新工作流
|
|
355
|
+
compose "描述" AI 智能编排工作流(一句话生成 YAML)
|
|
305
356
|
run <workflow.yaml> 执行工作流
|
|
306
357
|
validate <workflow.yaml> 校验工作流定义
|
|
307
358
|
plan <workflow.yaml> 查看执行计划
|
|
@@ -320,6 +371,7 @@ function printHelp() {
|
|
|
320
371
|
|
|
321
372
|
Examples:
|
|
322
373
|
ao init
|
|
374
|
+
ao compose "PR 代码审查,覆盖安全和性能"
|
|
323
375
|
ao run workflows/story-creation.yaml -i premise='一个时间旅行的故事' -i style='悬疑'
|
|
324
376
|
ao run workflows/product-review.yaml -i prd_content=@prd.md
|
|
325
377
|
ao plan workflows/content-pipeline.yaml
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export { ClaudeConnector } from './connectors/claude.js';
|
|
|
14
14
|
export { OllamaConnector } from './connectors/ollama.js';
|
|
15
15
|
export { OpenAICompatibleConnector } from './connectors/openai-compatible.js';
|
|
16
16
|
export { saveResults, loadPreviousContext, findLatestOutput } from './output/reporter.js';
|
|
17
|
+
export { composeWorkflow, buildRoleCatalog, extractYamlFromResponse } from './cli/compose.js';
|
|
17
18
|
export type { WorkflowDefinition, StepDefinition, LLMConfig, LLMConnector, LLMResult, AgentDefinition, WorkflowResult, StepResult, DAGNode, } from './types.js';
|
|
18
19
|
/**
|
|
19
20
|
* 一行运行工作流(高级 API)
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export { ClaudeConnector } from './connectors/claude.js';
|
|
|
14
14
|
export { OllamaConnector } from './connectors/ollama.js';
|
|
15
15
|
export { OpenAICompatibleConnector } from './connectors/openai-compatible.js';
|
|
16
16
|
export { saveResults, loadPreviousContext, findLatestOutput } from './output/reporter.js';
|
|
17
|
+
export { composeWorkflow, buildRoleCatalog, extractYamlFromResponse } from './cli/compose.js';
|
|
17
18
|
import { parseWorkflow, validateWorkflow } from './core/parser.js';
|
|
18
19
|
import { buildDAG } from './core/dag.js';
|
|
19
20
|
import { executeDAG } from './core/executor.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -5,18 +5,25 @@
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
# 1.
|
|
8
|
+
# 1. 下载 186 个 AI 角色
|
|
9
9
|
cd your-project
|
|
10
10
|
git clone --depth 1 https://github.com/jnMetaCode/agency-agents-zh.git
|
|
11
11
|
|
|
12
|
-
# 2.
|
|
13
|
-
|
|
12
|
+
# 2. 下载工作流模板和技能文件
|
|
13
|
+
git clone --depth 1 https://github.com/jnMetaCode/agency-orchestrator.git .ao-tmp
|
|
14
|
+
cp -r .ao-tmp/workflows ./workflows
|
|
15
|
+
cp .ao-tmp/integrations/antigravity/AGENTS.md ./AGENTS.md
|
|
16
|
+
rm -rf .ao-tmp
|
|
17
|
+
|
|
18
|
+
# 3. 开始使用
|
|
19
|
+
# 在 Antigravity 中直接说:运行 workflows/story-creation.yaml
|
|
14
20
|
```
|
|
15
21
|
|
|
16
|
-
如果项目根目录已有 `AGENTS.md
|
|
22
|
+
如果项目根目录已有 `AGENTS.md`,可将内容追加而非覆盖:
|
|
17
23
|
|
|
18
24
|
```bash
|
|
19
|
-
|
|
25
|
+
# 替换上面第 2 步中的 cp 命令为:
|
|
26
|
+
cat .ao-tmp/integrations/antigravity/AGENTS.md >> ./AGENTS.md
|
|
20
27
|
```
|
|
21
28
|
|
|
22
29
|
## 使用方式
|
|
@@ -5,19 +5,26 @@
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
# 1.
|
|
8
|
+
# 1. 下载 186 个 AI 角色
|
|
9
9
|
cd your-project
|
|
10
10
|
git clone --depth 1 https://github.com/jnMetaCode/agency-agents-zh.git
|
|
11
11
|
|
|
12
|
-
# 2.
|
|
12
|
+
# 2. 下载工作流模板和技能文件
|
|
13
|
+
git clone --depth 1 https://github.com/jnMetaCode/agency-orchestrator.git .ao-tmp
|
|
14
|
+
cp -r .ao-tmp/workflows ./workflows
|
|
13
15
|
mkdir -p .codex
|
|
14
|
-
cp integrations/codex/instructions.md .codex/instructions.md
|
|
16
|
+
cp .ao-tmp/integrations/codex/instructions.md .codex/instructions.md
|
|
17
|
+
rm -rf .ao-tmp
|
|
18
|
+
|
|
19
|
+
# 3. 开始使用
|
|
20
|
+
# 在 Codex CLI 中直接说:运行 workflows/story-creation.yaml
|
|
15
21
|
```
|
|
16
22
|
|
|
17
|
-
如果 `.codex/instructions.md`
|
|
23
|
+
如果 `.codex/instructions.md` 已存在,可将内容追加而非覆盖:
|
|
18
24
|
|
|
19
25
|
```bash
|
|
20
|
-
|
|
26
|
+
# 替换上面第 2 步中的 cp 命令为:
|
|
27
|
+
cat .ao-tmp/integrations/codex/instructions.md >> .codex/instructions.md
|
|
21
28
|
```
|
|
22
29
|
|
|
23
30
|
## 使用方式
|
|
@@ -5,16 +5,19 @@
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
# 1.
|
|
8
|
+
# 1. 下载 186 个 AI 角色
|
|
9
9
|
cd your-project
|
|
10
10
|
git clone --depth 1 https://github.com/jnMetaCode/agency-agents-zh.git
|
|
11
11
|
|
|
12
|
-
# 2.
|
|
13
|
-
git clone --depth 1 https://github.com/jnMetaCode/agency-orchestrator.git .ao-tmp
|
|
14
|
-
|
|
15
|
-
# 3. 添加工作流执行规则
|
|
12
|
+
# 2. 下载工作流模板和技能文件
|
|
13
|
+
git clone --depth 1 https://github.com/jnMetaCode/agency-orchestrator.git .ao-tmp
|
|
14
|
+
cp -r .ao-tmp/workflows ./workflows
|
|
16
15
|
mkdir -p .cursor/rules
|
|
17
|
-
cp
|
|
16
|
+
cp .ao-tmp/integrations/cursor/workflow-runner.mdc .cursor/rules/
|
|
17
|
+
rm -rf .ao-tmp
|
|
18
|
+
|
|
19
|
+
# 3. 开始使用
|
|
20
|
+
# 在 Cursor 中直接说:运行 workflows/story-creation.yaml
|
|
18
21
|
```
|
|
19
22
|
|
|
20
23
|
## 使用方式
|
|
@@ -87,11 +90,11 @@ ao run workflows/story-creation.yaml -i 'premise=时间旅行'
|
|
|
87
90
|
|
|
88
91
|
## 可用工作流
|
|
89
92
|
|
|
90
|
-
| 工作流 |
|
|
93
|
+
| 工作流 | 文件 | 说明 |
|
|
91
94
|
|--------|------|------|
|
|
92
|
-
| `story-creation.yaml` |
|
|
93
|
-
| `product-review.yaml` |
|
|
94
|
-
| `content-pipeline.yaml` |
|
|
95
|
+
| 短篇小说创作 | `story-creation.yaml` | 叙事学家 → 心理学家 + 叙事设计师 → 内容创作者 |
|
|
96
|
+
| 产品需求评审 | `product-review.yaml` | 产品经理 → 架构师 + UX 研究员 → 产品经理 |
|
|
97
|
+
| 内容流水线 | `content-pipeline.yaml` | 策略师 → 创作者 + SEO → 编辑 |
|
|
95
98
|
|
|
96
99
|
## 自定义
|
|
97
100
|
|
|
@@ -5,13 +5,19 @@
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
# 1.
|
|
8
|
+
# 1. 下载 186 个 AI 角色
|
|
9
9
|
cd your-project
|
|
10
10
|
git clone --depth 1 https://github.com/jnMetaCode/agency-agents-zh.git
|
|
11
11
|
|
|
12
|
-
# 2.
|
|
12
|
+
# 2. 下载工作流模板和技能文件
|
|
13
|
+
git clone --depth 1 https://github.com/jnMetaCode/agency-orchestrator.git .ao-tmp
|
|
14
|
+
cp -r .ao-tmp/workflows ./workflows
|
|
13
15
|
mkdir -p skills/custom/ao-workflow-runner
|
|
14
|
-
cp integrations/deerflow/SKILL.md skills/custom/ao-workflow-runner/SKILL.md
|
|
16
|
+
cp .ao-tmp/integrations/deerflow/SKILL.md skills/custom/ao-workflow-runner/SKILL.md
|
|
17
|
+
rm -rf .ao-tmp
|
|
18
|
+
|
|
19
|
+
# 3. 开始使用
|
|
20
|
+
# 在 DeerFlow 中直接说:运行 workflows/story-creation.yaml
|
|
15
21
|
```
|
|
16
22
|
|
|
17
23
|
## 使用方式
|
|
@@ -5,18 +5,25 @@
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
# 1.
|
|
8
|
+
# 1. 下载 186 个 AI 角色
|
|
9
9
|
cd your-project
|
|
10
10
|
git clone --depth 1 https://github.com/jnMetaCode/agency-agents-zh.git
|
|
11
11
|
|
|
12
|
-
# 2.
|
|
13
|
-
|
|
12
|
+
# 2. 下载工作流模板和技能文件
|
|
13
|
+
git clone --depth 1 https://github.com/jnMetaCode/agency-orchestrator.git .ao-tmp
|
|
14
|
+
cp -r .ao-tmp/workflows ./workflows
|
|
15
|
+
cp .ao-tmp/integrations/gemini-cli/GEMINI.md ./GEMINI.md
|
|
16
|
+
rm -rf .ao-tmp
|
|
17
|
+
|
|
18
|
+
# 3. 开始使用
|
|
19
|
+
# 在 Gemini CLI 中直接说:运行 workflows/story-creation.yaml
|
|
14
20
|
```
|
|
15
21
|
|
|
16
|
-
|
|
22
|
+
如果项目根目录已有 `GEMINI.md`,可将内容追加而非覆盖:
|
|
17
23
|
|
|
18
24
|
```bash
|
|
19
|
-
cp
|
|
25
|
+
# 替换上面第 2 步中的 cp 命令为:
|
|
26
|
+
cat .ao-tmp/integrations/gemini-cli/GEMINI.md >> ./GEMINI.md
|
|
20
27
|
```
|
|
21
28
|
|
|
22
29
|
## 使用方式
|
|
@@ -5,16 +5,19 @@
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
# 1.
|
|
8
|
+
# 1. 下载 186 个 AI 角色
|
|
9
9
|
cd your-project
|
|
10
10
|
git clone --depth 1 https://github.com/jnMetaCode/agency-agents-zh.git
|
|
11
11
|
|
|
12
|
-
# 2.
|
|
13
|
-
git clone --depth 1 https://github.com/jnMetaCode/agency-orchestrator.git .ao-tmp
|
|
14
|
-
|
|
15
|
-
# 3. 添加工作流执行规则
|
|
12
|
+
# 2. 下载工作流模板和技能文件
|
|
13
|
+
git clone --depth 1 https://github.com/jnMetaCode/agency-orchestrator.git .ao-tmp
|
|
14
|
+
cp -r .ao-tmp/workflows ./workflows
|
|
16
15
|
mkdir -p .kiro/steering
|
|
17
|
-
cp
|
|
16
|
+
cp .ao-tmp/integrations/kiro/ao-workflow-runner.md .kiro/steering/
|
|
17
|
+
rm -rf .ao-tmp
|
|
18
|
+
|
|
19
|
+
# 3. 开始使用
|
|
20
|
+
# 在 Kiro 中直接说:运行 workflows/story-creation.yaml
|
|
18
21
|
```
|
|
19
22
|
|
|
20
23
|
## 使用方式
|
|
@@ -5,16 +5,19 @@
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
# 1.
|
|
8
|
+
# 1. 下载 186 个 AI 角色
|
|
9
9
|
cd your-project
|
|
10
10
|
git clone --depth 1 https://github.com/jnMetaCode/agency-agents-zh.git
|
|
11
11
|
|
|
12
|
-
# 2.
|
|
13
|
-
git clone --depth 1 https://github.com/jnMetaCode/agency-orchestrator.git .ao-tmp
|
|
14
|
-
|
|
15
|
-
# 3. 添加工作流执行规则
|
|
12
|
+
# 2. 下载工作流模板和技能文件
|
|
13
|
+
git clone --depth 1 https://github.com/jnMetaCode/agency-orchestrator.git .ao-tmp
|
|
14
|
+
cp -r .ao-tmp/workflows ./workflows
|
|
16
15
|
mkdir -p .trae/rules
|
|
17
|
-
cp
|
|
16
|
+
cp .ao-tmp/integrations/trae/ao-workflow-runner.md .trae/rules/
|
|
17
|
+
rm -rf .ao-tmp
|
|
18
|
+
|
|
19
|
+
# 3. 开始使用
|
|
20
|
+
# 在 Trae 中直接说:运行 workflows/story-creation.yaml
|
|
18
21
|
```
|
|
19
22
|
|
|
20
23
|
## 使用方式
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agency-orchestrator",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "Multi-agent workflow orchestrator — 186
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"description": "Multi-agent workflow orchestrator — 186 AI roles, YAML pipelines, auto DAG parallelism, AI-powered workflow composer",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"multi-agent",
|
|
7
7
|
"ai-agents",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"scripts": {
|
|
45
45
|
"build": "tsc",
|
|
46
46
|
"dev": "tsc --watch",
|
|
47
|
-
"test": "npx tsx test/run.ts && npx tsx test/condition.ts && npx tsx test/cli.ts && npx tsx test/e2e.ts && npx tsx test/e2e-condition.ts && npx tsx test/e2e-loop.ts",
|
|
47
|
+
"test": "npx tsx test/run.ts && npx tsx test/condition.ts && npx tsx test/cli.ts && npx tsx test/compose.ts && npx tsx test/e2e.ts && npx tsx test/e2e-condition.ts && npx tsx test/e2e-loop.ts",
|
|
48
48
|
"prepublishOnly": "npm run build"
|
|
49
49
|
},
|
|
50
50
|
"files": [
|