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
@@ -0,0 +1,241 @@
1
+ /**
2
+ * CLI Retry Command
3
+ *
4
+ * 重新执行历史任务
5
+ */
6
+
7
+ import { Command } from 'commander';
8
+ import chalk from 'chalk';
9
+ import { createTaskRepository } from '../../../infrastructure/database/index.js';
10
+ import { TaskQueue } from '../../../infrastructure/queue/TaskQueue.js';
11
+ import { createLogger } from '../../../infrastructure/logging/logger.js';
12
+
13
+ const logger = createLogger('CLI:Retry');
14
+
15
+ function printSeparator() {
16
+ console.log(chalk.gray('─'.repeat(80)));
17
+ }
18
+
19
+ export const retryCommand = new Command('retry')
20
+ .description('重新执行任务')
21
+ .option('-t, --task-id <id>', '重新执行指定任务')
22
+ .option('-a, --all', '重新执行所有等待中的任务')
23
+ .option('-s, --status <status>', '按状态筛选任务 (pending, failed, cancelled)', 'pending')
24
+ .option('-l, --limit <number>', '处理数量限制', '10')
25
+ .option('--dry-run', '模拟运行,不实际执行')
26
+ .action(async (options) => {
27
+ try {
28
+ printSeparator();
29
+ console.log(chalk.bold.blue('🔄 重新执行任务'));
30
+ printSeparator();
31
+
32
+ const repository = createTaskRepository();
33
+ const queue = new TaskQueue();
34
+
35
+ // 方案 1: 重新执行指定任务
36
+ if (options.taskId) {
37
+ await retrySingleTask(options.taskId, repository, queue, options.dryRun);
38
+ process.exit(0);
39
+ }
40
+
41
+ // 方案 2: 批量重新执行
42
+ if (options.all) {
43
+ const limit = parseInt(options.limit) || 10;
44
+ await retryBatchTasks(options.status, limit, repository, queue, options.dryRun);
45
+ process.exit(0);
46
+ }
47
+
48
+ // 没有指定参数,显示帮助
49
+ console.log(chalk.yellow('请指定要重新执行的任务:'));
50
+ console.log(chalk.white('1. 重新执行单个任务:'));
51
+ console.log(chalk.gray(' pnpm run cli:retry --task-id <任务ID>'));
52
+ console.log(chalk.white('\n2. 批量重新执行所有等待任务:'));
53
+ console.log(chalk.gray(' pnpm run cli:retry --all'));
54
+ console.log(chalk.white('\n3. 批量重新执行失败任务:'));
55
+ console.log(chalk.gray(' pnpm run cli:retry --all --status failed'));
56
+ console.log(chalk.white('\n4. 模拟运行(不实际执行):'));
57
+ console.log(chalk.gray(' pnpm run cli:retry --all --dry-run'));
58
+ console.log();
59
+
60
+ process.exit(0);
61
+ } catch (error) {
62
+ logger.error('Failed to retry tasks', error as Error);
63
+ console.error(chalk.red('❌ 重新执行失败:'), (error as Error).message);
64
+ process.exit(1);
65
+ } finally {
66
+ // 清理队列连接
67
+ try {
68
+ const queue = new TaskQueue();
69
+ await queue.close();
70
+ } catch (error) {
71
+ // 忽略清理错误
72
+ }
73
+ }
74
+ });
75
+
76
+ /**
77
+ * 重新执行单个任务
78
+ */
79
+ async function retrySingleTask(
80
+ taskId: string,
81
+ repository: any,
82
+ queue: TaskQueue,
83
+ dryRun: boolean = false
84
+ ): Promise<void> {
85
+ console.log(chalk.white(`📝 任务 ID: ${chalk.bold(taskId)}`));
86
+ console.log();
87
+
88
+ // 1. 查询任务
89
+ const task = await repository.findById(taskId);
90
+
91
+ if (!task) {
92
+ console.log(chalk.red('❌ 任务不存在'));
93
+ process.exit(1);
94
+ }
95
+
96
+ console.log(chalk.gray('任务信息:'));
97
+ console.log(chalk.gray(` 主题: ${task.topic}`));
98
+ console.log(chalk.gray(` 状态: ${task.status}`));
99
+ console.log(chalk.gray(` 模式: ${task.mode}`));
100
+ console.log(chalk.gray(` 创建时间: ${task.createdAt?.toLocaleString('zh-CN')}`));
101
+ console.log();
102
+
103
+ // 2. 检查任务状态
104
+ if (task.status === 'running' || task.status === 'processing') {
105
+ console.log(chalk.yellow('⚠️ 任务正在运行中,无需重新执行'));
106
+ process.exit(0);
107
+ }
108
+
109
+ if (task.status === 'completed') {
110
+ console.log(chalk.yellow('⚠️ 任务已完成,如需重新执行请创建新任务'));
111
+ process.exit(0);
112
+ }
113
+
114
+ // 3. 模拟运行
115
+ if (dryRun) {
116
+ console.log(chalk.blue('🔍 [模拟运行] 将会执行以下操作:'));
117
+ console.log(chalk.gray(` 1. 将任务添加到 Redis 队列`));
118
+ console.log(chalk.gray(` 2. Worker 将会获取并处理该任务`));
119
+ console.log();
120
+ console.log(chalk.yellow('💡 这是模拟运行,没有实际执行'));
121
+ console.log(chalk.gray(' 去掉 --dry-run 参数即可实际执行'));
122
+ console.log();
123
+ return;
124
+ }
125
+
126
+ // 4. 添加到队列
127
+ try {
128
+ console.log(chalk.white('⏳ 正在添加到队列...'));
129
+
130
+ await queue.addTask({
131
+ taskId: task.taskId,
132
+ mode: task.mode === 'sync' ? 'sync' : 'async',
133
+ topic: task.topic,
134
+ requirements: task.requirements,
135
+ hardConstraints: task.hardConstraints,
136
+ });
137
+
138
+ console.log(chalk.green('✅ 任务已添加到队列!'));
139
+ console.log();
140
+ console.log(chalk.white('💡 后续操作:'));
141
+ console.log(chalk.gray(' 1. 确保 Worker 正在运行: pnpm run worker'));
142
+ console.log(chalk.gray(' 2. 查看任务状态: pnpm run cli:status --task-id ' + task.taskId));
143
+ console.log();
144
+
145
+ logger.info('Task retried', { taskId, topic: task.topic });
146
+ } catch (error) {
147
+ console.log(chalk.red('❌ 添加到队列失败:'), (error as Error).message);
148
+ throw error;
149
+ }
150
+ }
151
+
152
+ /**
153
+ * 批量重新执行任务
154
+ */
155
+ async function retryBatchTasks(
156
+ status: string,
157
+ limit: number,
158
+ repository: any,
159
+ queue: TaskQueue,
160
+ dryRun: boolean = false
161
+ ): Promise<void> {
162
+ console.log(chalk.white(`📊 批量重新执行 ${chalk.bold(status)} 状态的任务`));
163
+ console.log(chalk.gray(`限制: ${limit} 个`));
164
+ console.log();
165
+
166
+ // 1. 查询任务
167
+ const tasks = await repository.findMany({ status }, { limit });
168
+
169
+ if (tasks.length === 0) {
170
+ console.log(chalk.yellow('✅ 没有找到需要重新执行的任务'));
171
+ console.log();
172
+ return;
173
+ }
174
+
175
+ console.log(chalk.gray(`找到 ${tasks.length} 个任务\n`));
176
+
177
+ // 2. 显示任务列表
178
+ console.log(chalk.gray('任务列表:'));
179
+ tasks.forEach((task: any, index: number) => {
180
+ console.log(chalk.gray(` ${index + 1}. ${task.taskId}`));
181
+ console.log(chalk.gray(` 主题: ${task.topic}`));
182
+ console.log(chalk.gray(` 状态: ${task.status}`));
183
+ console.log();
184
+ });
185
+
186
+ // 3. 模拟运行
187
+ if (dryRun) {
188
+ console.log(chalk.blue('🔍 [模拟运行] 将会执行以下操作:'));
189
+ console.log(chalk.gray(` 将 ${tasks.length} 个任务添加到 Redis 队列`));
190
+ console.log();
191
+ console.log(chalk.yellow('💡 这是模拟运行,没有实际执行'));
192
+ console.log(chalk.gray(' 去掉 --dry-run 参数即可实际执行'));
193
+ console.log();
194
+ return;
195
+ }
196
+
197
+ // 4. 批量添加到队列
198
+ console.log(chalk.white('⏳ 正在批量添加到队列...\n'));
199
+
200
+ let successCount = 0;
201
+ let failCount = 0;
202
+
203
+ for (const task of tasks) {
204
+ try {
205
+ await queue.addTask({
206
+ taskId: task.taskId,
207
+ mode: task.mode === 'sync' ? 'sync' : 'async',
208
+ topic: task.topic,
209
+ requirements: task.requirements,
210
+ hardConstraints: task.hardConstraints,
211
+ });
212
+
213
+ console.log(chalk.green(`✅ ${task.taskId}`));
214
+ successCount++;
215
+ } catch (error) {
216
+ console.log(chalk.red(`❌ ${task.taskId} - ${(error as Error).message}`));
217
+ failCount++;
218
+ }
219
+ }
220
+
221
+ console.log();
222
+ console.log(chalk.white('📊 执行结果:'));
223
+ console.log(chalk.green(` 成功: ${successCount} 个`));
224
+ if (failCount > 0) {
225
+ console.log(chalk.red(` 失败: ${failCount} 个`));
226
+ }
227
+ console.log();
228
+
229
+ if (successCount > 0) {
230
+ console.log(chalk.white('💡 后续操作:'));
231
+ console.log(chalk.gray(' 1. 确保 Worker 正在运行: pnpm run worker'));
232
+ console.log(chalk.gray(' 2. 查看任务列表: pnpm run cli:list'));
233
+ console.log();
234
+ }
235
+
236
+ logger.info('Batch retry completed', {
237
+ total: tasks.length,
238
+ success: successCount,
239
+ failed: failCount,
240
+ });
241
+ }
@@ -6,7 +6,7 @@
6
6
 
7
7
  import { Command } from 'commander';
8
8
  import chalk from 'chalk';
9
- import { PostgresTaskRepository } from '../../../infrastructure/database/PostgresTaskRepository.js';
9
+ import { createTaskRepository } from '../../../infrastructure/database/index.js';
10
10
  import { getStatusText, formatDate, formatDuration, printSeparator } from '../utils/formatter.js';
11
11
  import { cleanupResources } from '../utils/cleanup.js';
12
12
 
@@ -14,7 +14,7 @@ export const statusCommand = new Command('status')
14
14
  .description('查询任务状态')
15
15
  .requiredOption('-t, --task-id <taskId>', '任务ID')
16
16
  .action(async (options) => {
17
- const taskRepo = new PostgresTaskRepository();
17
+ const taskRepo = createTaskRepository();
18
18
 
19
19
  try {
20
20
  const task = await taskRepo.findById(options.taskId);
@@ -71,6 +71,7 @@ export const statusCommand = new Command('status')
71
71
 
72
72
  // 清理资源并正常退出
73
73
  await cleanupResources(taskRepo);
74
+ process.exit(0);
74
75
 
75
76
  } catch (error) {
76
77
  console.error(chalk.red(`❌ 错误: ${error instanceof Error ? error.message : String(error)}`));
@@ -11,6 +11,8 @@ import { createCommand } from './commands/create.js';
11
11
  import { statusCommand } from './commands/status.js';
12
12
  import { resultCommand } from './commands/result.js';
13
13
  import { cancelCommand } from './commands/cancel.js';
14
+ import { listCommand } from './commands/list.js';
15
+ import { retryCommand } from './commands/retry.js';
14
16
  import { createLogger } from '../../infrastructure/logging/logger.js';
15
17
 
16
18
  const logger = createLogger('CLI');
@@ -26,6 +28,8 @@ program
26
28
 
27
29
  // 添加命令
28
30
  program.addCommand(createCommand);
31
+ program.addCommand(listCommand);
32
+ program.addCommand(retryCommand);
29
33
  program.addCommand(statusCommand);
30
34
  program.addCommand(resultCommand);
31
35
  program.addCommand(cancelCommand);
@@ -11,7 +11,7 @@ import { closeLogger } from '../../../infrastructure/logging/logger.js';
11
11
  *
12
12
  * @param repositories - 需要关闭的 Repository 数组
13
13
  */
14
- export async function cleanupResources(...repositories: Array<{ close?: () => Promise<void> }>): Promise<void> {
14
+ export async function cleanupResources(...repositories: Array<any>): Promise<void> {
15
15
  const errors: Array<Error> = [];
16
16
 
17
17
  // 1. 关闭所有 Repository 连接池
@@ -6,10 +6,8 @@
6
6
  */
7
7
 
8
8
  import { Command } from 'commander';
9
- // @ts-ignore - Module resolution issue with NodeNext
10
- import { startMonitorServer } from '../../monitoring/index';
11
- // @ts-ignore - Module resolution issue with NodeNext
12
- import { createLogger } from '../../infrastructure/logging/logger';
9
+ import { startMonitorServer } from '../monitoring/index.js';
10
+ import { createLogger } from '../infrastructure/logging/logger.js';
13
11
 
14
12
  const logger = createLogger('MonitorCLI');
15
13
  const program = new Command();
@@ -6,10 +6,9 @@
6
6
  */
7
7
 
8
8
  import { Command } from 'commander';
9
- // @ts-ignore - Module resolution issue with NodeNext
10
- import { createTaskWorker } from '../../workers/index';
11
- // @ts-ignore - Module resolution issue with NodeNext
12
- import { createLogger } from '../../infrastructure/logging/logger';
9
+ import { v4 as uuidv4 } from 'uuid';
10
+ import { createTaskWorker } from '../workers/TaskWorker.js';
11
+ import { createLogger } from '../infrastructure/logging/logger.js';
13
12
 
14
13
  const logger = createLogger('WorkerCLI');
15
14
  const program = new Command();
@@ -22,7 +21,7 @@ program
22
21
  program
23
22
  .command('start')
24
23
  .description('启动 Worker')
25
- .option('-w, --worker-id <id>', 'Worker ID', process.env.WORKER_ID || `worker-${process.pid}`)
24
+ .option('-w, --worker-id <id>', 'Worker ID', process.env.WORKER_ID || `worker-${uuidv4()}`)
26
25
  .option('-c, --concurrency <number>', '并发数', '2')
27
26
  .action(async (options) => {
28
27
  try {
@@ -55,6 +54,10 @@ program
55
54
  logger.info('Worker running, press Ctrl+C to stop');
56
55
  } catch (error) {
57
56
  logger.error('Failed to start worker', error as Error);
57
+ console.error('Detailed error:', error);
58
+ if (error instanceof Error) {
59
+ console.error('Stack trace:', error.stack);
60
+ }
58
61
  process.exit(1);
59
62
  }
60
63
  });
@@ -126,7 +126,17 @@ export class TaskScheduler {
126
126
  };
127
127
 
128
128
  // 4. 保存到数据库
129
- await this.repository.create(task as Task);
129
+ await this.repository.create({
130
+ id: task.id!,
131
+ traceId: undefined,
132
+ mode: task.mode!,
133
+ type: (task.type as any) || 'article',
134
+ topic: task.topic!,
135
+ requirements: task.requirements!,
136
+ hardConstraints: task.hardConstraints,
137
+ priority: task.priority,
138
+ maxRetries: 3,
139
+ });
130
140
 
131
141
  logger.info('Task created', {
132
142
  taskId,
@@ -263,10 +273,8 @@ export class TaskScheduler {
263
273
  return false;
264
274
  }
265
275
 
266
- await this.repository.update(taskId, {
267
- status: 'cancelled',
268
- updatedAt: new Date().toISOString(),
269
- });
276
+ // 使用 delete 方法标记任务为已取消
277
+ await this.repository.delete(taskId);
270
278
 
271
279
  logger.info('Task cancelled', { taskId });
272
280
 
@@ -5,9 +5,10 @@
5
5
  */
6
6
 
7
7
  import { Worker, Job } from 'bullmq';
8
+ import { v4 as uuidv4 } from 'uuid';
8
9
  import { getRedisClient } from '../infrastructure/redis/connection.js';
9
- import { createTaskRepository } from '../infrastructure/database/index.js';
10
- import { createSimpleContentCreatorGraph, createInitialState } from '../domain/workflow/index.js';
10
+ import { createTaskRepository, createResultRepository } from '../infrastructure/database/index.js';
11
+ import { createContentCreatorGraph, createInitialState } from '../domain/workflow/index.js';
11
12
  import { createLogger } from '../infrastructure/logging/logger.js';
12
13
  import type { TaskJobData } from '../infrastructure/queue/TaskQueue.js';
13
14
  import { ExecutionMode } from '../domain/entities/Task.js';
@@ -88,24 +89,35 @@ export class TaskWorker {
88
89
  // 更新任务进度
89
90
  await job.updateProgress(0);
90
91
 
92
+ let task: Awaited<ReturnType<typeof this.repository.findById>> | null = null;
93
+
91
94
  try {
92
95
  // 1. 抢占任务(使用乐观锁)
93
- const claimed = await this.repository.claimForProcessing(
96
+ task = await this.repository.findById(data.taskId);
97
+ if (!task) {
98
+ throw new Error(`Task not found: ${data.taskId}`);
99
+ }
100
+
101
+ const claimed = await this.repository.claimTask(
94
102
  data.taskId,
95
- this.workerId
103
+ this.workerId,
104
+ task.version
96
105
  );
97
106
 
98
107
  if (!claimed) {
99
- throw new Error(`Failed to claim task ${data.taskId}`);
108
+ throw new Error(`Failed to claim task ${data.taskId} (version mismatch or already claimed)`);
100
109
  }
101
110
 
111
+ // 更新任务版本号(claimTask 会将版本号 +1)
112
+ task.version = task.version + 1;
113
+
102
114
  logger.info('Task claimed', { taskId: data.taskId });
103
115
 
104
116
  // 更新进度 10%
105
117
  await job.updateProgress(10);
106
118
 
107
119
  // 2. 创建工作流图
108
- const graph = createSimpleContentCreatorGraph();
120
+ const graph = createContentCreatorGraph();
109
121
 
110
122
  // 3. 创建初始状态
111
123
  const initialState = createInitialState({
@@ -130,16 +142,31 @@ export class TaskWorker {
130
142
  await job.updateProgress(90);
131
143
 
132
144
  // 5. 保存结果
133
- await this.repository.update(data.taskId, {
134
- status: 'completed',
135
- completedAt: new Date().toISOString(),
136
- result: {
137
- articleContent: result.articleContent,
138
- searchResults: result.searchResults,
139
- organizedInfo: result.organizedInfo,
140
- images: result.images,
141
- },
142
- });
145
+ const resultRepo = createResultRepository();
146
+
147
+ if (result.articleContent) {
148
+ await resultRepo.create({
149
+ taskId: data.taskId,
150
+ resultType: 'article',
151
+ content: result.articleContent,
152
+ metadata: {
153
+ wordCount: result.articleContent.length,
154
+ },
155
+ });
156
+ }
157
+
158
+ if (result.images && result.images.length > 0) {
159
+ for (const image of result.images) {
160
+ await resultRepo.create({
161
+ taskId: data.taskId,
162
+ resultType: 'image',
163
+ content: image.url,
164
+ metadata: image.metadata,
165
+ });
166
+ }
167
+ }
168
+
169
+ await this.repository.markAsCompleted(data.taskId, task.version);
143
170
 
144
171
  const duration = Date.now() - startTime;
145
172
 
@@ -169,11 +196,9 @@ export class TaskWorker {
169
196
 
170
197
  // 保存错误信息
171
198
  try {
172
- await this.repository.update(data.taskId, {
173
- status: 'failed',
174
- error: errorMessage,
175
- completedAt: new Date().toISOString(),
176
- });
199
+ if (task) {
200
+ await this.repository.markAsFailed(data.taskId, errorMessage, task.version);
201
+ }
177
202
  } catch (updateError) {
178
203
  logger.error('Failed to update task error status', updateError as Error, {
179
204
  taskId: data.taskId,
@@ -315,6 +340,6 @@ export function createTaskWorker(
315
340
  workerId?: string,
316
341
  concurrency?: number
317
342
  ): TaskWorker {
318
- const id = workerId || process.env.WORKER_ID || `worker-${process.pid}`;
343
+ const id = workerId || process.env.WORKER_ID || `worker-${uuidv4()}`;
319
344
  return new TaskWorker(id, concurrency);
320
345
  }