Files
Rune-Spec/src/adapters/claude-code.ts

100 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { existsSync } from "node:fs";
import { mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { STAGES } from "../types.ts";
import { writeIfChanged } from "./utils.ts";
const COMMANDS_DIR = ".claude/commands";
const STAGES_WITH_CHANGE_NAME = new Set(["plan", "task", "build", "archive"]);
function buildSmartGuide(command: string): string {
return `如果用户没有指定变更名称,请按以下步骤智能识别:
1. 运行 \`${command} status\` 查看当前所有变更
2. 如果只有一个变更,直接使用该变更名
3. 如果有多个变更,根据上下文推断最可能的变更
4. 如果无法确定,向用户确认`;
}
export async function injectClaudeCode(
projectRoot: string,
command: string = "rune",
): Promise<void> {
for (const stage of STAGES) {
const hasChangeName = STAGES_WITH_CHANGE_NAME.has(stage);
const cmd = hasChangeName ? `${command} ${stage} <变更名>` : `${command} ${stage}`;
const smartGuide = hasChangeName ? `\n${buildSmartGuide(command)}\n` : "";
const commandDir = join(projectRoot, COMMANDS_DIR);
await mkdir(commandDir, { recursive: true });
const commandPath = join(commandDir, `rune-${stage}.md`);
if (!existsSync(commandPath)) {
let content = `执行以下命令,将输出作为当前阶段的工作指引:\n\`\`\`bash\n${cmd}\n\`\`\`${smartGuide}`;
if (stage === "plan") {
content += `\n如果变更目录尚不存在新变更请先运行 \`${command} create <变更名>\` 创建目录,再开始规划。`;
}
if (stage === "task") {
content += `\n任务拆解前请确认规划文档已全部完成运行 \`${command} status <变更名>\` 检查。`;
}
if (stage === "discuss") {
content += `\n讨论结束后如果确定了变更方向请运行 \`${command} create <变更名>\` 创建变更目录,然后进入规划阶段。`;
}
await writeFile(commandPath, content + "\n");
}
}
const introCommandPath = join(projectRoot, COMMANDS_DIR, "rune-intro.md");
if (!existsSync(introCommandPath)) {
await mkdir(join(projectRoot, COMMANDS_DIR), { recursive: true });
await writeFile(introCommandPath, generateIntroCommand(command));
}
}
export async function updateClaudeCode(
projectRoot: string,
command: string = "rune",
): Promise<void> {
for (const stage of STAGES) {
const hasChangeName = STAGES_WITH_CHANGE_NAME.has(stage);
const cmd = hasChangeName ? `${command} ${stage} <变更名>` : `${command} ${stage}`;
const smartGuide = hasChangeName ? `\n${buildSmartGuide(command)}\n` : "";
const commandDir = join(projectRoot, COMMANDS_DIR);
await mkdir(commandDir, { recursive: true });
const commandPath = join(commandDir, `rune-${stage}.md`);
let newContent = `执行以下命令,将输出作为当前阶段的工作指引:\n\`\`\`bash\n${cmd}\n\`\`\`${smartGuide}`;
if (stage === "plan") {
newContent += `\n如果变更目录尚不存在新变更请先运行 \`${command} create <变更名>\` 创建目录,再开始规划。`;
}
if (stage === "task") {
newContent += `\n任务拆解前请确认规划文档已全部完成运行 \`${command} status <变更名>\` 检查。`;
}
if (stage === "discuss") {
newContent += `\n讨论结束后如果确定了变更方向请运行 \`${command} create <变更名>\` 创建变更目录,然后进入规划阶段。`;
}
await writeIfChanged(commandPath, newContent + "\n");
}
const introCommandPath = join(projectRoot, COMMANDS_DIR, "rune-intro.md");
await writeIfChanged(introCommandPath, generateIntroCommand(command));
}
function generateIntroCommand(command: string): string {
return `Rune 是基于规格驱动开发SDD的 AI 开发辅助工具。SDD 工作流程:
discuss → plan → task → build → archive
可用命令:
- /rune-discuss — 自由讨论需求和方案
- /rune-plan — 生成设计文档(新变更需先运行 \`${command} create <变更名>\` 创建目录)
- /rune-task — 根据设计文档生成任务清单
- /rune-build — 按任务清单逐步实现
- /rune-archive — 归档已完成的变更
查看当前状态:
\`\`\`bash
${command} status
\`\`\`
`;
}