pixivflow 2.21.0 → 2.22.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.
@@ -256,13 +256,12 @@ class OutboxWorker {
256
256
  }
257
257
  catch (error) {
258
258
  const message = (0, redact_1.redactError)(error).slice(0, 1000);
259
- const { errorClass } = (0, errorClass_1.classifyError)(error);
260
- // A local configuration error is deterministic: every attempt re-reads the
261
- // same config, so retrying only parks the row in `retry_wait` until its
262
- // attempt budget runs out. Dead-letter it now so it is visible instead.
263
- if (errorClass === 'configuration_error') {
259
+ const { errorClass, retryable } = (0, errorClass_1.classifyError)(error);
260
+ // Deterministic failures cannot improve under the same idempotent intent.
261
+ // Retrying them only leaves the owning Slot running until the budget expires.
262
+ if (!retryable) {
264
263
  this.database.outbox.markDead(row.id, message);
265
- this.deadLetter(row, `${message} (configuration error)`, errorClass);
264
+ this.deadLetter(row, message, errorClass);
266
265
  return 'dead';
267
266
  }
268
267
  // Transport-level error (fetch threw) or ack-classified failure: retryable.
@@ -336,8 +335,7 @@ class OutboxWorker {
336
335
  this.onDeliveryTerminal?.(row.deliveryId, ack, payload);
337
336
  break;
338
337
  case 'permanent_failure':
339
- // Deterministic rejection: still retry a couple times to survive a
340
- // misconfigured blip, the outbox max-attempts then dead-letters it.
338
+ // Deterministic rejection: the same idempotent intent cannot recover.
341
339
  throw new Error(`permanent delivery failure: ${ack.error}`);
342
340
  case 'retryable_failure':
343
341
  throw new Error(`retryable delivery failure: ${ack.error}`);
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "type": "commonjs",
3
3
  "name": "pixivflow",
4
- "version": "2.21.0",
4
+ "version": "2.22.1",
5
5
  "private": true
6
6
  }
@@ -271,7 +271,7 @@ export type TerminalReasonCode =
271
271
  /** Every candidate the scan saw was already delivered/pending for this target. */
272
272
  | 'duplicate_exhausted'
273
273
  /** Candidates existed but none passed the target's own filters. */
274
- | 'filter_exhausted' | 'download_timeout' | 'download_failed' | 'rate_limited' | 'auth_failed' | 'remote_http_error' | 'delivery_failed' | 'telegram_failed' | 'network_error' | 'execution_timeout' | 'configuration_error' | 'internal_error';
274
+ | 'filter_exhausted' | 'download_timeout' | 'download_failed' | 'metadata_failed' | 'rate_limited' | 'auth_failed' | 'remote_http_error' | 'delivery_failed' | 'telepost_rejected' | 'telegram_failed' | 'network_error' | 'execution_timeout' | 'configuration_error' | 'internal_error';
275
275
  export interface TerminalReason {
276
276
  code: TerminalReasonCode;
277
277
  /** Business-language message an operator/reviewer reads directly. */
@@ -233,10 +233,12 @@ exports.TERMINAL_REASON_MESSAGES = {
233
233
  filter_exhausted: '没有符合筛选条件的新作品',
234
234
  download_timeout: '图片下载超时',
235
235
  download_failed: '图片下载失败',
236
+ metadata_failed: '作品信息获取失败',
236
237
  rate_limited: 'Pixiv 请求频率受限',
237
238
  auth_failed: 'Pixiv 登录已失效,需要重新登录',
238
239
  remote_http_error: 'Pixiv 服务器返回错误',
239
240
  delivery_failed: '投稿投递失败',
241
+ telepost_rejected: '投稿被接收端拒绝',
240
242
  telegram_failed: 'Telegram 发送失败',
241
243
  network_error: '网络异常',
242
244
  execution_timeout: '执行超时',
@@ -327,6 +329,18 @@ function classifyFailedReason(message, scan) {
327
329
  if (/not configured|missing (?:config|configuration|setting)|invalid config/i.test(text)) {
328
330
  return { code: 'configuration_error', message: exports.TERMINAL_REASON_MESSAGES.configuration_error };
329
331
  }
332
+ // A candidate's metadata could not be gathered/parsed: this is its own root
333
+ // cause (config is fine; the upstream work was unreadable), so it must not
334
+ // fall through to internal_error or configuration_error.
335
+ if (/\bmetadata\b.{0,60}\b(?:fail|error|unable|invalid|parse|serialize|gather)\b|failed to (?:gather|parse|fetch|load|save)\b.{0,40}\bmetadata\b/i.test(text)) {
336
+ return { code: 'metadata_failed', message: exports.TERMINAL_REASON_MESSAGES.metadata_failed };
337
+ }
338
+ // TelePost (or any theme/review submission endpoint) explicitly rejected the
339
+ // work with a client-side / payload verdict. This is not a delivery outage
340
+ // (5xx/unreachable — handled above) nor a generic delivery failure.
341
+ if (/\btele[ _-]?post\b[^.\n]{0,60}\b(?:reject|invalid|4\d\d)\b/i.test(text)) {
342
+ return { code: 'telepost_rejected', message: exports.TERMINAL_REASON_MESSAGES.telepost_rejected };
343
+ }
330
344
  if (/delivery|submit(?:t?ed)?|publish|post|outbox/i.test(text)) {
331
345
  return { code: 'delivery_failed', message: exports.TERMINAL_REASON_MESSAGES.delivery_failed };
332
346
  }
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.21.0', commit: '56d4043e026e' };
5
+ exports.BUILD = { version: '2.22.1', commit: 'd7d248938926' };
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.21.0",
4
+ "version": "2.22.1",
5
5
  "description": "PixivFlow WebUI Backend - CommonJS module"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixivflow",
3
- "version": "2.21.0",
3
+ "version": "2.22.1",
4
4
  "description": "🎨 Pixiv 下载、筛选与自动收集工具 - 批量下载插画和小说、按标签/热度/日期筛选、定时任务与可靠 HTTP 交付 | Pixiv downloader and automation toolkit with filtering, scheduling and reliable HTTP delivery",
5
5
  "repository": {
6
6
  "type": "git",