pixivflow 2.20.5 → 2.22.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 (32) hide show
  1. package/README.en.md +179 -56
  2. package/README.md +110 -57
  3. package/dist/commands/SchedulerCommand.js +63 -0
  4. package/dist/commands/SchedulerIdleLifecycle.d.ts +8 -0
  5. package/dist/commands/SchedulerIdleLifecycle.js +2 -1
  6. package/dist/commands/scheduler-runtime.js +17 -0
  7. package/dist/config/types.d.ts +26 -0
  8. package/dist/config/validation.js +21 -0
  9. package/dist/delivery/types.d.ts +15 -0
  10. package/dist/notification/NotificationPolicy.d.ts +2 -0
  11. package/dist/notification/NotificationPolicy.js +18 -1
  12. package/dist/package.json +1 -1
  13. package/dist/scheduler/MultiScheduleManager.d.ts +12 -1
  14. package/dist/scheduler/MultiScheduleManager.js +46 -50
  15. package/dist/scheduler/RecoveryPolicy.d.ts +45 -0
  16. package/dist/scheduler/RecoveryPolicy.js +63 -0
  17. package/dist/scheduler/ResourceAdmission.d.ts +68 -0
  18. package/dist/scheduler/ResourceAdmission.js +83 -0
  19. package/dist/scheduler/ScheduleTriggerServer.d.ts +16 -0
  20. package/dist/scheduler/ScheduleTriggerServer.js +55 -0
  21. package/dist/scheduler/Scheduler.d.ts +19 -2
  22. package/dist/scheduler/Scheduler.js +12 -3
  23. package/dist/scheduler/SlotCoordinator.d.ts +20 -0
  24. package/dist/scheduler/SlotCoordinator.js +44 -2
  25. package/dist/scheduler/TargetOutcome.d.ts +31 -0
  26. package/dist/scheduler/TargetOutcome.js +128 -0
  27. package/dist/storage/DatabaseMigration.js +17 -0
  28. package/dist/storage/repositories/SlotRepository.d.ts +29 -0
  29. package/dist/storage/repositories/SlotRepository.js +28 -2
  30. package/dist/version.js +1 -1
  31. package/dist/webui/package.json +1 -1
  32. package/package.json +2 -2
@@ -29,6 +29,15 @@ export interface SlotRecord {
29
29
  manualRequestId: string | null;
30
30
  /** Opaque caller correlation (review chain / review id); null unless manual. */
31
31
  correlationId: string | null;
32
+ /**
33
+ * Request UUID of a remote MANUAL RECOVERY run (§manual-recovery); null for
34
+ * scheduled occurrences and review refetches. A recovery slot re-runs the
35
+ * failed target(s) under a per-occurrence recovery policy and reports its
36
+ * outcome through the schedule-outcome channel.
37
+ */
38
+ recoveryRequestId: string | null;
39
+ /** Recovery policy preset ('normal'|'relaxed'); null for non-recovery slots. */
40
+ recoveryMode: string | null;
32
41
  }
33
42
  export interface SlotItemRecord {
34
43
  id: number;
@@ -45,6 +54,14 @@ export interface SlotItemRecord {
45
54
  */
46
55
  fallback_stage: number;
47
56
  lastError: string | null;
57
+ /**
58
+ * Normalized terminal failure reason code (§terminal-reason) — one of the
59
+ * stable codes in TargetOutcome's failure taxonomy. Null for non-terminal
60
+ * cells or successful submissions.
61
+ */
62
+ terminalReasonCode: string | null;
63
+ /** User-facing business message for the terminal reason. */
64
+ terminalReasonMessage: string | null;
48
65
  createdAt: string;
49
66
  updatedAt: string;
50
67
  completedAt: string | null;
@@ -61,6 +78,8 @@ export interface SlotItemRecord {
61
78
  export declare class SlotRepository extends BaseRepository {
62
79
  /** Exact manual request/target lookup for authenticated convergence checks. */
63
80
  findManualSlot(requestId: string, targetId: string): SlotRecord | null;
81
+ /** Exact manual RECOVERY request/target lookup (§manual-recovery). */
82
+ findRecoverySlot(requestId: string, targetId: string): SlotRecord | null;
64
83
  /**
65
84
  * Fetch an existing slot or create it. On creation the schedule's target
66
85
  * membership is snapshotted (target_ids); a later config reload never mutates
@@ -81,6 +100,10 @@ export declare class SlotRepository extends BaseRepository {
81
100
  manualRequestId?: string | null;
82
101
  /** Opaque caller correlation recorded with a manual slot. */
83
102
  correlationId?: string | null;
103
+ /** Manual recovery request UUID (opens a `recover-` slot). */
104
+ recoveryRequestId?: string | null;
105
+ /** Manual recovery policy preset ('normal' | 'relaxed'). */
106
+ recoveryMode?: string | null;
84
107
  }): {
85
108
  slot: SlotRecord;
86
109
  created: boolean;
@@ -143,6 +166,12 @@ export declare class SlotRepository extends BaseRepository {
143
166
  bumpFallbackStage(slotId: string, targetId: string, reason: string): number;
144
167
  cellFallbackStage(slotId: string, targetId: string): number;
145
168
  setCellStatus(slotId: string, targetId: string, status: CellStatus, error?: string): void;
169
+ /**
170
+ * Persist the normalized terminal failure reason for a cell (§terminal-reason).
171
+ * Idempotent; a retried recovery/rollup only ever overwrites with the same or
172
+ * a later reasoned verdict.
173
+ */
174
+ setCellTerminalReason(slotId: string, targetId: string, code: string, message: string): void;
146
175
  /**
147
176
  * Transition a cell with FSM validation. Never downgrades a confirmed cell;
148
177
  * an illegal transition throws rather than silently corrupting state.
@@ -17,6 +17,11 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
17
17
  const rows = this.db.prepare(`SELECT * FROM schedule_slots WHERE manual_request_id = ?`).all(requestId);
18
18
  return rows.map((row) => this.toSlot(row)).find((slot) => slot.targetIds.includes(targetId)) ?? null;
19
19
  }
20
+ /** Exact manual RECOVERY request/target lookup (§manual-recovery). */
21
+ findRecoverySlot(requestId, targetId) {
22
+ const rows = this.db.prepare(`SELECT * FROM schedule_slots WHERE recovery_request_id = ?`).all(requestId);
23
+ return rows.map((row) => this.toSlot(row)).find((slot) => slot.targetIds.includes(targetId)) ?? null;
24
+ }
20
25
  /**
21
26
  * Fetch an existing slot or create it. On creation the schedule's target
22
27
  * membership is snapshotted (target_ids); a later config reload never mutates
@@ -26,10 +31,12 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
26
31
  getOrCreateSlot(id, data) {
27
32
  const insert = this.db.prepare(`INSERT INTO schedule_slots
28
33
  (id, schedule_id, occurrence_at, occurrence_date, occurrence_label, timezone, target_ids,
29
- status, trigger_source, slot_date, slot_name, manual_request_id, correlation_id)
34
+ status, trigger_source, slot_date, slot_name, manual_request_id, correlation_id,
35
+ recovery_request_id, recovery_mode)
30
36
  VALUES
31
37
  (@id, @scheduleId, @occurrenceAt, @occurrenceDate, @occurrenceLabel, @timezone, @targetIds,
32
- 'pending', @triggerSource, @slotDate, @slotName, @manualRequestId, @correlationId)
38
+ 'pending', @triggerSource, @slotDate, @slotName, @manualRequestId, @correlationId,
39
+ @recoveryRequestId, @recoveryMode)
33
40
  ON CONFLICT(id) DO NOTHING`);
34
41
  const info = insert.run({
35
42
  id,
@@ -44,6 +51,8 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
44
51
  slotName: data.slotName ?? '',
45
52
  manualRequestId: data.manualRequestId ?? null,
46
53
  correlationId: data.correlationId ?? null,
54
+ recoveryRequestId: data.recoveryRequestId ?? null,
55
+ recoveryMode: data.recoveryMode ?? null,
47
56
  });
48
57
  const created = info.changes > 0;
49
58
  return { slot: this.getSlot(id), created };
@@ -244,6 +253,19 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
244
253
  .prepare(`UPDATE schedule_slot_items SET ${sets.join(', ')} WHERE slot_id = @slotId AND target_id = @targetId`)
245
254
  .run({ slotId, targetId, status, error: error ?? null });
246
255
  }
256
+ /**
257
+ * Persist the normalized terminal failure reason for a cell (§terminal-reason).
258
+ * Idempotent; a retried recovery/rollup only ever overwrites with the same or
259
+ * a later reasoned verdict.
260
+ */
261
+ setCellTerminalReason(slotId, targetId, code, message) {
262
+ this.db
263
+ .prepare(`UPDATE schedule_slot_items
264
+ SET terminal_reason_code = @code, terminal_reason_message = @message,
265
+ updated_at = CURRENT_TIMESTAMP
266
+ WHERE slot_id = @slotId AND target_id = @targetId`)
267
+ .run({ slotId, targetId, code: code.slice(0, 64), message: message.slice(0, 400) });
268
+ }
247
269
  /**
248
270
  * Transition a cell with FSM validation. Never downgrades a confirmed cell;
249
271
  * an illegal transition throws rather than silently corrupting state.
@@ -402,6 +424,8 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
402
424
  heartbeatAt: row.heartbeat_at ?? null,
403
425
  manualRequestId: row.manual_request_id ?? null,
404
426
  correlationId: row.correlation_id ?? null,
427
+ recoveryRequestId: row.recovery_request_id ?? null,
428
+ recoveryMode: row.recovery_mode ?? null,
405
429
  };
406
430
  }
407
431
  toItem(row) {
@@ -415,6 +439,8 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
415
439
  attemptCount: row.attempt_count,
416
440
  fallback_stage: Number(row.fallback_stage ?? 0),
417
441
  lastError: row.last_error,
442
+ terminalReasonCode: row.terminal_reason_code ?? null,
443
+ terminalReasonMessage: row.terminal_reason_message ?? null,
418
444
  createdAt: row.created_at,
419
445
  updatedAt: row.updated_at,
420
446
  completedAt: row.completed_at,
package/dist/version.js CHANGED
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BUILD = void 0;
4
4
  // GENERATED by scripts/write-version.js — do not edit manually.
5
- exports.BUILD = { version: '2.20.5', commit: '9352c0253571' };
5
+ exports.BUILD = { version: '2.22.0', commit: 'e6cd6211dba7' };
6
6
  //# sourceMappingURL=version.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "type": "commonjs",
3
3
  "name": "pixivflow-webui-backend",
4
- "version": "2.20.5",
4
+ "version": "2.22.0",
5
5
  "description": "PixivFlow WebUI Backend - CommonJS module"
6
6
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pixivflow",
3
- "version": "2.20.5",
4
- "description": "🎨 智能的 Pixiv 自动化下载工具 - 支持批量下载插画和小说、定时任务、Docker部署 | Intelligent Pixiv Automation Downloader with batch download, scheduler, and Docker support",
3
+ "version": "2.22.0",
4
+ "description": "🎨 Pixiv 下载、筛选与自动收集工具 - 批量下载插画和小说、按标签/热度/日期筛选、定时任务与可靠 HTTP 交付 | Pixiv downloader and automation toolkit with filtering, scheduling and reliable HTTP delivery",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/redtidev1918/PixivFlow.git"