llm-content-creator 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (438) hide show
  1. package/README.md +309 -0
  2. package/dist/application/workflow/SyncExecutor.d.ts +75 -0
  3. package/dist/application/workflow/SyncExecutor.d.ts.map +1 -0
  4. package/dist/application/workflow/SyncExecutor.js +370 -0
  5. package/dist/application/workflow/SyncExecutor.js.map +1 -0
  6. package/dist/application/workflow/types.d.ts +46 -0
  7. package/dist/application/workflow/types.d.ts.map +1 -0
  8. package/dist/application/workflow/types.js +7 -0
  9. package/dist/application/workflow/types.js.map +1 -0
  10. package/dist/config/index.d.ts +173 -0
  11. package/dist/config/index.d.ts.map +1 -0
  12. package/dist/config/index.js +288 -0
  13. package/dist/config/index.js.map +1 -0
  14. package/dist/domain/entities/QualityCheck.d.ts +181 -0
  15. package/dist/domain/entities/QualityCheck.d.ts.map +1 -0
  16. package/dist/domain/entities/QualityCheck.js +39 -0
  17. package/dist/domain/entities/QualityCheck.js.map +1 -0
  18. package/dist/domain/entities/Result.d.ts +103 -0
  19. package/dist/domain/entities/Result.d.ts.map +1 -0
  20. package/dist/domain/entities/Result.js +15 -0
  21. package/dist/domain/entities/Result.js.map +1 -0
  22. package/dist/domain/entities/Task.d.ts +130 -0
  23. package/dist/domain/entities/Task.d.ts.map +1 -0
  24. package/dist/domain/entities/Task.js +64 -0
  25. package/dist/domain/entities/Task.js.map +1 -0
  26. package/dist/domain/entities/TaskStep.d.ts +160 -0
  27. package/dist/domain/entities/TaskStep.d.ts.map +1 -0
  28. package/dist/domain/entities/TaskStep.js +30 -0
  29. package/dist/domain/entities/TaskStep.js.map +1 -0
  30. package/dist/domain/entities/TokenUsage.d.ts +70 -0
  31. package/dist/domain/entities/TokenUsage.d.ts.map +1 -0
  32. package/dist/domain/entities/TokenUsage.js +42 -0
  33. package/dist/domain/entities/TokenUsage.js.map +1 -0
  34. package/dist/domain/entities/index.d.ts +11 -0
  35. package/dist/domain/entities/index.d.ts.map +1 -0
  36. package/dist/domain/entities/index.js +16 -0
  37. package/dist/domain/entities/index.js.map +1 -0
  38. package/dist/domain/repositories/QualityCheckRepository.d.ts +49 -0
  39. package/dist/domain/repositories/QualityCheckRepository.d.ts.map +1 -0
  40. package/dist/domain/repositories/QualityCheckRepository.js +5 -0
  41. package/dist/domain/repositories/QualityCheckRepository.js.map +1 -0
  42. package/dist/domain/repositories/ResultRepository.d.ts +43 -0
  43. package/dist/domain/repositories/ResultRepository.d.ts.map +1 -0
  44. package/dist/domain/repositories/ResultRepository.js +5 -0
  45. package/dist/domain/repositories/ResultRepository.js.map +1 -0
  46. package/dist/domain/repositories/TaskRepository.d.ts +240 -0
  47. package/dist/domain/repositories/TaskRepository.d.ts.map +1 -0
  48. package/dist/domain/repositories/TaskRepository.js +7 -0
  49. package/dist/domain/repositories/TaskRepository.js.map +1 -0
  50. package/dist/domain/workflow/CheckpointManager.d.ts +94 -0
  51. package/dist/domain/workflow/CheckpointManager.d.ts.map +1 -0
  52. package/dist/domain/workflow/CheckpointManager.js +224 -0
  53. package/dist/domain/workflow/CheckpointManager.js.map +1 -0
  54. package/dist/domain/workflow/ContentCreatorGraph.d.ts +17 -0
  55. package/dist/domain/workflow/ContentCreatorGraph.d.ts.map +1 -0
  56. package/dist/domain/workflow/ContentCreatorGraph.js +381 -0
  57. package/dist/domain/workflow/ContentCreatorGraph.js.map +1 -0
  58. package/dist/domain/workflow/State.d.ts +172 -0
  59. package/dist/domain/workflow/State.d.ts.map +1 -0
  60. package/dist/domain/workflow/State.js +184 -0
  61. package/dist/domain/workflow/State.js.map +1 -0
  62. package/dist/domain/workflow/index.d.ts +11 -0
  63. package/dist/domain/workflow/index.d.ts.map +1 -0
  64. package/dist/domain/workflow/index.js +15 -0
  65. package/dist/domain/workflow/index.js.map +1 -0
  66. package/dist/domain/workflow/nodes/BaseNode.d.ts +134 -0
  67. package/dist/domain/workflow/nodes/BaseNode.d.ts.map +1 -0
  68. package/dist/domain/workflow/nodes/BaseNode.js +253 -0
  69. package/dist/domain/workflow/nodes/BaseNode.js.map +1 -0
  70. package/dist/domain/workflow/nodes/CheckImageNode.d.ts +43 -0
  71. package/dist/domain/workflow/nodes/CheckImageNode.d.ts.map +1 -0
  72. package/dist/domain/workflow/nodes/CheckImageNode.js +254 -0
  73. package/dist/domain/workflow/nodes/CheckImageNode.js.map +1 -0
  74. package/dist/domain/workflow/nodes/CheckTextNode.d.ts +66 -0
  75. package/dist/domain/workflow/nodes/CheckTextNode.d.ts.map +1 -0
  76. package/dist/domain/workflow/nodes/CheckTextNode.js +530 -0
  77. package/dist/domain/workflow/nodes/CheckTextNode.js.map +1 -0
  78. package/dist/domain/workflow/nodes/GenerateImageNode.d.ts +44 -0
  79. package/dist/domain/workflow/nodes/GenerateImageNode.d.ts.map +1 -0
  80. package/dist/domain/workflow/nodes/GenerateImageNode.js +272 -0
  81. package/dist/domain/workflow/nodes/GenerateImageNode.js.map +1 -0
  82. package/dist/domain/workflow/nodes/OrganizeNode.d.ts +49 -0
  83. package/dist/domain/workflow/nodes/OrganizeNode.d.ts.map +1 -0
  84. package/dist/domain/workflow/nodes/OrganizeNode.js +241 -0
  85. package/dist/domain/workflow/nodes/OrganizeNode.js.map +1 -0
  86. package/dist/domain/workflow/nodes/SearchNode.d.ts +48 -0
  87. package/dist/domain/workflow/nodes/SearchNode.d.ts.map +1 -0
  88. package/dist/domain/workflow/nodes/SearchNode.js +151 -0
  89. package/dist/domain/workflow/nodes/SearchNode.js.map +1 -0
  90. package/dist/domain/workflow/nodes/WriteNode.d.ts +68 -0
  91. package/dist/domain/workflow/nodes/WriteNode.d.ts.map +1 -0
  92. package/dist/domain/workflow/nodes/WriteNode.js +431 -0
  93. package/dist/domain/workflow/nodes/WriteNode.js.map +1 -0
  94. package/dist/domain/workflow/nodes/config/index.js +287 -0
  95. package/dist/domain/workflow/nodes/domain/entities/Task.js +68 -0
  96. package/dist/domain/workflow/nodes/domain/workflow/State.js +200 -0
  97. package/dist/domain/workflow/nodes/domain/workflow/nodes/BaseNode.js +328 -0
  98. package/dist/domain/workflow/nodes/domain/workflow/nodes/CheckTextNode.js +500 -0
  99. package/dist/domain/workflow/nodes/index.d.ts +13 -0
  100. package/dist/domain/workflow/nodes/index.d.ts.map +1 -0
  101. package/dist/domain/workflow/nodes/index.js +13 -0
  102. package/dist/domain/workflow/nodes/index.js.map +1 -0
  103. package/dist/domain/workflow/nodes/infrastructure/logging/logger.js +275 -0
  104. package/dist/domain/workflow/nodes/services/llm/EnhancedLLMService.js +559 -0
  105. package/dist/index.d.ts +24 -0
  106. package/dist/index.d.ts.map +1 -0
  107. package/dist/index.js +34 -0
  108. package/dist/index.js.map +1 -0
  109. package/dist/infrastructure/cache/CacheService.d.ts +139 -0
  110. package/dist/infrastructure/cache/CacheService.d.ts.map +1 -0
  111. package/dist/infrastructure/cache/CacheService.js +419 -0
  112. package/dist/infrastructure/cache/CacheService.js.map +1 -0
  113. package/dist/infrastructure/cache/index.d.ts +5 -0
  114. package/dist/infrastructure/cache/index.d.ts.map +1 -0
  115. package/dist/infrastructure/cache/index.js +6 -0
  116. package/dist/infrastructure/cache/index.js.map +1 -0
  117. package/dist/infrastructure/database/BaseRepository.d.ts +98 -0
  118. package/dist/infrastructure/database/BaseRepository.d.ts.map +1 -0
  119. package/dist/infrastructure/database/BaseRepository.js +178 -0
  120. package/dist/infrastructure/database/BaseRepository.js.map +1 -0
  121. package/dist/infrastructure/database/MemoryTaskRepository.d.ts +77 -0
  122. package/dist/infrastructure/database/MemoryTaskRepository.d.ts.map +1 -0
  123. package/dist/infrastructure/database/MemoryTaskRepository.js +309 -0
  124. package/dist/infrastructure/database/MemoryTaskRepository.js.map +1 -0
  125. package/dist/infrastructure/database/PostgresQualityCheckRepository.d.ts +36 -0
  126. package/dist/infrastructure/database/PostgresQualityCheckRepository.d.ts.map +1 -0
  127. package/dist/infrastructure/database/PostgresQualityCheckRepository.js +89 -0
  128. package/dist/infrastructure/database/PostgresQualityCheckRepository.js.map +1 -0
  129. package/dist/infrastructure/database/PostgresTaskRepository.d.ts +94 -0
  130. package/dist/infrastructure/database/PostgresTaskRepository.d.ts.map +1 -0
  131. package/dist/infrastructure/database/PostgresTaskRepository.js +364 -0
  132. package/dist/infrastructure/database/PostgresTaskRepository.js.map +1 -0
  133. package/dist/infrastructure/database/ResultRepository.d.ts +41 -0
  134. package/dist/infrastructure/database/ResultRepository.d.ts.map +1 -0
  135. package/dist/infrastructure/database/ResultRepository.js +86 -0
  136. package/dist/infrastructure/database/ResultRepository.js.map +1 -0
  137. package/dist/infrastructure/database/SQLiteTaskRepository.d.ts +101 -0
  138. package/dist/infrastructure/database/SQLiteTaskRepository.d.ts.map +1 -0
  139. package/dist/infrastructure/database/SQLiteTaskRepository.js +548 -0
  140. package/dist/infrastructure/database/SQLiteTaskRepository.js.map +1 -0
  141. package/dist/infrastructure/database/index.d.ts +32 -0
  142. package/dist/infrastructure/database/index.d.ts.map +1 -0
  143. package/dist/infrastructure/database/index.js +72 -0
  144. package/dist/infrastructure/database/index.js.map +1 -0
  145. package/dist/infrastructure/logging/logger.d.ts +69 -0
  146. package/dist/infrastructure/logging/logger.d.ts.map +1 -0
  147. package/dist/infrastructure/logging/logger.js +169 -0
  148. package/dist/infrastructure/logging/logger.js.map +1 -0
  149. package/dist/infrastructure/monitoring/LoggingService.d.ts +109 -0
  150. package/dist/infrastructure/monitoring/LoggingService.d.ts.map +1 -0
  151. package/dist/infrastructure/monitoring/LoggingService.js +198 -0
  152. package/dist/infrastructure/monitoring/LoggingService.js.map +1 -0
  153. package/dist/infrastructure/monitoring/MetricsService.d.ts +112 -0
  154. package/dist/infrastructure/monitoring/MetricsService.d.ts.map +1 -0
  155. package/dist/infrastructure/monitoring/MetricsService.js +362 -0
  156. package/dist/infrastructure/monitoring/MetricsService.js.map +1 -0
  157. package/dist/infrastructure/monitoring/SentryService.d.ts +108 -0
  158. package/dist/infrastructure/monitoring/SentryService.d.ts.map +1 -0
  159. package/dist/infrastructure/monitoring/SentryService.js +282 -0
  160. package/dist/infrastructure/monitoring/SentryService.js.map +1 -0
  161. package/dist/infrastructure/monitoring/index.d.ts +7 -0
  162. package/dist/infrastructure/monitoring/index.d.ts.map +1 -0
  163. package/dist/infrastructure/monitoring/index.js +10 -0
  164. package/dist/infrastructure/monitoring/index.js.map +1 -0
  165. package/dist/infrastructure/queue/TaskQueue.d.ts +110 -0
  166. package/dist/infrastructure/queue/TaskQueue.d.ts.map +1 -0
  167. package/dist/infrastructure/queue/TaskQueue.js +363 -0
  168. package/dist/infrastructure/queue/TaskQueue.js.map +1 -0
  169. package/dist/infrastructure/queue/index.d.ts +5 -0
  170. package/dist/infrastructure/queue/index.d.ts.map +1 -0
  171. package/dist/infrastructure/queue/index.js +5 -0
  172. package/dist/infrastructure/queue/index.js.map +1 -0
  173. package/dist/infrastructure/redis/connection.d.ts +61 -0
  174. package/dist/infrastructure/redis/connection.d.ts.map +1 -0
  175. package/dist/infrastructure/redis/connection.js +184 -0
  176. package/dist/infrastructure/redis/connection.js.map +1 -0
  177. package/dist/infrastructure/redis/index.d.ts +5 -0
  178. package/dist/infrastructure/redis/index.d.ts.map +1 -0
  179. package/dist/infrastructure/redis/index.js +5 -0
  180. package/dist/infrastructure/redis/index.js.map +1 -0
  181. package/dist/infrastructure/security/ApiKeyService.d.ts +103 -0
  182. package/dist/infrastructure/security/ApiKeyService.d.ts.map +1 -0
  183. package/dist/infrastructure/security/ApiKeyService.js +250 -0
  184. package/dist/infrastructure/security/ApiKeyService.js.map +1 -0
  185. package/dist/infrastructure/security/QuotaService.d.ts +87 -0
  186. package/dist/infrastructure/security/QuotaService.d.ts.map +1 -0
  187. package/dist/infrastructure/security/QuotaService.js +303 -0
  188. package/dist/infrastructure/security/QuotaService.js.map +1 -0
  189. package/dist/infrastructure/security/RateLimiter.d.ts +104 -0
  190. package/dist/infrastructure/security/RateLimiter.d.ts.map +1 -0
  191. package/dist/infrastructure/security/RateLimiter.js +331 -0
  192. package/dist/infrastructure/security/RateLimiter.js.map +1 -0
  193. package/dist/infrastructure/security/index.d.ts +7 -0
  194. package/dist/infrastructure/security/index.d.ts.map +1 -0
  195. package/dist/infrastructure/security/index.js +10 -0
  196. package/dist/infrastructure/security/index.js.map +1 -0
  197. package/dist/monitoring/index.d.ts +5 -0
  198. package/dist/monitoring/index.d.ts.map +1 -0
  199. package/dist/monitoring/index.js +5 -0
  200. package/dist/monitoring/index.js.map +1 -0
  201. package/dist/monitoring/server.d.ts +14 -0
  202. package/dist/monitoring/server.d.ts.map +1 -0
  203. package/dist/monitoring/server.js +99 -0
  204. package/dist/monitoring/server.js.map +1 -0
  205. package/dist/presentation/cli/commands/cancel.d.ts +8 -0
  206. package/dist/presentation/cli/commands/cancel.d.ts.map +1 -0
  207. package/dist/presentation/cli/commands/cancel.js +57 -0
  208. package/dist/presentation/cli/commands/cancel.js.map +1 -0
  209. package/dist/presentation/cli/commands/create.d.ts +8 -0
  210. package/dist/presentation/cli/commands/create.d.ts.map +1 -0
  211. package/dist/presentation/cli/commands/create.js +368 -0
  212. package/dist/presentation/cli/commands/create.js.map +1 -0
  213. package/dist/presentation/cli/commands/result.d.ts +8 -0
  214. package/dist/presentation/cli/commands/result.d.ts.map +1 -0
  215. package/dist/presentation/cli/commands/result.js +121 -0
  216. package/dist/presentation/cli/commands/result.js.map +1 -0
  217. package/dist/presentation/cli/commands/status.d.ts +8 -0
  218. package/dist/presentation/cli/commands/status.d.ts.map +1 -0
  219. package/dist/presentation/cli/commands/status.js +92 -0
  220. package/dist/presentation/cli/commands/status.js.map +1 -0
  221. package/dist/presentation/cli/index.d.ts +8 -0
  222. package/dist/presentation/cli/index.d.ts.map +1 -0
  223. package/dist/presentation/cli/index.js +32 -0
  224. package/dist/presentation/cli/index.js.map +1 -0
  225. package/dist/presentation/cli/utils/cleanup.d.ts +14 -0
  226. package/dist/presentation/cli/utils/cleanup.d.ts.map +1 -0
  227. package/dist/presentation/cli/utils/cleanup.js +62 -0
  228. package/dist/presentation/cli/utils/cleanup.js.map +1 -0
  229. package/dist/presentation/cli/utils/formatter.d.ts +28 -0
  230. package/dist/presentation/cli/utils/formatter.d.ts.map +1 -0
  231. package/dist/presentation/cli/utils/formatter.js +68 -0
  232. package/dist/presentation/cli/utils/formatter.js.map +1 -0
  233. package/dist/presentation/cli.d.ts +7 -0
  234. package/dist/presentation/cli.d.ts.map +1 -0
  235. package/dist/presentation/cli.js +8 -0
  236. package/dist/presentation/cli.js.map +1 -0
  237. package/dist/presentation/monitor-cli.d.ts +8 -0
  238. package/dist/presentation/monitor-cli.d.ts.map +1 -0
  239. package/dist/presentation/monitor-cli.js +44 -0
  240. package/dist/presentation/monitor-cli.js.map +1 -0
  241. package/dist/presentation/worker-cli.d.ts +8 -0
  242. package/dist/presentation/worker-cli.d.ts.map +1 -0
  243. package/dist/presentation/worker-cli.js +51 -0
  244. package/dist/presentation/worker-cli.js.map +1 -0
  245. package/dist/schedulers/TaskScheduler.d.ts +99 -0
  246. package/dist/schedulers/TaskScheduler.d.ts.map +1 -0
  247. package/dist/schedulers/TaskScheduler.js +233 -0
  248. package/dist/schedulers/TaskScheduler.js.map +1 -0
  249. package/dist/schedulers/index.d.ts +5 -0
  250. package/dist/schedulers/index.d.ts.map +1 -0
  251. package/dist/schedulers/index.js +5 -0
  252. package/dist/schedulers/index.js.map +1 -0
  253. package/dist/services/image/ImageService.d.ts +68 -0
  254. package/dist/services/image/ImageService.d.ts.map +1 -0
  255. package/dist/services/image/ImageService.js +166 -0
  256. package/dist/services/image/ImageService.js.map +1 -0
  257. package/dist/services/index.d.ts +8 -0
  258. package/dist/services/index.d.ts.map +1 -0
  259. package/dist/services/index.js +12 -0
  260. package/dist/services/index.js.map +1 -0
  261. package/dist/services/llm/EnhancedLLMService.d.ts +148 -0
  262. package/dist/services/llm/EnhancedLLMService.d.ts.map +1 -0
  263. package/dist/services/llm/EnhancedLLMService.js +425 -0
  264. package/dist/services/llm/EnhancedLLMService.js.map +1 -0
  265. package/dist/services/llm/LLMService.d.ts +103 -0
  266. package/dist/services/llm/LLMService.d.ts.map +1 -0
  267. package/dist/services/llm/LLMService.js +212 -0
  268. package/dist/services/llm/LLMService.js.map +1 -0
  269. package/dist/services/quality/HardRuleChecker.d.ts +143 -0
  270. package/dist/services/quality/HardRuleChecker.d.ts.map +1 -0
  271. package/dist/services/quality/HardRuleChecker.js +353 -0
  272. package/dist/services/quality/HardRuleChecker.js.map +1 -0
  273. package/dist/services/quality/LLMEvaluator.d.ts +105 -0
  274. package/dist/services/quality/LLMEvaluator.d.ts.map +1 -0
  275. package/dist/services/quality/LLMEvaluator.js +312 -0
  276. package/dist/services/quality/LLMEvaluator.js.map +1 -0
  277. package/dist/services/quality/QualityCheckService.d.ts +112 -0
  278. package/dist/services/quality/QualityCheckService.d.ts.map +1 -0
  279. package/dist/services/quality/QualityCheckService.js +342 -0
  280. package/dist/services/quality/QualityCheckService.js.map +1 -0
  281. package/dist/services/quality/QualityService.d.ts +75 -0
  282. package/dist/services/quality/QualityService.d.ts.map +1 -0
  283. package/dist/services/quality/QualityService.js +360 -0
  284. package/dist/services/quality/QualityService.js.map +1 -0
  285. package/dist/services/quality/index.d.ts +7 -0
  286. package/dist/services/quality/index.d.ts.map +1 -0
  287. package/dist/services/quality/index.js +10 -0
  288. package/dist/services/quality/index.js.map +1 -0
  289. package/dist/services/search/SearchService.d.ts +79 -0
  290. package/dist/services/search/SearchService.d.ts.map +1 -0
  291. package/dist/services/search/SearchService.js +193 -0
  292. package/dist/services/search/SearchService.js.map +1 -0
  293. package/dist/workers/TaskWorker.d.ts +61 -0
  294. package/dist/workers/TaskWorker.d.ts.map +1 -0
  295. package/dist/workers/TaskWorker.js +256 -0
  296. package/dist/workers/TaskWorker.js.map +1 -0
  297. package/dist/workers/index.d.ts +5 -0
  298. package/dist/workers/index.d.ts.map +1 -0
  299. package/dist/workers/index.js +5 -0
  300. package/dist/workers/index.js.map +1 -0
  301. package/docs/DOCUMENTATION-ANALYSIS.md +190 -0
  302. package/docs/README.md +145 -0
  303. package/docs/SOURCE-CODE-ANALYSIS.md +1107 -0
  304. package/docs/architecture-complete.md +5524 -0
  305. package/docs/archive/implementation/implementation-analysis/README.md +244 -0
  306. package/docs/archive/implementation/implementation-analysis/implementation-analysis-context.md +483 -0
  307. package/docs/archive/implementation/implementation-analysis/implementation-analysis-plan.md +1242 -0
  308. package/docs/archive/implementation/implementation-analysis/implementation-analysis-tasks.md +777 -0
  309. package/docs/archive/phases/phase-1/phase-1-completion-summary.md +284 -0
  310. package/docs/archive/phases/phase-1/phase-1-implementation-guide.md +1380 -0
  311. package/docs/archive/phases/phase-2/phase-2a/phase-2a-completion-summary.md +443 -0
  312. package/docs/archive/phases/phase-2/phase-2b/phase-2b-completion-report.md +430 -0
  313. package/docs/archive/phases/phase-2/phase-2b/phase-2b-completion-summary.md +592 -0
  314. package/docs/archive/phases/phase-2/phase-2b/phase-2b-final-summary.md +371 -0
  315. package/docs/archive/phases/phase-2/phase-2b/phase-2b-preparation-complete.md +343 -0
  316. package/docs/archive/phases/phase-2/phase-2b/phase-2b-preparation.md +945 -0
  317. package/docs/archive/phases/phase-2/phase-2b/phase-2b-progress-update.md +366 -0
  318. package/docs/archive/phases/phase-3/phase-3-completion-summary.md +354 -0
  319. package/docs/archive/phases/phase-3/phase-3-development-plan.md +878 -0
  320. package/docs/archive/phases/phase-3/phase-3-quick-start.md +324 -0
  321. package/docs/archive/phases/phase-4/phase-4-completion-summary.md +708 -0
  322. package/docs/archive/phases/phase-4/phase-4-development-plan.md +740 -0
  323. package/docs/archive/phases/phase-4/phase-4-quick-start.md +632 -0
  324. package/docs/archive/phases/phase-4/phase-4-session-3-security-testing.md +484 -0
  325. package/docs/archive/phases/phase-4/phase-4-session-4-unit-tests.md +550 -0
  326. package/docs/archive/phases/phase-4/phase-4-session-5-security-tests.md +564 -0
  327. package/docs/archive/phases/phase-4/phase-4-session-6-cache-integration.md +456 -0
  328. package/docs/archive/phases/phase-4/phase-4-session-7-test-fixes.md +348 -0
  329. package/docs/archive/phases/phase-4/phase-4-session-8-taskqueue-fixes.md +323 -0
  330. package/docs/archive/phases/phase-4/phase-4-session-summary-continued.md +373 -0
  331. package/docs/archive/phases/phase-4/phase-4-session-summary.md +595 -0
  332. package/docs/archive/reports/progress-reports/PHASE_0_PROGRESS.md +242 -0
  333. package/docs/archive/reports/progress-reports/PHASE_0_SUMMARY.md +262 -0
  334. package/docs/archive/reports/progress-reports/PHASE_1_2_ISSUES.md +399 -0
  335. package/docs/archive/reports/progress-reports/PHASE_1_PROGRESS.md +388 -0
  336. package/docs/archive/reports/progress-reports/PHASE_3_PREPARATION.md +574 -0
  337. package/docs/archive/reports/progress-reports/current-progress-update.md +294 -0
  338. package/docs/archive/reports/progress-reports/final-summary.md +215 -0
  339. package/docs/archive/reports/progress-reports/implementation-summary.md +287 -0
  340. package/docs/archive/reports/progress-reports/project-progress-report.md +440 -0
  341. package/docs/archive/reports/progress-reports/project-progress.md +386 -0
  342. package/docs/archive/reports/test-reports/TEST-COVERAGE-REPORT.md +441 -0
  343. package/docs/archive/reports/test-reports/e2e-test-report.md +293 -0
  344. package/docs/archive/reports/test-reports/final-test-report.md +367 -0
  345. package/docs/archive/reports/test-reports/real-env-test-report.md +391 -0
  346. package/docs/archive/reports/test-reports/test-completion-summary.md +356 -0
  347. package/docs/archive/reports/test-reports/test-report.md +371 -0
  348. package/docs/archive/sessions/session-2-summary.md +429 -0
  349. package/docs/archive/sessions/session-3-summary.md +395 -0
  350. package/docs/archive/sessions/session-summary.md +370 -0
  351. package/docs/config-system-update.md +239 -0
  352. package/docs/database-refactoring-PLAN.md +199 -0
  353. package/docs/database-refactoring-SUMMARY.md +384 -0
  354. package/docs/quality-check-architecture.md +1030 -0
  355. package/docs/quick-start.md +388 -0
  356. package/docs/references/bullmq-quick-reference.md +525 -0
  357. package/docs/references/monitoring-optimization-guide.md +871 -0
  358. package/docs/references/performance-optimization-guide.md +933 -0
  359. package/docs/storage-guide.md +612 -0
  360. package/docs/test-implementation-PLAN.md +223 -0
  361. package/docs/test-implementation-SUMMARY.md +194 -0
  362. package/docs/user-guide.md +719 -0
  363. package/docs/workflow-architecture.md +549 -0
  364. package/package.json +126 -0
  365. package/src/application/workflow/SyncExecutor.ts +444 -0
  366. package/src/application/workflow/types.ts +57 -0
  367. package/src/config/index.ts +352 -0
  368. package/src/domain/entities/QualityCheck.ts +202 -0
  369. package/src/domain/entities/Result.ts +130 -0
  370. package/src/domain/entities/Task.ts +178 -0
  371. package/src/domain/entities/TaskStep.ts +188 -0
  372. package/src/domain/entities/TokenUsage.ts +119 -0
  373. package/src/domain/entities/index.ts +20 -0
  374. package/src/domain/repositories/QualityCheckRepository.ts +52 -0
  375. package/src/domain/repositories/ResultRepository.ts +47 -0
  376. package/src/domain/repositories/TaskRepository.ts +271 -0
  377. package/src/domain/workflow/CheckpointManager.ts +283 -0
  378. package/src/domain/workflow/ContentCreatorGraph.ts +446 -0
  379. package/src/domain/workflow/State.ts +321 -0
  380. package/src/domain/workflow/index.ts +18 -0
  381. package/src/domain/workflow/nodes/BaseNode.ts +325 -0
  382. package/src/domain/workflow/nodes/CheckImageNode.ts +325 -0
  383. package/src/domain/workflow/nodes/CheckTextNode.ts +709 -0
  384. package/src/domain/workflow/nodes/GenerateImageNode.ts +342 -0
  385. package/src/domain/workflow/nodes/OrganizeNode.ts +304 -0
  386. package/src/domain/workflow/nodes/SearchNode.ts +192 -0
  387. package/src/domain/workflow/nodes/WriteNode.ts +505 -0
  388. package/src/domain/workflow/nodes/index.ts +13 -0
  389. package/src/index.ts +43 -0
  390. package/src/infrastructure/cache/CacheService.ts +483 -0
  391. package/src/infrastructure/cache/index.ts +6 -0
  392. package/src/infrastructure/database/BaseRepository.ts +214 -0
  393. package/src/infrastructure/database/MemoryTaskRepository.ts +377 -0
  394. package/src/infrastructure/database/PostgresQualityCheckRepository.ts +115 -0
  395. package/src/infrastructure/database/PostgresTaskRepository.ts +424 -0
  396. package/src/infrastructure/database/ResultRepository.ts +113 -0
  397. package/src/infrastructure/database/SQLiteTaskRepository.ts +651 -0
  398. package/src/infrastructure/database/index.ts +83 -0
  399. package/src/infrastructure/logging/logger.ts +231 -0
  400. package/src/infrastructure/monitoring/LoggingService.ts +292 -0
  401. package/src/infrastructure/monitoring/MetricsService.ts +468 -0
  402. package/src/infrastructure/monitoring/SentryService.ts +345 -0
  403. package/src/infrastructure/monitoring/index.ts +12 -0
  404. package/src/infrastructure/queue/TaskQueue.ts +429 -0
  405. package/src/infrastructure/queue/index.ts +5 -0
  406. package/src/infrastructure/redis/connection.ts +215 -0
  407. package/src/infrastructure/redis/index.ts +5 -0
  408. package/src/infrastructure/security/ApiKeyService.ts +340 -0
  409. package/src/infrastructure/security/QuotaService.ts +411 -0
  410. package/src/infrastructure/security/RateLimiter.ts +417 -0
  411. package/src/infrastructure/security/index.ts +12 -0
  412. package/src/monitoring/index.ts +5 -0
  413. package/src/monitoring/server.ts +109 -0
  414. package/src/presentation/cli/commands/cancel.ts +64 -0
  415. package/src/presentation/cli/commands/create.ts +400 -0
  416. package/src/presentation/cli/commands/result.ts +136 -0
  417. package/src/presentation/cli/commands/status.ts +102 -0
  418. package/src/presentation/cli/index.ts +39 -0
  419. package/src/presentation/cli/utils/cleanup.ts +65 -0
  420. package/src/presentation/cli/utils/formatter.ts +74 -0
  421. package/src/presentation/cli.ts +8 -0
  422. package/src/presentation/monitor-cli.ts +52 -0
  423. package/src/presentation/worker-cli.ts +62 -0
  424. package/src/schedulers/TaskScheduler.ts +314 -0
  425. package/src/schedulers/index.ts +11 -0
  426. package/src/services/image/ImageService.ts +221 -0
  427. package/src/services/index.ts +15 -0
  428. package/src/services/llm/EnhancedLLMService.ts +596 -0
  429. package/src/services/llm/LLMService.ts +310 -0
  430. package/src/services/quality/HardRuleChecker.ts +509 -0
  431. package/src/services/quality/LLMEvaluator.ts +400 -0
  432. package/src/services/quality/QualityCheckService.ts +473 -0
  433. package/src/services/quality/QualityService.ts +445 -0
  434. package/src/services/quality/index.ts +12 -0
  435. package/src/services/search/SearchService.ts +266 -0
  436. package/src/types/global.d.ts +17 -0
  437. package/src/workers/TaskWorker.ts +320 -0
  438. package/src/workers/index.ts +5 -0
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Search Node - 搜索节点
3
+ *
4
+ * 根据选题搜索相关资料,为后续写作提供参考素材
5
+ */
6
+
7
+ import { BaseNode } from './BaseNode.js';
8
+ import type { WorkflowState } from '../State.js';
9
+ import type { SearchResultItem } from '../State.js';
10
+ import { searchService } from '../../../services/search/SearchService.js';
11
+ import { createLogger } from '../../../infrastructure/logging/logger.js';
12
+
13
+ const logger = createLogger('SearchNode');
14
+
15
+ /**
16
+ * Search Node 配置
17
+ */
18
+ interface SearchNodeConfig {
19
+ maxResults?: number;
20
+ useCache?: boolean;
21
+ cacheTTL?: number; // 缓存时间(秒)
22
+ }
23
+
24
+ /**
25
+ * Search Node 实现
26
+ */
27
+ export class SearchNode extends BaseNode {
28
+ private config: SearchNodeConfig;
29
+
30
+ constructor(config: SearchNodeConfig = {}) {
31
+ super({
32
+ name: 'search',
33
+ retryCount: 2,
34
+ timeout: 30000, // 30 秒超时
35
+ });
36
+
37
+ this.config = {
38
+ maxResults: 10,
39
+ useCache: false, // 默认不使用缓存(需要 Redis 配置)
40
+ cacheTTL: 86400, // 24 小时
41
+ ...config,
42
+ };
43
+ }
44
+
45
+ /**
46
+ * 生成搜索查询
47
+ */
48
+ private generateSearchQuery(state: WorkflowState): string {
49
+ const { topic, hardConstraints } = state;
50
+
51
+ // 基础查询
52
+ let query = topic;
53
+
54
+ // 如果有指定关键词,组合到查询中
55
+ if (hardConstraints?.keywords && hardConstraints.keywords.length > 0) {
56
+ // 取前 3 个关键词
57
+ const keywords = hardConstraints.keywords.slice(0, 3).join(' ');
58
+ query = `${topic} ${keywords}`;
59
+ }
60
+
61
+ logger.debug('Generated search query', { query });
62
+ return query;
63
+ }
64
+
65
+ /**
66
+ * 从缓存获取搜索结果(可选)
67
+ */
68
+ private async getCachedResult(_query: string): Promise<SearchResultItem[] | null> {
69
+ // TODO: 实现 Redis 缓存
70
+ // 如果需要缓存,可以在这里添加 Redis 逻辑
71
+ return null;
72
+ }
73
+
74
+ /**
75
+ * 保存搜索结果到缓存(可选)
76
+ */
77
+ private async setCachedResult(
78
+ _query: string,
79
+ _results: SearchResultItem[]
80
+ ): Promise<void> {
81
+ // TODO: 实现 Redis 缓存
82
+ // 如果需要缓存,可以在这里添加 Redis 逻辑
83
+ }
84
+
85
+ /**
86
+ * 执行搜索逻辑
87
+ */
88
+ protected async executeLogic(state: WorkflowState): Promise<Partial<WorkflowState>> {
89
+ logger.info('Starting search', {
90
+ taskId: state.taskId,
91
+ topic: state.topic,
92
+ });
93
+
94
+ try {
95
+ // 1. 生成搜索查询
96
+ const searchQuery = this.generateSearchQuery(state);
97
+
98
+ // 2. 检查缓存(可选)
99
+ if (this.config.useCache) {
100
+ const cached = await this.getCachedResult(searchQuery);
101
+ if (cached && cached.length > 0) {
102
+ logger.info('Using cached search results', {
103
+ count: cached.length,
104
+ });
105
+
106
+ return {
107
+ searchQuery,
108
+ searchResults: cached,
109
+ };
110
+ }
111
+ }
112
+
113
+ // 3. 调用搜索服务
114
+ logger.debug('Calling search service', {
115
+ query: searchQuery,
116
+ maxResults: this.config.maxResults,
117
+ });
118
+
119
+ const response = await searchService.searchWithAnswer(
120
+ searchQuery,
121
+ this.config.maxResults || 10
122
+ );
123
+
124
+ // 4. 验证搜索结果
125
+ if (!response.results || response.results.length === 0) {
126
+ logger.warn('No search results found', { query: searchQuery });
127
+ // 不抛出错误,返回空结果
128
+ return {
129
+ searchQuery,
130
+ searchResults: [],
131
+ };
132
+ }
133
+
134
+ // 5. 转换搜索结果格式
135
+ const searchResults: SearchResultItem[] = response.results.map((item) => ({
136
+ title: item.title,
137
+ url: item.url,
138
+ content: item.content,
139
+ score: item.score,
140
+ publishedDate: item.publishedDate,
141
+ author: item.author,
142
+ }));
143
+
144
+ // 6. 保存到缓存(可选)
145
+ if (this.config.useCache) {
146
+ await this.setCachedResult(searchQuery, searchResults);
147
+ }
148
+
149
+ logger.info('Search completed successfully', {
150
+ taskId: state.taskId,
151
+ resultCount: searchResults.length,
152
+ hasAnswer: !!response.answer,
153
+ });
154
+
155
+ // 7. 返回状态更新
156
+ return {
157
+ searchQuery,
158
+ searchResults,
159
+ };
160
+ } catch (error) {
161
+ logger.error('Search failed', {
162
+ taskId: state.taskId,
163
+ topic: state.topic,
164
+ error: error instanceof Error ? error.message : String(error),
165
+ });
166
+
167
+ // 搜索失败时,返回空结果而不是抛出错误
168
+ // 这样可以让工作流继续,使用其他方式生成内容
169
+ logger.warn('Returning empty search results to allow workflow to continue');
170
+ return {
171
+ searchQuery: state.topic,
172
+ searchResults: [],
173
+ };
174
+ }
175
+ }
176
+
177
+ /**
178
+ * 验证输入状态
179
+ */
180
+ protected validateState(state: WorkflowState): void {
181
+ super.validateState(state);
182
+
183
+ if (!state.topic || state.topic.trim().length === 0) {
184
+ throw new Error('Topic is required for search');
185
+ }
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Search Node 单例导出(默认配置)
191
+ */
192
+ export const searchNode = new SearchNode();
@@ -0,0 +1,505 @@
1
+ /**
2
+ * Write Node - 写作节点
3
+ *
4
+ * 根据整理后的信息撰写文章内容
5
+ * 支持初始写作和重写两种模式
6
+ */
7
+
8
+ import { BaseNode } from './BaseNode.js';
9
+ import type { WorkflowState } from '../State.js';
10
+ import { enhancedLLMService } from '../../../services/llm/EnhancedLLMService.js';
11
+ import { createLogger } from '../../../infrastructure/logging/logger.js';
12
+
13
+ const logger = createLogger('WriteNode');
14
+
15
+ /**
16
+ * Write Node 配置
17
+ */
18
+ interface WriteNodeConfig {
19
+ maxRetries?: number;
20
+ }
21
+
22
+ /**
23
+ * 初始写作 Prompt 模板
24
+ */
25
+ const WRITE_PROMPT = `你是一位专业的内容创作者。根据以下信息撰写一篇文章:
26
+
27
+ 【主题】{topic}
28
+
29
+ 【要求】{requirements}
30
+
31
+ 【⚠️ 字数要求 - 必须严格遵守】
32
+ - 最少字数:{minWords} 字
33
+ - 最多字数:{maxWords} 字
34
+ - 字数范围:{minWords}-{maxWords} 字
35
+
36
+ 【必须包含的关键词】
37
+ {keywords}
38
+
39
+ 【参考资料】
40
+ 1. 搜索结果:
41
+ {searchResults}
42
+
43
+ 2. 文章大纲:
44
+ {outline}
45
+
46
+ 3. 关键点:
47
+ {keyPoints}
48
+
49
+ 【写作要求】
50
+ 请撰写一篇完整的文章,务必确保:
51
+
52
+ 1. ⚠️ 字数控制是最高优先级要求
53
+ - 如果字数不足 {minWords},需要补充内容
54
+ - 如果字数超过 {maxWords},必须精简内容
55
+ - 字数必须严格控制在 {minWords}-{maxWords} 之间
56
+
57
+ 2. 内容要求
58
+ - 内容原创,不抄袭
59
+ - 逻辑清晰,条理分明
60
+ - 语言流畅,表达准确
61
+
62
+ 3. 结构要求
63
+ - 包含标题、导语、正文、结语
64
+ - 参考大纲结构,但可以根据内容需要灵活调整
65
+
66
+ 4. 关键词要求
67
+ - 必须包含所有指定关键词:{keywords}
68
+ - 关键词要自然融入文章内容
69
+
70
+ 【输出格式】
71
+ 以 Markdown 格式输出完整文章。
72
+
73
+ 【⚠️ 重要提醒】
74
+ 请在生成文章后:
75
+ 1. 检查字数是否在 {minWords}-{maxWords} 范围内
76
+ 2. 如果字数不符合要求,请调整内容长度
77
+ 3. 字数不符合要求将被视为不合格作品
78
+ `;
79
+
80
+ /**
81
+ * 重写 Prompt 模板(有质检反馈时)
82
+ */
83
+ const REWRITE_PROMPT = `你是一位专业的内容创作者。根据以下质检反馈,修改上一版文章:
84
+
85
+ 【🚨 字数问题 - 最高优先级】
86
+ {hasWordCountIssue}
87
+ {wordCountFeedback}
88
+
89
+ 【⚠️ 字数要求 - 必须满足】
90
+ - 目标字数范围:{minWords} - {maxWords} 字
91
+ - 上次字数未达标,本次必须解决!
92
+
93
+ 【字数调整策略】
94
+ {strategy}
95
+
96
+ 【其他质检反馈】
97
+ {fixSuggestions}
98
+
99
+ 【修改要求】
100
+ 优先级顺序:
101
+ 1. ⚠️⚠️⚠️ 字数调整(最高优先级,必须解决)
102
+ - 如果上面标注了字数不足/超出,必须严格按照建议调整
103
+ - 字数必须在 {minWords}-{maxWords} 范围内
104
+ - 宁可超出也不要不足(但超出不能超过 {maxWords})
105
+
106
+ 2. 其他问题修复
107
+ - 根据其他质检反馈修改有问题的部分
108
+ - 保持文章的核心观点和关键信息
109
+ - 保持文章的整体风格和连贯性
110
+
111
+ 3. 关键词要求
112
+ - 必须包含所有关键词:{keywords}
113
+ - 关键词要自然融入文章内容
114
+
115
+ 【上一版文章】
116
+ {previousContent}
117
+
118
+ 【🚨 重要提醒】
119
+ 修改完成后请自检:
120
+ 1. ✅ 字数是否在 {minWords}-{maxWords} 范围内?← 最重要!
121
+ 2. ✅ 是否解决了所有字数问题?
122
+ 3. ✅ 是否包含了所有关键词?
123
+ 4. ✅ 文章逻辑是否连贯?
124
+
125
+ 请直接输出修改后的完整文章(Markdown 格式),不要添加任何额外说明。
126
+ `;
127
+
128
+ /**
129
+ * Write Node 实现
130
+ */
131
+ export class WriteNode extends BaseNode {
132
+ constructor(_config: WriteNodeConfig = {}) {
133
+ super({
134
+ name: 'write',
135
+ retryCount: 1, // 质检失败后会重试,这里设为 1
136
+ timeout: 240000, // 240 秒超时(流式请求 + 重试需要更长时间)
137
+ });
138
+
139
+ // Note: config.maxRetries is available but not currently used
140
+ // Retries are controlled by the workflow's checkText node
141
+ }
142
+
143
+ /**
144
+ * 判断是否为重写模式
145
+ */
146
+ private isRewriteMode(state: WorkflowState): boolean {
147
+ return !!(
148
+ state.previousContent &&
149
+ state.textQualityReport?.fixSuggestions &&
150
+ state.textQualityReport.fixSuggestions.length > 0
151
+ );
152
+ }
153
+
154
+ /**
155
+ * 从质检反馈中提取字数相关的建议
156
+ */
157
+ private extractWordCountFeedback(state: WorkflowState): {
158
+ hasWordCountIssue: boolean;
159
+ wordCountFeedback: string;
160
+ } {
161
+ if (!state.textQualityReport?.fixSuggestions) {
162
+ return { hasWordCountIssue: false, wordCountFeedback: '' };
163
+ }
164
+
165
+ // 查找包含"字数"关键词的建议
166
+ const wordCountSuggestions = state.textQualityReport.fixSuggestions.filter(s =>
167
+ s.includes('字数不足') || s.includes('字数超出')
168
+ );
169
+
170
+ if (wordCountSuggestions.length === 0) {
171
+ return { hasWordCountIssue: false, wordCountFeedback: '' };
172
+ }
173
+
174
+ return {
175
+ hasWordCountIssue: true,
176
+ wordCountFeedback: wordCountSuggestions.join('\n\n'),
177
+ };
178
+ }
179
+
180
+ /**
181
+ * 获取字数调整策略模板
182
+ */
183
+ private getWordCountStrategyTemplate(state: WorkflowState): string {
184
+ if (!state.previousContent) {
185
+ return '';
186
+ }
187
+
188
+ const wordCount = state.previousContent.length;
189
+ const minWords = state.hardConstraints.minWords || 500;
190
+ const maxWords = state.hardConstraints.maxWords || 1000;
191
+
192
+ if (wordCount < minWords) {
193
+ const shortage = minWords - wordCount;
194
+ const shortagePercent = Math.round((shortage / minWords) * 100);
195
+
196
+ if (shortagePercent < 10) {
197
+ return `【小幅扩充策略】
198
+ - 为每个段落添加1-2句补充说明
199
+ - 增加1-2个具体案例的细节描述
200
+ - 添加数据或引用支撑
201
+ - 优化过渡句,使段落更连贯`;
202
+ } else if (shortagePercent < 25) {
203
+ return `【中等扩充策略】
204
+ - 增加2-3个新案例,每个100-150字
205
+ - 为每个主要观点添加详细论证
206
+ - 增加背景介绍或相关研究数据
207
+ - 增加实际应用场景说明
208
+ - 扩展现有案例的分析深度`;
209
+ } else {
210
+ return `【大幅扩充策略】
211
+ - 增加3-5个全新案例(每个150-200字)
212
+ - 为每个主要观点添加详细论证和反面论证
213
+ - 添加完整的背景介绍、研究数据、行业趋势
214
+ - 增加实际应用场景、成功案例、失败教训
215
+ - 添加FAQ或常见问题解答部分
216
+ - 扩展每个案例的深度分析`;
217
+ }
218
+ } else if (wordCount > maxWords) {
219
+ const excess = wordCount - maxWords;
220
+ const excessPercent = Math.round((excess / wordCount) * 100);
221
+
222
+ if (excessPercent < 10) {
223
+ return `【小幅精简策略】
224
+ - 删除冗余的形容词和副词
225
+ - 合并相似的段落
226
+ - 删除重复的观点表达
227
+ - 简化过长的句子`;
228
+ } else if (excessPercent < 25) {
229
+ return `【中等精简策略】
230
+ - 删除1-2个次要案例
231
+ - 合并相似观点的段落
232
+ - 删除扩展说明,只保留核心内容
233
+ - 简化长句,使用更精炼的表达`;
234
+ } else {
235
+ return `【大幅精简策略】
236
+ - 只保留最核心的3-5个案例
237
+ - 删除所有扩展说明和背景介绍
238
+ - 每个案例只保留关键信息
239
+ - 删除FAQ和额外章节
240
+ - 使用最简洁的表达方式`;
241
+ }
242
+ }
243
+
244
+ return '';
245
+ }
246
+
247
+ /**
248
+ * 格式化搜索结果
249
+ */
250
+ private formatSearchResults(searchResults: WorkflowState['searchResults']): string {
251
+ if (!searchResults || searchResults.length === 0) {
252
+ return '(无搜索结果)';
253
+ }
254
+
255
+ // 限制显示前 5 条结果,避免 Token 过多
256
+ return searchResults
257
+ .slice(0, 5)
258
+ .map((result, index) => {
259
+ const content =
260
+ result.content.length > 300
261
+ ? result.content.substring(0, 300) + '...'
262
+ : result.content;
263
+
264
+ return `${index + 1}. ${result.title}
265
+ ${content}`;
266
+ })
267
+ .join('\n\n');
268
+ }
269
+
270
+ /**
271
+ * 构建 Prompt 参数
272
+ */
273
+ private buildPromptParams(state: WorkflowState): Record<string, string> {
274
+ const { hasWordCountIssue, wordCountFeedback } = this.extractWordCountFeedback(state);
275
+
276
+ return {
277
+ topic: state.topic,
278
+ requirements: state.requirements,
279
+ minWords: String(state.hardConstraints.minWords || 500),
280
+ maxWords: String(state.hardConstraints.maxWords || 1000),
281
+ keywords: state.hardConstraints.keywords?.join(', ') || '无',
282
+ searchResults: this.formatSearchResults(state.searchResults),
283
+ outline: state.organizedInfo?.outline || '',
284
+ keyPoints: state.organizedInfo?.keyPoints?.join('\n') || '',
285
+ previousContent: state.previousContent || '',
286
+ fixSuggestions:
287
+ state.textQualityReport?.fixSuggestions?.join('\n') || '',
288
+ // 🆕 添加专门字数反馈字段
289
+ hasWordCountIssue: hasWordCountIssue ? '是' : '否',
290
+ wordCountFeedback: wordCountFeedback,
291
+ strategy: this.getWordCountStrategyTemplate(state),
292
+ };
293
+ }
294
+
295
+ /**
296
+ * 构建 Prompt
297
+ */
298
+ private buildPrompt(
299
+ state: WorkflowState,
300
+ params: Record<string, string>
301
+ ): string {
302
+ const template = this.isRewriteMode(state) ? REWRITE_PROMPT : WRITE_PROMPT;
303
+
304
+ return template.replace(/\{(\w+)\}/g, (_, key) => params[key] || '');
305
+ }
306
+
307
+ /**
308
+ * 调用 LLM 生成/重写文章
309
+ */
310
+ private async callLLM(
311
+ state: WorkflowState,
312
+ prompt: string
313
+ ): Promise<string> {
314
+ const isRewrite = this.isRewriteMode(state);
315
+
316
+ // 🆕 增强日志记录
317
+ const logContext: any = {
318
+ taskId: state.taskId,
319
+ mode: isRewrite ? 'rewrite' : 'initial',
320
+ retryCount: state.textRetryCount,
321
+ stream: true,
322
+ };
323
+
324
+ // 如果是重写模式,记录字数分析信息
325
+ if (isRewrite && state.previousContent) {
326
+ const wordCount = state.previousContent.length;
327
+ const minWords = state.hardConstraints.minWords || 500;
328
+ const maxWords = state.hardConstraints.maxWords || 1000;
329
+ const { hasWordCountIssue } = this.extractWordCountFeedback(state);
330
+
331
+ logContext.previousWordCount = wordCount;
332
+ logContext.minRequired = minWords;
333
+ logContext.maxRequired = maxWords;
334
+ logContext.hasWordCountIssue = hasWordCountIssue;
335
+ logContext.strategy = this.getWordCountStrategyTemplate(state);
336
+
337
+ if (hasWordCountIssue) {
338
+ logger.info('Write retry word count analysis', logContext);
339
+ }
340
+ }
341
+
342
+ logger.debug('Calling LLM to write article', logContext);
343
+
344
+ const systemMessage =
345
+ '你是一位专业的内容创作者。请根据要求撰写高质量的文章。';
346
+
347
+ const result = await enhancedLLMService.chat({
348
+ messages: [
349
+ { role: 'system', content: systemMessage },
350
+ { role: 'user', content: prompt },
351
+ ],
352
+ taskId: state.taskId,
353
+ stepName: 'write',
354
+ stream: true, // 启用流式请求
355
+ });
356
+
357
+ logger.info('LLM write completed', {
358
+ taskId: state.taskId,
359
+ contentLength: result.content.length,
360
+ mode: isRewrite ? 'rewrite' : 'initial',
361
+ stream: true,
362
+ });
363
+
364
+ return result.content;
365
+ }
366
+
367
+ /**
368
+ * 验证文章内容
369
+ * 检查字数、关键词等约束,但只输出警告,不阻止流程
370
+ * 质量检查和重试决策由 checkText 节点负责
371
+ */
372
+ private validateContent(state: WorkflowState, content: string): void {
373
+ logger.debug('Validating article content', {
374
+ taskId: state.taskId,
375
+ contentLength: content.length,
376
+ });
377
+
378
+ const warnings: string[] = [];
379
+
380
+ // 1. 检查字数(改为警告)
381
+ const wordCount = content.length;
382
+
383
+ if (state.hardConstraints.minWords && wordCount < state.hardConstraints.minWords) {
384
+ warnings.push(`Word count insufficient: ${wordCount} < ${state.hardConstraints.minWords}`);
385
+ }
386
+
387
+ if (state.hardConstraints.maxWords && wordCount > state.hardConstraints.maxWords) {
388
+ warnings.push(`Word count exceeded: ${wordCount} > ${state.hardConstraints.maxWords}`);
389
+ }
390
+
391
+ // 2. 检查关键词(改为警告)
392
+ if (state.hardConstraints.keywords && state.hardConstraints.keywords.length > 0) {
393
+ const missingKeywords = state.hardConstraints.keywords.filter(
394
+ (keyword) => !content.includes(keyword)
395
+ );
396
+
397
+ if (missingKeywords.length > 0) {
398
+ warnings.push(`Missing keywords: ${missingKeywords.join(', ')}`);
399
+ }
400
+ }
401
+
402
+ // 3. 检查基本结构(警告)
403
+ const hasTitle = /^#\s+.+/.test(content);
404
+ if (!hasTitle) {
405
+ warnings.push('Article may be missing title');
406
+ }
407
+
408
+ // 输出所有警告信息(不阻止流程)
409
+ if (warnings.length > 0) {
410
+ logger.warn('Content validation warnings (will be checked by checkText node)', {
411
+ taskId: state.taskId,
412
+ wordCount,
413
+ warnings,
414
+ });
415
+ } else {
416
+ logger.info('Content validation passed', {
417
+ taskId: state.taskId,
418
+ wordCount,
419
+ });
420
+ }
421
+ }
422
+
423
+ /**
424
+ * 执行写作逻辑
425
+ */
426
+ protected async executeLogic(state: WorkflowState): Promise<Partial<WorkflowState>> {
427
+ const isRewrite = this.isRewriteMode(state);
428
+
429
+ logger.info('Starting write', {
430
+ taskId: state.taskId,
431
+ mode: isRewrite ? 'rewrite' : 'initial',
432
+ topic: state.topic,
433
+ });
434
+
435
+ try {
436
+ // 1. 构建 Prompt
437
+ const params = this.buildPromptParams(state);
438
+ const prompt = this.buildPrompt(state, params);
439
+
440
+ // 2. 调用 LLM
441
+ const content = await this.callLLM(state, prompt);
442
+
443
+ // 3. 验证内容
444
+ this.validateContent(state, content);
445
+
446
+ // 4. 返回结果
447
+ logger.info('Write completed successfully', {
448
+ taskId: state.taskId,
449
+ mode: isRewrite ? 'rewrite' : 'initial',
450
+ contentLength: content.length,
451
+ });
452
+
453
+ return {
454
+ articleContent: content,
455
+ };
456
+ } catch (error) {
457
+ logger.error('Write failed', {
458
+ taskId: state.taskId,
459
+ mode: isRewrite ? 'rewrite' : 'initial',
460
+ error: error instanceof Error ? {
461
+ message: error.message,
462
+ stack: error.stack,
463
+ } : {
464
+ message: String(error),
465
+ },
466
+ });
467
+
468
+ // 写作失败时抛出错误,让工作流重试
469
+ throw error;
470
+ }
471
+ }
472
+
473
+ /**
474
+ * 验证输入状态
475
+ */
476
+ protected validateState(state: WorkflowState): void {
477
+ super.validateState(state);
478
+
479
+ if (!state.requirements || state.requirements.trim().length === 0) {
480
+ throw new Error('Requirements are required for write');
481
+ }
482
+
483
+ // 如果是初始模式,需要有组织信息
484
+ if (!this.isRewriteMode(state)) {
485
+ if (!state.organizedInfo) {
486
+ throw new Error('Organized info is required for initial write');
487
+ }
488
+ }
489
+ // 如果是重写模式,需要有上一版内容和质检反馈
490
+ else {
491
+ if (!state.previousContent) {
492
+ throw new Error('Previous content is required for rewrite');
493
+ }
494
+
495
+ if (!state.textQualityReport?.fixSuggestions) {
496
+ throw new Error('Quality report with fix suggestions is required for rewrite');
497
+ }
498
+ }
499
+ }
500
+ }
501
+
502
+ /**
503
+ * Write Node 单例导出(默认配置)
504
+ */
505
+ export const writeNode = new WriteNode();
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Workflow Nodes 导出
3
+ *
4
+ * 统一导出所有节点
5
+ */
6
+
7
+ export * from './BaseNode.js';
8
+ export * from './SearchNode.js';
9
+ export * from './OrganizeNode.js';
10
+ export * from './WriteNode.js';
11
+ export * from './CheckTextNode.js';
12
+ export * from './GenerateImageNode.js';
13
+ export * from './CheckImageNode.js';