opencode-voice-dictation 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -189,4 +189,4 @@ public static class WinH {
|
|
|
189
189
|
[WinH]::Send()
|
|
190
190
|
`,_e="powershell.exe";function Ve(){const t=Q.join(ae.tmpdir(),"opencode-voice-dictation");K.mkdirSync(t,{recursive:!0});const e=oe.createHash("sha1").update(he).digest("hex").slice(0,12),i=Q.join(t,`win-h-${e}.ps1`);return K.writeFileSync(i,he,"utf8"),i}function ze(t){return ie.spawn(_e,t,{windowsHide:!0,stdio:"ignore"})}function De(){return new Promise((t,e)=>{const i=ze(["-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-File",Ve()]);i.on("error",c=>e(c)),i.on("close",c=>{c===0?t():e(new Error(`Win+H helper exited with code ${c??"unknown"}`))})})}const Fe=t=>{let e="idle",i="",c="",n,s=!1;const u=()=>{n=void 0,s=!1},a=t.provide(le,{state:()=>({status:e,error:i,locale:c}),start(S,R){n&&(s=!0,n.stop(),u()),e="starting",i="",c=S.locale,a.changed();const v=R.window;try{n=Pe({locale:S.locale,minConfidence:S.minConfidence},{onReady(C){e="listening",c=C,a.changed()},onFinal(C,I){a.emit("final",{text:C,confidence:I},v)},onError(C,I,z){e="error",i=C,a.changed(),a.emit("error",{code:C,detail:I,available:z},v)},onExit(C,I){if(s){u(),e="idle",i="",c="",a.changed();return}u(),e!=="error"&&(e="error",i=C===null?"ENGINE_EXIT":`ENGINE_EXIT_${C}`,a.changed(),a.emit("error",{code:"ENGINE_EXIT",detail:I||(C===null?"":String(C)),available:[]},v))}})}catch(C){throw e="error",i="ENGINE_START_FAILED",a.changed(),C}},stop(){n&&(s=!0,n.stop(),u()),e="idle",i="",c="",a.changed()},diagnose(){return Ie()}});let g;const h=t.provide(fe,{speak(S){g?.stop(),g=Ne(S,R=>{g=void 0,h.emit("done",{ok:R})})},stop(){g&&(g.stop(),g=void 0)},voices(){return Le()}});t.provide(ce,{toggle(){return De()}}),t.onCleanup(()=>{n&&(s=!0,n.stop(),u()),g?.stop(),g=void 0})},j={id:"voice-dictation.voice",methods:{edgeVoices:{input:{type:"object",additionalProperties:!1},output:{type:"array",items:{type:"object",properties:{id:{type:"string"},label:{type:"string"},locale:{type:"string"},gender:{type:"string"}},required:["id","label","locale","gender"],additionalProperties:!1}}},edgeSpeak:{input:{type:"object",properties:{text:{type:"string"},voice:{type:"string"},rate:{type:"number"}},required:["text","voice","rate"],additionalProperties:!1},output:{type:"string"}},whisperTranscribe:{input:{type:"object",properties:{audio:{type:"string"},mime:{type:"string"},language:{type:"string"},python:{type:"string"},model:{type:"string"}},required:["audio","mime","language","python","model"],additionalProperties:!1},output:{type:"object",properties:{text:{type:"string"},language:{type:"string"}},required:["text","language"],additionalProperties:!1}},whisperStatus:{input:{type:"object",properties:{python:{type:"string"},model:{type:"string"}},required:["python","model"],additionalProperties:!1},output:{type:"object",properties:{ready:{type:"boolean"},model:{type:"string"},device:{type:"string"},error:{type:"string"}},required:["ready","model","device","error"],additionalProperties:!1}},capabilities:{input:{type:"object",additionalProperties:!1},output:{type:"object",properties:{platform:{type:"string"},engines:{type:"array",items:{type:"string"}}},required:["platform","engines"],additionalProperties:!1}},whisperCppInstall:{input:{type:"object",properties:{model:{type:"string"}},required:["model"],additionalProperties:!1},output:{type:"object",properties:{ok:{type:"boolean"},model:{type:"string"},error:{type:"string"}},required:["ok","model","error"],additionalProperties:!1}},whisperCppStatus:{input:{type:"object",properties:{model:{type:"string"}},required:["model"],additionalProperties:!1},output:{type:"object",properties:{installed:{type:"boolean"},ready:{type:"boolean"},model:{type:"string"},error:{type:"string"},ffmpeg:{type:"boolean"},ffmpegVersion:{type:"string"},ffmpegPath:{type:"string"}},required:["installed","ready","model","error","ffmpeg","ffmpegVersion","ffmpegPath"],additionalProperties:!1}},whisperCppInstallFfmpeg:{input:{type:"object",additionalProperties:!1},output:{type:"object",properties:{ok:{type:"boolean"},error:{type:"string"},command:{type:"string"}},required:["ok","error","command"],additionalProperties:!1}},whisperCppTranscribe:{input:{type:"object",properties:{audio:{type:"string"},mime:{type:"string"},language:{type:"string"},model:{type:"string"}},required:["audio","mime","language","model"],additionalProperties:!1},output:{type:"object",properties:{text:{type:"string"},language:{type:"string"}},required:["text","language"],additionalProperties:!1}}},events:{}},Oe=250;function je(t,e){let i=t.replace(/\r\n/g,`
|
|
191
191
|
`);return e?i=i.replace(/```[\s\S]*?```/g," "):i=i.replace(/```[^\n]*\n([\s\S]*?)```/g,"$1"),i=i.replace(/`([^`]+)`/g,"$1"),i=i.replace(/!\[[^\]]*\]\([^)]*\)/g," "),i=i.replace(/\[([^\]]+)\]\([^)]*\)/g,"$1"),i=i.replace(/^\s*#{1,6}\s+/gm,""),i=i.replace(/^\s*>\s?/gm,""),i=i.replace(/^\s*[-*+]\s+/gm,""),i=i.replace(/^\s*\d+\.\s+/gm,""),i=i.replace(/(\*\*|__)(.*?)\1/g,"$2"),i=i.replace(/(\*|_)(.*?)\1/g,"$2"),i=i.replace(/^\s*\|.*\|\s*$/gm," "),i=i.replace(/\n{2,}/g,". "),i=i.replace(/\n/g," "),i=i.replace(/\s+/g," "),i=i.replace(/\s+([.,;:!?])/g,"$1"),i=i.replace(/([.,;:!?]){2,}/g,"$1"),i.trim()}function me(t,e=Oe){const i=t.trim();if(!i)return[];const c=i.split(new RegExp("(?<=[.!?…])\\s+")),n=[];let s="";const u=a=>{let g="";for(const h of a.split(/\s+/))h&&(g&&g.length+1+h.length>e?(n.push(g),g=h):g=g?`${g} ${h}`:h);return g};for(const a of c){if(a.length>e){s&&(n.push(s),s=""),s=u(a);continue}s&&s.length+1+a.length>e?(n.push(s),s=a):s=s?`${s} ${a}`:a}return s&&n.push(s),n}function Be(t,e){const i=t.stores.speech,c=t.stores.tts.value,[n,s]=y.createSignal(c.engine==="edge"?"edge":"system"),[u,a]=y.createSignal(c.voice),g=w=>{(w.engine==="edge"||w.engine==="system")&&s(w.engine),w.voice!==void 0&&a(w.voice)},[h,S]=y.createSignal(!1),[R,v]=y.createSignal(!1),[C,I]=y.createSignal([]),[z,B]=y.createSignal(""),[N,U]=y.createSignal("none");let A=0,q=[],Z="",L,F;const T=new Map,W=()=>typeof globalThis.speechSynthesis<"u"?globalThis.speechSynthesis:void 0,x=()=>{const w=W()?.getVoices()??[];if(w.length===0)return;const f=i.value.voiceURI;if(f){const P=w.find(X=>X.voiceURI===f);if(P)return P}const k=t.locale.locale().split("-")[0]?.toLowerCase()??"es";return w.find(P=>P.lang.toLowerCase().startsWith(k))??w[0]},_=async()=>{if(n()==="edge"){try{const f=await t.client.rpc(j).edgeVoices({});f.length>0?(I(f.map(k=>({id:k.id,label:k.label}))),B("")):B(t.t("speech.edge.error"))}catch(f){B(f instanceof Error?f.message:String(f))}U("edge");return}B("");const w=W()?.getVoices()??[];if(w.length>0){I(w.map(f=>({id:f.voiceURI,label:`${f.name} — ${f.lang}`}))),U("web");return}try{const f=await e.voices();if(f.length>0){I(f.map(k=>({id:k,label:k}))),U("sapi");return}}catch{}U("none")},H=()=>{L&&(L.onended=null,L.onerror=null,L.pause(),L=void 0),F&&(URL.revokeObjectURL(F),F=void 0)},l=()=>{A++,q=[],W()?.cancel(),H(),v(!1),S(!1),N()==="sapi"&&e.stop().catch(()=>{})},m=()=>N()==="web"||N()==="edge",b=()=>{if(!(!h()||R()||!m())){if(N()==="edge"){L?.pause(),v(!0);return}W()?.pause(),v(!0)}},E=()=>{if(!(!h()||!R()||!m())){if(N()==="edge"){L?.play().catch(()=>{}),v(!1);return}W()?.resume(),v(!1)}},ee=()=>{R()?E():b()},M=()=>Z?G(Z):Promise.resolve(!1),O=w=>{const f=u()||"es-ES-XimenaNeural",k=i.value.rate,P=me(w,4e3),X=`${f}|${k}|${w}`,Y=T.get(X)??[];T.clear(),T.set(X,Y);const V=A;S(!0),v(!1);const r=d=>{if(V===A){if(d>=P.length){v(!1),S(!1);return}(async()=>{let D=Y[d];try{D||(D=await t.client.rpc(j).edgeSpeak({text:P[d]??"",voice:f,rate:k}),Y[d]=D)}catch{V===A&&(v(!1),S(!1),t.toast.show({variant:"error",title:t.t("read.title"),description:t.t("error.edge")}));return}if(V!==A)return;const re=Uint8Array.from(atob(D),Ee=>Ee.charCodeAt(0)),de=URL.createObjectURL(new Blob([re],{type:"audio/mpeg"}));H(),F=de;const ne=new Audio(de);L=ne,ne.onended=()=>{V===A&&(H(),r(d+1))},ne.onerror=()=>{V===A&&(H(),v(!1),S(!1))},await ne.play().catch(()=>{V===A&&(H(),v(!1),S(!1),t.toast.show({variant:"error",title:t.t("read.title"),description:t.t("error.edge")}))})})()}};return r(0),!0},G=async w=>{Z=w;const f=je(w,i.value.skipCode);if(!f)return!1;if(l(),await _(),n()==="edge")return O(f);if(N()==="web"){const k=W();if(!k)return!1;const P=x(),X=i.value.rate,Y=A;q=me(f),S(!0),v(!1);const V=()=>{if(Y!==A)return;const r=q.shift();if(!r){v(!1),S(!1);return}const d=new SpeechSynthesisUtterance(r);P&&(d.voice=P),P?.lang&&(d.lang=P.lang),d.rate=X,d.onend=V,d.onerror=V,k.speak(d)};return V(),!0}if(N()==="sapi"){S(!0),v(!1);try{await e.speak({text:f,rate:i.value.rate,voice:i.value.voiceURI})}catch(k){throw S(!1),k}return!0}throw S(!1),new Error(t.t("read.noVoices"))},J=async()=>{const w=t.sessions.current();if(!w)return"";const k=(await w.server.client.message.list({sessionID:w.id,type:"assistant",order:"desc",limit:1})).data[0];return!k||k.type!=="assistant"?"":k.content.filter(P=>P.type==="text").map(P=>P.text).join(`
|
|
192
|
-
`)};return e.on("done",()=>{v(!1),S(!1)}),W()?.addEventListener?.("voiceschanged",()=>{_()}),_(),{speaking:h,paused:R,backend:N,engine:n,voice:u,error:z,canPause:m,setConfig:g,voices:C,refreshVoices:_,lastAssistantText:J,speak:G,cancel:l,pause:b,resume:E,togglePause:ee,restart:M,preview:async()=>{const w=await G(t.t("speech.preview.text"));if(w){const f=n()==="edge"?`Edge · ${u()}`:`${N()} · ${i.value.voiceURI||"auto"}`;t.toast.show({variant:"default",title:t.t("read.title"),description:f})}return w}}}function te(t,e){if(t instanceof Error&&t.message)return t.message;if(typeof t=="string"&&t)return t;if(t&&typeof t=="object"){const i=t;for(const n of["message","error","detail","defect"]){const s=i[n];if(typeof s=="string"&&s)return s}const c=i.data;if(c&&typeof c=="object"){const n=c.message;if(typeof n=="string"&&n)return n}try{const n=JSON.stringify(t);if(n&&n!=="{}")return n}catch{return e}}return e}const Ue=["es-ES","es-MX","es-AR","es-CO","pt-BR","pt-PT","en-US","en-GB","fr-FR","de-DE","it-IT"];function qe(t){const e=$.usePlugin(),i=e.ui,c=e.stores.prefs,n=e.stores.speech,s=e.stores.tts,u=e.stores.engine,a=e.stores.whisper,g=e.stores.whispercpp,h=e.main(le),S=e.main(ce),[R,v]=y.createSignal([]),[C,I]=y.createSignal(!1),[z,B]=y.createSignal(!1),[N,U]=y.createSignal(!1),[A,q]=y.createSignal(!1),[Z,L]=y.createSignal(!1),[F,T]=y.createSignal(void 0),[W,x]=y.createSignal(""),_=async()=>{const r=await e.client.rpc(j).whisperCppStatus({model:g.value.model});return T({available:r.ffmpeg,version:r.ffmpegVersion}),r},H=()=>{const r=F();return r?r.available?e.t("whispercpp.ffmpeg.ready",{version:r.version}):e.t("whispercpp.ffmpeg.missing"):e.t("whispercpp.ffmpeg.description")};y.onMount(()=>{t.speaker.setConfig({engine:s.value.engine,voice:s.value.voice});const r=()=>{h.diagnose().then(d=>{d.locales.length>0&&v(d.locales)}).catch(()=>{})};e.client.rpc(j).capabilities({}).then(d=>{const D=d;x(D.platform),!D.engines.includes(u.value.mode)&&D.engines.length>0&&G(D.engines[0]??"windows"),D.platform!=="linux"?r():_().catch(()=>{})}).catch(()=>r()),t.speaker.refreshVoices()});const l=()=>W()==="linux"?[{value:"whispercpp",label:e.t("engine.whispercpp")}]:[{value:"windows",label:e.t("engine.windows")},{value:"system",label:e.t("engine.system")},{value:"whisper",label:e.t("engine.whisper")}],m=()=>{const r=R(),d=c.value.locale;return(r.includes(d)?r:[d,...r]).map(re=>({value:re,label:re}))},b=()=>{const r=t.speaker.voices().map(d=>({value:d.id,label:d.label}));return s.value.engine==="edge"?r:[{value:"",label:e.t("speech.voice.auto")},...r]},E=()=>s.value.engine==="edge"?s.value.voice:n.value.voiceURI,ee=r=>{if(s.value.engine==="edge"){s.update(d=>{d.voice=r}),t.speaker.setConfig({voice:r});return}O({voiceURI:r})},M=r=>{c.update(d=>{r.locale!==void 0&&(d.locale=r.locale),r.minConfidence!==void 0&&(d.minConfidence=r.minConfidence),r.trailingSpace!==void 0&&(d.trailingSpace=r.trailingSpace),r.autoFocus!==void 0&&(d.autoFocus=r.autoFocus)})},O=r=>{n.update(d=>{r.voiceURI!==void 0&&(d.voiceURI=r.voiceURI),r.rate!==void 0&&(d.rate=r.rate),r.skipCode!==void 0&&(d.skipCode=r.skipCode)})},G=r=>{u.update(d=>{d.mode=r})},J=r=>{a.update(d=>{r.python!==void 0&&(d.python=r.python),r.model!==void 0&&(d.model=r.model),r.language!==void 0&&(d.language=r.language)})},se=r=>{g.update(d=>{r.model!==void 0&&(d.model=r.model),r.language!==void 0&&(d.language=r.language)})},pe=async()=>{U(!0);try{const r=await e.client.rpc(j).whisperCppInstall({model:g.value.model});r.ok?(e.toast.show({variant:"success",title:e.t("pill.title"),description:e.t("whispercpp.install.ok",{model:r.model})}),await _().catch(()=>{})):e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.install.error",{error:r.error||"?"}),persistent:!0})}catch(r){e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.install.error",{error:te(r,"?")}),persistent:!0})}finally{U(!1)}},w=async()=>{q(!0);try{const r=await _();r.error?e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.test.error",{error:r.error}),persistent:!0}):r.installed?r.ffmpeg?e.toast.show({variant:"success",title:e.t("pill.title"),description:e.t("whispercpp.test.ready",{model:r.model})}):e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.ffmpeg.missing"),persistent:!0}):e.toast.show({variant:"default",title:e.t("pill.title"),description:e.t("whispercpp.test.missing")})}catch(r){e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.test.error",{error:te(r,"?")})})}finally{q(!1)}},f=async()=>{L(!0);try{const r=await e.client.rpc(j).whisperCppInstallFfmpeg({});if(r.ok)e.toast.show({variant:"success",title:e.t("pill.title"),description:e.t("whispercpp.ffmpeg.install.ok")}),await _();else{const d=r.command?` ${e.t("whispercpp.ffmpeg.install.manual",{command:r.command})}`:"";e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.ffmpeg.install.error",{error:r.error||"?"})+d,persistent:!0})}}catch(r){e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.ffmpeg.install.error",{error:te(r,"?")}),persistent:!0})}finally{L(!1)}},k=async()=>{B(!0);try{const r=await e.client.rpc(j).whisperStatus({python:a.value.python,model:a.value.model});r.ready?e.toast.show({variant:"success",title:e.t("pill.title"),description:e.t("whisper.test.ready",{model:r.model,device:r.device})}):e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whisper.test.error",{error:r.error||"?"})})}catch(r){e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whisper.test.error",{error:r instanceof Error?r.message:String(r)})})}finally{B(!1)}},P=r=>{s.update(d=>{d.engine=r}),t.speaker.setConfig({engine:r}),t.speaker.refreshVoices()},X=async()=>{try{await S.toggle(),e.toast.show({variant:"default",title:e.t("settings.winh"),description:e.t("settings.winh.sent")})}catch(r){e.toast.show({variant:"error",title:e.t("pill.title"),description:r instanceof Error?r.message:e.t("error.winh")})}},Y=async()=>{try{await t.speaker.preview()}catch(r){e.toast.show({variant:"error",title:e.t("read.title"),description:r instanceof Error?r.message:e.t("read.error")})}},V=async()=>{I(!0);try{const r=await h.diagnose();if(r.locales.length===0){e.toast.show({variant:"error",title:e.t("error.title"),description:e.t("settings.test.failed",{reason:e.t("common.reason.no-recognizers")}),persistent:!0});return}if(!r.microphone){e.toast.show({variant:"error",title:e.t("error.title"),description:e.t("settings.test.failed",{reason:e.t("common.reason.no-microphone")}),persistent:!0});return}r.locales.length>0&&!R().length&&v(r.locales),e.toast.show({variant:"success",title:e.t("error.title"),description:e.t("settings.test.success",{locale:r.selected||r.locales[0]||c.value.locale})})}catch(r){e.toast.show({variant:"error",title:e.t("error.title"),description:r instanceof Error?r.message:String(r)})}finally{I(!1)}};return o.createComponent(i.SettingsLayout,{get title(){return e.t("settings.title")},get description(){return e.t("settings.description")},get children(){return[o.createComponent(i.SettingsSection,{get title(){return e.t("settings.section")},get children(){return[o.createComponent(i.SettingsRow,{id:"engine",get title(){return e.t("settings.engine")},get description(){return e.t("settings.engine.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("settings.engine")},get value(){return u.value.mode},get options(){return l()},onChange:r=>G(r)})}}),o.createComponent(y.Show,{get when(){return u.value.mode==="windows"},get children(){return o.createComponent(i.SettingsRow,{id:"winh",get title(){return e.t("settings.winh")},get description(){return e.t("settings.winh.description")},get children(){return o.createComponent(i.Button,{onClick:()=>{X()},get children(){return e.t("settings.winh.run")}})}})}}),o.createComponent(y.Show,{get when(){return u.value.mode==="whisper"},get children(){return[o.createComponent(i.SettingsRow,{id:"whisper-python",get title(){return e.t("whisper.python")},get description(){return e.t("whisper.python.description")},get children(){return o.createComponent(i.TextInput,{get label(){return e.t("whisper.python")},get value(){return a.value.python},onInput:r=>J({python:r})})}}),o.createComponent(i.SettingsRow,{id:"whisper-model",get title(){return e.t("whisper.model")},get description(){return e.t("whisper.model.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("whisper.model")},get value(){return a.value.model},options:[{value:"large-v3-turbo",label:"large-v3-turbo"},{value:"large-v3",label:"large-v3"},{value:"medium",label:"medium"}],onChange:r=>J({model:r})})}}),o.createComponent(i.SettingsRow,{id:"whisper-language",get title(){return e.t("whisper.language")},get description(){return e.t("whisper.language.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("whisper.language")},get value(){return a.value.language},get options(){return[{value:"",label:e.t("whisper.language.auto")},{value:"es",label:"Español"},{value:"en",label:"English"},{value:"pt",label:"Português"}]},onChange:r=>J({language:r})})}}),o.createComponent(i.SettingsRow,{id:"whisper-test",get title(){return e.t("whisper.test")},get description(){return e.t("whisper.test.description")},get children(){return o.createComponent(i.Button,{get busy(){return z()},onClick:()=>{k()},get children(){return e.t("whisper.test.run")}})}})]}}),o.createComponent(y.Show,{get when(){return u.value.mode==="whispercpp"},get children(){return[o.createComponent(i.SettingsRow,{id:"whispercpp-model",get title(){return e.t("whispercpp.model")},get description(){return e.t("whispercpp.model.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("whispercpp.model")},get value(){return g.value.model},options:[{value:"base-q5_1",label:"base-q5_1 · 57 MB"},{value:"small-q5_1",label:"small-q5_1 · 180 MB"}],onChange:r=>se({model:r})})}}),o.createComponent(i.SettingsRow,{id:"whispercpp-language",get title(){return e.t("whispercpp.language")},get description(){return e.t("whispercpp.language.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("whispercpp.language")},get value(){return g.value.language},get options(){return[{value:"auto",label:e.t("whispercpp.language.auto")},{value:"es",label:"Español"},{value:"en",label:"English"},{value:"pt",label:"Português"}]},onChange:r=>se({language:r})})}}),o.createComponent(i.SettingsRow,{id:"whispercpp-ffmpeg",get title(){return e.t("whispercpp.ffmpeg")},get description(){return H()},get children(){return[o.createComponent(y.Show,{get when(){return F()?.available===!1},get children(){return o.createComponent(i.Button,{get busy(){return Z()},onClick:()=>{f()},get children(){return e.t("whispercpp.ffmpeg.install")}})}}),o.createComponent(y.Show,{get when(){return F()?.available!==!1},get children(){return o.createComponent(i.Button,{onClick:()=>{_().catch(()=>{})},get children(){return e.t("whispercpp.test.run")}})}})]}}),o.createComponent(i.SettingsRow,{id:"whispercpp-install",get title(){return e.t("whispercpp.install")},get description(){return e.t("whispercpp.install.description")},get children(){return o.createComponent(i.Button,{get busy(){return N()},onClick:()=>{pe()},get children(){return e.t("whispercpp.install.run")}})}}),o.createComponent(i.SettingsRow,{id:"whispercpp-test",get title(){return e.t("whispercpp.test")},get description(){return e.t("whispercpp.test.description")},get children(){return o.createComponent(i.Button,{get busy(){return A()},onClick:()=>{w()},get children(){return e.t("whispercpp.test.run")}})}})]}}),o.createComponent(y.Show,{get when(){return u.value.mode==="system"},get children(){return[o.createComponent(i.SettingsRow,{id:"language",get title(){return e.t("settings.language")},get description(){return e.t("settings.language.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("settings.language")},get value(){return c.value.locale},get options(){return o.memo(()=>m().length>0)()?m():Ue.map(r=>({value:r,label:r}))},onChange:r=>M({locale:r})})}}),o.createComponent(i.SettingsRow,{id:"confidence",get title(){return e.t("settings.confidence")},get description(){return e.t("settings.confidence.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("settings.confidence")},get value(){return String(c.value.minConfidence)},get options(){return[{value:"0.2",label:e.t("confidence.low")},{value:"0.4",label:e.t("confidence.normal")},{value:"0.6",label:e.t("confidence.high")}]},onChange:r=>M({minConfidence:Number(r)||.4})})}}),o.createComponent(i.SettingsRow,{id:"space",get title(){return e.t("settings.space")},get description(){return e.t("settings.space.description")},get children(){return o.createComponent(i.Switch,{get label(){return e.t("settings.space")},hideLabel:!0,get checked(){return c.value.trailingSpace},onChange:r=>M({trailingSpace:r})})}}),o.createComponent(i.SettingsRow,{id:"focus",get title(){return e.t("settings.focus")},get description(){return e.t("settings.focus.description")},get children(){return o.createComponent(i.Switch,{get label(){return e.t("settings.focus")},hideLabel:!0,get checked(){return c.value.autoFocus},onChange:r=>M({autoFocus:r})})}})]}})]}}),o.createComponent(i.SettingsSection,{get title(){return e.t("speech.section")},get children(){return[o.createComponent(i.SettingsRow,{id:"tts-engine",get title(){return e.t("speech.engine")},get description(){return e.t("speech.engine.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("speech.engine")},get value(){return s.value.engine},get options(){return[{value:"edge",label:e.t("speech.engine.edge")},{value:"system",label:e.t("speech.engine.system")}]},onChange:r=>P(r)})}}),o.createComponent(i.SettingsRow,{id:"voice",get title(){return e.t("speech.voice")},get description(){return e.t("speech.voice.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("speech.voice")},get value(){return E()},get options(){return b()},onChange:r=>ee(r)})}}),o.createComponent(y.Show,{get when(){return t.speaker.error()},get children(){return o.createComponent(i.SettingsRow,{id:"tts-error",get title(){return e.t("speech.edge.error")},get description(){return t.speaker.error()}})}}),o.createComponent(i.SettingsRow,{id:"rate",get title(){return e.t("speech.rate")},get description(){return e.t("speech.rate.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("speech.rate")},get value(){return String(n.value.rate)},get options(){return[{value:"0.8",label:e.t("speech.rate.slow")},{value:"1",label:e.t("speech.rate.normal")},{value:"1.2",label:e.t("speech.rate.fast")},{value:"1.5",label:e.t("speech.rate.faster")}]},onChange:r=>O({rate:Number(r)||1})})}}),o.createComponent(i.SettingsRow,{id:"skip-code",get title(){return e.t("speech.skipCode")},get description(){return e.t("speech.skipCode.description")},get children(){return o.createComponent(i.Switch,{get label(){return e.t("speech.skipCode")},hideLabel:!0,get checked(){return n.value.skipCode},onChange:r=>O({skipCode:r})})}}),o.createComponent(i.SettingsRow,{id:"preview",get title(){return e.t("speech.preview")},get description(){return e.t("speech.preview.description")},get children(){return o.createComponent(i.Button,{onClick:()=>{Y()},get children(){return e.t("read.idle")}})}})]}}),o.createComponent(y.Show,{get when(){return W()!=="linux"},get children(){return o.createComponent(i.SettingsSection,{get title(){return e.t("settings.test.section")},get children(){return o.createComponent(i.SettingsRow,{id:"test",get title(){return e.t("settings.test")},get description(){return e.t("settings.test.description")},get children(){return o.createComponent(i.Button,{get busy(){return C()},onClick:()=>{V()},get children(){return e.t("settings.test.run")}})}})}})}})]}})}async function He(){const t=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,echoCancellation:!0,noiseSuppression:!0}}),e=MediaRecorder.isTypeSupported("audio/webm;codecs=opus")?"audio/webm;codecs=opus":"audio/webm",i=new MediaRecorder(t,{mimeType:e}),c=[];return i.ondataavailable=n=>{n.data.size>0&&c.push(n.data)},i.start(),{stop:()=>new Promise(n=>{i.onstop=()=>{t.getTracks().forEach(s=>s.stop()),n(new Blob(c,{type:e}))},i.stop()})}}async function Me(t){const e=new Uint8Array(await t.arrayBuffer());let i="";const c=32768;for(let n=0;n<e.length;n+=c)i+=String.fromCharCode(...e.subarray(n,n+c));return btoa(i)}function Ge(t){const e=$.usePlugin();return o.memo(()=>t.actions().map(i=>o.createComponent(e.ui.Button,{get variant(){return i.id==="stop"?"danger":"neutral"},get icon(){return i.icon},onClick:()=>{i.run(),t.close()},get children(){return i.label}})))}const Xe=t=>{const e=t.main(le),i=t.main(fe),c=t.main(ce),n=Be(t,i),s=t.stores.prefs,u=t.stores.engine,a=t.stores.whisper,g=t.stores.whispercpp,[h,S]=y.createSignal(!1),[R,v]=y.createSignal("idle");t.client.rpc(j).capabilities({}).then(l=>{const m=l;!m.engines.includes(u.value.mode)&&m.engines.length>0&&u.update(b=>{b.mode=m.engines[0]??"windows"})}).catch(()=>{});const C=()=>u.value.mode==="whisper"||u.value.mode==="whispercpp"?u.value.mode:void 0;let I,z;const B=(l,m,b)=>{switch(l){case"LANGUAGE_NOT_AVAILABLE":return t.t("error.language",{locale:m||s.value.locale,available:b.length>0?b.join(", "):"—"});case"NO_RECOGNIZERS":return t.t("error.none");case"MICROPHONE_UNAVAILABLE":return t.t("error.mic");case"SYSTEM_SPEECH_UNAVAILABLE":return t.t("error.system");case"ENGINE_EXIT":return t.t("error.exit");default:return t.t("error.unknown",{code:l})}},N=()=>{h()&&(S(!1),c.toggle().catch(()=>{})),n.cancel(),I=t.sessions.current()?.key,e.start({locale:s.value.locale,minConfidence:s.value.minConfidence}).catch(l=>{t.toast.show({variant:"error",title:t.t("error.title"),description:l instanceof Error?l.message:String(l)})})},U=()=>{e.stop().catch(()=>{})},A=()=>{n.cancel(),t.screen.current()?.composer.focus(),c.toggle().then(()=>S(l=>!l)).catch(l=>{S(!1),t.toast.show({variant:"error",title:t.t("pill.title"),description:l instanceof Error?`${t.t("error.winh")} ${l.message}`:t.t("error.winh")})})},q=()=>t.t(C()==="whispercpp"?"error.whispercpp":"error.whisper"),Z=async()=>{if(R()==="idle"){n.cancel();try{z=await He(),v("recording")}catch(l){t.toast.show({variant:"error",title:t.t("pill.title"),description:te(l,q())})}}},L=()=>{const l=z;z=void 0,l&&l.stop().catch(()=>{}),v("idle")},F=async()=>{const l=z;if(z=void 0,!l){v("idle");return}v("transcribing");const m=C();try{const b=await l.stop(),E=await Me(b),M=(m==="whispercpp"?await t.client.rpc(j).whisperCppTranscribe({audio:E,mime:b.type,language:g.value.language,model:g.value.model}):await t.client.rpc(j).whisperTranscribe({audio:E,mime:b.type,language:a.value.language,python:a.value.python,model:a.value.model})).text.trim();if(!M){t.toast.show({variant:"default",title:t.t("pill.title"),description:t.t(m==="whispercpp"?"whispercpp.empty":"whisper.empty")});return}const O=t.screen.current()?.composer;if(O){const G=O.text(),J=G.length>0&&!/\s$/.test(G)?" ":"";O.insert(J+M),O.focus()}}catch(b){const E=te(b,q());t.toast.show({variant:"error",title:t.t("pill.title"),description:E.includes("FFMPEG_MISSING")?t.t("error.ffmpeg"):E})}finally{v("idle")}},T=()=>{if(C()){R()==="recording"?F():R()==="idle"&&Z();return}if(u.value.mode==="windows"){A();return}const l=e.state()?.status??"idle";l==="starting"||l==="listening"?U():N()},W=()=>{if(R()==="recording"&&L(),n.speaking()){n.cancel();return}if(!t.sessions.current()){t.toast.show({variant:"error",title:t.t("read.title"),description:t.t("read.noSession")});return}const l=e.state()?.status??"idle";(l==="starting"||l==="listening")&&e.stop().catch(()=>{}),(async()=>{try{const m=await n.lastAssistantText();if(!m.trim()){t.toast.show({variant:"default",title:t.t("read.title"),description:t.t("read.empty")});return}await n.speak(m)||t.toast.show({variant:"default",title:t.t("read.title"),description:t.t("read.empty")})}catch(m){t.toast.show({variant:"error",title:t.t("read.title"),description:m instanceof Error?m.message:t.t("read.error")})}})()},x=()=>{if(!n.speaking())return[{id:"start",label:t.t("read.idle"),icon:"outline-audio",run:W}];const l=n.paused(),m=[{id:"restart",label:t.t("read.restart"),icon:"outline-reset",run:()=>{n.restart()}}];return n.canPause()&&m.push({id:"pause",label:l?t.t("read.resume"):t.t("read.pause"),icon:"outline-audio",run:()=>n.togglePause()}),m.push({id:"stop",label:t.t("read.stop"),icon:"xmark-small",run:()=>n.cancel()}),m};e.on("final",l=>{const m=t.sessions.current()?.key;if(I&&m&&m!==I){t.toast.show({variant:"error",title:t.t("error.title"),description:t.t("toast.discarded")});return}const b=t.screen.current()?.composer;if(!b)return;const E=b.text(),ee=s.value.trailingSpace&&E.length>0&&!/\s$/.test(E)?" ":"";b.insert(ee+l.text),s.value.autoFocus&&b.focus()}),e.on("error",l=>{t.toast.show({variant:"error",title:t.t("error.title"),description:B(l.code,l.detail,l.available),persistent:l.code==="LANGUAGE_NOT_AVAILABLE"||l.code==="NO_RECOGNIZERS",duration:8e3})});const _=()=>{if(t.app.platform!=="desktop")return;if(u.value.mode==="windows")return h()?{label:t.t("pill.dictating"),icon:"outline-wave-audio",tone:"danger",title:t.t("pill.stop"),run:T}:{label:t.t("pill.idle"),icon:"outline-wave-audio",title:t.t("pill.winH"),run:T};if(u.value.mode==="whisper"||u.value.mode==="whispercpp"){const m=t.t(u.value.mode==="whispercpp"?"pill.whispercpp":"pill.whisper");return R()==="recording"?{label:t.t("pill.recording"),icon:"outline-wave-audio",tone:"danger",title:t.t("pill.stop"),run:T}:R()==="transcribing"?{label:t.t("pill.transcribing"),icon:"outline-audio",title:m}:{label:t.t("pill.idle"),icon:"outline-wave-audio",title:m,run:T}}const l=e.state()?.status??"idle";return l==="starting"?{label:t.t("pill.starting"),icon:"outline-wave-audio",title:t.t("pill.title"),run:T}:l==="listening"?{label:t.t("pill.listening"),icon:"outline-wave-audio",tone:"danger",title:t.t("pill.stop"),run:T}:l==="error"?{label:t.t("pill.error"),icon:"outline-wave-audio",tone:"warning",title:t.t("pill.title"),run:T}:{label:t.t("pill.idle"),icon:"outline-wave-audio",title:t.t("pill.title"),run:T}},H=()=>{if(t.app.platform!=="desktop")return;const l=n.speaking(),m=n.paused(),b=l?x().map(E=>({id:E.id,label:E.label,icon:E.icon,tone:E.id==="stop"?"danger":void 0,run:E.run})):[];return{label:l?m?t.t("read.paused"):t.t("read.speaking"):t.t("read.idle"),icon:"outline-audio",tone:l?"success":void 0,title:t.t("read.title"),rows:b.length>0?b:void 0,run:l?void 0:W}};t.add($.ComposerPill,()=>({id:"dictate",show:()=>_()})),t.add($.ComposerPill,()=>({id:"read",order:1,show:()=>H(),menu:l=>o.createComponent(Ge,{actions:x,get close(){return l.close}})})),t.add($.Command,()=>({id:"toggle",title:t.t("command.toggle"),description:t.t("command.toggle.description"),keywords:"voice dictation microphone speech dictado voz microfono",group:t.t("pill.title"),section:"prompt",bind:"mod+shift+m",slash:{name:"dictado"},editable:!0,enabled:t.app.platform==="desktop",run:T})),t.add($.Command,()=>({id:"configure",title:t.t("command.configure"),keywords:"voice dictation microphone speech dictado voz microfono",group:t.t("pill.title"),enabled:t.app.platform==="desktop",run:()=>t.layout.settings(t.id)})),t.add($.Command,()=>({id:"read",title:t.t("command.read"),description:t.t("command.read.description"),keywords:"read aloud speech voice leer voz altavoz lectura",group:t.t("pill.title"),section:"prompt",bind:"mod+shift+l",slash:{name:"leer"},editable:!0,enabled:t.app.platform==="desktop",run:W})),t.add($.SettingsPage,{id:t.id,icon:"outline-audio",get title(){return t.t("settings.title")},get entries(){return[{id:"engine",title:t.t("settings.engine"),keywords:"engine motor dictation dictado winh voz"},{id:"winh",title:t.t("settings.winh"),keywords:"winh windows voice typing dictado"},{id:"language",title:t.t("settings.language"),keywords:"voice language idioma voz"},{id:"confidence",title:t.t("settings.confidence"),keywords:"voice confidence confianza"},{id:"test",title:t.t("settings.test"),keywords:"voice microphone microphone test microfono"},{id:"voice",title:t.t("speech.voice"),keywords:"read aloud voice voz lectura altavoz"},{id:"tts-engine",title:t.t("speech.engine"),keywords:"voice engine motor edge neural sistema"},{id:"whisper-python",title:t.t("whisper.python"),keywords:"whisper python venv entorno"},{id:"whisper-model",title:t.t("whisper.model"),keywords:"whisper model modelo"},{id:"whisper-language",title:t.t("whisper.language"),keywords:"whisper language idioma"},{id:"whisper-test",title:t.t("whisper.test"),keywords:"whisper check comprobar"},{id:"whispercpp-model",title:t.t("whispercpp.model"),keywords:"whisper.cpp model modelo"},{id:"whispercpp-language",title:t.t("whispercpp.language"),keywords:"whisper.cpp language idioma"},{id:"whispercpp-ffmpeg",title:t.t("whispercpp.ffmpeg"),keywords:"whisper.cpp ffmpeg audio convertir"},{id:"whispercpp-install",title:t.t("whispercpp.install"),keywords:"whisper.cpp download descargar instalar"},{id:"whispercpp-test",title:t.t("whispercpp.test"),keywords:"whisper.cpp check comprobar"},{id:"rate",title:t.t("speech.rate"),keywords:"read aloud speed velocidad lectura"},{id:"skip-code",title:t.t("speech.skipCode"),keywords:"read aloud code codigo lectura"},{id:"preview",title:t.t("speech.preview"),keywords:"read aloud test voice probar voz"}]},render:()=>o.createComponent(qe,{speaker:n})})},Ke=$.Plugin.define({...$e,setup:Xe,main:Fe});exports.default=Ke;
|
|
192
|
+
`)};return e.on("done",()=>{v(!1),S(!1)}),W()?.addEventListener?.("voiceschanged",()=>{_()}),_(),{speaking:h,paused:R,backend:N,engine:n,voice:u,error:z,canPause:m,setConfig:g,voices:C,refreshVoices:_,lastAssistantText:J,speak:G,cancel:l,pause:b,resume:E,togglePause:ee,restart:M,preview:async()=>{const w=await G(t.t("speech.preview.text"));if(w){const f=n()==="edge"?`Edge · ${u()}`:`${N()} · ${i.value.voiceURI||"auto"}`;t.toast.show({variant:"default",title:t.t("read.title"),description:f})}return w}}}function te(t,e){if(t instanceof Error&&t.message)return t.message;if(typeof t=="string"&&t)return t;if(t&&typeof t=="object"){const i=t;for(const n of["message","error","detail","defect"]){const s=i[n];if(typeof s=="string"&&s)return s}const c=i.data;if(c&&typeof c=="object"){const n=c.message;if(typeof n=="string"&&n)return n}try{const n=JSON.stringify(t);if(n&&n!=="{}")return n}catch{return e}}return e}const Ue=["es-ES","es-MX","es-AR","es-CO","pt-BR","pt-PT","en-US","en-GB","fr-FR","de-DE","it-IT"];function qe(t){const e=$.usePlugin(),i=e.ui,c=e.stores.prefs,n=e.stores.speech,s=e.stores.tts,u=e.stores.engine,a=e.stores.whisper,g=e.stores.whispercpp,h=e.main(le),S=e.main(ce),[R,v]=y.createSignal([]),[C,I]=y.createSignal(!1),[z,B]=y.createSignal(!1),[N,U]=y.createSignal(!1),[A,q]=y.createSignal(!1),[Z,L]=y.createSignal(!1),[F,T]=y.createSignal(void 0),[W,x]=y.createSignal(""),_=async()=>{const r=await e.client.rpc(j).whisperCppStatus({model:g.value.model});return T({available:r.ffmpeg,version:r.ffmpegVersion}),r},H=()=>{const r=F();return r?r.available?e.t("whispercpp.ffmpeg.ready",{version:r.version}):e.t("whispercpp.ffmpeg.missing"):e.t("whispercpp.ffmpeg.description")};y.onMount(()=>{t.speaker.setConfig({engine:s.value.engine,voice:s.value.voice});const r=()=>{h.diagnose().then(d=>{d.locales.length>0&&v(d.locales)}).catch(()=>{})};e.client.rpc(j).capabilities({}).then(d=>{const D=d;x(D.platform),!D.engines.includes(u.value.mode)&&D.engines.length>0&&G(D.engines[0]??"windows"),D.platform!=="linux"?r():_().catch(()=>{})}).catch(()=>r()),t.speaker.refreshVoices()});const l=()=>W()==="linux"?[{value:"whispercpp",label:e.t("engine.whispercpp")}]:[{value:"windows",label:e.t("engine.windows")},{value:"system",label:e.t("engine.system")},{value:"whisper",label:e.t("engine.whisper")}],m=()=>{const r=R(),d=c.value.locale;return(r.includes(d)?r:[d,...r]).map(re=>({value:re,label:re}))},b=()=>{const r=t.speaker.voices().map(d=>({value:d.id,label:d.label}));return s.value.engine==="edge"?r:[{value:"",label:e.t("speech.voice.auto")},...r]},E=()=>s.value.engine==="edge"?s.value.voice:n.value.voiceURI,ee=r=>{if(s.value.engine==="edge"){s.update(d=>{d.voice=r}),t.speaker.setConfig({voice:r});return}O({voiceURI:r})},M=r=>{c.update(d=>{r.locale!==void 0&&(d.locale=r.locale),r.minConfidence!==void 0&&(d.minConfidence=r.minConfidence),r.trailingSpace!==void 0&&(d.trailingSpace=r.trailingSpace),r.autoFocus!==void 0&&(d.autoFocus=r.autoFocus)})},O=r=>{n.update(d=>{r.voiceURI!==void 0&&(d.voiceURI=r.voiceURI),r.rate!==void 0&&(d.rate=r.rate),r.skipCode!==void 0&&(d.skipCode=r.skipCode)})},G=r=>{u.update(d=>{d.mode=r})},J=r=>{a.update(d=>{r.python!==void 0&&(d.python=r.python),r.model!==void 0&&(d.model=r.model),r.language!==void 0&&(d.language=r.language)})},se=r=>{g.update(d=>{r.model!==void 0&&(d.model=r.model),r.language!==void 0&&(d.language=r.language)})},pe=async()=>{U(!0);try{const r=await e.client.rpc(j).whisperCppInstall({model:g.value.model});r.ok?(e.toast.show({variant:"success",title:e.t("pill.title"),description:e.t("whispercpp.install.ok",{model:r.model})}),await _().catch(()=>{})):e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.install.error",{error:r.error||"?"}),persistent:!0})}catch(r){e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.install.error",{error:te(r,"?")}),persistent:!0})}finally{U(!1)}},w=async()=>{q(!0);try{const r=await _();r.error?e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.test.error",{error:r.error}),persistent:!0}):r.installed?r.ffmpeg?e.toast.show({variant:"success",title:e.t("pill.title"),description:e.t("whispercpp.test.ready",{model:r.model})}):e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.ffmpeg.missing"),persistent:!0}):e.toast.show({variant:"default",title:e.t("pill.title"),description:e.t("whispercpp.test.missing")})}catch(r){e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.test.error",{error:te(r,"?")})})}finally{q(!1)}},f=async()=>{L(!0);try{const r=await e.client.rpc(j).whisperCppInstallFfmpeg({});if(r.ok)e.toast.show({variant:"success",title:e.t("pill.title"),description:e.t("whispercpp.ffmpeg.install.ok")}),await _().catch(()=>{});else{const d=r.command?` ${e.t("whispercpp.ffmpeg.install.manual",{command:r.command})}`:"";e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.ffmpeg.install.error",{error:r.error||"?"})+d,persistent:!0})}}catch(r){e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whispercpp.ffmpeg.install.error",{error:te(r,"?")}),persistent:!0})}finally{L(!1)}},k=async()=>{B(!0);try{const r=await e.client.rpc(j).whisperStatus({python:a.value.python,model:a.value.model});r.ready?e.toast.show({variant:"success",title:e.t("pill.title"),description:e.t("whisper.test.ready",{model:r.model,device:r.device})}):e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whisper.test.error",{error:r.error||"?"})})}catch(r){e.toast.show({variant:"error",title:e.t("pill.title"),description:e.t("whisper.test.error",{error:r instanceof Error?r.message:String(r)})})}finally{B(!1)}},P=r=>{s.update(d=>{d.engine=r}),t.speaker.setConfig({engine:r}),t.speaker.refreshVoices()},X=async()=>{try{await S.toggle(),e.toast.show({variant:"default",title:e.t("settings.winh"),description:e.t("settings.winh.sent")})}catch(r){e.toast.show({variant:"error",title:e.t("pill.title"),description:r instanceof Error?r.message:e.t("error.winh")})}},Y=async()=>{try{await t.speaker.preview()}catch(r){e.toast.show({variant:"error",title:e.t("read.title"),description:r instanceof Error?r.message:e.t("read.error")})}},V=async()=>{I(!0);try{const r=await h.diagnose();if(r.locales.length===0){e.toast.show({variant:"error",title:e.t("error.title"),description:e.t("settings.test.failed",{reason:e.t("common.reason.no-recognizers")}),persistent:!0});return}if(!r.microphone){e.toast.show({variant:"error",title:e.t("error.title"),description:e.t("settings.test.failed",{reason:e.t("common.reason.no-microphone")}),persistent:!0});return}r.locales.length>0&&!R().length&&v(r.locales),e.toast.show({variant:"success",title:e.t("error.title"),description:e.t("settings.test.success",{locale:r.selected||r.locales[0]||c.value.locale})})}catch(r){e.toast.show({variant:"error",title:e.t("error.title"),description:r instanceof Error?r.message:String(r)})}finally{I(!1)}};return o.createComponent(i.SettingsLayout,{get title(){return e.t("settings.title")},get description(){return e.t("settings.description")},get children(){return[o.createComponent(i.SettingsSection,{get title(){return e.t("settings.section")},get children(){return[o.createComponent(i.SettingsRow,{id:"engine",get title(){return e.t("settings.engine")},get description(){return e.t("settings.engine.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("settings.engine")},get value(){return u.value.mode},get options(){return l()},onChange:r=>G(r)})}}),o.createComponent(y.Show,{get when(){return u.value.mode==="windows"},get children(){return o.createComponent(i.SettingsRow,{id:"winh",get title(){return e.t("settings.winh")},get description(){return e.t("settings.winh.description")},get children(){return o.createComponent(i.Button,{onClick:()=>{X()},get children(){return e.t("settings.winh.run")}})}})}}),o.createComponent(y.Show,{get when(){return u.value.mode==="whisper"},get children(){return[o.createComponent(i.SettingsRow,{id:"whisper-python",get title(){return e.t("whisper.python")},get description(){return e.t("whisper.python.description")},get children(){return o.createComponent(i.TextInput,{get label(){return e.t("whisper.python")},get value(){return a.value.python},onInput:r=>J({python:r})})}}),o.createComponent(i.SettingsRow,{id:"whisper-model",get title(){return e.t("whisper.model")},get description(){return e.t("whisper.model.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("whisper.model")},get value(){return a.value.model},options:[{value:"large-v3-turbo",label:"large-v3-turbo"},{value:"large-v3",label:"large-v3"},{value:"medium",label:"medium"}],onChange:r=>J({model:r})})}}),o.createComponent(i.SettingsRow,{id:"whisper-language",get title(){return e.t("whisper.language")},get description(){return e.t("whisper.language.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("whisper.language")},get value(){return a.value.language},get options(){return[{value:"",label:e.t("whisper.language.auto")},{value:"es",label:"Español"},{value:"en",label:"English"},{value:"pt",label:"Português"}]},onChange:r=>J({language:r})})}}),o.createComponent(i.SettingsRow,{id:"whisper-test",get title(){return e.t("whisper.test")},get description(){return e.t("whisper.test.description")},get children(){return o.createComponent(i.Button,{get busy(){return z()},onClick:()=>{k()},get children(){return e.t("whisper.test.run")}})}})]}}),o.createComponent(y.Show,{get when(){return u.value.mode==="whispercpp"},get children(){return[o.createComponent(i.SettingsRow,{id:"whispercpp-model",get title(){return e.t("whispercpp.model")},get description(){return e.t("whispercpp.model.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("whispercpp.model")},get value(){return g.value.model},options:[{value:"base-q5_1",label:"base-q5_1 · 57 MB"},{value:"small-q5_1",label:"small-q5_1 · 180 MB"}],onChange:r=>se({model:r})})}}),o.createComponent(i.SettingsRow,{id:"whispercpp-language",get title(){return e.t("whispercpp.language")},get description(){return e.t("whispercpp.language.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("whispercpp.language")},get value(){return g.value.language},get options(){return[{value:"auto",label:e.t("whispercpp.language.auto")},{value:"es",label:"Español"},{value:"en",label:"English"},{value:"pt",label:"Português"}]},onChange:r=>se({language:r})})}}),o.createComponent(i.SettingsRow,{id:"whispercpp-ffmpeg",get title(){return e.t("whispercpp.ffmpeg")},get description(){return H()},get children(){return[o.createComponent(y.Show,{get when(){return F()?.available===!1},get children(){return o.createComponent(i.Button,{get busy(){return Z()},onClick:()=>{f()},get children(){return e.t("whispercpp.ffmpeg.install")}})}}),o.createComponent(y.Show,{get when(){return F()?.available!==!1},get children(){return o.createComponent(i.Button,{onClick:()=>{_().catch(()=>{})},get children(){return e.t("whispercpp.test.run")}})}})]}}),o.createComponent(i.SettingsRow,{id:"whispercpp-install",get title(){return e.t("whispercpp.install")},get description(){return e.t("whispercpp.install.description")},get children(){return o.createComponent(i.Button,{get busy(){return N()},onClick:()=>{pe()},get children(){return e.t("whispercpp.install.run")}})}}),o.createComponent(i.SettingsRow,{id:"whispercpp-test",get title(){return e.t("whispercpp.test")},get description(){return e.t("whispercpp.test.description")},get children(){return o.createComponent(i.Button,{get busy(){return A()},onClick:()=>{w()},get children(){return e.t("whispercpp.test.run")}})}})]}}),o.createComponent(y.Show,{get when(){return u.value.mode==="system"},get children(){return[o.createComponent(i.SettingsRow,{id:"language",get title(){return e.t("settings.language")},get description(){return e.t("settings.language.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("settings.language")},get value(){return c.value.locale},get options(){return o.memo(()=>m().length>0)()?m():Ue.map(r=>({value:r,label:r}))},onChange:r=>M({locale:r})})}}),o.createComponent(i.SettingsRow,{id:"confidence",get title(){return e.t("settings.confidence")},get description(){return e.t("settings.confidence.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("settings.confidence")},get value(){return String(c.value.minConfidence)},get options(){return[{value:"0.2",label:e.t("confidence.low")},{value:"0.4",label:e.t("confidence.normal")},{value:"0.6",label:e.t("confidence.high")}]},onChange:r=>M({minConfidence:Number(r)||.4})})}}),o.createComponent(i.SettingsRow,{id:"space",get title(){return e.t("settings.space")},get description(){return e.t("settings.space.description")},get children(){return o.createComponent(i.Switch,{get label(){return e.t("settings.space")},hideLabel:!0,get checked(){return c.value.trailingSpace},onChange:r=>M({trailingSpace:r})})}}),o.createComponent(i.SettingsRow,{id:"focus",get title(){return e.t("settings.focus")},get description(){return e.t("settings.focus.description")},get children(){return o.createComponent(i.Switch,{get label(){return e.t("settings.focus")},hideLabel:!0,get checked(){return c.value.autoFocus},onChange:r=>M({autoFocus:r})})}})]}})]}}),o.createComponent(i.SettingsSection,{get title(){return e.t("speech.section")},get children(){return[o.createComponent(i.SettingsRow,{id:"tts-engine",get title(){return e.t("speech.engine")},get description(){return e.t("speech.engine.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("speech.engine")},get value(){return s.value.engine},get options(){return[{value:"edge",label:e.t("speech.engine.edge")},{value:"system",label:e.t("speech.engine.system")}]},onChange:r=>P(r)})}}),o.createComponent(i.SettingsRow,{id:"voice",get title(){return e.t("speech.voice")},get description(){return e.t("speech.voice.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("speech.voice")},get value(){return E()},get options(){return b()},onChange:r=>ee(r)})}}),o.createComponent(y.Show,{get when(){return t.speaker.error()},get children(){return o.createComponent(i.SettingsRow,{id:"tts-error",get title(){return e.t("speech.edge.error")},get description(){return t.speaker.error()}})}}),o.createComponent(i.SettingsRow,{id:"rate",get title(){return e.t("speech.rate")},get description(){return e.t("speech.rate.description")},get children(){return o.createComponent(i.Select,{get label(){return e.t("speech.rate")},get value(){return String(n.value.rate)},get options(){return[{value:"0.8",label:e.t("speech.rate.slow")},{value:"1",label:e.t("speech.rate.normal")},{value:"1.2",label:e.t("speech.rate.fast")},{value:"1.5",label:e.t("speech.rate.faster")}]},onChange:r=>O({rate:Number(r)||1})})}}),o.createComponent(i.SettingsRow,{id:"skip-code",get title(){return e.t("speech.skipCode")},get description(){return e.t("speech.skipCode.description")},get children(){return o.createComponent(i.Switch,{get label(){return e.t("speech.skipCode")},hideLabel:!0,get checked(){return n.value.skipCode},onChange:r=>O({skipCode:r})})}}),o.createComponent(i.SettingsRow,{id:"preview",get title(){return e.t("speech.preview")},get description(){return e.t("speech.preview.description")},get children(){return o.createComponent(i.Button,{onClick:()=>{Y()},get children(){return e.t("read.idle")}})}})]}}),o.createComponent(y.Show,{get when(){return W()!=="linux"},get children(){return o.createComponent(i.SettingsSection,{get title(){return e.t("settings.test.section")},get children(){return o.createComponent(i.SettingsRow,{id:"test",get title(){return e.t("settings.test")},get description(){return e.t("settings.test.description")},get children(){return o.createComponent(i.Button,{get busy(){return C()},onClick:()=>{V()},get children(){return e.t("settings.test.run")}})}})}})}})]}})}async function He(){const t=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,echoCancellation:!0,noiseSuppression:!0}}),e=MediaRecorder.isTypeSupported("audio/webm;codecs=opus")?"audio/webm;codecs=opus":"audio/webm",i=new MediaRecorder(t,{mimeType:e}),c=[];return i.ondataavailable=n=>{n.data.size>0&&c.push(n.data)},i.start(),{stop:()=>new Promise(n=>{i.onstop=()=>{t.getTracks().forEach(s=>s.stop()),n(new Blob(c,{type:e}))},i.stop()})}}async function Me(t){const e=new Uint8Array(await t.arrayBuffer());let i="";const c=32768;for(let n=0;n<e.length;n+=c)i+=String.fromCharCode(...e.subarray(n,n+c));return btoa(i)}function Ge(t){const e=$.usePlugin();return o.memo(()=>t.actions().map(i=>o.createComponent(e.ui.Button,{get variant(){return i.id==="stop"?"danger":"neutral"},get icon(){return i.icon},onClick:()=>{i.run(),t.close()},get children(){return i.label}})))}const Xe=t=>{const e=t.main(le),i=t.main(fe),c=t.main(ce),n=Be(t,i),s=t.stores.prefs,u=t.stores.engine,a=t.stores.whisper,g=t.stores.whispercpp,[h,S]=y.createSignal(!1),[R,v]=y.createSignal("idle");t.client.rpc(j).capabilities({}).then(l=>{const m=l;!m.engines.includes(u.value.mode)&&m.engines.length>0&&u.update(b=>{b.mode=m.engines[0]??"windows"})}).catch(()=>{});const C=()=>u.value.mode==="whisper"||u.value.mode==="whispercpp"?u.value.mode:void 0;let I,z;const B=(l,m,b)=>{switch(l){case"LANGUAGE_NOT_AVAILABLE":return t.t("error.language",{locale:m||s.value.locale,available:b.length>0?b.join(", "):"—"});case"NO_RECOGNIZERS":return t.t("error.none");case"MICROPHONE_UNAVAILABLE":return t.t("error.mic");case"SYSTEM_SPEECH_UNAVAILABLE":return t.t("error.system");case"ENGINE_EXIT":return t.t("error.exit");default:return t.t("error.unknown",{code:l})}},N=()=>{h()&&(S(!1),c.toggle().catch(()=>{})),n.cancel(),I=t.sessions.current()?.key,e.start({locale:s.value.locale,minConfidence:s.value.minConfidence}).catch(l=>{t.toast.show({variant:"error",title:t.t("error.title"),description:l instanceof Error?l.message:String(l)})})},U=()=>{e.stop().catch(()=>{})},A=()=>{n.cancel(),t.screen.current()?.composer.focus(),c.toggle().then(()=>S(l=>!l)).catch(l=>{S(!1),t.toast.show({variant:"error",title:t.t("pill.title"),description:l instanceof Error?`${t.t("error.winh")} ${l.message}`:t.t("error.winh")})})},q=()=>t.t(C()==="whispercpp"?"error.whispercpp":"error.whisper"),Z=async()=>{if(R()==="idle"){n.cancel();try{z=await He(),v("recording")}catch(l){t.toast.show({variant:"error",title:t.t("pill.title"),description:te(l,q())})}}},L=()=>{const l=z;z=void 0,l&&l.stop().catch(()=>{}),v("idle")},F=async()=>{const l=z;if(z=void 0,!l){v("idle");return}v("transcribing");const m=C();try{const b=await l.stop(),E=await Me(b),M=(m==="whispercpp"?await t.client.rpc(j).whisperCppTranscribe({audio:E,mime:b.type,language:g.value.language,model:g.value.model}):await t.client.rpc(j).whisperTranscribe({audio:E,mime:b.type,language:a.value.language,python:a.value.python,model:a.value.model})).text.trim();if(!M){t.toast.show({variant:"default",title:t.t("pill.title"),description:t.t(m==="whispercpp"?"whispercpp.empty":"whisper.empty")});return}const O=t.screen.current()?.composer;if(O){const G=O.text(),J=G.length>0&&!/\s$/.test(G)?" ":"";O.insert(J+M),O.focus()}}catch(b){const E=te(b,q());t.toast.show({variant:"error",title:t.t("pill.title"),description:E.includes("FFMPEG_MISSING")?t.t("error.ffmpeg"):E})}finally{v("idle")}},T=()=>{if(C()){R()==="recording"?F():R()==="idle"&&Z();return}if(u.value.mode==="windows"){A();return}const l=e.state()?.status??"idle";l==="starting"||l==="listening"?U():N()},W=()=>{if(R()==="recording"&&L(),n.speaking()){n.cancel();return}if(!t.sessions.current()){t.toast.show({variant:"error",title:t.t("read.title"),description:t.t("read.noSession")});return}const l=e.state()?.status??"idle";(l==="starting"||l==="listening")&&e.stop().catch(()=>{}),(async()=>{try{const m=await n.lastAssistantText();if(!m.trim()){t.toast.show({variant:"default",title:t.t("read.title"),description:t.t("read.empty")});return}await n.speak(m)||t.toast.show({variant:"default",title:t.t("read.title"),description:t.t("read.empty")})}catch(m){t.toast.show({variant:"error",title:t.t("read.title"),description:m instanceof Error?m.message:t.t("read.error")})}})()},x=()=>{if(!n.speaking())return[{id:"start",label:t.t("read.idle"),icon:"outline-audio",run:W}];const l=n.paused(),m=[{id:"restart",label:t.t("read.restart"),icon:"outline-reset",run:()=>{n.restart()}}];return n.canPause()&&m.push({id:"pause",label:l?t.t("read.resume"):t.t("read.pause"),icon:"outline-audio",run:()=>n.togglePause()}),m.push({id:"stop",label:t.t("read.stop"),icon:"xmark-small",run:()=>n.cancel()}),m};e.on("final",l=>{const m=t.sessions.current()?.key;if(I&&m&&m!==I){t.toast.show({variant:"error",title:t.t("error.title"),description:t.t("toast.discarded")});return}const b=t.screen.current()?.composer;if(!b)return;const E=b.text(),ee=s.value.trailingSpace&&E.length>0&&!/\s$/.test(E)?" ":"";b.insert(ee+l.text),s.value.autoFocus&&b.focus()}),e.on("error",l=>{t.toast.show({variant:"error",title:t.t("error.title"),description:B(l.code,l.detail,l.available),persistent:l.code==="LANGUAGE_NOT_AVAILABLE"||l.code==="NO_RECOGNIZERS",duration:8e3})});const _=()=>{if(t.app.platform!=="desktop")return;if(u.value.mode==="windows")return h()?{label:t.t("pill.dictating"),icon:"outline-wave-audio",tone:"danger",title:t.t("pill.stop"),run:T}:{label:t.t("pill.idle"),icon:"outline-wave-audio",title:t.t("pill.winH"),run:T};if(u.value.mode==="whisper"||u.value.mode==="whispercpp"){const m=t.t(u.value.mode==="whispercpp"?"pill.whispercpp":"pill.whisper");return R()==="recording"?{label:t.t("pill.recording"),icon:"outline-wave-audio",tone:"danger",title:t.t("pill.stop"),run:T}:R()==="transcribing"?{label:t.t("pill.transcribing"),icon:"outline-audio",title:m}:{label:t.t("pill.idle"),icon:"outline-wave-audio",title:m,run:T}}const l=e.state()?.status??"idle";return l==="starting"?{label:t.t("pill.starting"),icon:"outline-wave-audio",title:t.t("pill.title"),run:T}:l==="listening"?{label:t.t("pill.listening"),icon:"outline-wave-audio",tone:"danger",title:t.t("pill.stop"),run:T}:l==="error"?{label:t.t("pill.error"),icon:"outline-wave-audio",tone:"warning",title:t.t("pill.title"),run:T}:{label:t.t("pill.idle"),icon:"outline-wave-audio",title:t.t("pill.title"),run:T}},H=()=>{if(t.app.platform!=="desktop")return;const l=n.speaking(),m=n.paused(),b=l?x().map(E=>({id:E.id,label:E.label,icon:E.icon,tone:E.id==="stop"?"danger":void 0,run:E.run})):[];return{label:l?m?t.t("read.paused"):t.t("read.speaking"):t.t("read.idle"),icon:"outline-audio",tone:l?"success":void 0,title:t.t("read.title"),rows:b.length>0?b:void 0,run:l?void 0:W}};t.add($.ComposerPill,()=>({id:"dictate",show:()=>_()})),t.add($.ComposerPill,()=>({id:"read",order:1,show:()=>H(),menu:l=>o.createComponent(Ge,{actions:x,get close(){return l.close}})})),t.add($.Command,()=>({id:"toggle",title:t.t("command.toggle"),description:t.t("command.toggle.description"),keywords:"voice dictation microphone speech dictado voz microfono",group:t.t("pill.title"),section:"prompt",bind:"mod+shift+m",slash:{name:"dictado"},editable:!0,enabled:t.app.platform==="desktop",run:T})),t.add($.Command,()=>({id:"configure",title:t.t("command.configure"),keywords:"voice dictation microphone speech dictado voz microfono",group:t.t("pill.title"),enabled:t.app.platform==="desktop",run:()=>t.layout.settings(t.id)})),t.add($.Command,()=>({id:"read",title:t.t("command.read"),description:t.t("command.read.description"),keywords:"read aloud speech voice leer voz altavoz lectura",group:t.t("pill.title"),section:"prompt",bind:"mod+shift+l",slash:{name:"leer"},editable:!0,enabled:t.app.platform==="desktop",run:W})),t.add($.SettingsPage,{id:t.id,icon:"outline-audio",get title(){return t.t("settings.title")},get entries(){return[{id:"engine",title:t.t("settings.engine"),keywords:"engine motor dictation dictado winh voz"},{id:"winh",title:t.t("settings.winh"),keywords:"winh windows voice typing dictado"},{id:"language",title:t.t("settings.language"),keywords:"voice language idioma voz"},{id:"confidence",title:t.t("settings.confidence"),keywords:"voice confidence confianza"},{id:"test",title:t.t("settings.test"),keywords:"voice microphone microphone test microfono"},{id:"voice",title:t.t("speech.voice"),keywords:"read aloud voice voz lectura altavoz"},{id:"tts-engine",title:t.t("speech.engine"),keywords:"voice engine motor edge neural sistema"},{id:"whisper-python",title:t.t("whisper.python"),keywords:"whisper python venv entorno"},{id:"whisper-model",title:t.t("whisper.model"),keywords:"whisper model modelo"},{id:"whisper-language",title:t.t("whisper.language"),keywords:"whisper language idioma"},{id:"whisper-test",title:t.t("whisper.test"),keywords:"whisper check comprobar"},{id:"whispercpp-model",title:t.t("whispercpp.model"),keywords:"whisper.cpp model modelo"},{id:"whispercpp-language",title:t.t("whispercpp.language"),keywords:"whisper.cpp language idioma"},{id:"whispercpp-ffmpeg",title:t.t("whispercpp.ffmpeg"),keywords:"whisper.cpp ffmpeg audio convertir"},{id:"whispercpp-install",title:t.t("whispercpp.install"),keywords:"whisper.cpp download descargar instalar"},{id:"whispercpp-test",title:t.t("whispercpp.test"),keywords:"whisper.cpp check comprobar"},{id:"rate",title:t.t("speech.rate"),keywords:"read aloud speed velocidad lectura"},{id:"skip-code",title:t.t("speech.skipCode"),keywords:"read aloud code codigo lectura"},{id:"preview",title:t.t("speech.preview"),keywords:"read aloud test voice probar voz"}]},render:()=>o.createComponent(qe,{speaker:n})})},Ke=$.Plugin.define({...$e,setup:Xe,main:Fe});exports.default=Ke;
|
package/package.json
CHANGED
package/src/gui/settings.tsx
CHANGED
|
@@ -274,7 +274,7 @@ export function VoiceSettings(props: { speaker: Speaker }) {
|
|
|
274
274
|
title: ctx.t("pill.title"),
|
|
275
275
|
description: ctx.t("whispercpp.ffmpeg.install.ok"),
|
|
276
276
|
})
|
|
277
|
-
await readWhisperCppStatus()
|
|
277
|
+
await readWhisperCppStatus().catch(() => {})
|
|
278
278
|
} else {
|
|
279
279
|
const manual = result.command
|
|
280
280
|
? ` ${ctx.t("whispercpp.ffmpeg.install.manual", { command: result.command })}`
|