feat(phase-1): persistent generation library

- Save every completed generation to SQLite (generation_store.py) with
  WAV and waveform peaks written to data/generations/<id>/
- Deferred DB write until success — cancelled/errored generations never
  touch the DB and never appear in the library
- Fixed cancel+regenerate IndexError: _reset_scheduler_caches() now
  directly zeros scheduler._step_index and running state in addition to
  clearing VibePod cache dicts; same explicit resets added in the fresh
  path of prepare_noise_scheduler as belt-and-suspenders
- Added /library page with GenerationCard, WaveformPreview, waveform
  fetch, play/pause, download, delete, pagination, empty + error states
- Added generation API routes (list, single, audio stream, waveform,
  delete) proxying to Python server
- Added Library nav link to Header with active state
- Persist script/speaker/CFG to localStorage so generate page state
  survives navigation
- Updated build plan: Phase 0+1 ticked off, better-sqlite3 moved to
  Phase 2, architectural note on Python owning all persistence
This commit is contained in:
2026-05-02 23:05:11 +01:00
parent 47e0c7e512
commit 13085166fb
13 changed files with 913 additions and 29 deletions
+34
View File
@@ -0,0 +1,34 @@
export type GenerationStatus = "generating" | "complete" | "error" | "cancelled";
export interface GenerationJob {
id: string;
created_at: string;
status: GenerationStatus;
script: string;
speaker: string;
cfg_scale: number;
inference_steps: number | null;
duration_secs: number | null;
sample_rate: number | null;
audio_path: string | null;
waveform_path: string | null;
error_message: string | null;
}
export interface WaveformPeaks {
sampleRate: number;
durationSecs: number;
channels: number;
samplesPerPixel: number;
length: number;
data: {
min: number[];
max: number[];
};
}
export interface GenerationsListResponse {
items: GenerationJob[];
limit: number;
offset: number;
}