Commit Graph
10 Commits
Author SHA1 Message Date
Giancarmine Salucci cd83c30e8e D3: Wire health preflight into pipeline before whisper submission
- Add health preflight gate after ensureWhisperRunning, before submitJob
- Uses getHealth() (existing) + retryWithBackoff for transient failures
- Network errors wrapped with 'whisper health check failed:' prefix
- Non-ok status fails job early with actual status in error message
- Revert compose.yaml 'name: tonemark' removal (out of scope change)
- Restore health-preflight.test.ts (228-line test covering all ACs)
- 8 test cases, 202 total tests passing, typecheck clean, build OK
2026-07-09 04:12:14 +02:00
Giancarmine Salucci 4de9390913 D2: Fix upload retry 500 on missing file — async fire-and-forget
retryJob() now wraps the file read in a fire-and-forget async IIFE using
fs/promises.readFile instead of readFileSync. When the original upload
file has been cleaned up (common after failure), the IIFE catches the
ENOENT error and marks the job as 'failed' with a 'retry failed:' prefix
asynchronously — the endpoint returns 200 immediately.

Includes 4 new integration tests:
- Missing file returns immediately (no throw), job async-fails
- ENOENT message propagated in job.error
- 404 on unknown job still works (unchanged contract)
- File present resets job to pending (runJob triggered)
2026-07-08 22:54:47 +02:00
Giancarmine Salucci f03b757174 D2: Widen retry to upload-source jobs
- Remove http-only guard in retry endpoint (src/routes/api/jobs/[id]/retry/+server.ts)
- Extend pipeline.ts retryJob() to handle upload-source jobs:
  read file from persistent storage, pass buffer to runJob
- Change saveUploadedFile() to save to DATA_DIR/uploads/{jobId}/
  (survives cleanupJobTmp, available for retry on failure)
- Add getUploadPath(), cleanupUploadDir() to downloader.ts
- Remove cleanupFiles(rawAudioPath) from catch block in runJob()
  — cleanupJobTmp handles TMP_DIR for YouTube, uploads survive
- Add cleanupUploadDir() on webhook success path
- Add retry-endpoint.test.ts with 9 tests covering:
  - 404 for unknown job
  - 409 for non-retryable status (done, pending)
  - 200 for cancelled (retryable)
  - 200 for failed YouTube job (existing behavior)
  - 200 for failed upload-source job (new behavior, .webm and .mp3)
  - Negative: retryJob not called on 404/409
- Add downloader.test.ts tests for saveUploadedFile persistent path,
  getUploadPath, cleanupUploadDir, isolation, and non-existent cleanup
- Fix webhook.test.ts mock to include cleanupUploadDir

All 189 tests pass across 12 test files.
2026-07-08 01:25:49 +02:00
Giancarmine Salucci d633f74689 Merge branch 'fleet/story-d1-webm-remux' 2026-07-08 01:18:41 +02:00
Giancarmine Salucci ffa931e959 D1: webm upload remux step for MediaRecorder output
New src/lib/server/remux.ts:
- remuxUpload(inputPath, jobId) — ffmpeg stream copy to fix Cues/duration
- Detects .webm by extension (case-insensitive), pass-through for others
- Wired into pipeline.ts upload branch after saveUploadedFile(),
  before prepareAudio() — YouTube path untouched

Regression tests (all passing, 0 regressions across 158 tests):
- Mock-based unit tests: ffmpeg invocation, non-webm pass-through, error cleanup
- Integration test w/ synthetic opus-in-webm fixture (lower-confidence flag)
  verifies remux produces valid webm with finalized duration
2026-07-08 00:43:43 +02:00
mozempkandCopilot f70cefc5e9 fix(progress): separate model warmup state
Build & Push Docker Image / test (push) Successful in 11s
Build & Push Docker Image / build-and-push (push) Successful in 42s
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-12 00:52:33 +02:00
mozempkandCopilot 929c482497 refactor(transcript): drop Tonemark rewrite
Build & Push Docker Image / test (push) Successful in 10s
Build & Push Docker Image / build-and-push (push) Successful in 50s
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-12 00:10:32 +02:00
Giancarmine SalucciandCopilot b90d57984c feat: model-on-demand lifecycle — retry on 503, live status pill, warming indicator
- whisper.ts: add getModelStatus(); fix submitJob() to retry on 503 using
  Retry-After header instead of throwing; optional onModelWaiting callback
  lets the pipeline surface model state to the UI during the wait
- pipeline.ts: pass onModelWaiting callback → emits model_warming SSE event
  so the job detail page can show 'Warming up model…' while waiting
- types.ts: add ModelStateTag union and ModelStatus interface
- api/model/status: GET route proxies whisper /model/status (falls back to
  {state:'unloaded'} if whisper unreachable)
- api/model/events: GET route relays whisper SSE stream to the browser;
  AbortController tied to request.signal cleans up on disconnect
- layout.svelte: status pill is now live — initial fetch + EventSource on
  /api/model/events; dot colour + label reflect real model state with a
  pulsing animation while loading or waiting_for_gpu
- jobs/[id]/+page.svelte: handle model_warming event type → show a yellow
  'Warming up model…' sub-label with spinner inside the progress card
- whisper.test.ts: update submitJob mocks to status:202 to match real API

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 00:08:21 +02:00
Giancarmine SalucciandCopilot d1295ce343 feat: add retry/delete for jobs
Build & Push Docker Image / build-and-push (push) Successful in 41s
- db.ts: add resetJob() and deleteJob() statements + exports
- pipeline.ts: export retryJob() — resets job state and re-runs pipeline
- DELETE /api/jobs/[id]: hard-delete terminal jobs (done/failed/cancelled);
  keep cancel-only behavior for active jobs
- POST /api/jobs/[id]/retry: new endpoint; validates failed/cancelled URL job,
  resets and re-runs via retryJob()
- jobs/[id]/+page.svelte: wire Cancel/Retry/Delete buttons with fetch calls;
  fix hardcoded ACCENT → accent store
- jobs/+page.svelte: per-row Retry+Delete icon buttons (visible on hover);
  fix hardcoded ACCENT → accent store

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 17:42:54 +02:00
Giancarmine SalucciandCopilot 13a96b6efa Initial commit: Tonemark PWA
Build & Push Docker Image / build-and-push (push) Failing after 11s
Tonemark is a SvelteKit PWA for transcribing YouTube videos, audio
and video files, and microphone recordings using a local Whisper backend.

Features:
- Dark glassmorphic UI with electric-lime accent (5 switchable themes)
- Rail nav (desktop) / tab bar (mobile) layout
- Drop zone, YouTube URL input, and live audio recording inputs
- Audio mode waveform cards (none / standard / aggressive / auto)
- Real-time transcription progress with animated waveform
- Job queue with SSE streaming updates
- Push notifications on job completion
- PWA with native SvelteKit service worker
- SRT / TXT / MD / JSON transcript downloads

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 16:41:25 +02:00