diff --git a/packages/kilo-vscode/src/services/input-tools.ts b/packages/kilo-vscode/src/services/input-tools.ts index 23479bbf208..76157c11ff2 100644 --- a/packages/kilo-vscode/src/services/input-tools.ts +++ b/packages/kilo-vscode/src/services/input-tools.ts @@ -20,7 +20,7 @@ export async function routeInputToolMessage(message: Msg, ctx: Ctx): Promise console.warn("[Kilo New] Speech capture prewarm failed:", err)) + void prewarmSpeechCapture().catch((err: unknown) => console.warn("[Kilo New] Speech capture prewarm failed:", err)) return true } diff --git a/packages/kilo-vscode/src/speech-to-text/capture.ts b/packages/kilo-vscode/src/speech-to-text/capture.ts index a2d61885bc7..6250c0822c1 100644 --- a/packages/kilo-vscode/src/speech-to-text/capture.ts +++ b/packages/kilo-vscode/src/speech-to-text/capture.ts @@ -235,10 +235,10 @@ function requireActive(requestId: string): Recording { } async function resolveFFmpeg(): Promise { - if (ffmpeg) { - const bin = await ffmpeg + const cached = ffmpeg + if (cached) { + const bin = await cached if (!path.isAbsolute(bin) || existsSync(bin)) return bin - ffmpeg = undefined } const task = findFFmpeg() diff --git a/packages/kilo-vscode/webview-ui/src/components/speech-to-text/SpeechToTextButton.tsx b/packages/kilo-vscode/webview-ui/src/components/speech-to-text/SpeechToTextButton.tsx index ade6048443c..5a6d4f056a8 100644 --- a/packages/kilo-vscode/webview-ui/src/components/speech-to-text/SpeechToTextButton.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/speech-to-text/SpeechToTextButton.tsx @@ -13,6 +13,7 @@ type Props = { export const SpeechToTextButton: Component = (props) => { const unavailable = () => !!props.disabled && props.speech.state() === "idle" + const locked = () => unavailable() || props.speech.state() === "starting" const busy = () => props.speech.state() === "starting" || props.speech.state() === "transcribing" const label = () => { if (props.speech.state() === "starting") return props.label("speechToText.tooltip.starting") @@ -50,9 +51,9 @@ export const SpeechToTextButton: Component = (props) => { variant="ghost" size="small" onClick={click} - disabled={unavailable()} + disabled={locked()} aria-label={label()} - aria-disabled={unavailable() || props.speech.state() === "starting"} + aria-disabled={locked()} aria-busy={busy()} aria-pressed={props.speech.state() === "recording"} class={`prompt-speech-button prompt-speech-button--${props.speech.state()}`} diff --git a/packages/kilo-vscode/webview-ui/src/styles/prompt-input.css b/packages/kilo-vscode/webview-ui/src/styles/prompt-input.css index 77209132756..3188bf86c99 100644 --- a/packages/kilo-vscode/webview-ui/src/styles/prompt-input.css +++ b/packages/kilo-vscode/webview-ui/src/styles/prompt-input.css @@ -654,6 +654,11 @@ } } +.prompt-speech-button--starting { + cursor: progress; + opacity: 0.7; +} + .prompt-speech-button--recording::after { content: ""; position: absolute;