Apply repo-wide Prettier/lint normalization across admin-web,
desktop-client and ops-web: single quotes, no semicolons, trailing
commas, consistent line wrapping, and import ordering. Also drop an
unused brand-logo import in DesktopShell.vue.
No behavior changes — formatting only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The desktop publish queue could stall for a long time and end users assumed
the software was broken. Root cause: a hung adapter held its execution slot
with no wall-clock timeout while auto-renewing its lease forever, so the
server never reclaimed it and every queued task behind it stayed 等待发布.
Auto-recovery also risked silently re-posting a non-idempotent article.
Client (Electron):
- per-task wall-clock deadline + abort; progress-gated lease renewal that
stops and aborts a stalled task instead of renewing it forever
- decouple the concurrency cap from CDP-induced CPU/memory pressure
(admission gate instead of self-throttling collapse); 15s watchdog pump
- all adapter network I/O now has fetch timeouts and honors context.signal;
bounded image-upload concurrency with per-image timeout
- surface live adapter progress, elapsed time, queue position and a
working-vs-queued distinction in the publish view
Server (tenant-api):
- publish lease-recovery worker (every 3m) + supporting index: reclaim
expired in_progress publish leases, requeue (<3 attempts) or terminal-fail
- 3-minute lease TTL with client-presence-gated extension; max 3 attempts
Idempotency (production-grade core):
- durable publish_submit_started_at marker, set before the irreversible
platform submit POST; recovery and abort route a maybe-submitted task to
unknown (manual reconcile, kept in the dedup set) instead of re-posting
- desktop UI requires explicit confirmation before retrying a possibly-
already-published task
Verified: go build/vet/test (incl. resolvePublishRecoveryOutcome), vue-tsc,
vitest 141/141, gofmt all clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When a public asset URL fails (e.g. stale signed token), retry via the
new /api/desktop/content/assets endpoint with the desktop Bearer token
so editor images keep rendering across token rotations.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduce a reusable helper that produces upload-ready blobs for
adapters that share the same image-asset semantics (dongchedi,
sohuhao, wangyihao, weixin-gzh, zol). Centralizes URL candidate
expansion and passthrough mime detection so each adapter focuses on
its own publish protocol.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>