mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-25 02:29:37 +00:00
bec8c7ede4
Frontend for the new omni audio API
(`/v1/omni_gen/{models,generate,cost}/audio`).
### New pages
- **Webapp**: `/create-audio` page (desktop layout + mobile
Generate/History tabs with settings drawers), added to sidebar.
- **Desktop**: new `AUDIO` tab ("Create Audio") with `PromptBoxAudio`,
registered in the app menu / TopBar. Audio enqueues over HTTP and polls
the jobs feed (Tauri task queue untouched).
### Models & promptbox
- Suno Music / Remix / Sounds / Sample + Seed Audio 1.0, fetched live
from `GET /v1/omni_gen/models/audio` with per-model capability gating.
- Always-visible **style prompt** row (Suno tags), instrumental /
keep-lyrics / loop toggles, BPM + musical key popover (Suno Sounds),
sample rate + speed/volume/pitch tuning popover (Seed Audio).
- Audio/image reference uploads with server rules mirrored client-side
(remix/sample require exactly 1 audio track; Seed Audio can't combine
audio + image refs).
- One request can return multiple job tokens (Suno multi-clip) - every
token becomes its own pending card.
### Audio playback in galleries
- New **`@storyteller/ui-audio-player`** lib (wavesurfer.js v7):
waveform + seek, play/pause, volume, duration - only one player plays at
a time.
- Lazy waveform decode (IntersectionObserver + peaks cache) and a
no-waveform `<audio>` fallback if CORS/decode fails.
- Audio cards/rows added once in the shared `ui-generation-list`, so
both hosts' grid + list views get them.
- Audio playback in both lightboxes (webapp lightbox + desktop
lightbox-modal); Library gets an **Audio** filter tab and includes audio
in "All"; downloads keep the right extension.
### Shared plumbing
- `OmniGenApi` gains audio types + `getAudioModels` / `generateAudio` /
`estimateAudioCost`.
- `useOmniGenAudioModels`, request builder, enqueue + cost hook shared
via `@storyteller/omni-gen` (used by both hosts).
- `useGenerationJobs` moved from the webapp into `ui-generation-list`
(with re-export shim) and taught the `audio_generation` category - the
desktop audio feed reuses it.
- Suno model names/descriptions/creator icon added to `model-list`.
60 lines
1.4 KiB
TypeScript
60 lines
1.4 KiB
TypeScript
/**
|
|
* Shared Vite configuration for library builds.
|
|
*
|
|
* This ensures that:
|
|
* 1. React is always externalized (peer dependency)
|
|
* 2. @preact/signals-* packages are externalized to prevent duplicate state
|
|
* 3. @storyteller/* workspace packages are externalized so libraries don't bundle each other
|
|
*
|
|
* Without this, stateful modules like signals get bundled multiple times,
|
|
* causing state isolation issues in production builds.
|
|
*/
|
|
|
|
/**
|
|
* Returns true if the given module ID should be externalized during library builds.
|
|
*/
|
|
export function isExternal(id: string): boolean {
|
|
// Always externalize React
|
|
if (
|
|
id === 'react' ||
|
|
id === 'react-dom' ||
|
|
id === 'react/jsx-runtime' ||
|
|
id.startsWith('react/') ||
|
|
id.startsWith('react-dom/')
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
// Other react libraries
|
|
if (
|
|
id === 'react-hot-toast' ||
|
|
id === 'react-router-dom' ||
|
|
id.startsWith('react-')
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
// Externalize @preact/signals to prevent duplicate signal state
|
|
if (id.startsWith('@preact/signals')) {
|
|
return true;
|
|
}
|
|
|
|
// Other important libraries
|
|
if (
|
|
id === 'konva' ||
|
|
id === 'three' ||
|
|
id === 'zustand' ||
|
|
id === 'wavesurfer.js' ||
|
|
id.startsWith('@fortawesome/')
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
// Externalize all workspace packages so libraries don't bundle each other
|
|
if (id.startsWith('@storyteller/') || id.startsWith('@frontend/')) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|