@bojackduy/opencode-voice 0.10.0 → 0.10.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.
- package/lib/stt.js +8 -0
- package/lib/tts.js +29 -5
- package/package.json +1 -1
package/lib/stt.js
CHANGED
|
@@ -2021,6 +2021,14 @@ export function registerSTT(api, kv, complete, prompts, opts, logger, deps = {})
|
|
|
2021
2021
|
}
|
|
2022
2022
|
|
|
2023
2023
|
api.lifecycle?.onDispose?.(() => {
|
|
2024
|
+
// Unload mid-recording must not orphan the sox child: cancel kills it,
|
|
2025
|
+
// bumps the pipeline generation (late transcriptions are dropped), and
|
|
2026
|
+
// clears the sticky toast. processing is not owned by cancel, reset it
|
|
2027
|
+
// here so a later registration starts from idle.
|
|
2028
|
+
try {
|
|
2029
|
+
cancelRecording(logger);
|
|
2030
|
+
} catch {}
|
|
2031
|
+
processing = false;
|
|
2024
2032
|
if (streamController) {
|
|
2025
2033
|
const c = streamController;
|
|
2026
2034
|
streamController = null;
|
package/lib/tts.js
CHANGED
|
@@ -638,11 +638,23 @@ export function registerTTS(api, kv, complete, prompts, opts, logger, deps = {})
|
|
|
638
638
|
let conversationActive = false;
|
|
639
639
|
let liveNotesActive = false;
|
|
640
640
|
|
|
641
|
-
|
|
641
|
+
// Auto-mode session subscriptions. The unsubscribe handles are kept so
|
|
642
|
+
// plugin unload (resumed session / reload) removes them: without this a
|
|
643
|
+
// second registration doubled auto-TTS speech and stale handlers fired
|
|
644
|
+
// cross-session. api.event.on may return nothing (older host), so guard.
|
|
645
|
+
const eventUnsubs = [];
|
|
646
|
+
function subscribe(name, fn) {
|
|
647
|
+
try {
|
|
648
|
+
const unsub = api.event.on(name, fn);
|
|
649
|
+
if (typeof unsub === "function") eventUnsubs.push(unsub);
|
|
650
|
+
} catch {}
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
subscribe("session.status", (event) => {
|
|
642
654
|
if (event.properties?.status?.type === "busy") wasBusy = true;
|
|
643
655
|
});
|
|
644
656
|
|
|
645
|
-
|
|
657
|
+
subscribe("session.idle", async (event) => {
|
|
646
658
|
if (conversationActive || liveNotesActive) {
|
|
647
659
|
wasBusy = false;
|
|
648
660
|
return;
|
|
@@ -674,7 +686,7 @@ export function registerTTS(api, kv, complete, prompts, opts, logger, deps = {})
|
|
|
674
686
|
await speakWithSessionPrefix(sessionID, llmResult.text, "Ready for your input.");
|
|
675
687
|
});
|
|
676
688
|
|
|
677
|
-
|
|
689
|
+
subscribe("permission.asked", async (event) => {
|
|
678
690
|
if (conversationActive || liveNotesActive) return;
|
|
679
691
|
if (kv.get("tts.mode", "off") !== "on") return;
|
|
680
692
|
await speakWithSessionPrefix(
|
|
@@ -683,7 +695,7 @@ export function registerTTS(api, kv, complete, prompts, opts, logger, deps = {})
|
|
|
683
695
|
);
|
|
684
696
|
});
|
|
685
697
|
|
|
686
|
-
|
|
698
|
+
subscribe("question.asked", async (event) => {
|
|
687
699
|
if (conversationActive || liveNotesActive) return;
|
|
688
700
|
if (kv.get("tts.mode", "off") !== "on") return;
|
|
689
701
|
await speakWithSessionPrefix(
|
|
@@ -822,8 +834,20 @@ export function registerTTS(api, kv, complete, prompts, opts, logger, deps = {})
|
|
|
822
834
|
|
|
823
835
|
// The Chatterbox sidecar holds a multi-hundred-MB torch model; leaving it
|
|
824
836
|
// running past the session would strand that memory. Same lifecycle hook the
|
|
825
|
-
// STT and live-notes servers use.
|
|
837
|
+
// STT and live-notes servers use. Also drops the session subscriptions (no
|
|
838
|
+
// duplicate auto-speech after re-registration), kills owned piper/play
|
|
839
|
+
// audio, and invalidates in-flight normalization so a late completion can
|
|
840
|
+
// never speak after unload.
|
|
826
841
|
api.lifecycle?.onDispose?.(() => {
|
|
842
|
+
for (const unsub of eventUnsubs) {
|
|
843
|
+
try {
|
|
844
|
+
unsub();
|
|
845
|
+
} catch {}
|
|
846
|
+
}
|
|
847
|
+
eventUnsubs.length = 0;
|
|
848
|
+
try {
|
|
849
|
+
stopSpeech();
|
|
850
|
+
} catch {}
|
|
827
851
|
chatterboxClient?.stop();
|
|
828
852
|
chatterboxClient = null;
|
|
829
853
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bojackduy/opencode-voice",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Speech-to-text and text-to-speech for OpenCode. Record voice prompts with whisper-cpp, hear responses via Piper TTS, with LLM normalization through any OpenAI-compatible endpoint.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"opencode",
|