A voice-to-text tool for vibe coders: talk to your agents instead of typing to them. Paste links, code and notes into the box while you talk; everything you say is added to the end, ready to copy into a chat.
Bluetooth headsets: Rudder switches them to their stable voice mode (CVSD), because the higher-quality mode (mSBC) kept dropping the mic after a few words.
',4)])])):xe("",!0),!s.value||Te.value?(ie(),re("section",Sc,[A("button",{class:Pt(["mic",{on:T.value}]),disabled:Q.value||g.value!=="ready","aria-pressed":T.value,"aria-label":T.value?"Stop recording":"Start recording",onClick:fe},[A("span",Tc,X(T.value?"β ":"β"),1),Ge(" "+X(T.value?"Stop":"Record"),1)],10,Cc),A("div",Ec,[A("div",{class:"fill",style:vn({width:(ne.value*100).toFixed(0)+"%"})},null,4)]),A("label",Ac,[p[17]||(p[17]=A("span",null,"Language",-1)),ms(A("select",{"onUpdate:modelValue":p[3]||(p[3]=D=>K.value=D),disabled:T.value,onChange:d},[(ie(),re(Ie,null,Pi(l,([D,De])=>A("option",{key:D,value:D},X(De),9,Oc)),64))],40,Rc),[[Cr,K.value]])])])):xe("",!0),!s.value||Te.value?(ie(),re("section",Pc,[A("label",Mc,[p[18]||(p[18]=A("span",null,"Microphone",-1)),ms(A("select",{"onUpdate:modelValue":p[4]||(p[4]=D=>Y.value=D),disabled:T.value||W.value,onChange:p[5]||(p[5]=D=>{d(),j.value=null})},[A("option",Ic,"System default"+X(He.value?" β "+He.value.label:""),1),(ie(!0),re(Ie,null,Pi(Ne.value,D=>(ie(),re("option",{key:D.id,value:D.id},X(Vt(D)),9,Nc))),128))],40,kc),[[Cr,Y.value]])]),A("button",{class:"small",disabled:W.value||T.value||g.value==="offline",onClick:Is},X(W.value?"Testingβ¦ speak now":"Test mic"),9,Dc),A("button",{class:"small ghost",title:"Look for microphones again","aria-label":"Look for microphones again",disabled:T.value,onClick:Wn},"β»",8,Fc)])):xe("",!0),j.value?(ie(),re("p",{key:5,class:"notice","data-kind":j.value.ok?j.value.peak<.01?"warn":"ok":"error"},X(j.value.ok?"β ":"β ")+X(j.value.verdict),9,jc)):xe("",!0),Se.value&&Se.value.muted?(ie(),re("p",Vc,"β"+X(Se.value.label)+"β is muted in your system sound settings β Rudder won't hear anything until it's unmuted.",1)):xe("",!0),Et.value?(ie(),re("p",Lc,X(Et.value),1)):!Ne.value.length&&g.value!=="offline"?(ie(),re("p",Hc,"No microphone found. Connect a headset or turn on your computer's microphone in Sound settings.")):xe("",!0),ht.value.length?(ie(),re("p",$c,"Also available but switched off in Sound settings: "+X(ht.value.join(", "))+". Turn it on there to use it here.",1)):xe("",!0),ye.value?(ie(),re("p",{key:10,class:"notice","data-kind":me.value},X(ye.value),9,Uc)):g.value==="offline"?(ie(),re("p",Bc,[p[19]||(p[19]=Ge(" The local speech engine isn't reachable at ",-1)),A("code",null,X(o.value),1),p[20]||(p[20]=Ge(". In the Plugin Studio it starts with ",-1)),p[21]||(p[21]=A("code",null,"bun run dev",-1)),p[22]||(p[22]=Ge(" once built: ",-1)),p[23]||(p[23]=A("code",null,"cd backend/rudder-engine && go build -o ../bin/rudder-engine .",-1))])):xe("",!0),A("section",Kc,[ms(A("textarea",{ref_key:"box",ref:k,"onUpdate:modelValue":p[6]||(p[6]=D=>O.value=D),class:"draft",spellcheck:"true","aria-label":"Your text. Type or paste here; everything Rudder hears is added to the end.",placeholder:"Type or paste here β and press Record (Ctrl+Shift+Space) to talk. Your words stream into the end of this box as you speak.",onInput:P,onKeydown:C},null,544),[[lc,O.value]]),A("p",Wc,[T.value?(ie(),re(Ie,{key:0},[p[24]||(p[24]=A("span",{class:"tag"},"listening",-1)),p[25]||(p[25]=Ge(" words appear at the end of the box as you speak β keep typing or pasting anywhere",-1))],64)):xe("",!0)])]),A("footer",zc,[s.value?(ie(),re("button",{key:0,class:Pt(["mic sm",{on:T.value}]),disabled:Q.value||g.value!=="ready","aria-pressed":T.value,"aria-label":T.value?"Stop recording":"Start recording",onClick:fe},[A("span",Gc,X(T.value?"β ":"β"),1),Ge(" "+X(T.value?"Stop":"Record"),1)],10,Jc)):xe("",!0),A("button",{disabled:!O.value.trim(),onClick:p[7]||(p[7]=D=>cn(O.value,"all"))},X(we.value==="all"?"Copied β":"Copy all"),9,qc),!s.value||Te.value?(ie(),re("button",{key:1,disabled:!O.value.trim()||T.value,onClick:zn},"Clear",8,Xc)):xe("",!0),A("span",Yc,X(Oe.value)+" "+X(Oe.value===1?"word":"words"),1),p[26]||(p[26]=A("span",{class:"spacer"},null,-1)),!s.value||Te.value?(ie(),re("button",{key:2,class:"ghost","aria-expanded":ot.value,onClick:p[8]||(p[8]=D=>ot.value=!ot.value)},"π Debug",8,Zc)):xe("",!0)]),ot.value?(ie(),re("section",Qc,[A("dl",null,[p[27]||(p[27]=A("dt",null,"API",-1)),A("dd",null,[A("code",null,X(o.value),1)]),p[28]||(p[28]=A("dt",null,"Runtime",-1)),A("dd",null,X(R.value||"β"),1),p[29]||(p[29]=A("dt",null,"Model",-1)),A("dd",null,X(B.value||"β"),1),p[30]||(p[30]=A("dt",null,"Engine",-1)),A("dd",null,[Ge(X(g.value),1),E.value?(ie(),re("span",ea," β "+X(E.value),1)):xe("",!0)])]),A("button",{onClick:ra},X(we.value==="debug"?"Copied β":"Copy debug report for an agent"),1)])):xe("",!0)],2))}}),[["styles",[pc]]]));typeof customElements<"u"&&(customElements.get("rudder-voice")||customElements.define("rudder-voice",ta))})(); +`).replace(ra,"XX:XX:XX:XX:XX:XX");kr(D,"debug")}function Mr(_){_.ctrlKey&&_.shiftKey&&_.code==="Space"&&(_.preventDefault(),Ht())}Ei(()=>{an(),gt(),window.addEventListener("keydown",Mr)}),Ri(()=>{clearTimeout(Lt);try{ge==null||ge.close()}catch{}window.removeEventListener("keydown",Mr)}),kn(k,_=>i("recording",_));const Ir=lt(()=>({connecting:"Connectingβ¦",starting:"Loading speech modelβ¦ (about 20 s the first time)",ready:k.value?"Listening":"Ready",error:"Engine error",offline:a.value?"Engine offline":"Runs on your computer"})[E.value]||E.value);return(_,p)=>(ee(),te("div",{class:Ot(["rudder",{rec:k.value,compact:s.value}])},[s.value?(ee(),te("header",mc,[p[12]||(p[12]=R("b",{class:"name"},"Rudder",-1)),R("div",{class:"status","data-state":E.value,role:"status"},[p[9]||(p[9]=R("span",{class:"dot","aria-hidden":"true"},null,-1)),ke(q(Ir.value),1)],8,vc),p[13]||(p[13]=R("span",{class:"spacer"},null,-1)),R("button",{class:"icon-btn","aria-expanded":Ne.value,title:"Language and microphone","aria-label":"Language and microphone",onClick:p[0]||(p[0]=D=>Ne.value=!Ne.value)},[...p[10]||(p[10]=[R("svg",{viewBox:"0 0 24 24","aria-hidden":"true"},[R("path",{d:"M4 7h10M18 7h2M4 17h4M12 17h8"}),R("circle",{cx:"16",cy:"7",r:"2"}),R("circle",{cx:"10",cy:"17",r:"2"})],-1)])],8,bc),R("button",{class:"icon-btn","aria-expanded":Ie.value,title:"What is Rudder?","aria-label":"What is Rudder?",onClick:p[1]||(p[1]=D=>Ie.value=!Ie.value)},[...p[11]||(p[11]=[R("svg",{viewBox:"0 0 24 24","aria-hidden":"true"},[R("circle",{cx:"12",cy:"12",r:"9"}),R("path",{d:"M12 11v6M12 7.5v.5"})],-1)])],8,_c)])):(ee(),te("header",xc,[p[15]||(p[15]=R("div",{class:"brand"},[R("span",{class:"logo","aria-hidden":"true"},"β"),R("div",null,[R("h1",null,"Rudder"),R("p",{class:"sub"},"Voice-to-text for vibe coders Β· private Β· runs on this computer Β· no internet")])],-1)),R("button",{class:"info-btn","aria-expanded":Ie.value,title:"What is Rudder?","aria-label":"What is Rudder?",onClick:p[2]||(p[2]=D=>Ie.value=!Ie.value)},"β",8,yc),R("div",{class:"status","data-state":E.value,role:"status"},[p[14]||(p[14]=R("span",{class:"dot","aria-hidden":"true"},null,-1)),ke(q(Ir.value),1)],8,wc)])),Ie.value?(ee(),te("section",Sc,[...p[16]||(p[16]=[wl('A voice-to-text tool for vibe coders: talk to your agents instead of typing to them. Paste links, code and notes into the box while you talk; everything you say is added to the end, ready to copy into a chat.
Bluetooth headsets: Rudder switches them to their stable voice mode (CVSD), because the higher-quality mode (mSBC) kept dropping the mic after a few words.
',4)])])):_e("",!0),!s.value||Ne.value?(ee(),te("section",Cc,[R("button",{class:Ot(["mic",{on:k.value}]),disabled:V.value||E.value!=="ready","aria-pressed":k.value,"aria-label":k.value?"Stop recording":"Start recording",onClick:Ht},[R("span",Ac,q(k.value?"β ":"β"),1),ke(" "+q(k.value?"Stop":"Record"),1)],10,Tc),R("div",Ec,[R("div",{class:"fill",style:_n({width:(he.value*100).toFixed(0)+"%"})},null,4)]),R("label",Rc,[p[17]||(p[17]=R("span",null,"Language",-1)),vs(R("select",{"onUpdate:modelValue":p[3]||(p[3]=D=>H.value=D),disabled:k.value,onChange:g},[(ee(),te(Pe,null,Pi(d,([D,Fe])=>R("option",{key:D,value:D},q(Fe),9,Pc)),64))],40,Oc),[[Cr,H.value]])])])):_e("",!0),!s.value||Ne.value?(ee(),te("section",kc,[R("label",Mc,[p[18]||(p[18]=R("span",null,"Microphone",-1)),vs(R("select",{"onUpdate:modelValue":p[4]||(p[4]=D=>j.value=D),disabled:k.value||ye.value,onChange:p[5]||(p[5]=D=>{g(),ue.value=null})},[R("option",Nc,"System default"+q(Vt.value?" β "+Vt.value.label:""),1),(ee(!0),te(Pe,null,Pi(Qe.value,D=>(ee(),te("option",{key:D.id,value:D.id},q(De(D)),9,Dc))),128))],40,Ic),[[Cr,j.value]])]),R("button",{class:"small",disabled:ye.value||k.value||E.value==="offline",onClick:jt},q(ye.value?"Testingβ¦ speak now":"Test mic"),9,Fc),R("button",{class:"small ghost",title:"Look for microphones again","aria-label":"Look for microphones again",disabled:k.value,onClick:gt},"β»",8,Vc)])):_e("",!0),ue.value?(ee(),te("p",{key:5,class:"notice","data-kind":ue.value.ok?ue.value.peak<.01?"warn":"ok":"error"},q(ue.value.ok?"β ":"β ")+q(ue.value.verdict),9,jc)):_e("",!0),cn.value&&cn.value.muted?(ee(),te("p",Lc,"β"+q(cn.value.label)+"β is muted in your system sound settings β Rudder won't hear anything until it's unmuted.",1)):_e("",!0),J.value?(ee(),te("p",Hc,q(J.value),1)):!Qe.value.length&&E.value!=="offline"?(ee(),te("p",$c,"No microphone found. Connect a headset or turn on your computer's microphone in Sound settings.")):_e("",!0),re.value.length?(ee(),te("p",Uc,"Also available but switched off in Sound settings: "+q(re.value.join(", "))+". Turn it on there to use it here.",1)):_e("",!0),Me.value?(ee(),te("p",{key:10,class:"notice","data-kind":at.value},q(Me.value),9,Bc)):E.value==="offline"&&!a.value?(ee(),te("p",Kc,[...p[19]||(p[19]=[ke(" Voice to text runs on your own computer, not on this server: it listens to the microphone of the machine the engine runs on. Open the Plugin Studio on your computer (",-1),R("code",null,"bun run dev",-1),ke(") or use the Rudder desktop app. ",-1)])])):E.value==="offline"?(ee(),te("p",Wc,[p[20]||(p[20]=ke(" The local speech engine isn't reachable at ",-1)),R("code",null,q(o.value),1),p[21]||(p[21]=ke(". In the Plugin Studio it starts with ",-1)),p[22]||(p[22]=R("code",null,"bun run dev",-1)),p[23]||(p[23]=ke(" once built: ",-1)),p[24]||(p[24]=R("code",null,"cd backend/rudder-engine && go build -o ../bin/rudder-engine .",-1))])):_e("",!0),R("section",zc,[vs(R("textarea",{ref_key:"box",ref:xe,"onUpdate:modelValue":p[6]||(p[6]=D=>T.value=D),class:"draft",spellcheck:"true","aria-label":"Your text. Type or paste here; everything Rudder hears is added to the end.",placeholder:"Type or paste here β and press Record (Ctrl+Shift+Space) to talk. Your words stream into the end of this box as you speak.",onInput:L,onKeydown:I},null,544),[[cc,T.value]]),R("p",Jc,[k.value?(ee(),te(Pe,{key:0},[p[25]||(p[25]=R("span",{class:"tag"},"listening",-1)),p[26]||(p[26]=ke(" words appear at the end of the box as you speak β keep typing or pasting anywhere",-1))],64)):_e("",!0)])]),R("footer",Gc,[s.value?(ee(),te("button",{key:0,class:Ot(["mic sm",{on:k.value}]),disabled:V.value||E.value!=="ready","aria-pressed":k.value,"aria-label":k.value?"Stop recording":"Start recording",onClick:Ht},[R("span",Xc,q(k.value?"β ":"β"),1),ke(" "+q(k.value?"Stop":"Record"),1)],10,qc)):_e("",!0),R("button",{disabled:!T.value.trim(),onClick:p[7]||(p[7]=D=>kr(T.value,"all"))},q(Ae.value==="all"?"Copied β":"Copy all"),9,Yc),!s.value||Ne.value?(ee(),te("button",{key:1,disabled:!T.value.trim()||k.value,onClick:ia},"Clear",8,Zc)):_e("",!0),R("span",Qc,q(un.value)+" "+q(un.value===1?"word":"words"),1),p[27]||(p[27]=R("span",{class:"spacer"},null,-1)),!s.value||Ne.value?(ee(),te("button",{key:2,class:"ghost","aria-expanded":Ze.value,onClick:p[8]||(p[8]=D=>Ze.value=!Ze.value)},"π Debug",8,ea)):_e("",!0)]),Ze.value?(ee(),te("section",ta,[R("dl",null,[p[28]||(p[28]=R("dt",null,"API",-1)),R("dd",null,[R("code",null,q(o.value),1)]),p[29]||(p[29]=R("dt",null,"Runtime",-1)),R("dd",null,q(N.value||"β"),1),p[30]||(p[30]=R("dt",null,"Model",-1)),R("dd",null,q(ne.value||"β"),1),p[31]||(p[31]=R("dt",null,"Engine",-1)),R("dd",null,[ke(q(E.value),1),$.value?(ee(),te("span",na," β "+q($.value),1)):_e("",!0)])]),R("button",{onClick:ca},q(Ae.value==="debug"?"Copied β":"Copy debug report for an agent"),1)])):_e("",!0)],2))}}),[["styles",[hc]]]));typeof customElements<"u"&&(customElements.get("rudder-voice")||customElements.define("rudder-voice",sa))})(); diff --git a/public/dx-maps/rudder-voice/rudder-voice/index.html b/public/dx-maps/rudder-voice/rudder-voice/index.html index 7b8e0cc28..31e58b5e7 100644 --- a/public/dx-maps/rudder-voice/rudder-voice/index.html +++ b/public/dx-maps/rudder-voice/rudder-voice/index.html @@ -32,7 +32,7 @@ - +