run-refine-acceptance.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { createDirectory, readFile, writeFile } from "@/commands/fs"
  2. import { hasOutlineForRefinement, generateOutlineRefinementFiles } from "@/lib/novel/outline-generation"
  3. import { useWikiStore, type LlmConfig } from "@/stores/wiki-store"
  4. const PROJECT_PATH = "/acceptance-refine-project"
  5. const OUTLINES_DIR = `${PROJECT_PATH}/wiki/outlines`
  6. const OUTLINE_PATH = `${OUTLINES_DIR}/story-outline.md`
  7. const IMPORTED_OUTLINE = [
  8. "---",
  9. "type: outline",
  10. 'title: "导入示例总纲"',
  11. "---",
  12. "",
  13. "# 导入示例总纲",
  14. "",
  15. "## 故事核心",
  16. "- 主角因旧案回到故乡,卷入多方势力争夺。",
  17. "",
  18. "## 卷一目标",
  19. "- 查明第一起失踪案的真实动机。",
  20. "",
  21. "## 卷二目标",
  22. "- 揭示幕后组织与主角家族的关联。",
  23. "",
  24. "## 长线伏笔",
  25. "- 失踪名单中的同姓者身份。",
  26. "- 夜潮会账本缺页来源。",
  27. "",
  28. ].join("\n")
  29. const llmConfig: LlmConfig = {
  30. provider: "custom",
  31. apiKey: "",
  32. model: "mock-refine-model",
  33. ollamaUrl: "http://127.0.0.1:11434",
  34. customEndpoint: "http://127.0.0.1:18080",
  35. maxContextSize: 131072,
  36. apiMode: "chat_completions",
  37. reasoning: { mode: "off" },
  38. }
  39. async function main() {
  40. console.log("[accept] start")
  41. useWikiStore.getState().setNovelMode(true)
  42. await createDirectory(OUTLINES_DIR)
  43. await writeFile(OUTLINE_PATH, IMPORTED_OUTLINE)
  44. console.log("[accept] outline imported:", OUTLINE_PATH)
  45. const canRefine = await hasOutlineForRefinement(PROJECT_PATH)
  46. console.log("[accept] hasOutlineForRefinement:", canRefine)
  47. if (!canRefine) {
  48. throw new Error("Outline import check failed: hasOutlineForRefinement=false")
  49. }
  50. console.log("[accept] submit refine generation ...")
  51. const result = await generateOutlineRefinementFiles(
  52. PROJECT_PATH,
  53. llmConfig,
  54. "请基于已有总纲,细化第一卷章节推进,并补全人物、组织、能力体系、伏笔与地点设定。",
  55. )
  56. console.log("[accept] refine generated:", result.writtenPaths.length)
  57. const written = await Promise.all(
  58. result.writtenPaths.map(async (path) => {
  59. const content = await readFile(path)
  60. const firstLine = content.split("\n").find((line) => line.trim().length > 0) ?? ""
  61. return { path, firstLine, length: content.length }
  62. }),
  63. )
  64. console.log(JSON.stringify({
  65. projectPath: PROJECT_PATH,
  66. importedOutline: OUTLINE_PATH,
  67. primaryPath: result.primaryPath,
  68. writtenCount: result.writtenPaths.length,
  69. written,
  70. }, null, 2))
  71. }
  72. main().catch((error) => {
  73. console.error(error instanceof Error ? error.stack ?? error.message : String(error))
  74. process.exit(1)
  75. })