opencode-voice-dictation 0.3.1 → 0.3.2

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.
@@ -187,6 +187,6 @@ public static class WinH {
187
187
  "@
188
188
 
189
189
  [WinH]::Send()
190
- `,pe="powershell.exe";function ue(){const e=L.join(D.tmpdir(),"opencode-voice-dictation");A.mkdirSync(e,{recursive:!0});const t=V.createHash("sha1").update(G).digest("hex").slice(0,12),n=L.join(e,`win-h-${t}.ps1`);return A.writeFileSync(n,G,"utf8"),n}function ge(e){return z.spawn(pe,e,{windowsHide:!0,stdio:"ignore"})}function me(){return new Promise((e,t)=>{const n=ge(["-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-File",ue()]);n.on("error",l=>t(l)),n.on("close",l=>{l===0?e():t(new Error(`Win+H helper exited with code ${l??"unknown"}`))})})}const he=e=>{let t="idle",n="",l="",o,r=!1;const u=()=>{o=void 0,r=!1},s=e.provide(H,{state:()=>({status:t,error:n,locale:l}),start(y,E){o&&(r=!0,o.stop(),u()),t="starting",n="",l=y.locale,s.changed();const C=E.window;try{o=oe({locale:y.locale,minConfidence:y.minConfidence},{onReady(f){t="listening",l=f,s.changed()},onFinal(f,h){s.emit("final",{text:f,confidence:h},C)},onError(f,h,k){t="error",n=f,s.changed(),s.emit("error",{code:f,detail:h,available:k},C)},onExit(f,h){if(r){u(),t="idle",n="",l="",s.changed();return}u(),t!=="error"&&(t="error",n=f===null?"ENGINE_EXIT":`ENGINE_EXIT_${f}`,s.changed(),s.emit("error",{code:"ENGINE_EXIT",detail:h||(f===null?"":String(f)),available:[]},C))}})}catch(f){throw t="error",n="ENGINE_START_FAILED",s.changed(),f}},stop(){o&&(r=!0,o.stop(),u()),t="idle",n="",l="",s.changed()},diagnose(){return re()}});let a;const p=e.provide(q,{speak(y){a?.stop(),a=le(y,E=>{a=void 0,p.emit("done",{ok:E})})},stop(){a&&(a.stop(),a=void 0),p.emit("done",{ok:!0})},voices(){return de()}});e.provide(U,{toggle(){return me()}}),e.onCleanup(()=>{o&&(r=!0,o.stop(),u()),a?.stop(),a=void 0})},fe=250;function Se(e,t){let n=e.replace(/\r\n/g,`
191
- `);return t?n=n.replace(/```[\s\S]*?```/g," "):n=n.replace(/```[^\n]*\n([\s\S]*?)```/g,"$1"),n=n.replace(/`([^`]+)`/g,"$1"),n=n.replace(/!\[[^\]]*\]\([^)]*\)/g," "),n=n.replace(/\[([^\]]+)\]\([^)]*\)/g,"$1"),n=n.replace(/^\s*#{1,6}\s+/gm,""),n=n.replace(/^\s*>\s?/gm,""),n=n.replace(/^\s*[-*+]\s+/gm,""),n=n.replace(/^\s*\d+\.\s+/gm,""),n=n.replace(/(\*\*|__)(.*?)\1/g,"$2"),n=n.replace(/(\*|_)(.*?)\1/g,"$2"),n=n.replace(/^\s*\|.*\|\s*$/gm," "),n=n.replace(/\n{2,}/g,". "),n=n.replace(/\n/g," "),n=n.replace(/\s+/g," "),n=n.replace(/\s+([.,;:!?])/g,"$1"),n=n.replace(/([.,;:!?]){2,}/g,"$1"),n.trim()}function ve(e,t=fe){const n=e.trim();if(!n)return[];const l=n.split(new RegExp("(?<=[.!?…])\\s+")),o=[];let r="";const u=s=>{let a="";for(const p of s.split(/\s+/))p&&(a&&a.length+1+p.length>t?(o.push(a),a=p):a=a?`${a} ${p}`:p);return a};for(const s of l){if(s.length>t){r&&(o.push(r),r=""),r=u(s);continue}r&&r.length+1+s.length>t?(o.push(r),r=s):r=r?`${r} ${s}`:s}return r&&o.push(r),o}function we(e,t){const n=e.stores.speech,[l,o]=T.createSignal(!1),[r,u]=T.createSignal(!1),[s,a]=T.createSignal([]),[p,y]=T.createSignal("none");let E=0,C=[],f="";const h=()=>typeof globalThis.speechSynthesis<"u"?globalThis.speechSynthesis:void 0,k=()=>{const v=h()?.getVoices()??[];if(v.length===0)return;const w=n.value.voiceURI;if(w){const $=v.find(O=>O.voiceURI===w);if($)return $}const b=e.locale.locale().split("-")[0]?.toLowerCase()??"es";return v.find($=>$.lang.toLowerCase().startsWith(b))??v[0]},R=async()=>{const v=h()?.getVoices()??[];if(v.length>0){a(v.map(w=>({id:w.voiceURI,label:`${w.name} — ${w.lang}`}))),y("web");return}try{const w=await t.voices();if(w.length>0){a(w.map(b=>({id:b,label:b}))),y("sapi");return}}catch{}y("none")},_=()=>{E++,C=[],h()?.cancel(),u(!1),o(!1),t.stop().catch(()=>{})},P=()=>p()==="web",c=()=>{!l()||r()||!P()||(h()?.pause(),u(!0))},i=()=>{!l()||!r()||!P()||(h()?.resume(),u(!1))},m=()=>{r()?i():c()},I=()=>f?N(f):Promise.resolve(!1),N=async v=>{f=v;const w=Se(v,n.value.skipCode);if(!w)return!1;if(_(),await R(),p()==="web"){const b=h();if(!b)return!1;const $=k(),O=n.value.rate,te=E;C=ve(w),o(!0),u(!1);const F=()=>{if(te!==E)return;const B=C.shift();if(!B){u(!1),o(!1);return}const W=new SpeechSynthesisUtterance(B);$&&(W.voice=$),$?.lang&&(W.lang=$.lang),W.rate=O,W.onend=F,W.onerror=F,b.speak(W)};return F(),!0}if(p()==="sapi"){o(!0),u(!1);try{await t.speak({text:w,rate:n.value.rate,voice:n.value.voiceURI})}catch(b){throw o(!1),b}return!0}throw o(!1),new Error(e.t("read.noVoices"))},ee=async()=>{const v=e.sessions.current();if(!v)return"";const b=(await v.server.client.message.list({sessionID:v.id,type:"assistant",order:"desc",limit:1})).data[0];return!b||b.type!=="assistant"?"":b.content.filter($=>$.type==="text").map($=>$.text).join(`
190
+ `,pe="powershell.exe";function ue(){const e=L.join(D.tmpdir(),"opencode-voice-dictation");A.mkdirSync(e,{recursive:!0});const t=V.createHash("sha1").update(G).digest("hex").slice(0,12),n=L.join(e,`win-h-${t}.ps1`);return A.writeFileSync(n,G,"utf8"),n}function ge(e){return z.spawn(pe,e,{windowsHide:!0,stdio:"ignore"})}function me(){return new Promise((e,t)=>{const n=ge(["-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-File",ue()]);n.on("error",l=>t(l)),n.on("close",l=>{l===0?e():t(new Error(`Win+H helper exited with code ${l??"unknown"}`))})})}const he=e=>{let t="idle",n="",l="",o,r=!1;const u=()=>{o=void 0,r=!1},s=e.provide(H,{state:()=>({status:t,error:n,locale:l}),start(y,E){o&&(r=!0,o.stop(),u()),t="starting",n="",l=y.locale,s.changed();const C=E.window;try{o=oe({locale:y.locale,minConfidence:y.minConfidence},{onReady(f){t="listening",l=f,s.changed()},onFinal(f,h){s.emit("final",{text:f,confidence:h},C)},onError(f,h,k){t="error",n=f,s.changed(),s.emit("error",{code:f,detail:h,available:k},C)},onExit(f,h){if(r){u(),t="idle",n="",l="",s.changed();return}u(),t!=="error"&&(t="error",n=f===null?"ENGINE_EXIT":`ENGINE_EXIT_${f}`,s.changed(),s.emit("error",{code:"ENGINE_EXIT",detail:h||(f===null?"":String(f)),available:[]},C))}})}catch(f){throw t="error",n="ENGINE_START_FAILED",s.changed(),f}},stop(){o&&(r=!0,o.stop(),u()),t="idle",n="",l="",s.changed()},diagnose(){return re()}});let a;const p=e.provide(q,{speak(y){a?.stop(),a=le(y,E=>{a=void 0,p.emit("done",{ok:E})})},stop(){a&&(a.stop(),a=void 0)},voices(){return de()}});e.provide(U,{toggle(){return me()}}),e.onCleanup(()=>{o&&(r=!0,o.stop(),u()),a?.stop(),a=void 0})},fe=250;function Se(e,t){let n=e.replace(/\r\n/g,`
191
+ `);return t?n=n.replace(/```[\s\S]*?```/g," "):n=n.replace(/```[^\n]*\n([\s\S]*?)```/g,"$1"),n=n.replace(/`([^`]+)`/g,"$1"),n=n.replace(/!\[[^\]]*\]\([^)]*\)/g," "),n=n.replace(/\[([^\]]+)\]\([^)]*\)/g,"$1"),n=n.replace(/^\s*#{1,6}\s+/gm,""),n=n.replace(/^\s*>\s?/gm,""),n=n.replace(/^\s*[-*+]\s+/gm,""),n=n.replace(/^\s*\d+\.\s+/gm,""),n=n.replace(/(\*\*|__)(.*?)\1/g,"$2"),n=n.replace(/(\*|_)(.*?)\1/g,"$2"),n=n.replace(/^\s*\|.*\|\s*$/gm," "),n=n.replace(/\n{2,}/g,". "),n=n.replace(/\n/g," "),n=n.replace(/\s+/g," "),n=n.replace(/\s+([.,;:!?])/g,"$1"),n=n.replace(/([.,;:!?]){2,}/g,"$1"),n.trim()}function ve(e,t=fe){const n=e.trim();if(!n)return[];const l=n.split(new RegExp("(?<=[.!?…])\\s+")),o=[];let r="";const u=s=>{let a="";for(const p of s.split(/\s+/))p&&(a&&a.length+1+p.length>t?(o.push(a),a=p):a=a?`${a} ${p}`:p);return a};for(const s of l){if(s.length>t){r&&(o.push(r),r=""),r=u(s);continue}r&&r.length+1+s.length>t?(o.push(r),r=s):r=r?`${r} ${s}`:s}return r&&o.push(r),o}function we(e,t){const n=e.stores.speech,[l,o]=T.createSignal(!1),[r,u]=T.createSignal(!1),[s,a]=T.createSignal([]),[p,y]=T.createSignal("none");let E=0,C=[],f="";const h=()=>typeof globalThis.speechSynthesis<"u"?globalThis.speechSynthesis:void 0,k=()=>{const v=h()?.getVoices()??[];if(v.length===0)return;const w=n.value.voiceURI;if(w){const $=v.find(O=>O.voiceURI===w);if($)return $}const b=e.locale.locale().split("-")[0]?.toLowerCase()??"es";return v.find($=>$.lang.toLowerCase().startsWith(b))??v[0]},R=async()=>{const v=h()?.getVoices()??[];if(v.length>0){a(v.map(w=>({id:w.voiceURI,label:`${w.name} — ${w.lang}`}))),y("web");return}try{const w=await t.voices();if(w.length>0){a(w.map(b=>({id:b,label:b}))),y("sapi");return}}catch{}y("none")},_=()=>{E++,C=[],h()?.cancel(),u(!1),o(!1),p()==="sapi"&&t.stop().catch(()=>{})},P=()=>p()==="web",c=()=>{!l()||r()||!P()||(h()?.pause(),u(!0))},i=()=>{!l()||!r()||!P()||(h()?.resume(),u(!1))},m=()=>{r()?i():c()},I=()=>f?N(f):Promise.resolve(!1),N=async v=>{f=v;const w=Se(v,n.value.skipCode);if(!w)return!1;if(_(),await R(),p()==="web"){const b=h();if(!b)return!1;const $=k(),O=n.value.rate,te=E;C=ve(w),o(!0),u(!1);const F=()=>{if(te!==E)return;const B=C.shift();if(!B){u(!1),o(!1);return}const W=new SpeechSynthesisUtterance(B);$&&(W.voice=$),$?.lang&&(W.lang=$.lang),W.rate=O,W.onend=F,W.onerror=F,b.speak(W)};return F(),!0}if(p()==="sapi"){o(!0),u(!1);try{await t.speak({text:w,rate:n.value.rate,voice:n.value.voiceURI})}catch(b){throw o(!1),b}return!0}throw o(!1),new Error(e.t("read.noVoices"))},ee=async()=>{const v=e.sessions.current();if(!v)return"";const b=(await v.server.client.message.list({sessionID:v.id,type:"assistant",order:"desc",limit:1})).data[0];return!b||b.type!=="assistant"?"":b.content.filter($=>$.type==="text").map($=>$.text).join(`
192
192
  `)};return t.on("done",()=>{u(!1),o(!1)}),h()?.addEventListener?.("voiceschanged",()=>{R()}),R(),{speaking:l,paused:r,backend:p,canPause:P,voices:s,refreshVoices:R,lastAssistantText:ee,speak:N,cancel:_,pause:c,resume:i,togglePause:m,restart:I,preview:()=>N(e.t("speech.preview.text"))}}const ye=["es-ES","es-MX","es-AR","es-CO","pt-BR","pt-PT","en-US","en-GB","fr-FR","de-DE","it-IT"];function be(e){const t=S.usePlugin(),n=t.ui,l=t.stores.prefs,o=t.stores.speech,r=t.stores.engine,u=t.main(H),s=t.main(U),[a,p]=T.createSignal([]),[y,E]=T.createSignal(!1);T.onMount(()=>{u.diagnose().then(i=>{i.locales.length>0&&p(i.locales)}).catch(()=>{}),e.speaker.refreshVoices()});const C=()=>{const i=a(),m=l.value.locale;return(i.includes(m)?i:[m,...i]).map(N=>({value:N,label:N}))},f=()=>[{value:"",label:t.t("speech.voice.auto")},...e.speaker.voices().map(i=>({value:i.id,label:i.label}))],h=i=>{l.update(m=>{i.locale!==void 0&&(m.locale=i.locale),i.minConfidence!==void 0&&(m.minConfidence=i.minConfidence),i.trailingSpace!==void 0&&(m.trailingSpace=i.trailingSpace),i.autoFocus!==void 0&&(m.autoFocus=i.autoFocus)})},k=i=>{o.update(m=>{i.voiceURI!==void 0&&(m.voiceURI=i.voiceURI),i.rate!==void 0&&(m.rate=i.rate),i.skipCode!==void 0&&(m.skipCode=i.skipCode)})},R=i=>{r.update(m=>{m.mode=i})},_=async()=>{try{await s.toggle(),t.toast.show({variant:"default",title:t.t("settings.winh"),description:t.t("settings.winh.sent")})}catch(i){t.toast.show({variant:"error",title:t.t("pill.title"),description:i instanceof Error?i.message:t.t("error.winh")})}},P=async()=>{try{await e.speaker.preview()}catch(i){t.toast.show({variant:"error",title:t.t("read.title"),description:i instanceof Error?i.message:t.t("read.error")})}},c=async()=>{E(!0);try{const i=await u.diagnose();if(i.locales.length===0){t.toast.show({variant:"error",title:t.t("error.title"),description:t.t("settings.test.failed",{reason:t.t("common.reason.no-recognizers")}),persistent:!0});return}if(!i.microphone){t.toast.show({variant:"error",title:t.t("error.title"),description:t.t("settings.test.failed",{reason:t.t("common.reason.no-microphone")}),persistent:!0});return}i.locales.length>0&&!a().length&&p(i.locales),t.toast.show({variant:"success",title:t.t("error.title"),description:t.t("settings.test.success",{locale:i.selected||i.locales[0]||l.value.locale})})}catch(i){t.toast.show({variant:"error",title:t.t("error.title"),description:i instanceof Error?i.message:String(i)})}finally{E(!1)}};return g.createComponent(n.SettingsLayout,{get title(){return t.t("settings.title")},get description(){return t.t("settings.description")},get children(){return[g.createComponent(n.SettingsSection,{get title(){return t.t("settings.section")},get children(){return[g.createComponent(n.SettingsRow,{id:"engine",get title(){return t.t("settings.engine")},get description(){return t.t("settings.engine.description")},get children(){return g.createComponent(n.Select,{get label(){return t.t("settings.engine")},get value(){return r.value.mode},get options(){return[{value:"windows",label:t.t("engine.windows")},{value:"system",label:t.t("engine.system")}]},onChange:i=>R(i)})}}),g.createComponent(T.Show,{get when(){return r.value.mode==="windows"},get children(){return g.createComponent(n.SettingsRow,{id:"winh",get title(){return t.t("settings.winh")},get description(){return t.t("settings.winh.description")},get children(){return g.createComponent(n.Button,{onClick:()=>{_()},get children(){return t.t("settings.winh.run")}})}})}}),g.createComponent(T.Show,{get when(){return r.value.mode==="system"},get children(){return[g.createComponent(n.SettingsRow,{id:"language",get title(){return t.t("settings.language")},get description(){return t.t("settings.language.description")},get children(){return g.createComponent(n.Select,{get label(){return t.t("settings.language")},get value(){return l.value.locale},get options(){return g.memo(()=>C().length>0)()?C():ye.map(i=>({value:i,label:i}))},onChange:i=>h({locale:i})})}}),g.createComponent(n.SettingsRow,{id:"confidence",get title(){return t.t("settings.confidence")},get description(){return t.t("settings.confidence.description")},get children(){return g.createComponent(n.Select,{get label(){return t.t("settings.confidence")},get value(){return String(l.value.minConfidence)},get options(){return[{value:"0.2",label:t.t("confidence.low")},{value:"0.4",label:t.t("confidence.normal")},{value:"0.6",label:t.t("confidence.high")}]},onChange:i=>h({minConfidence:Number(i)||.4})})}}),g.createComponent(n.SettingsRow,{id:"space",get title(){return t.t("settings.space")},get description(){return t.t("settings.space.description")},get children(){return g.createComponent(n.Switch,{get label(){return t.t("settings.space")},hideLabel:!0,get checked(){return l.value.trailingSpace},onChange:i=>h({trailingSpace:i})})}}),g.createComponent(n.SettingsRow,{id:"focus",get title(){return t.t("settings.focus")},get description(){return t.t("settings.focus.description")},get children(){return g.createComponent(n.Switch,{get label(){return t.t("settings.focus")},hideLabel:!0,get checked(){return l.value.autoFocus},onChange:i=>h({autoFocus:i})})}})]}})]}}),g.createComponent(n.SettingsSection,{get title(){return t.t("speech.section")},get children(){return[g.createComponent(n.SettingsRow,{id:"voice",get title(){return t.t("speech.voice")},get description(){return t.t("speech.voice.description")},get children(){return g.createComponent(n.Select,{get label(){return t.t("speech.voice")},get value(){return o.value.voiceURI},get options(){return f()},onChange:i=>k({voiceURI:i})})}}),g.createComponent(n.SettingsRow,{id:"rate",get title(){return t.t("speech.rate")},get description(){return t.t("speech.rate.description")},get children(){return g.createComponent(n.Select,{get label(){return t.t("speech.rate")},get value(){return String(o.value.rate)},get options(){return[{value:"0.8",label:t.t("speech.rate.slow")},{value:"1",label:t.t("speech.rate.normal")},{value:"1.2",label:t.t("speech.rate.fast")},{value:"1.5",label:t.t("speech.rate.faster")}]},onChange:i=>k({rate:Number(i)||1})})}}),g.createComponent(n.SettingsRow,{id:"skip-code",get title(){return t.t("speech.skipCode")},get description(){return t.t("speech.skipCode.description")},get children(){return g.createComponent(n.Switch,{get label(){return t.t("speech.skipCode")},hideLabel:!0,get checked(){return o.value.skipCode},onChange:i=>k({skipCode:i})})}}),g.createComponent(n.SettingsRow,{id:"preview",get title(){return t.t("speech.preview")},get description(){return t.t("speech.preview.description")},get children(){return g.createComponent(n.Button,{onClick:()=>{P()},get children(){return t.t("read.idle")}})}})]}}),g.createComponent(n.SettingsSection,{get title(){return t.t("settings.test.section")},get children(){return g.createComponent(n.SettingsRow,{id:"test",get title(){return t.t("settings.test")},get description(){return t.t("settings.test.description")},get children(){return g.createComponent(n.Button,{get busy(){return y()},onClick:()=>{c()},get children(){return t.t("settings.test.run")}})}})}})]}})}function $e(e){const t=S.usePlugin();return g.memo(()=>e.actions().map(n=>g.createComponent(t.ui.Button,{get variant(){return n.id==="stop"?"danger":"neutral"},get icon(){return n.icon},onClick:()=>{n.run(),e.close()},get children(){return n.label}})))}const Ee=e=>{const t=e.main(H),n=e.main(q),l=e.main(U),o=we(e,n),r=e.stores.prefs,u=e.stores.engine,[s,a]=T.createSignal(!1);let p;const y=(c,i,m)=>{switch(c){case"LANGUAGE_NOT_AVAILABLE":return e.t("error.language",{locale:i||r.value.locale,available:m.length>0?m.join(", "):"—"});case"NO_RECOGNIZERS":return e.t("error.none");case"MICROPHONE_UNAVAILABLE":return e.t("error.mic");case"SYSTEM_SPEECH_UNAVAILABLE":return e.t("error.system");case"ENGINE_EXIT":return e.t("error.exit");default:return e.t("error.unknown",{code:c})}},E=()=>{s()&&(a(!1),l.toggle().catch(()=>{})),o.cancel(),p=e.sessions.current()?.key,t.start({locale:r.value.locale,minConfidence:r.value.minConfidence}).catch(c=>{e.toast.show({variant:"error",title:e.t("error.title"),description:c instanceof Error?c.message:String(c)})})},C=()=>{t.stop().catch(()=>{})},f=()=>{o.cancel(),e.screen.current()?.composer.focus(),l.toggle().then(()=>a(c=>!c)).catch(c=>{a(!1),e.toast.show({variant:"error",title:e.t("pill.title"),description:c instanceof Error?`${e.t("error.winh")} ${c.message}`:e.t("error.winh")})})},h=()=>{if(u.value.mode==="windows"){f();return}const c=t.state()?.status??"idle";c==="starting"||c==="listening"?C():E()},k=()=>{if(o.speaking()){o.cancel();return}if(!e.sessions.current()){e.toast.show({variant:"error",title:e.t("read.title"),description:e.t("read.noSession")});return}const c=t.state()?.status??"idle";(c==="starting"||c==="listening")&&t.stop().catch(()=>{}),(async()=>{try{const i=await o.lastAssistantText();if(!i.trim()){e.toast.show({variant:"default",title:e.t("read.title"),description:e.t("read.empty")});return}await o.speak(i)||e.toast.show({variant:"default",title:e.t("read.title"),description:e.t("read.empty")})}catch(i){e.toast.show({variant:"error",title:e.t("read.title"),description:i instanceof Error?i.message:e.t("read.error")})}})()},R=()=>{if(!o.speaking())return[{id:"start",label:e.t("read.idle"),icon:"outline-audio",run:k}];const c=o.paused(),i=[{id:"restart",label:e.t("read.restart"),icon:"outline-reset",run:()=>{o.restart()}}];return o.canPause()&&i.push({id:"pause",label:c?e.t("read.resume"):e.t("read.pause"),icon:"outline-audio",run:()=>o.togglePause()}),i.push({id:"stop",label:e.t("read.stop"),icon:"xmark-small",run:()=>o.cancel()}),i};t.on("final",c=>{const i=e.sessions.current()?.key;if(p&&i&&i!==p){e.toast.show({variant:"error",title:e.t("error.title"),description:e.t("toast.discarded")});return}const m=e.screen.current()?.composer;if(!m)return;const I=m.text(),N=r.value.trailingSpace&&I.length>0&&!/\s$/.test(I)?" ":"";m.insert(N+c.text),r.value.autoFocus&&m.focus()}),t.on("error",c=>{e.toast.show({variant:"error",title:e.t("error.title"),description:y(c.code,c.detail,c.available),persistent:c.code==="LANGUAGE_NOT_AVAILABLE"||c.code==="NO_RECOGNIZERS",duration:8e3})});const _=()=>{if(e.app.platform!=="desktop")return;if(u.value.mode==="windows")return s()?{label:e.t("pill.dictating"),icon:"outline-wave-audio",tone:"danger",title:e.t("pill.stop"),run:h}:{label:e.t("pill.idle"),icon:"outline-wave-audio",title:e.t("pill.winH"),run:h};const c=t.state()?.status??"idle";return c==="starting"?{label:e.t("pill.starting"),icon:"outline-wave-audio",title:e.t("pill.title"),run:h}:c==="listening"?{label:e.t("pill.listening"),icon:"outline-wave-audio",tone:"danger",title:e.t("pill.stop"),run:h}:c==="error"?{label:e.t("pill.error"),icon:"outline-wave-audio",tone:"warning",title:e.t("pill.title"),run:h}:{label:e.t("pill.idle"),icon:"outline-wave-audio",title:e.t("pill.title"),run:h}},P=()=>{if(e.app.platform!=="desktop")return;const c=o.speaking(),i=o.paused(),m=c?R().map(I=>({id:I.id,label:I.label,icon:I.icon,tone:I.id==="stop"?"danger":void 0,run:I.run})):[];return{label:c?i?e.t("read.paused"):e.t("read.speaking"):e.t("read.idle"),icon:"outline-audio",tone:c?"success":void 0,title:e.t("read.title"),rows:m.length>0?m:void 0,run:c?void 0:k}};e.add(S.ComposerPill,()=>({id:"dictate",show:()=>_()})),e.add(S.ComposerPill,()=>({id:"read",order:1,show:()=>P(),menu:c=>g.createComponent($e,{actions:R,get close(){return c.close}})})),e.add(S.Command,()=>({id:"toggle",title:e.t("command.toggle"),description:e.t("command.toggle.description"),keywords:"voice dictation microphone speech dictado voz microfono",group:e.t("pill.title"),section:"prompt",bind:"mod+shift+m",slash:{name:"dictado"},editable:!0,enabled:e.app.platform==="desktop",run:h})),e.add(S.Command,()=>({id:"configure",title:e.t("command.configure"),keywords:"voice dictation microphone speech dictado voz microfono",group:e.t("pill.title"),enabled:e.app.platform==="desktop",run:()=>e.layout.settings(e.id)})),e.add(S.Command,()=>({id:"read",title:e.t("command.read"),description:e.t("command.read.description"),keywords:"read aloud speech voice leer voz altavoz lectura",group:e.t("pill.title"),section:"prompt",bind:"mod+shift+l",slash:{name:"leer"},editable:!0,enabled:e.app.platform==="desktop",run:k})),e.add(S.SettingsPage,{id:e.id,icon:"outline-audio",get title(){return e.t("settings.title")},get entries(){return[{id:"engine",title:e.t("settings.engine"),keywords:"engine motor dictation dictado winh voz"},{id:"winh",title:e.t("settings.winh"),keywords:"winh windows voice typing dictado"},{id:"language",title:e.t("settings.language"),keywords:"voice language idioma voz"},{id:"confidence",title:e.t("settings.confidence"),keywords:"voice confidence confianza"},{id:"test",title:e.t("settings.test"),keywords:"voice microphone microphone test microfono"},{id:"voice",title:e.t("speech.voice"),keywords:"read aloud voice voz lectura altavoz"},{id:"rate",title:e.t("speech.rate"),keywords:"read aloud speed velocidad lectura"},{id:"skip-code",title:e.t("speech.skipCode"),keywords:"read aloud code codigo lectura"},{id:"preview",title:e.t("speech.preview"),keywords:"read aloud test voice probar voz"}]},render:()=>g.createComponent(be,{speaker:o})})},Ce=S.Plugin.define({...ne,setup:Ee,main:he});exports.default=Ce;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-voice-dictation",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Offline voice dictation and read-aloud for OpenCode Desktop on Windows",
5
5
  "license": "MIT",
6
6
  "author": "Fran Carlos <francarlos803@gmail.com>",
package/src/gui/main.ts CHANGED
@@ -124,7 +124,6 @@ export const main: Plugin.MainSetup = (ctx) => {
124
124
  talking.stop()
125
125
  talking = undefined
126
126
  }
127
- speech.emit("done", { ok: true })
128
127
  },
129
128
 
130
129
  voices() {
package/src/gui/speak.ts CHANGED
@@ -167,7 +167,7 @@ export function createSpeaker(
167
167
  synth()?.cancel()
168
168
  setPaused(false)
169
169
  setSpeaking(false)
170
- void speech.stop().catch(() => {})
170
+ if (backend() === "sapi") void speech.stop().catch(() => {})
171
171
  }
172
172
 
173
173
  const canPause = () => backend() === "web"