ethan-skill 1.14.0 → 1.15.0
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/agents/orchestrator.test.js +5 -6
- package/dist/agents/orchestrator.test.js.map +1 -1
- package/dist/cli/index.js +305 -24
- package/dist/cli/index.js.map +1 -1
- package/dist/extension/index.d.ts +54 -0
- package/dist/extension/index.d.ts.map +1 -0
- package/dist/extension/index.js +198 -0
- package/dist/extension/index.js.map +1 -0
- package/dist/memory/index.d.ts +42 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +320 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/types.d.ts +47 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +7 -0
- package/dist/memory/types.js.map +1 -0
- 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
|
@@ -61,7 +61,7 @@ const mockPipeline = {
|
|
|
61
61
|
(0, vitest_1.expect)(prompt).toContain('Agent 阵容');
|
|
62
62
|
(0, vitest_1.expect)(prompt).toContain('Architect Agent');
|
|
63
63
|
(0, vitest_1.expect)(prompt).toContain('Code Agent');
|
|
64
|
-
|
|
64
|
+
// dev-workflow uses architect+coder+pm (no reviewer/qa in this pipeline)
|
|
65
65
|
});
|
|
66
66
|
(0, vitest_1.it)('contains collaboration protocol', () => {
|
|
67
67
|
(0, vitest_1.expect)(prompt).toContain('协作协议');
|
|
@@ -70,7 +70,6 @@ const mockPipeline = {
|
|
|
70
70
|
(0, vitest_1.it)('contains step headings with agent names', () => {
|
|
71
71
|
(0, vitest_1.expect)(prompt).toContain('🏗️ Architect Agent');
|
|
72
72
|
(0, vitest_1.expect)(prompt).toContain('💻 Code Agent');
|
|
73
|
-
(0, vitest_1.expect)(prompt).toContain('🔍 Review Agent');
|
|
74
73
|
});
|
|
75
74
|
(0, vitest_1.it)('contains handoff markers between different agents', () => {
|
|
76
75
|
(0, vitest_1.expect)(prompt).toContain('Handoff →');
|
|
@@ -97,8 +96,8 @@ const mockPipeline = {
|
|
|
97
96
|
});
|
|
98
97
|
});
|
|
99
98
|
(0, vitest_1.describe)('BUILT_IN_AGENTS', () => {
|
|
100
|
-
(0, vitest_1.it)('has
|
|
101
|
-
(0, vitest_1.expect)(presets_1.BUILT_IN_AGENTS).toHaveLength(
|
|
99
|
+
(0, vitest_1.it)('has 8 agents', () => {
|
|
100
|
+
(0, vitest_1.expect)(presets_1.BUILT_IN_AGENTS).toHaveLength(8);
|
|
102
101
|
});
|
|
103
102
|
(0, vitest_1.it)('all agents have required fields', () => {
|
|
104
103
|
for (const agent of presets_1.BUILT_IN_AGENTS) {
|
|
@@ -130,7 +129,7 @@ const mockPipeline = {
|
|
|
130
129
|
const routing = (0, presets_1.buildSkillRouting)(presets_1.BUILT_IN_AGENTS);
|
|
131
130
|
(0, vitest_1.expect)(routing['requirement-understanding']).toBe('architect');
|
|
132
131
|
(0, vitest_1.expect)(routing['implementation']).toBe('coder');
|
|
133
|
-
(0, vitest_1.expect)(routing['code-review']).toBe('
|
|
132
|
+
(0, vitest_1.expect)(routing['code-review']).toBe('qa'); // qa overrides reviewer (last-writer-wins)
|
|
134
133
|
(0, vitest_1.expect)(routing['deployment']).toBe('devops');
|
|
135
134
|
(0, vitest_1.expect)(routing['debug']).toBe('pm');
|
|
136
135
|
});
|
|
@@ -139,7 +138,7 @@ const mockPipeline = {
|
|
|
139
138
|
(0, vitest_1.it)('returns only agents participating in the pipeline', () => {
|
|
140
139
|
const routing = (0, presets_1.buildSkillRouting)(presets_1.BUILT_IN_AGENTS);
|
|
141
140
|
const agents = (0, presets_1.getAgentsForPipeline)(['requirement-understanding', 'implementation', 'code-review'], presets_1.BUILT_IN_AGENTS, routing);
|
|
142
|
-
(0, vitest_1.expect)(agents.map((a) => a.id)).toEqual(['architect', 'coder', '
|
|
141
|
+
(0, vitest_1.expect)(agents.map((a) => a.id)).toEqual(['architect', 'coder', 'qa']);
|
|
143
142
|
});
|
|
144
143
|
(0, vitest_1.it)('deduplicates consecutive same-agent steps', () => {
|
|
145
144
|
const routing = (0, presets_1.buildSkillRouting)(presets_1.BUILT_IN_AGENTS);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.test.js","sourceRoot":"","sources":["../../src/agents/orchestrator.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,iDAAuD;AACvD,uCAAqF;AAGrF,+EAA+E;AAE/E,MAAM,UAAU,GAAsB;IACpC;QACE,EAAE,EAAE,2BAA2B;QAC/B,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,2BAA2B;QACnC,WAAW,EAAE,oBAAoB;QACjC,iBAAiB,EAAE,MAAM;QACzB,QAAQ,EAAE,CAAC,MAAM,CAAC;QAClB,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;QACtD,YAAY,EAAE,gBAAgB;QAC9B,KAAK,EAAE,CAAC;KACT;IACD;QACE,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,gBAAgB;QACxB,WAAW,EAAE,aAAa;QAC1B,iBAAiB,EAAE,MAAM;QACzB,QAAQ,EAAE,CAAC,MAAM,CAAC;QAClB,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;QACrD,YAAY,EAAE,aAAa;QAC3B,KAAK,EAAE,CAAC;KACT;IACD;QACE,EAAE,EAAE,aAAa;QACjB,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,aAAa;QACrB,WAAW,EAAE,WAAW;QACxB,iBAAiB,EAAE,MAAM;QACzB,QAAQ,EAAE,CAAC,MAAM,CAAC;QAClB,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;QACpD,YAAY,EAAE,eAAe;QAC7B,KAAK,EAAE,CAAC;KACT;CACF,CAAC;AAEF,MAAM,YAAY,GAAuB;IACvC,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,oBAAoB;IACjC,QAAQ,EAAE,CAAC,2BAA2B,EAAE,gBAAgB,EAAE,aAAa,CAAC;CACzE,CAAC;AAEF,+EAA+E;AAE/E,IAAA,iBAAQ,EAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,MAAM,MAAM,GAAG,IAAA,oCAAqB,EAAC,YAAY,EAAE,UAAU,EAAE,yBAAe,EAAE;QAC9E,OAAO,EAAE,UAAU;QACnB,IAAI,EAAE,IAAI;KACX,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,kBAAkB,EAAE,GAAG,EAAE;QAC1B,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACrC,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC5C,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACvC,
|
|
1
|
+
{"version":3,"file":"orchestrator.test.js","sourceRoot":"","sources":["../../src/agents/orchestrator.test.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -752,6 +752,32 @@ program
|
|
|
752
752
|
console.log(` ✅ claude-code → 工作流: ${cmdDir}/ethan-{cmd}.md × ${WORKFLOW_SLASH_COMMANDS.length}`);
|
|
753
753
|
console.log(` 使用方式:在 Claude Code 聊天中输入 /ethan-commit、/ethan-auto 等`);
|
|
754
754
|
console.log(` ⚡ 动态注入:提示词自动注入对话,无需复制粘贴`);
|
|
755
|
+
// ── Agent 命令(Claude Code 专属:每个 Agent 一个 .md 文件)─────────────
|
|
756
|
+
const { getActiveAgents } = await Promise.resolve().then(() => __importStar(require('../agents/index')));
|
|
757
|
+
const agents = getActiveAgents(dir);
|
|
758
|
+
// ethan-agent-list.md
|
|
759
|
+
const agentListContent = `---\ndescription: "Ethan — 查看所有可用 Agent 及其 Skill 分配"\n---\n\n` +
|
|
760
|
+
`$(ethan agent list 2>/dev/null)\n`;
|
|
761
|
+
fs.writeFileSync(path.join(outDir, 'ethan-agent-list.md'), agentListContent, 'utf-8');
|
|
762
|
+
// ethan-agent-run.md
|
|
763
|
+
const agentRunContent = `---\ndescription: "Ethan — Multi-Agent 编排:将任务分配给多个专业 Agent 协作执行"\n---\n\n` +
|
|
764
|
+
`$(![ -n "$ARGUMENTS" ] && ethan agent run $ARGUMENTS --no-copy 2>/dev/null || printf "## Ethan Multi-Agent 编排\\n\\n用法: /ethan-agent-run <pipeline> -c \\"任务描述\\"\\n\\n示例:\\n /ethan-agent-run dev-workflow -c \\"实现用户登录功能\\"\\n\\n可用模式: sequential / parallel / review-loop / consensus")\n`;
|
|
765
|
+
fs.writeFileSync(path.join(outDir, 'ethan-agent-run.md'), agentRunContent, 'utf-8');
|
|
766
|
+
// ethan-agent-new.md
|
|
767
|
+
const agentNewContent = `---\ndescription: "Ethan — 创建自定义 Agent,生成 .ethan/agents/<id>.yaml"\n---\n\n` +
|
|
768
|
+
`$(ethan agent new $ARGUMENTS 2>/dev/null)\n`;
|
|
769
|
+
fs.writeFileSync(path.join(outDir, 'ethan-agent-new.md'), agentNewContent, 'utf-8');
|
|
770
|
+
// 每个内置 Agent 生成独立快捷命令
|
|
771
|
+
let agentFileCount = 3;
|
|
772
|
+
for (const agent of agents) {
|
|
773
|
+
const agentSkillList = agent.skillIds.slice(0, 8).join('、') + (agent.skillIds.length > 8 ? '...' : '');
|
|
774
|
+
const agentContent = `---\ndescription: "Ethan — ${agent.emoji} ${agent.name}:${agent.role}"\n---\n\n` +
|
|
775
|
+
`$(![ -n "$ARGUMENTS" ] && ethan agent run --no-copy -c "$ARGUMENTS" 2>/dev/null || printf "## ${agent.emoji} ${agent.name}\\n\\n**职责**: ${agent.role}\\n\\n**负责 Skill**: ${agentSkillList}\\n\\n用法: /ethan-agent-${agent.id} <任务描述>")\n`;
|
|
776
|
+
fs.writeFileSync(path.join(outDir, `ethan-agent-${agent.id}.md`), agentContent, 'utf-8');
|
|
777
|
+
agentFileCount++;
|
|
778
|
+
total++;
|
|
779
|
+
}
|
|
780
|
+
console.log(` ✅ claude-code → Agents: ${cmdDir}/ethan-agent-*.md × ${agentFileCount}(含 ${agents.length} 个 Agent 快捷键)`);
|
|
755
781
|
}
|
|
756
782
|
else {
|
|
757
783
|
// CodeBuddy:静态提示词(各 /ethan-xxx 命令文件)
|
|
@@ -797,14 +823,28 @@ program
|
|
|
797
823
|
continue: 'Continue(@ethan 触发)',
|
|
798
824
|
lingma: '灵码(@ethan 触发)',
|
|
799
825
|
};
|
|
826
|
+
// ── Agent 速查表章节 ─────────────────────────────────────────────────
|
|
827
|
+
const { getActiveAgents: getAgentsForOther } = await Promise.resolve().then(() => __importStar(require('../agents/index')));
|
|
828
|
+
const otherAgents = getAgentsForOther(dir);
|
|
829
|
+
const agentRows = otherAgents
|
|
830
|
+
.map((a) => `| \`/ethan-agent-${a.id}\` | \`@ethan agent ${a.id}\` | ${a.emoji} ${a.name} | Agent | ${a.role} |`)
|
|
831
|
+
.join('\n');
|
|
832
|
+
const agentSection = `## Multi-Agent 命令\n\n` +
|
|
833
|
+
`| Slash 命令 | @ethan 形式 | Agent | 类型 | 职责 |\n` +
|
|
834
|
+
`|-----------|------------|-------|------|------|\n` +
|
|
835
|
+
`| \`/ethan-agent-list\` | \`@ethan agent list\` | — | Agent | 查看所有可用 Agent |\n` +
|
|
836
|
+
`| \`/ethan-agent-run\` | \`@ethan agent run\` | — | Agent | Multi-Agent 编排执行 |\n` +
|
|
837
|
+
`| \`/ethan-agent-new\` | \`@ethan agent new\` | — | Agent | 创建自定义 Agent |\n` +
|
|
838
|
+
`${agentRows}\n`;
|
|
800
839
|
const content = `# Ethan Slash 命令速查表 — ${platformLabel[p] ?? p}\n\n` +
|
|
801
840
|
`> 生成时间:${new Date().toISOString()}\n\n` +
|
|
802
|
-
`## Skills
|
|
841
|
+
`## Skills 命令(${skills.length} 个)\n\n` +
|
|
803
842
|
`| Slash 命令 | @ethan 形式 | Skill 名称 | 类型 | 说明 |\n` +
|
|
804
843
|
`|-----------|------------|-----------|------|------|\n` +
|
|
805
844
|
`${skillRows}\n\n` +
|
|
806
845
|
`## 工作流命令\n\n` +
|
|
807
846
|
`${wfSections}\n\n` +
|
|
847
|
+
`${agentSection}\n` +
|
|
808
848
|
`## 快速示例\n\n` +
|
|
809
849
|
`\`\`\`\n` +
|
|
810
850
|
`/ethan-code-review # Skill:代码审查\n` +
|
|
@@ -812,7 +852,8 @@ program
|
|
|
812
852
|
`/ethan-commit # 工作流:生成提交信息\n` +
|
|
813
853
|
`/ethan-review # 工作流:Code Review\n` +
|
|
814
854
|
`/ethan-auto # 工作流:Auto-Pilot 超级 Prompt\n` +
|
|
815
|
-
`/ethan-
|
|
855
|
+
`/ethan-agent-run # Agent:Multi-Agent 协作编排\n` +
|
|
856
|
+
`/ethan-agent-architect # Agent:架构师 Agent 直接对话\n` +
|
|
816
857
|
`\`\`\`\n`;
|
|
817
858
|
const destFile = path.join(outDir, 'ethan-commands.md');
|
|
818
859
|
fs.writeFileSync(destFile, content, 'utf-8');
|
|
@@ -1267,7 +1308,27 @@ program
|
|
|
1267
1308
|
const nodeOk = nodeMajor >= 18;
|
|
1268
1309
|
console.log(`\n[环境检查]`);
|
|
1269
1310
|
console.log(` Node.js: v${nodeVersion} ${nodeOk ? '✅' : '❌ (需要 Node.js >= 18)'}`);
|
|
1270
|
-
// 2.
|
|
1311
|
+
// 2. Windows 专项检查
|
|
1312
|
+
if (process.platform === 'win32') {
|
|
1313
|
+
console.log('\n[Windows 环境检查]');
|
|
1314
|
+
// 检查 PowerShell 执行策略
|
|
1315
|
+
try {
|
|
1316
|
+
const psPolicy = (0, child_process_1.spawnSync)('powershell', ['-Command', 'Get-ExecutionPolicy'], { encoding: 'utf-8' });
|
|
1317
|
+
const policy = (psPolicy.stdout ?? '').trim();
|
|
1318
|
+
const policyOk = !['Restricted', 'AllSigned'].includes(policy);
|
|
1319
|
+
console.log(` PowerShell 执行策略: ${policy} ${policyOk ? '✅' : '⚠️ 需设置(Set-ExecutionPolicy RemoteSigned -Scope CurrentUser)'}`);
|
|
1320
|
+
}
|
|
1321
|
+
catch { /* PowerShell not available */ }
|
|
1322
|
+
// 检查 npm 全局路径是否在 PATH 中
|
|
1323
|
+
const npmGlobal = (0, child_process_1.spawnSync)('npm', ['config', 'get', 'prefix'], { encoding: 'utf-8', shell: true });
|
|
1324
|
+
const npmPrefix = (npmGlobal.stdout ?? '').trim();
|
|
1325
|
+
if (npmPrefix) {
|
|
1326
|
+
const inPath = (process.env.PATH ?? '').includes(npmPrefix);
|
|
1327
|
+
console.log(` npm global prefix: ${npmPrefix} ${inPath ? '✅ (在 PATH 中)' : '⚠️ 不在 PATH 中(需手动添加)'}`);
|
|
1328
|
+
}
|
|
1329
|
+
console.log(` UTF-8 编码: ${process.env.CHCP === '65001' || process.env.LC_ALL?.includes('UTF') ? '✅' : '⚠️ 建议 chcp 65001'}`);
|
|
1330
|
+
}
|
|
1331
|
+
// 3. MCP SDK check
|
|
1271
1332
|
const sdkOk = fs.existsSync(path.join(__dirname, '../../node_modules/@modelcontextprotocol/sdk'));
|
|
1272
1333
|
console.log(` @modelcontextprotocol/sdk: ${sdkOk ? '✅ 已安装' : '❌ 未安装'}`);
|
|
1273
1334
|
// 3. Rules files status
|
|
@@ -1471,6 +1532,166 @@ program
|
|
|
1471
1532
|
console.log(`\n文件路径:${configPath}`);
|
|
1472
1533
|
console.log('\n💡 提示:现在运行 ethan install --platform <platform> 将使用此配置\n');
|
|
1473
1534
|
});
|
|
1535
|
+
// ─── setup 命令(零门槛一键安装向导) ────────────────────────────────────────
|
|
1536
|
+
// 面向产品、测试等非技术用户,自动检测环境,提供最简安装体验
|
|
1537
|
+
program
|
|
1538
|
+
.command('setup')
|
|
1539
|
+
.description('一键安装向导:自动检测编辑器,为非技术用户提供最简配置体验')
|
|
1540
|
+
.option('--role <role>', '用户角色:dev(开发)/ pm(产品)/ qa(测试)/ design(设计)')
|
|
1541
|
+
.option('--platform <platform>', '强制指定平台(跳过自动检测)')
|
|
1542
|
+
.option('--lang <lang>', '界面语言:zh(默认)/ en')
|
|
1543
|
+
.option('-y, --yes', '跳过所有确认,使用推荐配置')
|
|
1544
|
+
.action(async (options) => {
|
|
1545
|
+
const readline = await Promise.resolve().then(() => __importStar(require('readline')));
|
|
1546
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1547
|
+
const ask = (q, def) => new Promise((resolve) => rl.question(def !== undefined ? `${q} [${def}]: ` : `${q}: `, (a) => resolve(a.trim() || def || '')));
|
|
1548
|
+
const isEn = options.lang === 'en';
|
|
1549
|
+
const isAuto = !!options.yes;
|
|
1550
|
+
const t = {
|
|
1551
|
+
title: isEn ? 'Ethan Setup Wizard' : 'Ethan 快速安装向导',
|
|
1552
|
+
welcome: isEn
|
|
1553
|
+
? 'This wizard will configure Ethan for your editor in 3 steps.'
|
|
1554
|
+
: '3 步完成配置,无需任何编程知识。',
|
|
1555
|
+
step1: isEn ? '[1/3] Detecting your editor...' : '[1/3] 检测你的编辑器...',
|
|
1556
|
+
step2: isEn ? '[2/3] Configuring your role...' : '[2/3] 配置你的角色...',
|
|
1557
|
+
step3: isEn ? '[3/3] Generating slash commands...' : '[3/3] 生成编辑器快捷指令...',
|
|
1558
|
+
done: isEn ? 'Setup complete!' : '安装完成!',
|
|
1559
|
+
};
|
|
1560
|
+
console.log(`\n${'═'.repeat(52)}`);
|
|
1561
|
+
console.log(` ${t.title}`);
|
|
1562
|
+
console.log(` ${t.welcome}`);
|
|
1563
|
+
console.log(`${'═'.repeat(52)}\n`);
|
|
1564
|
+
// ── 步骤 1:自动检测编辑器 ─────────────────────────────────────────────
|
|
1565
|
+
console.log(t.step1);
|
|
1566
|
+
// 检测逻辑:查找 .cursor / .vscode / .windsurf 等目录
|
|
1567
|
+
const detectedPlatforms = [];
|
|
1568
|
+
const checkDir = (d) => fs.existsSync(path.join(process.cwd(), d));
|
|
1569
|
+
if (checkDir('.cursor'))
|
|
1570
|
+
detectedPlatforms.push('cursor');
|
|
1571
|
+
if (checkDir('.vscode') || checkDir('.github'))
|
|
1572
|
+
detectedPlatforms.push('copilot');
|
|
1573
|
+
if (checkDir('.windsurf'))
|
|
1574
|
+
detectedPlatforms.push('windsurf');
|
|
1575
|
+
if (checkDir('.codebuddy'))
|
|
1576
|
+
detectedPlatforms.push('codebuddy');
|
|
1577
|
+
if (checkDir('.claude'))
|
|
1578
|
+
detectedPlatforms.push('claude-code');
|
|
1579
|
+
if (checkDir('.continue'))
|
|
1580
|
+
detectedPlatforms.push('continue');
|
|
1581
|
+
// 如果没有检测到任何编辑器,给出选项列表
|
|
1582
|
+
const ALL_PLATFORMS_SETUP = ['claude-code', 'cursor', 'copilot', 'codebuddy', 'windsurf', 'zed', 'jetbrains', 'continue', 'cline', 'lingma'];
|
|
1583
|
+
let chosenPlatform = options.platform ?? '';
|
|
1584
|
+
if (!chosenPlatform) {
|
|
1585
|
+
if (detectedPlatforms.length === 1 && isAuto) {
|
|
1586
|
+
chosenPlatform = detectedPlatforms[0];
|
|
1587
|
+
console.log(` ✅ 检测到 ${chosenPlatform},将自动配置`);
|
|
1588
|
+
}
|
|
1589
|
+
else if (detectedPlatforms.length > 0) {
|
|
1590
|
+
console.log(` 检测到以下编辑器:${detectedPlatforms.join(', ')}`);
|
|
1591
|
+
const detected = detectedPlatforms.join('/');
|
|
1592
|
+
if (isAuto) {
|
|
1593
|
+
chosenPlatform = detectedPlatforms[0];
|
|
1594
|
+
}
|
|
1595
|
+
else {
|
|
1596
|
+
const choice = await ask(isEn
|
|
1597
|
+
? ` Which editor? (${ALL_PLATFORMS_SETUP.join('|')}|all)`
|
|
1598
|
+
: ` 选择编辑器(${ALL_PLATFORMS_SETUP.join('|')}|all)`, detectedPlatforms[0]);
|
|
1599
|
+
chosenPlatform = choice || detectedPlatforms[0];
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
else {
|
|
1603
|
+
if (isAuto) {
|
|
1604
|
+
chosenPlatform = 'claude-code';
|
|
1605
|
+
}
|
|
1606
|
+
else {
|
|
1607
|
+
console.log(isEn ? ' No editor auto-detected. Common options:' : ' 未检测到编辑器,请选择:');
|
|
1608
|
+
ALL_PLATFORMS_SETUP.forEach((p, i) => console.log(` ${i + 1}. ${p}`));
|
|
1609
|
+
const choice = await ask(isEn ? ' Enter number or name' : ' 输入序号或名称', '1');
|
|
1610
|
+
const num = parseInt(choice, 10);
|
|
1611
|
+
chosenPlatform = (!isNaN(num) && num >= 1 && num <= ALL_PLATFORMS_SETUP.length)
|
|
1612
|
+
? ALL_PLATFORMS_SETUP[num - 1]
|
|
1613
|
+
: (choice || 'claude-code');
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
console.log(` → 目标平台:${chosenPlatform}\n`);
|
|
1618
|
+
// ── 步骤 2:角色配置 ──────────────────────────────────────────────────
|
|
1619
|
+
console.log(t.step2);
|
|
1620
|
+
const ROLE_PRESETS = {
|
|
1621
|
+
pm: { lang: 'zh', disabledSkills: ['unit-testing', 'docker', 'cicd', 'observability', 'data-pipeline', 'ml-experiment'] },
|
|
1622
|
+
qa: { lang: 'zh', disabledSkills: ['docker', 'cicd', 'ml-experiment', 'green-code', 'api-mock'] },
|
|
1623
|
+
design: { lang: 'zh', disabledSkills: ['unit-testing', 'docker', 'cicd', 'database-optimize', 'data-pipeline', 'ml-experiment', 'observability'] },
|
|
1624
|
+
dev: { lang: 'zh', disabledSkills: [] },
|
|
1625
|
+
};
|
|
1626
|
+
let chosenRole = options.role ?? '';
|
|
1627
|
+
if (!chosenRole && !isAuto) {
|
|
1628
|
+
console.log(isEn ? ' Your role:' : ' 你的角色:');
|
|
1629
|
+
console.log(' 1. dev - 开发工程师(启用所有 36 个 Skill)');
|
|
1630
|
+
console.log(' 2. qa - 测试工程师(测试、审查相关 Skill)');
|
|
1631
|
+
console.log(' 3. pm - 产品经理(需求、设计、周报相关 Skill)');
|
|
1632
|
+
console.log(' 4. design - 设计师(流程、文档类 Skill)');
|
|
1633
|
+
const roleChoice = await ask(isEn ? ' Select (1-4)' : ' 选择(1-4)', '1');
|
|
1634
|
+
const roleMap = { '1': 'dev', '2': 'qa', '3': 'pm', '4': 'design' };
|
|
1635
|
+
chosenRole = roleMap[roleChoice] ?? roleChoice ?? 'dev';
|
|
1636
|
+
}
|
|
1637
|
+
chosenRole = chosenRole || 'dev';
|
|
1638
|
+
console.log(` → 角色:${chosenRole}\n`);
|
|
1639
|
+
const preset = ROLE_PRESETS[chosenRole] ?? ROLE_PRESETS.dev;
|
|
1640
|
+
// 语言选择
|
|
1641
|
+
let chosenLang = preset.lang;
|
|
1642
|
+
if (!isAuto && !options.lang) {
|
|
1643
|
+
const langChoice = await ask(isEn ? ' Output language (zh/en)' : ' 输出语言(zh/en)', 'zh');
|
|
1644
|
+
chosenLang = langChoice === 'en' ? 'en' : 'zh';
|
|
1645
|
+
}
|
|
1646
|
+
rl.close();
|
|
1647
|
+
// 写入 .ethanrc.json
|
|
1648
|
+
const existingConfig = (0, config_1.readConfig)(process.cwd());
|
|
1649
|
+
const newConfig = {
|
|
1650
|
+
...existingConfig,
|
|
1651
|
+
lang: chosenLang,
|
|
1652
|
+
...(preset.disabledSkills.length > 0 ? { disabledSkills: preset.disabledSkills } : {}),
|
|
1653
|
+
setup: { role: chosenRole, platform: chosenPlatform, setupAt: new Date().toISOString() },
|
|
1654
|
+
};
|
|
1655
|
+
(0, config_1.writeConfig)(newConfig, process.cwd());
|
|
1656
|
+
console.log(` ✅ .ethanrc.json 已生成(角色:${chosenRole},语言:${chosenLang})`);
|
|
1657
|
+
// ── 步骤 3:生成编辑器快捷指令 ───────────────────────────────────────
|
|
1658
|
+
console.log(`\n${t.step3}`);
|
|
1659
|
+
const slashPlatforms = chosenPlatform === 'all' ? 'all' : chosenPlatform;
|
|
1660
|
+
// 动态调用 slash 命令逻辑(通过 execSync,保持 tty)
|
|
1661
|
+
const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
1662
|
+
try {
|
|
1663
|
+
execSync(`ethan slash --platform ${slashPlatforms} --dir "${process.cwd()}"`, { stdio: 'inherit' });
|
|
1664
|
+
}
|
|
1665
|
+
catch {
|
|
1666
|
+
// 如果 ethan 还未在全局安装(开发模式),尝试直接调用 ts-node
|
|
1667
|
+
console.log(isEn ? ' Note: Run "ethan slash" manually if above failed.' : ' 提示:如以上失败,请手动运行 ethan slash。');
|
|
1668
|
+
}
|
|
1669
|
+
// ── 完成 ─────────────────────────────────────────────────────────────
|
|
1670
|
+
console.log(`\n${'═'.repeat(52)}`);
|
|
1671
|
+
console.log(` ${t.done}`);
|
|
1672
|
+
console.log('═'.repeat(52));
|
|
1673
|
+
console.log(isEn ? '\nNext steps:' : '\n下一步:');
|
|
1674
|
+
if (chosenPlatform === 'claude-code') {
|
|
1675
|
+
console.log(isEn
|
|
1676
|
+
? ' 1. Restart Claude Code editor'
|
|
1677
|
+
: ' 1. 重启 Claude Code 编辑器');
|
|
1678
|
+
console.log(isEn
|
|
1679
|
+
? ' 2. Type /ethan- in chat to see all commands'
|
|
1680
|
+
: ' 2. 在聊天中输入 /ethan- 即可看到所有快捷指令');
|
|
1681
|
+
}
|
|
1682
|
+
else {
|
|
1683
|
+
console.log(isEn
|
|
1684
|
+
? ` 1. Open ethan-commands.md in your ${chosenPlatform} context`
|
|
1685
|
+
: ` 1. 将 ethan-commands.md 加入你的 ${chosenPlatform} 上下文`);
|
|
1686
|
+
console.log(isEn
|
|
1687
|
+
? ' 2. Type /ethan-code-review or @ethan code-review to start'
|
|
1688
|
+
: ' 2. 输入 /ethan-code-review 或 @ethan code-review 开始使用');
|
|
1689
|
+
}
|
|
1690
|
+
console.log(isEn
|
|
1691
|
+
? ' 3. Run "ethan agent run" for multi-agent collaboration'
|
|
1692
|
+
: ' 3. 运行 ethan agent run 体验多 Agent 协作');
|
|
1693
|
+
console.log('');
|
|
1694
|
+
});
|
|
1474
1695
|
// ─── workflow 命令(有状态一键工作流) ──────────────────────────────────────
|
|
1475
1696
|
const workflowCmd = program.command('workflow').description('有状态工作流执行:一键推进各阶段任务');
|
|
1476
1697
|
workflowCmd
|
|
@@ -3014,36 +3235,34 @@ memoryCmd
|
|
|
3014
3235
|
});
|
|
3015
3236
|
memoryCmd
|
|
3016
3237
|
.command('search <keyword>')
|
|
3017
|
-
.description('
|
|
3238
|
+
.description('在记忆库中全文检索(加权评分 + 片段高亮)')
|
|
3018
3239
|
.option('--global', '搜索全局记忆库')
|
|
3019
|
-
.option('--tag <tag>', '
|
|
3240
|
+
.option('--tag <tag>', '按标签过滤(AND 语义)')
|
|
3241
|
+
.option('--type <type>', '按类型过滤:workflow|skill|manual|decision|knowledge')
|
|
3020
3242
|
.option('-n, --limit <n>', '最多显示 N 条', '10')
|
|
3021
|
-
.action((keyword, options) => {
|
|
3022
|
-
const
|
|
3023
|
-
const
|
|
3024
|
-
const
|
|
3025
|
-
const
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
e.tags.some((t) => t.toLowerCase().includes(kw));
|
|
3030
|
-
const matchTag = options.tag ? e.tags.includes(options.tag) : true;
|
|
3031
|
-
return matchKw && matchTag;
|
|
3243
|
+
.action(async (keyword, options) => {
|
|
3244
|
+
const { searchMemory, getMemoryDir: getMemDir } = await Promise.resolve().then(() => __importStar(require('../memory/index')));
|
|
3245
|
+
const dir = getMemDir(!!options.global);
|
|
3246
|
+
const limit = parseInt(options.limit ?? '10', 10) || 10;
|
|
3247
|
+
const results = searchMemory(keyword, dir, {
|
|
3248
|
+
tags: options.tag ? [options.tag] : undefined,
|
|
3249
|
+
type: options.type,
|
|
3250
|
+
limit,
|
|
3032
3251
|
});
|
|
3033
|
-
results = results.slice(0, limit);
|
|
3034
3252
|
if (results.length === 0) {
|
|
3035
3253
|
console.log(`\n🔍 未找到匹配 "${keyword}" 的记忆\n`);
|
|
3254
|
+
console.log(' 💡 尝试更宽泛的关键词,或用 ethan memory list 查看所有记忆\n');
|
|
3036
3255
|
return;
|
|
3037
3256
|
}
|
|
3038
3257
|
console.log(`\n🔍 找到 ${results.length} 条记忆(关键词:"${keyword}")\n`);
|
|
3039
|
-
console.log('─'.repeat(
|
|
3040
|
-
for (const e of results) {
|
|
3041
|
-
|
|
3042
|
-
console.log(
|
|
3043
|
-
console.log(`
|
|
3044
|
-
console.log(`
|
|
3258
|
+
console.log('─'.repeat(70));
|
|
3259
|
+
for (const { entry: e, score, matchedFields, snippet } of results) {
|
|
3260
|
+
console.log(`\n 📌 [${e.type}] ${e.title}`);
|
|
3261
|
+
console.log(` ID: ${e.id} | ${e.createdAt.slice(0, 10)} | 相关度: ${score} | 命中: ${matchedFields.join(', ')}`);
|
|
3262
|
+
console.log(` 标签:${e.tags.join(', ') || '无'}`);
|
|
3263
|
+
console.log(` 摘要:${snippet}`);
|
|
3045
3264
|
}
|
|
3046
|
-
console.log('\n' + '─'.repeat(
|
|
3265
|
+
console.log('\n' + '─'.repeat(70));
|
|
3047
3266
|
console.log(`\n💡 用 ethan memory show <id> 查看完整内容\n`);
|
|
3048
3267
|
});
|
|
3049
3268
|
memoryCmd
|
|
@@ -5063,5 +5282,67 @@ agentCmd
|
|
|
5063
5282
|
console.log(` ethan agent run --context "任务" # 在编排中使用此 Agent`);
|
|
5064
5283
|
console.log('');
|
|
5065
5284
|
});
|
|
5285
|
+
// ─── extension 命令(事件钩子 + Webhook 扩展)─────────────────────────────────
|
|
5286
|
+
const extCmd = program
|
|
5287
|
+
.command('extension')
|
|
5288
|
+
.alias('ext')
|
|
5289
|
+
.description('扩展管理:事件钩子、Webhook 集成、Extension SDK');
|
|
5290
|
+
extCmd
|
|
5291
|
+
.command('list')
|
|
5292
|
+
.description('查看当前项目的钩子和 Webhook 配置')
|
|
5293
|
+
.action(async () => {
|
|
5294
|
+
const { readExtensionsConfig } = await Promise.resolve().then(() => __importStar(require('../extension/index')));
|
|
5295
|
+
const cfg = readExtensionsConfig(process.cwd());
|
|
5296
|
+
console.log('\n🔌 Ethan 扩展配置\n');
|
|
5297
|
+
console.log('─'.repeat(50));
|
|
5298
|
+
console.log(`\n钩子文件(${cfg.hooks.length} 个):`);
|
|
5299
|
+
if (cfg.hooks.length === 0)
|
|
5300
|
+
console.log(' (无)');
|
|
5301
|
+
cfg.hooks.forEach((h) => console.log(` ${h.enabled ? '✅' : '⏸️ '} ${h.file}`));
|
|
5302
|
+
console.log(`\nWebhook(${cfg.webhooks.length} 个):`);
|
|
5303
|
+
if (cfg.webhooks.length === 0)
|
|
5304
|
+
console.log(' (无)');
|
|
5305
|
+
cfg.webhooks.forEach((w) => console.log(` ${w.enabled ? '✅' : '⏸️ '} ${w.url} [${w.events.join(', ')}]`));
|
|
5306
|
+
console.log('');
|
|
5307
|
+
});
|
|
5308
|
+
extCmd
|
|
5309
|
+
.command('hook-init [name]')
|
|
5310
|
+
.description('在 .ethan/hooks/ 生成示例钩子文件')
|
|
5311
|
+
.action(async (name) => {
|
|
5312
|
+
const { generateHookTemplate } = await Promise.resolve().then(() => __importStar(require('../extension/index')));
|
|
5313
|
+
const hookName = name || 'my-hook';
|
|
5314
|
+
const file = generateHookTemplate(process.cwd(), hookName);
|
|
5315
|
+
console.log(`\n✅ 钩子文件已生成:${file}`);
|
|
5316
|
+
console.log('\n支持的事件:before:skill | after:skill | before:pipeline | after:pipeline | workflow:done | memory:save\n');
|
|
5317
|
+
});
|
|
5318
|
+
extCmd
|
|
5319
|
+
.command('webhook-add <url>')
|
|
5320
|
+
.description('添加 Webhook(在工作流事件后推送通知)')
|
|
5321
|
+
.option('--events <events>', '监听事件(逗号分隔)', 'after:skill,workflow:done')
|
|
5322
|
+
.option('--secret <secret>', 'HMAC 签名密钥(可选)')
|
|
5323
|
+
.action(async (url, opts) => {
|
|
5324
|
+
const { readExtensionsConfig, writeExtensionsConfig } = await Promise.resolve().then(() => __importStar(require('../extension/index')));
|
|
5325
|
+
const cfg = readExtensionsConfig(process.cwd());
|
|
5326
|
+
const events = opts.events.split(',').map((e) => e.trim());
|
|
5327
|
+
cfg.webhooks.push({ url, events, secret: opts.secret, enabled: true, headers: {} });
|
|
5328
|
+
writeExtensionsConfig(cfg, process.cwd());
|
|
5329
|
+
console.log(`\n✅ Webhook 已添加:${url}`);
|
|
5330
|
+
console.log(` 监听事件:${events.join(', ')}\n`);
|
|
5331
|
+
});
|
|
5332
|
+
extCmd
|
|
5333
|
+
.command('webhook-remove <url>')
|
|
5334
|
+
.description('移除 Webhook')
|
|
5335
|
+
.action(async (url) => {
|
|
5336
|
+
const { readExtensionsConfig, writeExtensionsConfig } = await Promise.resolve().then(() => __importStar(require('../extension/index')));
|
|
5337
|
+
const cfg = readExtensionsConfig(process.cwd());
|
|
5338
|
+
const before = cfg.webhooks.length;
|
|
5339
|
+
cfg.webhooks = cfg.webhooks.filter((w) => w.url !== url);
|
|
5340
|
+
if (cfg.webhooks.length === before) {
|
|
5341
|
+
console.error(`\n❌ 未找到 Webhook: ${url}\n`);
|
|
5342
|
+
process.exit(1);
|
|
5343
|
+
}
|
|
5344
|
+
writeExtensionsConfig(cfg, process.cwd());
|
|
5345
|
+
console.log(`\n✅ Webhook 已移除:${url}\n`);
|
|
5346
|
+
});
|
|
5066
5347
|
program.parse(process.argv);
|
|
5067
5348
|
//# sourceMappingURL=index.js.map
|