draft.ts 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. import { Command } from "commander";
  2. import { PipelineRunner } from "@actalk/inkos-core";
  3. import { loadConfig, buildPipelineConfig, findProjectRoot, resolveContext, resolveBookId, log, logError } from "../utils.js";
  4. export const draftCommand = new Command("draft")
  5. .description("Write a draft chapter (no audit/revise)")
  6. .argument("[book-id]", "Book ID (auto-detected if only one book)")
  7. .option("--words <n>", "Words per chapter (overrides book config)")
  8. .option("--context <text>", "Creative guidance (natural language)")
  9. .option("--context-file <path>", "Read guidance from file")
  10. .option("--json", "Output JSON")
  11. .option("-q, --quiet", "Suppress console output")
  12. .action(async (bookIdArg: string | undefined, opts) => {
  13. try {
  14. const config = await loadConfig();
  15. const root = findProjectRoot();
  16. const bookId = await resolveBookId(bookIdArg, root);
  17. const context = await resolveContext(opts);
  18. const pipeline = new PipelineRunner(buildPipelineConfig(config, root, { quiet: opts.quiet }));
  19. const wordCount = opts.words ? parseInt(opts.words, 10) : undefined;
  20. if (!opts.json) log(`Writing draft for "${bookId}"...`);
  21. const result = await pipeline.writeDraft(bookId, context, wordCount);
  22. if (opts.json) {
  23. log(JSON.stringify(result, null, 2));
  24. } else {
  25. log(` Chapter ${result.chapterNumber}: ${result.title}`);
  26. log(` Words: ${result.wordCount}`);
  27. log(` File: ${result.filePath}`);
  28. }
  29. } catch (e) {
  30. if (opts.json) {
  31. log(JSON.stringify({ error: String(e) }));
  32. } else {
  33. logError(`Failed to write draft: ${e}`);
  34. }
  35. process.exit(1);
  36. }
  37. });