Commit Graph
3 Commits
Author SHA1 Message Date
pastilhasandClaude Opus 4.8 c55ec5884b download job: collapse to one phase (no metadata prefetch)
The job's two phases were a misread — the "count" phase is the client-side
playlist expansion (for the inline-vs-job decision, already done in the panel).
The job itself is just one download request per item.

Dropped the in-job metadata pass entirely:
- reclip-client: reclipDownloadOne no longer prefetches /api/info for a title —
  ReClip names the file from the video title itself, so it's a single request
  per item.
- execute-download: one phase — expand the playlist, then /api/download each url,
  skip failures. Progress is a single { done, failed, total, current } counter
  (no meta/dl split); ~2× faster and downloads start right after expansion.
- UI (DownloadJobDetail + panel JobView): one "Downloaded" bar instead of two.

Verified: every item is attempted directly (no /api/info gate), skip-on-error
counts correct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 18:35:10 +00:00
pastilhasandClaude Opus 4.8 bc1b799a27 jobs: download-job UI — panel decision screen + live progress + /jobs renderer
Front half of the download-job feature.

Panel (VideoDownloadPanel): after Fetch expands a playlist and the count is known,
a decision screen — "Found N items" → pick Audio/Video + subfolder → "Download all
as a job" (POST /jobs/download), or "fetch inline to pick individually" (the
existing card grid). A single video still goes straight to the inline card. The
job phase shows live two-phase progress (polled from the job) + a "View in Jobs"
link; it notes the job runs server-side so closing the panel is fine, and it
refreshes the browser as each file lands.

/jobs (DownloadJobDetail + JobsPage dispatch): a `download` job renders a compact
two-phase readout — Metadata and Download bars (processed/total, found/skipped and
saved/failed) + the current item — polled from the job's progress, with a Stop.

Executor tweak: phase-1 meta.done now counts kept (not processed) so both phases
read the same `(done+failed)/total`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 18:20:07 +00:00
pastilhasandClaude Opus 4.8 4e78986e39 jobs: video/audio download as a two-phase job (backend)
Turns the downloader into a server-side job on the existing jobs spine (Postgres
persistence, live WS viewers + replay, abort, /jobs UI) — but with its own
executor and its own lane, since it's deterministic scripting, not an agent, and
a multi-hour playlist mustn't block agentic jobs.

- reclip-client.ts (new, shared): reclipInfo / reclipPlaylist / reclipDownloadOne
  (single download → streams the file to a dir, abort-aware). Extracted so both
  the file-browser endpoints and the job executor use one client.
- execute-download.ts (new): the two-phase executor —
  phase 1 metadata (expand playlist, fetch each info, keep survivors, skip
  errors), phase 2 download (each survivor in the chosen format; skip download
  errors). Emits a compact `download:progress` snapshot (counters, not per-item
  events — playlists are thousands of items). Throws on abort / fatal.
- job manager: `download` mode dispatch → executeDownload; persists
  download:progress; adds execution LANES (download vs default) so the two run
  independently and each serializes on its own; promoteNext fills both lanes.
- POST /api/tasks/jobs/download { url, format, dir, root?, label? } — enqueues a
  download job (own lane, no capability task needed; traversal-guarded target).
- schema: `download` added to the mode enum (drizzle text-enum — no DB migration);
  getPendingJobs() query for lane filling.

Verified the executor with a mocked ReClip client: two-phase filtering, skip-on-
error counts, and abort-throws all correct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 18:09:37 +00:00