feat: TTS usage v1 — input character fallback (openai legacy, google, kotodama)
enhancement
Part of #1415. Follow-up from #1420 research.
## What
Surface input-character usage for TTS providers whose upstream response carries no per-call usage. Pure derivation from `namedInputs.text` — no SDK rework.
Targets:
- `src/agents/tts_openai_agent.ts` for `tts-1` and `tts-1-hd` (the gpt-4o-mini-tts case is split out into a v2 issue)
- `src/agents/tts_google_agent.ts`
- `src/agents/tts_kotodama_agent.ts`
## Return shape
Each agent returns:
```ts
return {
buffer,
usage: {
provider: "openai" | "google" | "kotodama",
model: usedModel, // openai: "tts-1" | "tts-1-hd"; google: voice tier; kotodama: voice/decoration ID
inputChars: text.length, // Unicode code points; spaces + newlines included
cached: false,
},
};
```
## Notes
- **Google TTS** charges spaces, newlines, and most SSML tags (except `<mark>`). mulmocast currently doesn't emit SSML, so `text.length` is correct. If SSML emission lands later, count includes tags too — no agent change needed.
- **Kotodama** is subscription-billed externally; we just surface what was sent so the API/billing layer can do its own accounting.
- **OpenAI tts-1 / tts-1-hd** are character-billed (see #1420 research). `gpt-4o-mini-tts` is token-billed and is handled by a separate issue.
## Acceptance
- [ ] All 3 agents extended (backward compatible — existing consumers only read `buffer`)
- [ ] Callback in `src/actions/audio.ts` pushes `usage` into `context.usageCollector`
- [ ] Unit / mocked test asserting an `UsageRecord` with the correct `inputChars` is recorded
- [ ] Cache hits not recorded (verify)
## Dependencies
- #1416 (UsageCollector foundation)
- Research closed via #1420
关闭于 2026-06-20 0 条评论