diff --git a/src/core/assembler.ts b/src/core/assembler.ts index 22dd300..9ed6c1f 100644 --- a/src/core/assembler.ts +++ b/src/core/assembler.ts @@ -4,7 +4,7 @@ import { join } from "node:path"; import type { RuneConfig } from "../types.ts"; import { CommandError } from "../cli/errors.ts"; import { getChangeDir } from "./config.ts"; -import { parseTasks, validateTaskFormat } from "./task-parser.ts"; +import { parseTasks, validateTaskFormat, TaskFormatError } from "./task-parser.ts"; import { applyCommandPrefix, getPmPrefix } from "./pm.ts"; export function assembleDiscussPrompt(config: RuneConfig): string { @@ -100,7 +100,16 @@ export async function assembleBuildPrompt( }); } - validateTaskFormat(taskContent); + try { + validateTaskFormat(taskContent); + } catch (e) { + if (e instanceof TaskFormatError) { + throw new CommandError(e.message, { + hint: `请确保 ${taskPath} 中包含格式正确的 checkbox 任务项(如 - [ ] 任务描述)`, + }); + } + throw e; + } const tasks = parseTasks(taskContent); const pendingTasks = tasks.filter((t) => !t.checked); diff --git a/tests/core/assembler.test.ts b/tests/core/assembler.test.ts index 936e7b9..e281c20 100644 --- a/tests/core/assembler.test.ts +++ b/tests/core/assembler.test.ts @@ -179,6 +179,7 @@ describe("assembleBuildPrompt", () => { } catch (e: any) { expect(e.message).toContain("task.md"); expect(e.message).toContain("checkbox"); + expect(e.hint).toBeTruthy(); } }); @@ -195,6 +196,7 @@ describe("assembleBuildPrompt", () => { expect.unreachable(); } catch (e: any) { expect(e.message).toContain("checkbox"); + expect(e.hint).toBeTruthy(); } }); });