ethan-skill 1.5.6 → 1.5.8
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/dist/cli/autopilot.d.ts +20 -0
- package/dist/cli/autopilot.d.ts.map +1 -0
- package/dist/cli/autopilot.js +164 -0
- package/dist/cli/autopilot.js.map +1 -0
- package/dist/cli/autopilot.test.d.ts +2 -0
- package/dist/cli/autopilot.test.d.ts.map +1 -0
- package/dist/cli/autopilot.test.js +113 -0
- package/dist/cli/autopilot.test.js.map +1 -0
- package/dist/cli/index.js +227 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/context/builder.d.ts +31 -0
- package/dist/context/builder.d.ts.map +1 -0
- package/dist/context/builder.js +230 -0
- package/dist/context/builder.js.map +1 -0
- package/dist/context/builder.test.d.ts +2 -0
- package/dist/context/builder.test.d.ts.map +1 -0
- package/dist/context/builder.test.js +138 -0
- package/dist/context/builder.test.js.map +1 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +111 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/templates/copilot-md.template.d.ts.map +1 -1
- package/dist/templates/copilot-md.template.js +116 -9
- package/dist/templates/copilot-md.template.js.map +1 -1
- package/dist/workflow/state.d.ts +1 -1
- package/dist/workflow/state.d.ts.map +1 -1
- package/dist/workflow/state.js +4 -1
- package/dist/workflow/state.js.map +1 -1
- package/package.json +1 -1
- package/rules/claude-code/CLAUDE.md +2 -2
- package/rules/cline/.clinerules +2 -2
- package/rules/codebuddy/CODEBUDDY.md +2 -2
- package/rules/continue/.continuerules +2 -2
- package/rules/copilot/copilot-instructions.md +2 -2
- package/rules/cursor/.cursorrules +2 -2
- package/rules/cursor/smart-flow.mdc +2 -2
- package/rules/jetbrains/smart-flow.md +2 -2
- package/rules/lingma/smart-flow.md +2 -2
- package/rules/windsurf/.windsurf/rules/smart-flow.md +2 -2
- package/rules/zed/smart-flow.rules +1 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-Pilot 超级 Prompt 生成器
|
|
3
|
+
* 将 Pipeline 的所有步骤打包成单次可执行的链式指令
|
|
4
|
+
* 粘贴到 AI 编辑器后,AI 自动链式执行所有步骤,无需手动推进
|
|
5
|
+
*/
|
|
6
|
+
import type { PipelineDefinition, SkillDefinition } from '../skills/types';
|
|
7
|
+
import type { ProjectSnapshot } from '../context/builder';
|
|
8
|
+
export interface AutopilotOptions {
|
|
9
|
+
context: string;
|
|
10
|
+
isEn?: boolean;
|
|
11
|
+
snapshot?: ProjectSnapshot;
|
|
12
|
+
}
|
|
13
|
+
/** 生成单条 Pipeline 的超级 prompt */
|
|
14
|
+
export declare function buildAutopilotPrompt(pipeline: PipelineDefinition, skills: SkillDefinition[], options: AutopilotOptions): string;
|
|
15
|
+
/** 生成全部 Pipeline 的超级 prompt(依次串联所有 Pipeline) */
|
|
16
|
+
export declare function buildAllPipelinesAutopilotPrompt(pipelines: Array<{
|
|
17
|
+
pipeline: PipelineDefinition;
|
|
18
|
+
skills: SkillDefinition[];
|
|
19
|
+
}>, options: AutopilotOptions): string;
|
|
20
|
+
//# sourceMappingURL=autopilot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autopilot.d.ts","sourceRoot":"","sources":["../../src/cli/autopilot.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,+BAA+B;AAC/B,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,kBAAkB,EAC5B,MAAM,EAAE,eAAe,EAAE,EACzB,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAwHR;AAwCD,gDAAgD;AAChD,wBAAgB,gCAAgC,CAC9C,SAAS,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,kBAAkB,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC,EAC7E,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAeR"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Auto-Pilot 超级 Prompt 生成器
|
|
4
|
+
* 将 Pipeline 的所有步骤打包成单次可执行的链式指令
|
|
5
|
+
* 粘贴到 AI 编辑器后,AI 自动链式执行所有步骤,无需手动推进
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.buildAutopilotPrompt = buildAutopilotPrompt;
|
|
9
|
+
exports.buildAllPipelinesAutopilotPrompt = buildAllPipelinesAutopilotPrompt;
|
|
10
|
+
const builder_1 = require("../context/builder");
|
|
11
|
+
/** 生成单条 Pipeline 的超级 prompt */
|
|
12
|
+
function buildAutopilotPrompt(pipeline, skills, options) {
|
|
13
|
+
const { context, isEn = false } = options;
|
|
14
|
+
const total = skills.length;
|
|
15
|
+
if (isEn) {
|
|
16
|
+
const header = `# Auto-Pilot Workflow Instruction
|
|
17
|
+
|
|
18
|
+
**Context**: ${context}
|
|
19
|
+
**Pipeline**: ${pipeline.name} (\`${pipeline.id}\`)
|
|
20
|
+
**Total Steps**: ${total}
|
|
21
|
+
**Mode**: Fully automatic — no user confirmation between steps`;
|
|
22
|
+
const rules = `## Execution Rules (Must Follow)
|
|
23
|
+
|
|
24
|
+
1. Execute all ${total} steps below **in order without waiting for user confirmation**
|
|
25
|
+
2. After each step completes, wrap the output with \`<details>\` collapse tags (see format below)
|
|
26
|
+
3. Pass each step's **core output** (≤200 word summary) as background context to the next step
|
|
27
|
+
4. After all steps complete, output a single merged final report`;
|
|
28
|
+
const foldFormat = `## Output Format for Each Step
|
|
29
|
+
|
|
30
|
+
After each step completes, use this exact format:
|
|
31
|
+
|
|
32
|
+
\`\`\`
|
|
33
|
+
<details>
|
|
34
|
+
<summary>✅ Step N: [Skill Name] — Completed</summary>
|
|
35
|
+
|
|
36
|
+
[Full output of this step]
|
|
37
|
+
|
|
38
|
+
</details>
|
|
39
|
+
\`\`\``;
|
|
40
|
+
const stepsSection = skills.map((skill, i) => {
|
|
41
|
+
const stepNum = i + 1;
|
|
42
|
+
const prevNote = i > 0
|
|
43
|
+
? `**Prior Input**: Use the core output of Step ${i} as background context for this step.\n\n`
|
|
44
|
+
: '';
|
|
45
|
+
const stepsContent = skill.steps
|
|
46
|
+
.map((s, si) => {
|
|
47
|
+
const title = s.title.replace(/^\d+[.、]\s*/, '');
|
|
48
|
+
const indented = s.content.split('\n').map((l) => ` ${l}`).join('\n');
|
|
49
|
+
return ` ${si + 1}. **${title}**\n${indented}`;
|
|
50
|
+
})
|
|
51
|
+
.join('\n\n');
|
|
52
|
+
return `### Step ${stepNum}/${total}: ${skill.nameEn.replace(/_/g, ' ')}
|
|
53
|
+
|
|
54
|
+
${prevNote}**Goal**: ${skill.descriptionEn ?? skill.description}
|
|
55
|
+
|
|
56
|
+
**Execution Steps**:
|
|
57
|
+
|
|
58
|
+
${stepsContent}
|
|
59
|
+
|
|
60
|
+
**Output Format**: ${skill.outputFormat}`;
|
|
61
|
+
}).join('\n\n---\n\n');
|
|
62
|
+
const reportTemplate = buildReportTemplate(pipeline, skills, context, true);
|
|
63
|
+
const startCmd = `**Begin executing Step 1 now.**`;
|
|
64
|
+
const snapshotBlock = options.snapshot ? (0, builder_1.formatSnapshotForPrompt)(options.snapshot, true) : '';
|
|
65
|
+
return [header, snapshotBlock, '---', rules, '---', foldFormat, '---', `## Step Details`, stepsSection, '---', reportTemplate, startCmd].filter(Boolean).join('\n\n');
|
|
66
|
+
}
|
|
67
|
+
// 中文版
|
|
68
|
+
const header = `# Auto-Pilot 工作流指令
|
|
69
|
+
|
|
70
|
+
**任务背景**:${context}
|
|
71
|
+
**Pipeline**:${pipeline.name}(\`${pipeline.id}\`)
|
|
72
|
+
**总步数**:${total} 步
|
|
73
|
+
**执行模式**:全自动,步骤间自动传递上下文,无需用户介入`;
|
|
74
|
+
const rules = `## 执行规则(必须严格遵守)
|
|
75
|
+
|
|
76
|
+
1. 按顺序执行以下全部 ${total} 个步骤,**不等待用户确认**
|
|
77
|
+
2. 每步完成后,用 \`<details>\` 标签折叠展示中间结果(见下方格式)
|
|
78
|
+
3. 将每步的**核心产出**(≤200字摘要)作为下一步的背景信息
|
|
79
|
+
4. 全部步骤完成后,输出完整合并报告`;
|
|
80
|
+
const foldFormat = `## 每步输出格式
|
|
81
|
+
|
|
82
|
+
每个步骤完成后,使用如下格式:
|
|
83
|
+
|
|
84
|
+
\`\`\`
|
|
85
|
+
<details>
|
|
86
|
+
<summary>✅ 步骤 N:[Skill名称] — 已完成</summary>
|
|
87
|
+
|
|
88
|
+
[本步骤完整输出]
|
|
89
|
+
|
|
90
|
+
</details>
|
|
91
|
+
\`\`\``;
|
|
92
|
+
const stepsSection = skills.map((skill, i) => {
|
|
93
|
+
const stepNum = i + 1;
|
|
94
|
+
const prevNote = i > 0
|
|
95
|
+
? `**前序输入**:使用步骤 ${i} 的核心产出(≤200字)作为本步骤的背景信息。\n\n`
|
|
96
|
+
: '';
|
|
97
|
+
const stepsContent = skill.steps
|
|
98
|
+
.map((s, si) => {
|
|
99
|
+
const title = s.title.replace(/^\d+[.、]\s*/, '');
|
|
100
|
+
const indented = s.content.split('\n').map((l) => ` ${l}`).join('\n');
|
|
101
|
+
return ` ${si + 1}. **${title}**\n${indented}`;
|
|
102
|
+
})
|
|
103
|
+
.join('\n\n');
|
|
104
|
+
return `### 步骤 ${stepNum}/${total}:${skill.name}
|
|
105
|
+
|
|
106
|
+
${prevNote}**目标**:${skill.description}
|
|
107
|
+
|
|
108
|
+
**执行内容**:
|
|
109
|
+
|
|
110
|
+
${stepsContent}
|
|
111
|
+
|
|
112
|
+
**输出格式**:${skill.outputFormat}`;
|
|
113
|
+
}).join('\n\n---\n\n');
|
|
114
|
+
const reportTemplate = buildReportTemplate(pipeline, skills, context, false);
|
|
115
|
+
const startCmd = `**立即开始执行步骤 1。**`;
|
|
116
|
+
const snapshotBlock = options.snapshot ? (0, builder_1.formatSnapshotForPrompt)(options.snapshot, false) : '';
|
|
117
|
+
return [header, snapshotBlock, '---', rules, '---', foldFormat, '---', `## 步骤详情`, stepsSection, '---', reportTemplate, startCmd].filter(Boolean).join('\n\n');
|
|
118
|
+
}
|
|
119
|
+
/** 生成合并报告模板段落 */
|
|
120
|
+
function buildReportTemplate(pipeline, skills, context, isEn) {
|
|
121
|
+
if (isEn) {
|
|
122
|
+
const skillSections = skills
|
|
123
|
+
.map((s) => `## ${s.nameEn.replace(/_/g, ' ')}\n[Full output]\n\n---`)
|
|
124
|
+
.join('\n\n');
|
|
125
|
+
return `## Final Output Requirements
|
|
126
|
+
|
|
127
|
+
After all steps complete, output the following merged report:
|
|
128
|
+
|
|
129
|
+
# Workflow Report — ${context}
|
|
130
|
+
> Pipeline: ${pipeline.name}
|
|
131
|
+
|
|
132
|
+
${skillSections}
|
|
133
|
+
|
|
134
|
+
*Auto-generated by Ethan Auto-Pilot*`;
|
|
135
|
+
}
|
|
136
|
+
const skillSections = skills
|
|
137
|
+
.map((s) => `## ${s.name}\n[完整输出]\n\n---`)
|
|
138
|
+
.join('\n\n');
|
|
139
|
+
return `## 最终输出要求
|
|
140
|
+
|
|
141
|
+
全部步骤完成后,输出以下合并报告:
|
|
142
|
+
|
|
143
|
+
# 工作流执行报告 — ${context}
|
|
144
|
+
> Pipeline:${pipeline.name}
|
|
145
|
+
|
|
146
|
+
${skillSections}
|
|
147
|
+
|
|
148
|
+
*由 Ethan Auto-Pilot 自动生成*`;
|
|
149
|
+
}
|
|
150
|
+
/** 生成全部 Pipeline 的超级 prompt(依次串联所有 Pipeline) */
|
|
151
|
+
function buildAllPipelinesAutopilotPrompt(pipelines, options) {
|
|
152
|
+
const { isEn = false } = options;
|
|
153
|
+
const divider = '\n\n' + '═'.repeat(60) + '\n\n';
|
|
154
|
+
const header = isEn
|
|
155
|
+
? `# Auto-Pilot — All Pipelines\n\n**Context**: ${options.context}\n**Mode**: Execute all ${pipelines.length} pipelines sequentially`
|
|
156
|
+
: `# Auto-Pilot — 全部工作流\n\n**任务背景**:${options.context}\n**执行模式**:依次执行全部 ${pipelines.length} 条 Pipeline`;
|
|
157
|
+
const sections = pipelines.map(({ pipeline, skills }, i) => {
|
|
158
|
+
const label = isEn ? `Pipeline ${i + 1}/${pipelines.length}` : `Pipeline ${i + 1}/${pipelines.length}`;
|
|
159
|
+
const prompt = buildAutopilotPrompt(pipeline, skills, options);
|
|
160
|
+
return `# ${label}:${pipeline.name}\n\n${prompt}`;
|
|
161
|
+
});
|
|
162
|
+
return [header, ...sections].join(divider);
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=autopilot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autopilot.js","sourceRoot":"","sources":["../../src/cli/autopilot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autopilot.test.d.ts","sourceRoot":"","sources":["../../src/cli/autopilot.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const autopilot_1 = require("./autopilot");
|
|
5
|
+
const pipeline_1 = require("../skills/pipeline");
|
|
6
|
+
(0, vitest_1.describe)('buildAutopilotPrompt', () => {
|
|
7
|
+
const devWorkflow = (0, pipeline_1.resolvePipeline)('dev-workflow');
|
|
8
|
+
(0, vitest_1.it)('includes task context', () => {
|
|
9
|
+
const prompt = (0, autopilot_1.buildAutopilotPrompt)(devWorkflow.pipeline, devWorkflow.skills, {
|
|
10
|
+
context: '实现用户登录功能',
|
|
11
|
+
});
|
|
12
|
+
(0, vitest_1.expect)(prompt).toContain('实现用户登录功能');
|
|
13
|
+
});
|
|
14
|
+
(0, vitest_1.it)('includes pipeline name and id', () => {
|
|
15
|
+
const prompt = (0, autopilot_1.buildAutopilotPrompt)(devWorkflow.pipeline, devWorkflow.skills, {
|
|
16
|
+
context: '测试',
|
|
17
|
+
});
|
|
18
|
+
(0, vitest_1.expect)(prompt).toContain(devWorkflow.pipeline.name);
|
|
19
|
+
(0, vitest_1.expect)(prompt).toContain(devWorkflow.pipeline.id);
|
|
20
|
+
});
|
|
21
|
+
(0, vitest_1.it)('includes all step headings in order', () => {
|
|
22
|
+
const prompt = (0, autopilot_1.buildAutopilotPrompt)(devWorkflow.pipeline, devWorkflow.skills, {
|
|
23
|
+
context: '测试',
|
|
24
|
+
});
|
|
25
|
+
devWorkflow.skills.forEach((skill, i) => {
|
|
26
|
+
(0, vitest_1.expect)(prompt).toContain(`步骤 ${i + 1}/${devWorkflow.skills.length}`);
|
|
27
|
+
(0, vitest_1.expect)(prompt).toContain(skill.name);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
(0, vitest_1.it)('includes <details> fold instruction', () => {
|
|
31
|
+
const prompt = (0, autopilot_1.buildAutopilotPrompt)(devWorkflow.pipeline, devWorkflow.skills, {
|
|
32
|
+
context: '测试',
|
|
33
|
+
});
|
|
34
|
+
(0, vitest_1.expect)(prompt).toContain('<details>');
|
|
35
|
+
(0, vitest_1.expect)(prompt).toContain('<summary>');
|
|
36
|
+
});
|
|
37
|
+
(0, vitest_1.it)('includes "no user confirmation" instruction', () => {
|
|
38
|
+
const prompt = (0, autopilot_1.buildAutopilotPrompt)(devWorkflow.pipeline, devWorkflow.skills, {
|
|
39
|
+
context: '测试',
|
|
40
|
+
});
|
|
41
|
+
(0, vitest_1.expect)(prompt).toContain('不等待用户确认');
|
|
42
|
+
});
|
|
43
|
+
(0, vitest_1.it)('includes prior-input reference for steps after first', () => {
|
|
44
|
+
const prompt = (0, autopilot_1.buildAutopilotPrompt)(devWorkflow.pipeline, devWorkflow.skills, {
|
|
45
|
+
context: '测试',
|
|
46
|
+
});
|
|
47
|
+
(0, vitest_1.expect)(prompt).toContain('步骤 1 的核心产出');
|
|
48
|
+
});
|
|
49
|
+
(0, vitest_1.it)('includes context-passing rule (≤200字)', () => {
|
|
50
|
+
const prompt = (0, autopilot_1.buildAutopilotPrompt)(devWorkflow.pipeline, devWorkflow.skills, {
|
|
51
|
+
context: '测试',
|
|
52
|
+
});
|
|
53
|
+
(0, vitest_1.expect)(prompt).toContain('200');
|
|
54
|
+
});
|
|
55
|
+
(0, vitest_1.it)('ends with start instruction', () => {
|
|
56
|
+
const prompt = (0, autopilot_1.buildAutopilotPrompt)(devWorkflow.pipeline, devWorkflow.skills, {
|
|
57
|
+
context: '测试',
|
|
58
|
+
});
|
|
59
|
+
(0, vitest_1.expect)(prompt.trimEnd()).toMatch(/立即开始执行步骤 1[。.]?\*{0,2}$/);
|
|
60
|
+
});
|
|
61
|
+
(0, vitest_1.it)('includes merged report template', () => {
|
|
62
|
+
const prompt = (0, autopilot_1.buildAutopilotPrompt)(devWorkflow.pipeline, devWorkflow.skills, {
|
|
63
|
+
context: '测试需求',
|
|
64
|
+
});
|
|
65
|
+
(0, vitest_1.expect)(prompt).toContain('工作流执行报告');
|
|
66
|
+
(0, vitest_1.expect)(prompt).toContain('测试需求');
|
|
67
|
+
(0, vitest_1.expect)(prompt).toContain('Ethan Auto-Pilot');
|
|
68
|
+
});
|
|
69
|
+
(0, vitest_1.it)('generates english prompt when isEn=true', () => {
|
|
70
|
+
const prompt = (0, autopilot_1.buildAutopilotPrompt)(devWorkflow.pipeline, devWorkflow.skills, {
|
|
71
|
+
context: 'implement login',
|
|
72
|
+
isEn: true,
|
|
73
|
+
});
|
|
74
|
+
(0, vitest_1.expect)(prompt).toContain('Auto-Pilot Workflow Instruction');
|
|
75
|
+
(0, vitest_1.expect)(prompt).toContain('Begin executing Step 1 now');
|
|
76
|
+
(0, vitest_1.expect)(prompt).not.toContain('任务背景');
|
|
77
|
+
(0, vitest_1.expect)(prompt).toContain('<details>');
|
|
78
|
+
});
|
|
79
|
+
(0, vitest_1.it)('works for all built-in pipelines', () => {
|
|
80
|
+
for (const p of pipeline_1.PIPELINES) {
|
|
81
|
+
const resolved = (0, pipeline_1.resolvePipeline)(p.id);
|
|
82
|
+
const prompt = (0, autopilot_1.buildAutopilotPrompt)(resolved.pipeline, resolved.skills, {
|
|
83
|
+
context: '测试',
|
|
84
|
+
});
|
|
85
|
+
(0, vitest_1.expect)(prompt.length).toBeGreaterThan(500);
|
|
86
|
+
(0, vitest_1.expect)(prompt).toContain(resolved.pipeline.name);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
(0, vitest_1.describe)('buildAllPipelinesAutopilotPrompt', () => {
|
|
91
|
+
const allResolved = pipeline_1.PIPELINES.map((p) => (0, pipeline_1.resolvePipeline)(p.id));
|
|
92
|
+
(0, vitest_1.it)('includes all pipeline names', () => {
|
|
93
|
+
const prompt = (0, autopilot_1.buildAllPipelinesAutopilotPrompt)(allResolved, { context: '测试' });
|
|
94
|
+
for (const p of pipeline_1.PIPELINES) {
|
|
95
|
+
(0, vitest_1.expect)(prompt).toContain(p.name);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
(0, vitest_1.it)('includes pipeline count header', () => {
|
|
99
|
+
const prompt = (0, autopilot_1.buildAllPipelinesAutopilotPrompt)(allResolved, { context: '测试' });
|
|
100
|
+
(0, vitest_1.expect)(prompt).toContain(`${pipeline_1.PIPELINES.length}`);
|
|
101
|
+
(0, vitest_1.expect)(prompt).toContain('全部工作流');
|
|
102
|
+
});
|
|
103
|
+
(0, vitest_1.it)('separates pipelines with dividers', () => {
|
|
104
|
+
const prompt = (0, autopilot_1.buildAllPipelinesAutopilotPrompt)(allResolved, { context: '测试' });
|
|
105
|
+
(0, vitest_1.expect)(prompt).toContain('═'.repeat(60));
|
|
106
|
+
});
|
|
107
|
+
(0, vitest_1.it)('includes context in all sections', () => {
|
|
108
|
+
const context = '我的任务背景';
|
|
109
|
+
const prompt = (0, autopilot_1.buildAllPipelinesAutopilotPrompt)(allResolved, { context });
|
|
110
|
+
(0, vitest_1.expect)(prompt).toContain(context);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
//# sourceMappingURL=autopilot.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autopilot.test.js","sourceRoot":"","sources":["../../src/cli/autopilot.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,2CAAqF;AACrF,iDAAgE;AAEhE,IAAA,iBAAQ,EAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,MAAM,WAAW,GAAG,IAAA,0BAAe,EAAC,cAAc,CAAE,CAAC;IAErD,IAAA,WAAE,EAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,MAAM,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE;YAC5E,OAAO,EAAE,UAAU;SACpB,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE;YAC5E,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpD,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE;YAC5E,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;YACtC,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;YACrE,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE;YAC5E,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACtC,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE;YAC5E,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,MAAM,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE;YAC5E,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,MAAM,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE;YAC5E,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,MAAM,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE;YAC5E,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,MAAM,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE;YAC5E,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACpC,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACjC,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,MAAM,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE;YAC5E,OAAO,EAAE,iBAAiB;YAC1B,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;QAC5D,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC;QACvD,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACrC,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,KAAK,MAAM,CAAC,IAAI,oBAAS,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,IAAA,0BAAe,EAAC,CAAC,CAAC,EAAE,CAAE,CAAC;YACxC,MAAM,MAAM,GAAG,IAAA,gCAAoB,EAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE;gBACtE,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;YACH,IAAA,eAAM,EAAC,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YAC3C,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,IAAA,iBAAQ,EAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,MAAM,WAAW,GAAG,oBAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,0BAAe,EAAC,CAAC,CAAC,EAAE,CAAE,CAAC,CAAC;IAEjE,IAAA,WAAE,EAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,MAAM,GAAG,IAAA,4CAAgC,EAAC,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAChF,KAAK,MAAM,CAAC,IAAI,oBAAS,EAAE,CAAC;YAC1B,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,MAAM,GAAG,IAAA,4CAAgC,EAAC,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAChF,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,GAAG,oBAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QAChD,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,MAAM,GAAG,IAAA,4CAAgC,EAAC,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAChF,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC;QACzB,MAAM,MAAM,GAAG,IAAA,4CAAgC,EAAC,WAAW,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1E,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/cli/index.js
CHANGED
|
@@ -1073,6 +1073,7 @@ workflowCmd
|
|
|
1073
1073
|
.command('done [summary]')
|
|
1074
1074
|
.description('完成当前步骤,自动推进到下一步(摘要可选)')
|
|
1075
1075
|
.option('-n, --name <name>', '具名会话名称')
|
|
1076
|
+
.option('-r, --rating <rating>', '评分本步 Skill 质量(1-5)')
|
|
1076
1077
|
.action(async (summary, options) => {
|
|
1077
1078
|
const { loadSession, markStepDone, buildStepPrompt, getCurrentStep, getCurrentStepIndex, calcProgress, } = await Promise.resolve().then(() => __importStar(require('../workflow/state')));
|
|
1078
1079
|
const { resolvePipeline } = await Promise.resolve().then(() => __importStar(require('../skills/pipeline')));
|
|
@@ -1096,6 +1097,23 @@ workflowCmd
|
|
|
1096
1097
|
const progress = calcProgress(session);
|
|
1097
1098
|
// 自动归档到 Skill Memory(T16)
|
|
1098
1099
|
archiveWorkflowToMemory(session.id, currentStep.skillId, session.pipelineName, stepSummary, process.cwd());
|
|
1100
|
+
// 记录 Skill 质量评分(--rating 1-5)
|
|
1101
|
+
if (options.rating !== undefined) {
|
|
1102
|
+
const ratingNum = parseInt(options.rating, 10);
|
|
1103
|
+
if (isNaN(ratingNum) || ratingNum < 1 || ratingNum > 5) {
|
|
1104
|
+
console.warn('⚠️ 评分无效,已忽略(必须为 1-5 的整数)');
|
|
1105
|
+
}
|
|
1106
|
+
else {
|
|
1107
|
+
const statsData = readStatsV2();
|
|
1108
|
+
if (!statsData.ratings)
|
|
1109
|
+
statsData.ratings = {};
|
|
1110
|
+
if (!statsData.ratings[currentStep.skillId])
|
|
1111
|
+
statsData.ratings[currentStep.skillId] = [];
|
|
1112
|
+
statsData.ratings[currentStep.skillId].push(ratingNum);
|
|
1113
|
+
writeStatsV2(statsData);
|
|
1114
|
+
console.log(`⭐ 已记录评分 ${ratingNum}/5 → ${currentStep.skillId}`);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1099
1117
|
if (!nextStep) {
|
|
1100
1118
|
console.log('\n🎉 恭喜!工作流全部完成!');
|
|
1101
1119
|
console.log(` Pipeline: ${session.pipelineName}`);
|
|
@@ -2879,6 +2897,215 @@ function loadCustomPipelines(cwd) {
|
|
|
2879
2897
|
}
|
|
2880
2898
|
return results;
|
|
2881
2899
|
}
|
|
2900
|
+
// ─── context 命令组 ────────────────────────────────────────────────────────
|
|
2901
|
+
const contextCmd = program.command('context').description('采集并展示当前项目上下文快照(技术栈/git/目录树)');
|
|
2902
|
+
contextCmd
|
|
2903
|
+
.command('show')
|
|
2904
|
+
.description('显示项目上下文快照(使用缓存,TTL 30min)')
|
|
2905
|
+
.option('--refresh', '强制重新采集,忽略缓存')
|
|
2906
|
+
.option('--json', '以 JSON 格式输出')
|
|
2907
|
+
.action(async (options) => {
|
|
2908
|
+
const { buildProjectSnapshot, loadCachedSnapshot, saveSnapshotCache, formatSnapshotForPrompt } = await Promise.resolve().then(() => __importStar(require('../context/builder')));
|
|
2909
|
+
let snapshot = options.refresh ? null : loadCachedSnapshot(process.cwd());
|
|
2910
|
+
if (!snapshot) {
|
|
2911
|
+
console.log('🔍 正在采集项目上下文...');
|
|
2912
|
+
snapshot = buildProjectSnapshot(process.cwd());
|
|
2913
|
+
saveSnapshotCache(snapshot, process.cwd());
|
|
2914
|
+
}
|
|
2915
|
+
if (options.json) {
|
|
2916
|
+
console.log(JSON.stringify(snapshot, null, 2));
|
|
2917
|
+
}
|
|
2918
|
+
else {
|
|
2919
|
+
console.log('\n' + formatSnapshotForPrompt(snapshot, false) + '\n');
|
|
2920
|
+
console.log(`(缓存时间:${snapshot.generatedAt})\n`);
|
|
2921
|
+
}
|
|
2922
|
+
});
|
|
2923
|
+
contextCmd
|
|
2924
|
+
.command('refresh')
|
|
2925
|
+
.description('强制重新采集,更新 .ethan/context.json 缓存')
|
|
2926
|
+
.action(async () => {
|
|
2927
|
+
const { buildProjectSnapshot, saveSnapshotCache, formatSnapshotForPrompt } = await Promise.resolve().then(() => __importStar(require('../context/builder')));
|
|
2928
|
+
console.log('🔍 正在采集项目上下文...');
|
|
2929
|
+
const snapshot = buildProjectSnapshot(process.cwd());
|
|
2930
|
+
saveSnapshotCache(snapshot, process.cwd());
|
|
2931
|
+
console.log('\n' + formatSnapshotForPrompt(snapshot, false) + '\n');
|
|
2932
|
+
console.log('✅ 项目上下文已更新并缓存到 .ethan/context.json\n');
|
|
2933
|
+
});
|
|
2934
|
+
// ─── quality 命令组 ────────────────────────────────────────────────────────
|
|
2935
|
+
const qualityCmd = program.command('quality').description('Skill 质量评估报告(基于 workflow done --rating 的评分数据)');
|
|
2936
|
+
qualityCmd
|
|
2937
|
+
.command('report')
|
|
2938
|
+
.description('显示各 Skill 的质量评分报告(ASCII 条形图)')
|
|
2939
|
+
.option('--min-count <n>', '最少评分次数过滤(低于此数量的 Skill 不显示)', '1')
|
|
2940
|
+
.action((options) => {
|
|
2941
|
+
const minCount = parseInt(options.minCount, 10) || 1;
|
|
2942
|
+
const data = readStatsV2();
|
|
2943
|
+
const ratings = data.ratings || {};
|
|
2944
|
+
const entries = Object.entries(ratings)
|
|
2945
|
+
.map(([skillId, scores]) => ({
|
|
2946
|
+
skillId,
|
|
2947
|
+
scores,
|
|
2948
|
+
avg: scores.reduce((a, b) => a + b, 0) / scores.length,
|
|
2949
|
+
count: scores.length,
|
|
2950
|
+
}))
|
|
2951
|
+
.filter((e) => e.count >= minCount)
|
|
2952
|
+
.sort((a, b) => b.avg - a.avg);
|
|
2953
|
+
if (entries.length === 0) {
|
|
2954
|
+
console.log('\n📊 暂无评分数据。运行 ethan workflow done "摘要" --rating 4 记录评分。\n');
|
|
2955
|
+
return;
|
|
2956
|
+
}
|
|
2957
|
+
const globalAvg = entries.reduce((s, e) => s + e.avg, 0) / entries.length;
|
|
2958
|
+
console.log('\n📊 Skill 质量评估报告');
|
|
2959
|
+
console.log('─'.repeat(60));
|
|
2960
|
+
const BAR_MAX = 25;
|
|
2961
|
+
for (const e of entries) {
|
|
2962
|
+
const indicator = e.avg > 4 ? '🟢' : e.avg >= 3 ? '🟡' : '🔴';
|
|
2963
|
+
const bars = Math.round((e.avg / 5) * BAR_MAX);
|
|
2964
|
+
const bar = '█'.repeat(bars) + '░'.repeat(BAR_MAX - bars);
|
|
2965
|
+
const avgStr = e.avg.toFixed(1);
|
|
2966
|
+
console.log(`${indicator} ${e.skillId.padEnd(28)} ${bar} ${avgStr}/5 (n=${e.count})`);
|
|
2967
|
+
}
|
|
2968
|
+
console.log('─'.repeat(60));
|
|
2969
|
+
console.log(` 全局平均分:${globalAvg.toFixed(1)}/5 (${entries.length} 个 Skill,共 ${entries.reduce((s, e) => s + e.count, 0)} 条评分)`);
|
|
2970
|
+
const lowSkills = entries.filter((e) => e.avg < 3);
|
|
2971
|
+
if (lowSkills.length > 0) {
|
|
2972
|
+
console.log('\n⚠️ 低分 Skill(平均 < 3)需要关注:');
|
|
2973
|
+
lowSkills.forEach((e) => console.log(` 🔴 ${e.skillId} avg=${e.avg.toFixed(1)}`));
|
|
2974
|
+
}
|
|
2975
|
+
console.log('');
|
|
2976
|
+
});
|
|
2977
|
+
// ─── autopilot 命令 ──────────────────────────────────────────────────────────
|
|
2978
|
+
program
|
|
2979
|
+
.command('autopilot [pipelineId]')
|
|
2980
|
+
.description('生成「超级 prompt」:一次粘贴即可让 AI 自动链式执行完整 Pipeline,无需手动推进每一步')
|
|
2981
|
+
.option('-c, --context <context>', '任务上下文描述(如"实现用户登录功能")', '')
|
|
2982
|
+
.option('--all', '生成全部 3 条 Pipeline 的超级 prompt')
|
|
2983
|
+
.option('--lang <lang>', '输出语言:zh(默认)或 en', '')
|
|
2984
|
+
.option('--with-context', '自动采集项目上下文(技术栈/git 提交/目录树)注入到提示词')
|
|
2985
|
+
.option('--no-copy', '不自动复制到剪贴板,直接打印到终端')
|
|
2986
|
+
.action(async (pipelineId, options) => {
|
|
2987
|
+
const { resolvePipeline, PIPELINES } = await Promise.resolve().then(() => __importStar(require('../skills/pipeline')));
|
|
2988
|
+
const { buildAutopilotPrompt, buildAllPipelinesAutopilotPrompt } = await Promise.resolve().then(() => __importStar(require('./autopilot')));
|
|
2989
|
+
const { buildProjectSnapshot, loadCachedSnapshot, saveSnapshotCache } = await Promise.resolve().then(() => __importStar(require('../context/builder')));
|
|
2990
|
+
const config = (0, config_1.readConfig)(process.cwd());
|
|
2991
|
+
const isEn = (options.lang || config.lang || 'zh') === 'en';
|
|
2992
|
+
// 采集项目上下文快照(--with-context 或自动检测缓存)
|
|
2993
|
+
let snapshot = undefined;
|
|
2994
|
+
if (options.withContext) {
|
|
2995
|
+
const cached = loadCachedSnapshot(process.cwd());
|
|
2996
|
+
if (cached) {
|
|
2997
|
+
snapshot = cached;
|
|
2998
|
+
}
|
|
2999
|
+
else {
|
|
3000
|
+
console.log(isEn ? '🔍 Collecting project context...' : '🔍 正在采集项目上下文...');
|
|
3001
|
+
snapshot = buildProjectSnapshot(process.cwd());
|
|
3002
|
+
saveSnapshotCache(snapshot, process.cwd());
|
|
3003
|
+
}
|
|
3004
|
+
}
|
|
3005
|
+
else {
|
|
3006
|
+
// 静默注入:若缓存存在且未过期则自动使用
|
|
3007
|
+
const cached = loadCachedSnapshot(process.cwd());
|
|
3008
|
+
if (cached)
|
|
3009
|
+
snapshot = cached;
|
|
3010
|
+
}
|
|
3011
|
+
// 获取任务上下文(--context 或交互式输入)
|
|
3012
|
+
let context = (options.context || '').trim();
|
|
3013
|
+
if (!context) {
|
|
3014
|
+
const readline = await Promise.resolve().then(() => __importStar(require('readline')));
|
|
3015
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
3016
|
+
const ask = (q) => new Promise((resolve) => rl.question(q, (a) => resolve(a.trim())));
|
|
3017
|
+
context = await ask(isEn
|
|
3018
|
+
? 'Describe your task context (e.g. "implement user login with JWT"):\n> '
|
|
3019
|
+
: '请描述任务背景(例如:实现用户登录功能,支持 JWT 认证):\n> ');
|
|
3020
|
+
rl.close();
|
|
3021
|
+
if (!context) {
|
|
3022
|
+
console.error(isEn ? '\n❌ Context cannot be empty\n' : '\n❌ 任务背景不能为空\n');
|
|
3023
|
+
process.exit(1);
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
let prompt;
|
|
3027
|
+
if (options.all) {
|
|
3028
|
+
// 生成全部 Pipeline 的超级 prompt
|
|
3029
|
+
const allResolved = PIPELINES.map((p) => resolvePipeline(p.id)).filter(Boolean);
|
|
3030
|
+
prompt = buildAllPipelinesAutopilotPrompt(allResolved, { context, isEn, snapshot });
|
|
3031
|
+
console.log(isEn
|
|
3032
|
+
? `\n🚀 Auto-Pilot prompt generated for all ${PIPELINES.length} pipelines`
|
|
3033
|
+
: `\n🚀 已生成全部 ${PIPELINES.length} 条 Pipeline 的超级 prompt`);
|
|
3034
|
+
}
|
|
3035
|
+
else {
|
|
3036
|
+
// 确定目标 Pipeline
|
|
3037
|
+
let id = pipelineId;
|
|
3038
|
+
if (!id) {
|
|
3039
|
+
const customPipelines = loadCustomPipelines(process.cwd());
|
|
3040
|
+
const allPipelines = [
|
|
3041
|
+
...PIPELINES,
|
|
3042
|
+
...customPipelines.map((p) => ({ id: p.id, name: p.name, description: p.description, skillIds: p.skillIds })),
|
|
3043
|
+
];
|
|
3044
|
+
const readline = await Promise.resolve().then(() => __importStar(require('readline')));
|
|
3045
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
3046
|
+
const ask = (q) => new Promise((resolve) => rl.question(q, (a) => resolve(a.trim())));
|
|
3047
|
+
console.log(isEn ? '\n🔄 Available Pipelines\n' : '\n🔄 可用工作流 Pipeline\n');
|
|
3048
|
+
console.log('─'.repeat(60));
|
|
3049
|
+
allPipelines.forEach((p, i) => {
|
|
3050
|
+
console.log(` ${i + 1}. ${p.name} [${p.id}]`);
|
|
3051
|
+
console.log(` ${isEn ? p.description : p.description}`);
|
|
3052
|
+
});
|
|
3053
|
+
console.log('');
|
|
3054
|
+
const choice = await ask(isEn
|
|
3055
|
+
? `Select pipeline (1-${allPipelines.length} or ID):\n> `
|
|
3056
|
+
: `选择 Pipeline(输入序号 1-${allPipelines.length},或直接输入 ID):\n> `);
|
|
3057
|
+
rl.close();
|
|
3058
|
+
const num = parseInt(choice, 10);
|
|
3059
|
+
if (!isNaN(num) && num >= 1 && num <= allPipelines.length) {
|
|
3060
|
+
id = allPipelines[num - 1].id;
|
|
3061
|
+
}
|
|
3062
|
+
else {
|
|
3063
|
+
id = choice;
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
let resolved = resolvePipeline(id);
|
|
3067
|
+
if (!resolved) {
|
|
3068
|
+
const customPipelines = loadCustomPipelines(process.cwd());
|
|
3069
|
+
const custom = customPipelines.find((p) => p.id === id);
|
|
3070
|
+
if (custom) {
|
|
3071
|
+
const customSkills = custom.skillIds
|
|
3072
|
+
.map((sid) => index_1.ALL_SKILLS.find((s) => s.id === sid))
|
|
3073
|
+
.filter((s) => s != null);
|
|
3074
|
+
if (customSkills.length > 0) {
|
|
3075
|
+
resolved = { pipeline: { id: custom.id, name: custom.name, description: custom.description, skillIds: custom.skillIds }, skills: customSkills };
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
if (!resolved) {
|
|
3080
|
+
console.error(isEn ? `\n❌ Unknown pipeline: ${id}\n` : `\n❌ 未找到 Pipeline: ${id}\n`);
|
|
3081
|
+
console.error(`Available: ${PIPELINES.map((p) => p.id).join(' | ')}`);
|
|
3082
|
+
process.exit(1);
|
|
3083
|
+
}
|
|
3084
|
+
const { pipeline, skills } = resolved;
|
|
3085
|
+
prompt = buildAutopilotPrompt(pipeline, skills, { context, isEn, snapshot });
|
|
3086
|
+
console.log(isEn
|
|
3087
|
+
? `\n🚀 Auto-Pilot prompt generated: ${pipeline.name} (${skills.length} steps)`
|
|
3088
|
+
: `\n🚀 超级 prompt 已生成:${pipeline.name}(${skills.length} 步)`);
|
|
3089
|
+
trackUsageWithStreak(`autopilot-${pipeline.id}`);
|
|
3090
|
+
}
|
|
3091
|
+
console.log('─'.repeat(60));
|
|
3092
|
+
if (options.copy !== false) {
|
|
3093
|
+
if (copyToClipboard(prompt)) {
|
|
3094
|
+
console.log(isEn
|
|
3095
|
+
? '\n✅ Super prompt copied to clipboard! Paste it into your AI editor.'
|
|
3096
|
+
: '\n✅ 超级 prompt 已复制到剪贴板!粘贴到 AI 编辑器后,AI 将自动执行所有步骤。');
|
|
3097
|
+
}
|
|
3098
|
+
else {
|
|
3099
|
+
console.log('\n' + prompt + '\n');
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
else {
|
|
3103
|
+
console.log('\n' + prompt + '\n');
|
|
3104
|
+
}
|
|
3105
|
+
console.log(isEn
|
|
3106
|
+
? '\n💡 The AI will automatically chain all steps and deliver the final merged report.\n'
|
|
3107
|
+
: '\n💡 AI 将自动链式执行所有步骤,每步折叠展示,最终输出完整合并报告。\n');
|
|
3108
|
+
});
|
|
2882
3109
|
program
|
|
2883
3110
|
.command('pipeline-init')
|
|
2884
3111
|
.description('在 .ethan/pipelines/ 生成自定义 Pipeline YAML 模板')
|