compose.ts 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. import { Command } from "commander";
  2. import { PipelineRunner } from "@actalk/inkos-core";
  3. import { buildPipelineConfig, findProjectRoot, loadConfig, log, logError, resolveBookId, resolveContext } from "../utils.js";
  4. export const composeCommand = new Command("compose")
  5. .description("Compose chapter runtime artifacts");
  6. composeCommand
  7. .command("chapter")
  8. .description("Generate context/rule-stack/trace artifacts for the next chapter")
  9. .argument("[book-id]", "Book ID (auto-detected if only one book)")
  10. .option("--context <text>", "Chapter steering guidance")
  11. .option("--context-file <path>", "Read guidance from file")
  12. .option("--json", "Output JSON")
  13. .option("-q, --quiet", "Suppress console output")
  14. .action(async (bookIdArg: string | undefined, opts) => {
  15. try {
  16. const config = await loadConfig({ requireApiKey: false });
  17. const root = findProjectRoot();
  18. const bookId = await resolveBookId(bookIdArg, root);
  19. const context = await resolveContext(opts);
  20. const pipeline = new PipelineRunner(
  21. buildPipelineConfig(config, root, {
  22. externalContext: context,
  23. inputGovernanceMode: "v2",
  24. quiet: opts.quiet,
  25. }),
  26. );
  27. const result = await pipeline.composeChapter(bookId, context);
  28. if (opts.json) {
  29. log(JSON.stringify(result, null, 2));
  30. } else {
  31. log(`Composed chapter ${result.chapterNumber} for "${bookId}"`);
  32. log(` Intent: ${result.intentPath}`);
  33. log(` Context: ${result.contextPath}`);
  34. log(` Rule stack: ${result.ruleStackPath}`);
  35. log(` Trace: ${result.tracePath}`);
  36. }
  37. } catch (e) {
  38. if (opts.json) {
  39. log(JSON.stringify({ error: String(e) }));
  40. } else {
  41. logError(`Failed to compose chapter: ${e}`);
  42. }
  43. process.exit(1);
  44. }
  45. });