feat: TTS usage v1.5 — upstream-precise (elevenlabs header, gemini usageMetadata)
enhancement
Part of #1415. Follow-up from #1420 research.
## What
For the two TTS providers that DO expose per-call billing info, capture it precisely instead of relying on input length.
### ElevenLabs (`tts_elevenlabs_agent.ts`)
ElevenLabs returns a `character-cost` HTTP header on every successful TTS call. Currently we discard the `Response` after `arrayBuffer()` so the header is dropped.
Refactor:
```ts
const response = await fetch(...);
// ... existing ok check
const charactersBilled = Number(response.headers.get("character-cost") ?? 0);
const requestId = response.headers.get("request-id") ?? undefined;
const arrayBuffer = await response.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
return {
buffer,
usage: {
provider: "elevenlabs",
model: usedModel,
charactersBilled, // exact billed amount (already 0.5-1 per char depending on model)
inputChars: text.length, // for cross-check / fallback
requestId,
cached: false,
},
};
```
### Gemini TTS (`tts_gemini_agent.ts`)
`response.usageMetadata` is available (verified in `@google/genai/dist/genai.d.ts` → `GenerateContentResponseUsageMetadata`).
```ts
return {
buffer: await pcmToMp3(rawPcm, sampleRate),
usage: {
provider: "gemini",
model: usedModel,
inputTokens: response.usageMetadata?.promptTokenCount,
outputTokens: response.usageMetadata?.candidatesTokenCount,
totalTokens: response.usageMetadata?.totalTokenCount,
cached: false,
},
};
```
This mirrors the pattern used in #1418 (`image_genai_agent`).
## UsageRecord shape impact
`UsageRecord` already supports `inputTokens` / `outputTokens` / `totalTokens` / `inputChars`. Add an optional `charactersBilled?: number` field for ElevenLabs precision (or fold into a generic `charges?` map — open question). Surface the decision in this issue's PR.
## Acceptance
- [ ] ElevenLabs agent reads `character-cost` / `request-id` headers
- [ ] Gemini TTS agent extracts `usageMetadata`
- [ ] `UsageRecord` extended (or decision recorded for why not)
- [ ] Callback wiring (sharing the pattern from #1419)
- [ ] Tests with mocked HTTP / mocked Gemini response
## Dependencies
- #1416 (UsageCollector foundation)
- Research closed via #1420
关闭于 2026-06-20 0 条评论