Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,154 @@
# Tasks: voice-elevenlabs
**Change ID**: voice-elevenlabs
**Package**: `@suaveplan/voice-elevenlabs`
**Target path**: `packages/audio/voice-elevenlabs`
**Prerequisite packages on Verdaccio**: `@suaveplan/voice`, `@suaveplan/third-party-elevenlabs`, `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/streams`
> Supersedes the 2026-04-24 fused-HTTP design. The prior `packages/audio/voice-elevenlabs` implementation MUST be deleted before this rebuild starts.
---
## 0. Pre-rebuild teardown
- [x] Confirm `git status` shows the prior `packages/audio/voice-elevenlabs` content is committed or accounted for; if uncommitted scratch work exists, stash it explicitly with the user.
- [x] `rm -rf packages/audio/voice-elevenlabs` — delete the entire prior implementation.
- [x] Confirm no other package imports from `@suaveplan/voice-elevenlabs` (`grep -rln '@suaveplan/voice-elevenlabs' packages/`); the only references should be inside the to-be-deleted folder itself.
---
## 1. Scaffold
- [x] Create `packages/audio/voice-elevenlabs/` with `src/`, `tests/`, `src/__benchmarks__/`.
- [x] Write `package.json` at version `0.1.0`, `"type": "module"`, `"sideEffects": false`, full subpath `exports` map per feature module, deps `@suaveplan/voice`, `@suaveplan/third-party-elevenlabs`, `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/streams`, `zod`, `tslib` (catalogs only).
- [x] Write `tsconfig.lib.json` extending `../../../tsconfig.base.json`.
- [x] Write `vite.config.ts` with multi-entry build for every feature module + factory.
- [x] Write `vitest.config.ts` using `createTestConfig()` from `@suaveplan/testing/config`, coverage thresholds 100/100/100/100.
- [x] Add `lint`, `lint:fix`, `format`, `check`, `typecheck`, `test`, `test:coverage`, `build`, `docs:check` scripts.
---
## 2. Error remapping module
- [x] `src/errors/remap.ts` — `mapElevenLabsError(err: unknown, context: { operation: VoiceOperation; voiceId?: string }): VoiceError` covering every `ElevenLabsApiError` subclass per the proposal §Error remapping table. Preserves the original error via `cause`.
- [x] `src/errors/remap.schemas.ts` — Zod for `VoiceOperation = 'tts' | 'tts-stream' | 'stt' | 'voices' | 'sound-generation' | 'audio-isolation'`.
- [x] `src/errors/remap.md`
- [x] `src/errors/remap.test.ts` — every `ElevenLabsApiError` subclass produces the expected `VoiceError` code, preserves `cause`, and threads through `context.voiceId` where the table specifies.
---
## 3. Engine implementations
### 3.1 `tts`
- [x] `src/tts/tts.ts` — `ElevenLabsTtsEngine` implements `VoiceSynthesizer`.
- `synthesize(req)`: maps `SynthesisRequest` → ElevenLabs TTS body via `mapSynthesisRequest()`; calls `tts.synthesize(req.voiceId, body)`; maps `BinaryResponse` → `SynthesisResult` (audio bytes, format echoed from request, `charactersUsed` from `metadata.characterCost`).
- `synthesizeStream(req)`: maps request, calls `tts.synthesizeStream(req.voiceId, body)`, returns `response.body` directly.
- All errors flow through `mapElevenLabsError`.
- [x] `src/tts/tts.schemas.ts` — Zod for `ElevenLabsTtsAdapterOptions`, `mapSynthesisRequest` input/output.
- [x] `src/tts/tts.md`
- [x] `src/tts/tts.test.ts` — happy-path synthesize, happy-path stream, voice-not-found, validation error, rate-limited with `retryAfterMs`, abort, `cause` chain preserved.
### 3.2 `stt`
- [x] `src/stt/stt.ts` — `ElevenLabsSttEngine` implements `TranscriptionEngine`.
- `transcribe(req)`: maps `TranscriptionRequest` → ElevenLabs STT multipart body (audio: `Uint8Array | ReadableStream | string` passed through to third-party `MultipartFile`); calls `stt.transcribe(body)`; maps response to `TranscriptionResult` (words, derived speakers, entities split from word-stream).
- [x] `src/stt/stt.schemas.ts`
- [x] `src/stt/stt.md`
- [x] `src/stt/stt.test.ts` — transcribe from bytes / stream / URL, with diarization, with entity detection, error remapping.
### 3.3 `voices`
- [x] `src/voices/voices.ts` — `ElevenLabsVoiceRepository` implements `VoiceRepository`.
- `list(opts)`: calls `voices.list({ ...opts })`; maps each ElevenLabs voice DTO → `Voice`; `nextPageToken`/`hasMore` derived from response.
- `get(id)`: calls `voices.get(id)`; remaps `THIRD_PARTY_ELEVENLABS.REQUEST.NOT_FOUND` → `null` (per `VoiceRepository.get` contract); other errors flow through `mapElevenLabsError` with `voiceId` context.
- [x] `src/voices/voices.schemas.ts`
- [x] `src/voices/voices.md`
- [x] `src/voices/voices.test.ts`
### 3.4 `sound-effects`
- [x] `src/sound-effects/sound-effects.ts` — `ElevenLabsSoundEffectEngine` implements `SoundEffectEngine`.
- `generate(req)`: maps `SoundEffectRequest` → ElevenLabs sound-generation body; calls `soundGeneration.generate(body)`; maps response to `SoundEffectResult`.
- [x] `src/sound-effects/sound-effects.schemas.ts`
- [x] `src/sound-effects/sound-effects.md`
- [x] `src/sound-effects/sound-effects.test.ts`
### 3.5 `voice-isolation`
- [x] `src/voice-isolation/voice-isolation.ts` — `ElevenLabsVoiceIsolationEngine` implements `VoiceIsolationEngine`.
- `isolate(req)`: maps `IsolationRequest` → ElevenLabs isolation multipart body; calls `audioIsolation.isolate(body)`; maps response to `IsolationResult`.
- [x] `src/voice-isolation/voice-isolation.schemas.ts`
- [x] `src/voice-isolation/voice-isolation.md`
- [x] `src/voice-isolation/voice-isolation.test.ts`
---
## 4. Composite factory
- [x] `src/factory/factory.ts` — `createElevenLabsVoice(options)` returns `{ client, tts, stt, voices, effects, isolation }`.
- Accepts either an existing `ElevenLabsClient` or `ElevenLabsClientOptions` to construct one fresh.
- Wires every engine to share the same client instance.
- [x] `src/factory/factory.schemas.ts` — Zod for `CreateElevenLabsVoiceOptions`.
- [x] `src/factory/factory.md`
- [x] `src/factory/factory.test.ts` — factory returns five engines + client; engines share client; both option shapes (existing client vs construct fresh) work.
---
## 5. Index
- [x] `src/index.ts` — barrel re-export of all five engines + factory + adapter-options types + `mapElevenLabsError` (for advanced callers).
---
## 6. Property-based tests (`tests/property.test.ts`)
- [x] `AudioFormat` round-trip — every `@suaveplan/voice` `AudioFormat` value passes through to ElevenLabs `output_format` and back without modification.
- [x] `SynthesisRequest` round-trip — arbitrary valid request maps to ElevenLabs body and remaps to equivalent `SynthesisResult` shape (subject to documented field mappings).
- [x] Error remapping totality — every `ElevenLabsApiError` subclass produces a `VoiceError` for every documented operation; no unmapped paths.
---
## 7. Benchmarks (`src/__benchmarks__/voice-elevenlabs.bench.ts`)
- [x] `ElevenLabsTtsEngine.synthesize` round-trip with mocked `fetchImpl` (no network).
- [x] `ElevenLabsSttEngine.transcribe` round-trip with mocked `fetchImpl`.
---
## 8. Pre-publish gate
- [x] `bunx turbo lint typecheck test --filter=@suaveplan/voice-elevenlabs` — green.
- [x] `bunx turbo test:coverage --filter=@suaveplan/voice-elevenlabs` — 100/100/100/100.
- [x] `bun run docs:check --filter=@suaveplan/voice-elevenlabs` — ≥ 90%.
- [x] Banned-pattern scan in `src/` — zero hits.
- [x] `README.md` exists at package root.
- [x] Subpath exports count matches feature module count.
- [x] No bare versions in `package.json`.
- [x] `bunx turbo test --filter=...@suaveplan/voice-elevenlabs` — dependents pass (currently none).
---
## 9. Archive
- [x] Fold spec deltas into `openspec/specs/voice-elevenlabs/spec.md`.
- [x] Move `openspec/changes/voice-elevenlabs/` → `openspec/archive/2026-05-02-voice-elevenlabs/`.
- [x] Publish to Verdaccio: `bun scripts/publish.ts --package @suaveplan/voice-elevenlabs`.
- [x] Update `STATUS.md`.
---
## Audit Note (2026-05-02)
**Status**: DEFERRED.
State at audit:
- The package directory `packages/audio/voice-elevenlabs/` does not exist on genesis. The teardown step (Section 0) is a no-op for the audit.
- Upstream `@suaveplan/voice` is shipped (103 tests / 100% coverage / archived 2026-05-02).
- Upstream `@suaveplan/third-party-elevenlabs` is **also deferred** (typecheck green after this audit's edits, but missing `src/index.ts`, factory implementation, property tests, benchmarks, README) — `voice-elevenlabs` cannot ship until that prerequisite lands.
Resuming work:
1. Finish `third-party-elevenlabs` (see its audit note) so the third-party client surface is stable.
2. Then execute Sections 1–9 of this tasks file to scaffold `packages/audio/voice-elevenlabs/` and wire the five engines + factory.