<mxfile>
  <diagram id="seqlayout" name="Muxiva full-duplex voice interruption">
    <mxGraphModel dx="800" dy="600" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
      <root>
        <mxCell id="0"/>
        <mxCell id="1" parent="0"/>
        <mxCell id="client" value="Voice Room&#xa;Browser Client" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;size=40;participant=umlActor;verticalAlign=bottom;spacingBottom=-14;labelBackgroundColor=#ffffff;" vertex="1" parent="1">
          <mxGeometry x="40" y="40" width="100" height="1830" as="geometry"/>
        </mxCell>
        <mxCell id="rtc" value="Agora RTC&#xa;Network Channel" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;size=40;" vertex="1" parent="1">
          <mxGeometry x="330" y="40" width="100" height="1830" as="geometry"/>
        </mxCell>
        <mxCell id="source" value="Agora Audio&#xa;Source Node" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;size=40;" vertex="1" parent="1">
          <mxGeometry x="620" y="40" width="100" height="1830" as="geometry"/>
        </mxCell>
        <mxCell id="runtime" value="Muxiva Rust&#xa;Runtime" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;size=40;" vertex="1" parent="1">
          <mxGeometry x="910" y="40" width="100" height="1830" as="geometry"/>
        </mxCell>
        <mxCell id="qwen" value="Qwen Audio&#xa;Realtime Node" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;size=40;" vertex="1" parent="1">
          <mxGeometry x="1200" y="40" width="100" height="1830" as="geometry"/>
        </mxCell>
        <mxCell id="api" value="Qwen Realtime&#xa;API + Server VAD" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;size=40;" vertex="1" parent="1">
          <mxGeometry x="1490" y="40" width="100" height="1830" as="geometry"/>
        </mxCell>
        <mxCell id="audio_sink" value="Agora Audio&#xa;Sink Node" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;size=40;" vertex="1" parent="1">
          <mxGeometry x="1780" y="40" width="100" height="1830" as="geometry"/>
        </mxCell>
        <mxCell id="data_sink" value="Agora Data&#xa;Sink Node" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;size=40;" vertex="1" parent="1">
          <mxGeometry x="2070" y="40" width="100" height="1830" as="geometry"/>
        </mxCell>
        <mxCell id="note0" value="Normal full duplex: microphone uplink stays live while the answer plays" style="shape=note;whiteSpace=wrap;html=1;size=14;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
          <mxGeometry x="980" y="110" width="230" height="40" as="geometry"/>
        </mxCell>
        <mxCell id="m1" value="publish microphone PCM continuously" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.082;entryX=0.5;entryY=0.082;" edge="1" parent="1" source="client" target="rtc">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m2" value="remote PCM callback" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.1093;entryX=0.5;entryY=0.1093;" edge="1" parent="1" source="rtc" target="source">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m3" value="ctx.emit(audio_out, AudioFrame)" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.1366;entryX=0.5;entryY=0.1366;" edge="1" parent="1" source="source" target="runtime">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m4" value="explicit Audio Edge → on_process" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.1639;entryX=0.5;entryY=0.1639;" edge="1" parent="1" source="runtime" target="qwen">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m5" value="input_audio_buffer.append" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.1913;entryX=0.5;entryY=0.1913;" edge="1" parent="1" source="qwen" target="api">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m6" value="response.created + audio.delta" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.2186;entryX=0.5;entryY=0.2186;" edge="1" parent="1" source="api" target="qwen">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m7" value="ctx.emit(audio_out, 24 kHz PCM)" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.2459;entryX=0.5;entryY=0.2459;" edge="1" parent="1" source="qwen" target="runtime">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m8" value="Audio Edge (48 kHz after resampling)" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.2732;entryX=0.5;entryY=0.2732;" edge="1" parent="1" source="runtime" target="audio_sink">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m9" value="10 ms PCM packets" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.3005;entryX=0.5;entryY=0.3005;" edge="1" parent="1" source="audio_sink" target="rtc">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m10" value="play Agent answer" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.3279;entryX=0.5;entryY=0.3279;" edge="1" parent="1" source="rtc" target="client">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="note11" value="Barge-in: the user starts speaking while the Agent is answering" style="shape=note;whiteSpace=wrap;html=1;size=14;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
          <mxGeometry x="1270" y="670" width="230" height="40" as="geometry"/>
        </mxCell>
        <mxCell id="m12" value="user starts speaking again" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.388;entryX=0.5;entryY=0.388;" edge="1" parent="1" source="client" target="rtc">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m13" value="new remote PCM" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.4153;entryX=0.5;entryY=0.4153;" edge="1" parent="1" source="rtc" target="source">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m14" value="AudioFrame" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.4426;entryX=0.5;entryY=0.4426;" edge="1" parent="1" source="source" target="runtime">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m15" value="on_process(audio)" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.4699;entryX=0.5;entryY=0.4699;" edge="1" parent="1" source="runtime" target="qwen">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m16" value="continue appending input audio" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.4973;entryX=0.5;entryY=0.4973;" edge="1" parent="1" source="qwen" target="api">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m17" value="input_audio_buffer.speech_started" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.5246;entryX=0.5;entryY=0.5246;" edge="1" parent="1" source="api" target="qwen">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m18" value="response.cancel (only if old response is active)" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.5519;entryX=0.5;entryY=0.5519;" edge="1" parent="1" source="qwen" target="api">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m19" value="set discard_response_output=true" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.5792;entryX=0.5;entryY=0.5956;" edge="1" parent="1" source="qwen" target="qwen">
          <mxGeometry relative="1" as="geometry">
            <Array as="points"><mxPoint x="1310" y="1100"/><mxPoint x="1310" y="1130"/></Array>
          </mxGeometry>
        </mxCell>
        <mxCell id="m20" value="ctx.emit_signal(muxiva.voice.speech.started)" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.6175;entryX=0.5;entryY=0.6175;" edge="1" parent="1" source="qwen" target="runtime">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m21" value="explicit Signal Edge → on_signal" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.6448;entryX=0.5;entryY=0.6448;" edge="1" parent="1" source="runtime" target="audio_sink">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m22" value="clear PCM queue + advance sequence watermark" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.6721;entryX=0.5;entryY=0.6885;" edge="1" parent="1" source="audio_sink" target="audio_sink">
          <mxGeometry relative="1" as="geometry">
            <Array as="points"><mxPoint x="1890" y="1270"/><mxPoint x="1890" y="1300"/></Array>
          </mxGeometry>
        </mxCell>
        <mxCell id="m23" value="event_out: speech.started / barge_in" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.7104;entryX=0.5;entryY=0.7104;" edge="1" parent="1" source="qwen" target="runtime">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m24" value="publish_notification: process-local logs/metrics only" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.7377;entryX=0.5;entryY=0.7377;" edge="1" parent="1" source="qwen" target="runtime">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m25" value="Semantic Frames → project encoder → ByteFrame" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.765;entryX=0.5;entryY=0.765;" edge="1" parent="1" source="runtime" target="data_sink">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m26" value="ordered RTC Data Message" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.7923;entryX=0.5;entryY=0.7923;" edge="1" parent="1" source="data_sink" target="rtc">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m27" value="show SPEAKING / BARGE-IN state" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.8197;entryX=0.5;entryY=0.8197;" edge="1" parent="1" source="rtc" target="client">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m28" value="possibly late old response.delta" style="html=1;verticalAlign=bottom;endArrow=open;dashed=1;curved=0;rounded=0;exitX=0.5;exitY=0.847;entryX=0.5;entryY=0.847;" edge="1" parent="1" source="api" target="qwen">
          <mxGeometry relative="1" as="geometry"/>
        </mxCell>
        <mxCell id="m29" value="discard stale chunk before the Audio Edge" style="html=1;verticalAlign=bottom;endArrow=block;curved=0;rounded=0;exitX=0.5;exitY=0.8743;entryX=0.5;entryY=0.8907;" edge="1" parent="1" source="qwen" target="qwen">
          <mxGeometry relative="1" as="geometry">
            <Array as="points"><mxPoint x="1310" y="1640"/><mxPoint x="1310" y="1670"/></Array>
          </mxGeometry>
        </mxCell>
        <mxCell id="note30" value="Two guards: the Node rejects late model chunks; Audio Sink clears its queue and drops old frames at or below the watermark. Audio already sent into RTC/client playback cannot be recalled, so buffering must stay bounded." style="shape=note;whiteSpace=wrap;html=1;size=14;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
          <mxGeometry x="1790" y="1670" width="360" height="130" as="geometry"/>
        </mxCell>
        <mxCell id="note31" value="Boundary: Runtime routes opaque Signals only. It understands neither speech nor application Turns, and NotificationBus is never exposed to the remote client." style="shape=note;whiteSpace=wrap;html=1;size=14;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
          <mxGeometry x="900" y="1740" width="390" height="100" as="geometry"/>
        </mxCell>
      </root>
    </mxGraphModel>
  </diagram>
</mxfile>
