Parent
#39 — PRD: AI Radio — Host-driven Channel experience with chat timeline
What to build
Implement the Host Service — the AI orchestrator that turns a Channel Style and an optional Intervention into a completed Programme.
Interface:
generateProgramme(
channelStyle: ChannelStyle,
candidateTracks: Track[],
intervention?: Intervention
) → Promise<Programme>
The Host Service accepts the CandidateSet (already filtered by the caller) rather than querying the Library itself — this keeps it pure and testable.
Steps the Host performs:
- Call the Claude API (model:
claude-sonnet-4-6) with the CandidateSet track list, the Channel Style, and any Intervention. The prompt asks Claude to: select and sequence 5–8 Tracks, and write a short Interlude Script (1–3 sentences, in Chinese) to insert before the first Track and between every 2–3 Tracks.
- Parse Claude's response into an ordered list of
{ kind: 'track', trackId } and { kind: 'interlude', script } items.
- For each Interlude Script, call the TTS provider to synthesise audio and obtain a URL.
- Assemble and return the full
Programme: Segment[] with all audio URLs resolved.
TTS provider: use a cloud TTS API (e.g. OpenAI TTS, Azure TTS, or similar) that returns a streamable audio URL. The specific provider is a configuration choice — inject it as a dependency so it can be swapped. For v1, any provider that returns an MP3/AAC URL is acceptable.
Prompt caching: use the Anthropic SDK's prompt caching (cache_control) on the system prompt and the CandidateSet track list (these are stable across calls for the same Channel). This reduces latency and cost for Intervention-triggered regenerations.
The Host Service does not handle offline fallback — that is a separate module (#51).
Acceptance criteria
Blocked by
Parent
#39 — PRD: AI Radio — Host-driven Channel experience with chat timeline
What to build
Implement the Host Service — the AI orchestrator that turns a Channel Style and an optional Intervention into a completed Programme.
Interface:
The Host Service accepts the CandidateSet (already filtered by the caller) rather than querying the Library itself — this keeps it pure and testable.
Steps the Host performs:
claude-sonnet-4-6) with the CandidateSet track list, the Channel Style, and any Intervention. The prompt asks Claude to: select and sequence 5–8 Tracks, and write a short Interlude Script (1–3 sentences, in Chinese) to insert before the first Track and between every 2–3 Tracks.{ kind: 'track', trackId }and{ kind: 'interlude', script }items.Programme: Segment[]with all audio URLs resolved.TTS provider: use a cloud TTS API (e.g. OpenAI TTS, Azure TTS, or similar) that returns a streamable audio URL. The specific provider is a configuration choice — inject it as a dependency so it can be swapped. For v1, any provider that returns an MP3/AAC URL is acceptable.
Prompt caching: use the Anthropic SDK's prompt caching (
cache_control) on the system prompt and the CandidateSet track list (these are stable across calls for the same Channel). This reduces latency and cost for Intervention-triggered regenerations.The Host Service does not handle offline fallback — that is a separate module (#51).
Acceptance criteria
generateProgrammereturns a validProgrammewith at least one TrackSegment and at least one InterlSegmentscriptand a non-emptyaudioUrlcandidateTracksBlocked by
Segment,Programme,ChannelStyle,Intervention)