llm-content-creator 0.1.0 → 0.1.1

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 (91) hide show
  1. package/dist/application/workflow/SyncExecutor.d.ts.map +1 -1
  2. package/dist/application/workflow/SyncExecutor.js +1 -0
  3. package/dist/application/workflow/SyncExecutor.js.map +1 -1
  4. package/dist/config/index.d.ts +2 -2
  5. package/dist/config/index.js +3 -3
  6. package/dist/config/index.js.map +1 -1
  7. package/dist/domain/repositories/TaskRepository.d.ts +1 -0
  8. package/dist/domain/repositories/TaskRepository.d.ts.map +1 -1
  9. package/dist/infrastructure/database/MemoryTaskRepository.d.ts +17 -1
  10. package/dist/infrastructure/database/MemoryTaskRepository.d.ts.map +1 -1
  11. package/dist/infrastructure/database/MemoryTaskRepository.js +76 -1
  12. package/dist/infrastructure/database/MemoryTaskRepository.js.map +1 -1
  13. package/dist/infrastructure/database/SQLiteQualityCheckRepository.d.ts +27 -0
  14. package/dist/infrastructure/database/SQLiteQualityCheckRepository.d.ts.map +1 -0
  15. package/dist/infrastructure/database/SQLiteQualityCheckRepository.js +80 -0
  16. package/dist/infrastructure/database/SQLiteQualityCheckRepository.js.map +1 -0
  17. package/dist/infrastructure/database/SQLiteResultRepository.d.ts +31 -0
  18. package/dist/infrastructure/database/SQLiteResultRepository.d.ts.map +1 -0
  19. package/dist/infrastructure/database/SQLiteResultRepository.js +77 -0
  20. package/dist/infrastructure/database/SQLiteResultRepository.js.map +1 -0
  21. package/dist/infrastructure/database/SQLiteTaskRepository.d.ts +12 -0
  22. package/dist/infrastructure/database/SQLiteTaskRepository.d.ts.map +1 -1
  23. package/dist/infrastructure/database/SQLiteTaskRepository.js +69 -2
  24. package/dist/infrastructure/database/SQLiteTaskRepository.js.map +1 -1
  25. package/dist/infrastructure/database/index.d.ts +23 -2
  26. package/dist/infrastructure/database/index.d.ts.map +1 -1
  27. package/dist/infrastructure/database/index.js +33 -2
  28. package/dist/infrastructure/database/index.js.map +1 -1
  29. package/dist/infrastructure/redis/connection.d.ts.map +1 -1
  30. package/dist/infrastructure/redis/connection.js +14 -3
  31. package/dist/infrastructure/redis/connection.js.map +1 -1
  32. package/dist/presentation/cli/commands/cancel.d.ts.map +1 -1
  33. package/dist/presentation/cli/commands/cancel.js +1 -0
  34. package/dist/presentation/cli/commands/cancel.js.map +1 -1
  35. package/dist/presentation/cli/commands/create.d.ts.map +1 -1
  36. package/dist/presentation/cli/commands/create.js +29 -14
  37. package/dist/presentation/cli/commands/create.js.map +1 -1
  38. package/dist/presentation/cli/commands/list.d.ts +8 -0
  39. package/dist/presentation/cli/commands/list.d.ts.map +1 -0
  40. package/dist/presentation/cli/commands/list.js +154 -0
  41. package/dist/presentation/cli/commands/list.js.map +1 -0
  42. package/dist/presentation/cli/commands/result.d.ts.map +1 -1
  43. package/dist/presentation/cli/commands/result.js +33 -3
  44. package/dist/presentation/cli/commands/result.js.map +1 -1
  45. package/dist/presentation/cli/commands/retry.d.ts +8 -0
  46. package/dist/presentation/cli/commands/retry.d.ts.map +1 -0
  47. package/dist/presentation/cli/commands/retry.js +203 -0
  48. package/dist/presentation/cli/commands/retry.js.map +1 -0
  49. package/dist/presentation/cli/commands/status.d.ts.map +1 -1
  50. package/dist/presentation/cli/commands/status.js +3 -2
  51. package/dist/presentation/cli/commands/status.js.map +1 -1
  52. package/dist/presentation/cli/index.js +4 -0
  53. package/dist/presentation/cli/index.js.map +1 -1
  54. package/dist/presentation/cli/utils/cleanup.d.ts +1 -3
  55. package/dist/presentation/cli/utils/cleanup.d.ts.map +1 -1
  56. package/dist/presentation/cli/utils/cleanup.js.map +1 -1
  57. package/dist/presentation/monitor-cli.js +2 -4
  58. package/dist/presentation/monitor-cli.js.map +1 -1
  59. package/dist/presentation/worker-cli.js +8 -5
  60. package/dist/presentation/worker-cli.js.map +1 -1
  61. package/dist/schedulers/TaskScheduler.d.ts.map +1 -1
  62. package/dist/schedulers/TaskScheduler.js +13 -5
  63. package/dist/schedulers/TaskScheduler.js.map +1 -1
  64. package/dist/workers/TaskWorker.d.ts.map +1 -1
  65. package/dist/workers/TaskWorker.js +39 -21
  66. package/dist/workers/TaskWorker.js.map +1 -1
  67. package/docs/cli-reference.md +623 -0
  68. package/docs/quick-start.md +47 -0
  69. package/docs/user-guide.md +191 -24
  70. package/package.json +3 -1
  71. package/src/application/workflow/SyncExecutor.ts +1 -0
  72. package/src/config/index.ts +3 -3
  73. package/src/domain/repositories/TaskRepository.ts +1 -0
  74. package/src/infrastructure/database/MemoryTaskRepository.ts +89 -1
  75. package/src/infrastructure/database/SQLiteQualityCheckRepository.ts +102 -0
  76. package/src/infrastructure/database/SQLiteResultRepository.ts +95 -0
  77. package/src/infrastructure/database/SQLiteTaskRepository.ts +80 -2
  78. package/src/infrastructure/database/index.ts +39 -2
  79. package/src/infrastructure/redis/connection.ts +16 -3
  80. package/src/presentation/cli/commands/cancel.ts +1 -0
  81. package/src/presentation/cli/commands/create.ts +30 -14
  82. package/src/presentation/cli/commands/list.ts +172 -0
  83. package/src/presentation/cli/commands/result.ts +33 -3
  84. package/src/presentation/cli/commands/retry.ts +241 -0
  85. package/src/presentation/cli/commands/status.ts +3 -2
  86. package/src/presentation/cli/index.ts +4 -0
  87. package/src/presentation/cli/utils/cleanup.ts +1 -1
  88. package/src/presentation/monitor-cli.ts +2 -4
  89. package/src/presentation/worker-cli.ts +8 -5
  90. package/src/schedulers/TaskScheduler.ts +13 -5
  91. package/src/workers/TaskWorker.ts +47 -22
@@ -65,11 +65,11 @@ cp .env.example .env
65
65
  pnpm run db:migrate
66
66
 
67
67
  # 5. 创建第一个任务
68
- pnpm run cli:create \
68
+ pnpm run cli create \
69
69
  --topic "人工智能的未来" \
70
70
  --requirements "写一篇关于 AI 未来发展的文章" \
71
71
  --audience "技术爱好者" \
72
- --sync
72
+ --mode sync
73
73
  ```
74
74
 
75
75
  ### Docker 快速启动
@@ -294,7 +294,7 @@ pnpm run start
294
294
  #### 创建内容创作任务
295
295
 
296
296
  ```bash
297
- pnpm run cli:create \
297
+ pnpm run cli create \
298
298
  --topic "文章主题" \
299
299
  --requirements "创作要求" \
300
300
  --audience "目标受众" \
@@ -302,7 +302,7 @@ pnpm run cli:create \
302
302
  --keywords "关键词1,关键词2" \
303
303
  --min-words 500 \
304
304
  --max-words 2000 \
305
- --sync
305
+ --mode sync
306
306
  ```
307
307
 
308
308
  #### 参数说明
@@ -324,7 +324,7 @@ pnpm run cli:create \
324
324
  ##### 示例 1:技术博客文章
325
325
 
326
326
  ```bash
327
- pnpm run cli:create \
327
+ pnpm run cli create \
328
328
  --topic "TypeScript 5.0 新特性解析" \
329
329
  --requirements "详细介绍 TypeScript 5.0 的新特性、改进和迁移指南" \
330
330
  --audience "前端开发者" \
@@ -332,13 +332,13 @@ pnpm run cli:create \
332
332
  --keywords "TypeScript,JavaScript,前端开发" \
333
333
  --min-words 1000 \
334
334
  --max-words 2000 \
335
- --sync
335
+ --mode sync
336
336
  ```
337
337
 
338
338
  ##### 示例 2:生活类文章
339
339
 
340
340
  ```bash
341
- pnpm run cli:create \
341
+ pnpm run cli create \
342
342
  --topic "健康生活方式建议" \
343
343
  --requirements "提供实用的健康生活建议,包括饮食、运动和睡眠" \
344
344
  --audience "普通读者" \
@@ -346,7 +346,7 @@ pnpm run cli:create \
346
346
  --keywords "健康,生活,养生" \
347
347
  --min-words 800 \
348
348
  --max-words 1200 \
349
- --sync
349
+ --mode sync
350
350
  ```
351
351
 
352
352
  ### 方式二:程序化调用
@@ -394,20 +394,20 @@ console.log('配图 URL:', result.finalState.imageUrl);
394
394
  ### create - 创建任务
395
395
 
396
396
  ```bash
397
- pnpm run cli:create [options]
397
+ pnpm run cli create [options]
398
398
  ```
399
399
 
400
400
  **示例**:
401
401
 
402
402
  ```bash
403
403
  # 同步执行(推荐用于测试)
404
- pnpm run cli:create \
404
+ pnpm run cli create \
405
405
  --topic "主题" \
406
406
  --requirements "要求" \
407
- --sync
407
+ --mode sync
408
408
 
409
409
  # 异步执行(推荐用于生产)
410
- pnpm run cli:create \
410
+ pnpm run cli create \
411
411
  --topic "主题" \
412
412
  --requirements "要求" \
413
413
  --mode async
@@ -415,27 +415,122 @@ pnpm run cli:create \
415
415
 
416
416
  ### 其他 CLI 命令
417
417
 
418
+ #### 查看历史任务列表
419
+
420
+ ```bash
421
+ # 查看最近 20 个任务(默认)
422
+ pnpm run cli list
423
+
424
+ # 查看最近 10 个任务
425
+ pnpm run cli list --limit 10
426
+
427
+ # 只查看已完成的任务
428
+ pnpm run cli list --status completed
429
+
430
+ # 只查看失败的任务
431
+ pnpm run cli list --status failed
432
+
433
+ # 只查看异步任务
434
+ pnpm run cli list --mode async
435
+
436
+ # 查看第 2 页(分页)
437
+ pnpm run cli list --offset 20
438
+
439
+ # 以 JSON 格式输出(方便脚本处理)
440
+ pnpm run cli list --json
441
+ ```
442
+
443
+ **显示内容**:
444
+ - 任务主题
445
+ - 任务 ID
446
+ - 当前状态(等待中/运行中/已完成/失败)
447
+ - 执行模式(同步/异步)
448
+ - 创建时间(智能相对时间)
449
+ - 执行耗时
450
+ - 错误信息(如果失败)
451
+
452
+ #### 重新执行任务
453
+
454
+ ```bash
455
+ # 重新执行单个任务
456
+ pnpm run cli retry --task-id <任务ID>
457
+
458
+ # 批量重新执行所有等待任务
459
+ pnpm run cli retry --all
460
+
461
+ # 批量重新执行失败任务
462
+ pnpm run cli retry --all --status failed
463
+
464
+ # 模拟运行(预览但不实际执行)
465
+ pnpm run cli retry --all --dry-run
466
+
467
+ # 限制处理数量
468
+ pnpm run cli retry --all --limit 5
469
+ ```
470
+
471
+ **使用场景**:
472
+ - Worker 临时停止导致任务堆积
473
+ - 任务创建时队列不可用
474
+ - 失败的任务需要重试
475
+ - 想要重新执行历史任务
476
+
418
477
  #### 查看任务状态
419
478
 
420
479
  ```bash
421
- pnpm run cli:status <task-id>
480
+ pnpm run cli status --task-id <task-id>
481
+ ```
482
+
483
+ #### 获取任务结果
484
+
485
+ ```bash
486
+ pnpm run cli result --task-id <task-id>
422
487
  ```
423
488
 
424
489
  #### 取消任务
425
490
 
426
491
  ```bash
427
- pnpm run cli:cancel <task-id>
492
+ pnpm run cli cancel --task-id <task-id>
428
493
  ```
429
494
 
430
- #### 监控面板
495
+ #### 监控面板 (Monitor)
496
+
497
+ **启动监控面板**:
431
498
 
432
499
  ```bash
433
- # 启动 BullMQ 监控面板
500
+ # 启动 BullMQ 监控面板(默认端口 3000)
434
501
  pnpm run monitor
435
502
 
436
- # 访问 http://localhost:3000/admin/queues
503
+ # 指定端口启动
504
+ npx tsx src/presentation/monitor-cli.ts start -p 3001
437
505
  ```
438
506
 
507
+ **访问 Web UI**:
508
+
509
+ 启动后访问: `http://localhost:3000/admin/queues`
510
+
511
+ **功能特性**:
512
+ - ✅ **实时队列监控** - 查看待处理、执行中、已完成、失败的任务
513
+ - ✅ **任务详情查看** - 查看任务数据、堆栈跟踪、执行日志
514
+ - ✅ **任务管理** - 手动重试失败任务、删除任务、暂停/恢复队列
515
+ - ✅ **队列统计** - 实时查看队列状态和任务数量
516
+ - ✅ **错误追踪** - 查看失败任务的原因和错误信息
517
+
518
+ **API 端点**:
519
+
520
+ ```bash
521
+ # 健康检查
522
+ curl http://localhost:3000/health
523
+
524
+ # 获取队列统计
525
+ curl http://localhost:3000/api/stats
526
+ ```
527
+
528
+ **使用场景**:
529
+ - 监控异步任务执行状态
530
+ - 查看失败任务并进行手动重试
531
+ - 清理堆积的任务队列
532
+ - 调试任务执行问题
533
+
439
534
  ---
440
535
 
441
536
  ## 🔌 API 接口
@@ -459,10 +554,10 @@ pnpm run monitor
459
554
  ```bash
460
555
  # 创建批量脚本
461
556
  for topic in "AI发展" "区块链应用" "云计算趋势"; do
462
- pnpm run cli:create \
557
+ pnpm run cli create \
463
558
  --topic "$topic" \
464
559
  --requirements "详细介绍 $topic" \
465
- --sync
560
+ --mode sync
466
561
  done
467
562
  ```
468
563
 
@@ -481,17 +576,30 @@ LLM_TEMPERATURE=0.3 # 降低创造性(更确定性)
481
576
  创建任务时设置:
482
577
 
483
578
  ```bash
484
- pnpm run cli:create \
579
+ pnpm run cli create \
485
580
  --topic "主题" \
486
- --requirements "要求" \
487
- --no-search # 如果支持
581
+ --requirements "要求"
582
+ # --no-search # 暂不支持此参数
488
583
  ```
489
584
 
490
585
  或在代码中设置 `useCache: true` 强制使用缓存。
491
586
 
492
587
  ### Q4: 如何查看任务历史?
493
588
 
494
- 查询数据库:
589
+ 使用 CLI 命令:
590
+
591
+ ```bash
592
+ # 查看最近的任务
593
+ pnpm run cli list
594
+
595
+ # 查看失败的任务
596
+ pnpm run cli list --status failed
597
+
598
+ # 以 JSON 格式输出
599
+ pnpm run cli list --json
600
+ ```
601
+
602
+ 或直接查询数据库:
495
603
 
496
604
  ```bash
497
605
  # 使用 psql
@@ -660,11 +768,52 @@ pnpm run verify-env
660
768
 
661
769
  # 数据库状态
662
770
  pnpm run db:status
771
+ ```
772
+
773
+ ### Monitor 监控面板
663
774
 
664
- # 监控面板
775
+ **启动监控面板**:
776
+
777
+ ```bash
778
+ # 启动 Monitor(推荐)
665
779
  pnpm run monitor
780
+
781
+ # 指定端口
782
+ npx tsx src/presentation/monitor-cli.ts start -p 3001
666
783
  ```
667
784
 
785
+ **访问地址**:
786
+ - Web UI: http://localhost:3000/admin/queues
787
+ - 健康检查: http://localhost:3000/health
788
+ - 队列统计: http://localhost:3000/api/stats
789
+
790
+ **监控面板功能**:
791
+
792
+ 1. **队列概览**
793
+ - Waiting(等待中)- 待处理的任务
794
+ - Active(执行中)- 正在执行的任务
795
+ - Completed(已完成)- 成功完成的任务
796
+ - Failed(失败)- 执行失败的任务
797
+ - Delayed(延迟)- 延迟执行的任务
798
+
799
+ 2. **任务操作**
800
+ - 查看任务详情(点击任务 ID)
801
+ - 重试失败任务(Retry 按钮)
802
+ - 删除任务(Delete 按钮)
803
+ - 查看任务日志和堆栈跟踪
804
+
805
+ 3. **队列管理**
806
+ - 暂停队列(Pause 按钮)
807
+ - 恢复队列(Resume 按钮)
808
+ - 清空队列(Clean all 按钮)
809
+ - 批量操作失败任务
810
+
811
+ 4. **性能监控**
812
+ - 任务处理速度
813
+ - 队列堆积情况
814
+ - 失败率统计
815
+ - Worker 性能指标
816
+
668
817
  ### 日志查看
669
818
 
670
819
  ```bash
@@ -673,6 +822,9 @@ tail -f ./logs/app.log
673
822
 
674
823
  # 搜索错误日志
675
824
  grep "error" ./logs/app.log
825
+
826
+ # 查看 Monitor 日志
827
+ tail -f ./logs/app.log | grep BullBoard
676
828
  ```
677
829
 
678
830
  ### 性能指标
@@ -683,6 +835,21 @@ grep "error" ./logs/app.log
683
835
  - 缓存命中率
684
836
  - 错误率
685
837
 
838
+ ### 常用监控组合
839
+
840
+ ```bash
841
+ # 终端 1: 启动监控面板
842
+ pnpm run monitor
843
+
844
+ # 终端 2: 启动 Worker
845
+ pnpm run worker
846
+
847
+ # 终端 3: 创建异步任务
848
+ pnpm run cli create --topic "测试" --requirements "测试描述" --mode async
849
+
850
+ # 浏览器: 访问 http://localhost:3000/admin/queues 观察任务执行
851
+ ```
852
+
686
853
  ---
687
854
 
688
855
  ## 📞 技术支持
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llm-content-creator",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "AI 驱动的内容创作工具库",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -52,6 +52,8 @@
52
52
  "db:status": "tsx scripts/run-migration.ts status",
53
53
  "cli": "tsx src/presentation/cli/index.ts",
54
54
  "cli:create": "tsx src/presentation/cli/index.ts create",
55
+ "cli:list": "tsx src/presentation/cli/index.ts list",
56
+ "cli:retry": "tsx src/presentation/cli/index.ts retry",
55
57
  "cli:status": "tsx src/presentation/cli/index.ts status",
56
58
  "cli:result": "tsx src/presentation/cli/index.ts result",
57
59
  "cli:cancel": "tsx src/presentation/cli/index.ts cancel",
@@ -206,6 +206,7 @@ export class SyncExecutor {
206
206
  id: taskId,
207
207
  userId: params.userId,
208
208
  mode: params.mode,
209
+ type: 'content-creator', // 添加默认类型
209
210
  topic: params.topic,
210
211
  requirements: params.requirements,
211
212
  hardConstraints: params.hardConstraints,
@@ -62,7 +62,7 @@ const envSchema = z.object({
62
62
  S3_BUCKET: z.string().optional(),
63
63
 
64
64
  // Worker 配置
65
- WORKER_ID: z.string().default('worker-1'),
65
+ WORKER_ID: z.string().optional(),
66
66
  WORKER_CONCURRENCY: z.coerce.number().int().positive().default(2),
67
67
 
68
68
  // 日志配置
@@ -160,7 +160,7 @@ class Config {
160
160
  console.log('Configuration Loaded Successfully');
161
161
  console.log('========================================');
162
162
  console.log(`Environment: ${this.env.NODE_ENV}`);
163
- console.log(`Worker ID: ${this.env.WORKER_ID}`);
163
+ console.log(`Worker ID: ${this.env.WORKER_ID || 'Not set (auto-generating UUID)'}`);
164
164
  console.log(`Concurrency: ${this.env.WORKER_CONCURRENCY}`);
165
165
  console.log(`Database Type: ${this.databaseType}`);
166
166
 
@@ -256,7 +256,7 @@ class Config {
256
256
  // 连接超时
257
257
  connectTimeout: 10000,
258
258
  // 命令超时
259
- commandTimeout: 5000,
259
+ commandTimeout: 30000,
260
260
  };
261
261
  }
262
262
 
@@ -17,6 +17,7 @@ export interface CreateTaskInput {
17
17
  id?: string;
18
18
  userId?: string;
19
19
  mode: ExecutionMode;
20
+ type?: string;
20
21
  topic: string;
21
22
  requirements: string;
22
23
  hardConstraints?: {
@@ -127,7 +127,42 @@ export class MemoryTaskRepository {
127
127
  }
128
128
 
129
129
  /**
130
- * 抢占任务(Worker 抢占机制)
130
+ * 抢占任务(Worker 抢占机制)- 按任务ID抢占
131
+ */
132
+ async claimTask(taskId: string, workerId: string, version: number): Promise<boolean> {
133
+ const task = this.tasks.get(taskId);
134
+ if (!task) {
135
+ return false;
136
+ }
137
+
138
+ // 检查版本号(乐观锁)
139
+ if (task.version !== version || task.status !== TaskStatus.PENDING) {
140
+ logger.warn('Task claim failed (version mismatch or not pending)', {
141
+ taskId,
142
+ expectedVersion: version,
143
+ actualVersion: task.version,
144
+ status: task.status
145
+ });
146
+ return false;
147
+ }
148
+
149
+ const now = new Date();
150
+ const updatedTask: Task = {
151
+ ...task,
152
+ status: TaskStatus.RUNNING,
153
+ workerId,
154
+ startedAt: now,
155
+ version: version + 1,
156
+ updatedAt: now,
157
+ };
158
+
159
+ this.tasks.set(taskId, updatedTask);
160
+ logger.info('Task claimed (memory)', { taskId, workerId });
161
+ return true;
162
+ }
163
+
164
+ /**
165
+ * 抢占任务(Worker 抢占机制)- 批量抢占
131
166
  */
132
167
  async claimForProcessing(workerId: string, limit: number = 1): Promise<Task[]> {
133
168
  const now = new Date();
@@ -361,6 +396,59 @@ export class MemoryTaskRepository {
361
396
  return true;
362
397
  }
363
398
 
399
+ /**
400
+ * 查询任务列表(支持过滤和分页)
401
+ */
402
+ async findMany(filter?: any, pagination?: any): Promise<Task[]> {
403
+ const { limit = 50, offset = 0 } = pagination || {};
404
+
405
+ let tasks = Array.from(this.tasks.values());
406
+
407
+ // 应用过滤
408
+ if (filter?.status) {
409
+ tasks = tasks.filter((t) => t.status === filter.status);
410
+ }
411
+ if (filter?.userId) {
412
+ tasks = tasks.filter((t) => t.id === filter.userId); // Memory 没有 userId 字段
413
+ }
414
+ if (filter?.mode) {
415
+ tasks = tasks.filter((t) => t.mode === filter.mode);
416
+ }
417
+
418
+ // 按创建时间倒序排序
419
+ tasks.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
420
+
421
+ // 分页
422
+ return tasks.slice(offset, offset + limit);
423
+ }
424
+
425
+ /**
426
+ * 统计任务数量
427
+ */
428
+ async count(filter?: any): Promise<number> {
429
+ let tasks = Array.from(this.tasks.values());
430
+
431
+ // 应用过滤
432
+ if (filter?.status) {
433
+ tasks = tasks.filter((t) => t.status === filter.status);
434
+ }
435
+ if (filter?.userId) {
436
+ tasks = tasks.filter((t) => t.id === filter.userId);
437
+ }
438
+ if (filter?.mode) {
439
+ tasks = tasks.filter((t) => t.mode === filter.mode);
440
+ }
441
+
442
+ return tasks.length;
443
+ }
444
+
445
+ /**
446
+ * 根据 userId 查询任务列表
447
+ */
448
+ async findByUserId(userId: string, pagination?: any): Promise<Task[]> {
449
+ return this.findMany({ userId }, pagination);
450
+ }
451
+
364
452
  /**
365
453
  * 获取统计信息
366
454
  */
@@ -0,0 +1,102 @@
1
+ /**
2
+ * SQLite Quality Check Repository
3
+ *
4
+ * 使用 better-sqlite3 实现的轻量级质量检查数据访问层
5
+ * 适合开发和测试环境
6
+ */
7
+
8
+ import Database from 'better-sqlite3';
9
+ import { v4 as uuidv4 } from 'uuid';
10
+ import { createLogger } from '../../infrastructure/logging/logger.js';
11
+ import type { IQualityCheckRepository, CreateQualityCheckParams, QualityCheckRecord } from '../../domain/repositories/QualityCheckRepository.js';
12
+
13
+ const logger = createLogger('SQLite:QualityCheckRepository');
14
+
15
+ /**
16
+ * SQLite Quality Check Repository 实现
17
+ */
18
+ export class SQLiteQualityCheckRepository implements IQualityCheckRepository {
19
+ private db: Database.Database;
20
+
21
+ constructor(dbPath?: string) {
22
+ const actualDbPath = dbPath || './data/content-creator.db';
23
+ this.db = new Database(actualDbPath);
24
+ logger.info('SQLite quality check repository initialized', { dbPath: actualDbPath });
25
+ }
26
+
27
+ /**
28
+ * 创建质量检查记录
29
+ */
30
+ async create(params: CreateQualityCheckParams): Promise<void> {
31
+ const now = new Date().toISOString();
32
+ const stmt = this.db.prepare(`
33
+ INSERT INTO quality_checks (
34
+ id, task_id, check_type, score, passed, hard_constraints_passed,
35
+ details, fix_suggestions, rubric_version, model_name, prompt_hash, created_at
36
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
37
+ `);
38
+
39
+ const details = params.details ? JSON.stringify(params.details) : null;
40
+ const fixSuggestions = (params.fixSuggestions && params.fixSuggestions.length > 0)
41
+ ? JSON.stringify(params.fixSuggestions)
42
+ : null;
43
+
44
+ try {
45
+ stmt.run(
46
+ uuidv4(), // 使用 UUID v4 确保唯一性
47
+ params.taskId,
48
+ params.checkType,
49
+ params.score,
50
+ params.passed,
51
+ params.hardConstraintsPassed,
52
+ details,
53
+ fixSuggestions,
54
+ params.rubricVersion || null,
55
+ params.modelName || null,
56
+ params.promptHash || null,
57
+ now
58
+ );
59
+
60
+ logger.info('Quality check created', {
61
+ taskId: params.taskId,
62
+ checkType: params.checkType,
63
+ score: params.score,
64
+ passed: params.passed,
65
+ });
66
+ } catch (error) {
67
+ logger.error('Failed to create quality check', { error: error as any, params });
68
+ throw error;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * 根据任务 ID 查询质量检查
74
+ */
75
+ async findByTaskId(taskId: string): Promise<QualityCheckRecord[]> {
76
+ const stmt = this.db.prepare('SELECT * FROM quality_checks WHERE task_id = ? ORDER BY created_at DESC');
77
+ const rows = stmt.all(taskId) as any[];
78
+
79
+ return rows.map((row) => ({
80
+ id: row.id,
81
+ taskId: row.task_id,
82
+ checkType: row.check_type,
83
+ score: row.score,
84
+ passed: row.passed,
85
+ hardConstraintsPassed: row.hard_constraints_passed,
86
+ details: row.details ? JSON.parse(row.details) : null,
87
+ fixSuggestions: row.fix_suggestions ? JSON.parse(row.fix_suggestions) : null,
88
+ rubricVersion: row.rubric_version,
89
+ modelName: row.model_name,
90
+ promptHash: row.prompt_hash,
91
+ createdAt: new Date(row.created_at),
92
+ })) as QualityCheckRecord[];
93
+ }
94
+
95
+ /**
96
+ * 关闭数据库连接
97
+ */
98
+ close(): void {
99
+ this.db.close();
100
+ logger.info('SQLite quality check repository connection closed');
101
+ }
102
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * SQLite Result Repository
3
+ *
4
+ * 使用 better-sqlite3 实现的轻量级结果数据访问层
5
+ * 适合开发和测试环境
6
+ */
7
+
8
+ import Database from 'better-sqlite3';
9
+ import { v4 as uuidv4 } from 'uuid';
10
+ import { createLogger } from '../../infrastructure/logging/logger.js';
11
+ import type { IResultRepository, CreateResultParams, ResultRecord } from '../../domain/repositories/ResultRepository.js';
12
+
13
+ const logger = createLogger('SQLite:ResultRepository');
14
+
15
+ /**
16
+ * SQLite Result Repository 实现
17
+ */
18
+ export class SQLiteResultRepository implements IResultRepository {
19
+ private db: Database.Database;
20
+
21
+ constructor(dbPath?: string) {
22
+ const actualDbPath = dbPath || './data/content-creator.db';
23
+ this.db = new Database(actualDbPath);
24
+ logger.info('SQLite result repository initialized', { dbPath: actualDbPath });
25
+ }
26
+
27
+ /**
28
+ * 创建结果记录
29
+ */
30
+ async create(params: CreateResultParams): Promise<void> {
31
+ const now = new Date().toISOString();
32
+ const stmt = this.db.prepare(`
33
+ INSERT INTO results (
34
+ id, task_id, result_type, content, file_path, metadata, created_at
35
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
36
+ `);
37
+
38
+ const metadata = params.metadata ? JSON.stringify(params.metadata) : null;
39
+
40
+ try {
41
+ stmt.run(
42
+ uuidv4(), // 使用 UUID v4 确保唯一性
43
+ params.taskId,
44
+ params.resultType,
45
+ params.content || null,
46
+ params.filePath || null,
47
+ metadata,
48
+ now
49
+ );
50
+
51
+ logger.info('Result created', {
52
+ taskId: params.taskId,
53
+ resultType: params.resultType,
54
+ });
55
+ } catch (error) {
56
+ logger.error('Failed to create result', { error: error as any, params });
57
+ throw error;
58
+ }
59
+ }
60
+
61
+ /**
62
+ * 根据任务 ID 查询结果
63
+ */
64
+ async findByTaskId(taskId: string): Promise<ResultRecord[]> {
65
+ const stmt = this.db.prepare('SELECT * FROM results WHERE task_id = ? ORDER BY result_type');
66
+ const rows = stmt.all(taskId) as any[];
67
+
68
+ return rows.map((row) => ({
69
+ id: row.id,
70
+ taskId: row.task_id,
71
+ resultType: row.result_type,
72
+ content: row.content,
73
+ filePath: row.file_path,
74
+ metadata: row.metadata ? JSON.parse(row.metadata) : null,
75
+ createdAt: new Date(row.created_at),
76
+ })) as ResultRecord[];
77
+ }
78
+
79
+ /**
80
+ * 删除任务的所有结果
81
+ */
82
+ async deleteByTaskId(taskId: string): Promise<void> {
83
+ const stmt = this.db.prepare('DELETE FROM results WHERE task_id = ?');
84
+ stmt.run(taskId);
85
+ logger.info('Results deleted', { taskId });
86
+ }
87
+
88
+ /**
89
+ * 关闭数据库连接
90
+ */
91
+ close(): void {
92
+ this.db.close();
93
+ logger.info('SQLite result repository connection closed');
94
+ }
95
+ }