var t=class{constructor(t={}){this.cache=new Map,this.ctx=new AudioContext({sampleRate:48e3}),this.dest=this.ctx.createMediaStreamDestination(),this.manifest=t}get stream(){return this.dest.stream}async preload(t){await Promise.all(t.map(t=>this.load(t)))}async speakAsUser(t){return this.play(await this.load(t))}async speakBuffer(t){return this.play(await this.ctx.decodeAudioData(t))}async play(t){"suspended"===this.ctx.state&&await this.ctx.resume();const e=this.ctx.createBufferSource();return e.buffer=t,e.connect(this.dest),new Promise(t=>{e.addEventListener("ended",()=>t(),{once:!0}),e.start()})}close(){this.dest.stream.getTracks().forEach(t=>t.stop()),this.ctx.close()}async load(t){const e=this.cache.get(t);if(e)return e;const a=this.manifest[t];if(!a)throw new Error(`DevMicSource: no fixture for utterance ${JSON.stringify(t)}. Generate one with \`yarn workspace @ant/claude-ai gen-dev-utterance ${JSON.stringify(t)}\` and add it to the dev-loop utterance manifest.`);const s=await fetch(a);if(!s.ok)throw new Error(`DevMicSource: failed to fetch ${a} (${s.status})`);const r=await this.ctx.decodeAudioData(await s.arrayBuffer());return this.cache.set(t,r),r}};export{t as DevMicSource};