Voice nodes (openpanel V4): stt, tts, wren reply/unhandled, socket publish

- `stt`: one realtime transcription session per utterance on the speech
  server's url, opened at `listening` true or the first chunk, committed at
  false; a whole clip goes to /v1/audio/transcriptions. Returns at once and
  publishes `partial` and `text` when the server answers.
- `tts`: one /v1/audio/speech call per sentence, cached by voice and text in
  node state; a reference is marked `append` while earlier ones still play.
- wren: `reply` says what was applied, `unhandled` carries the prompt when
  nothing was. The install hint names the git pin (PyPI's `wren` is another
  package).
- ai/client: transcribe, speak and transcribe_stream beside stream_completion.
- A device socket publishes scalar `in` ports as {"type": "publish"} text,
  in order with its binary frames.
- Pipeline.publish walks only what its values reach: a node downstream of a
  consumer that published nothing no longer runs again (wren re-acted on
  every microphone chunk).
This commit is contained in:
Melvin Strobl
2026-10-19 21:34:02 +02:00
parent 85dad39973
commit 16383ea6e2
15 changed files with 890 additions and 24 deletions
@@ -12,6 +12,7 @@ import {
Filter,
Globe,
Merge,
Mic,
MonitorSmartphone,
Play,
Plug,
@@ -22,6 +23,7 @@ import {
Square,
Terminal,
Timer,
Volume2,
} from "lucide-react"
import { memo, useEffect, useRef, useState } from "react"
@@ -63,6 +65,8 @@ const NODE_ICONS = {
file: FileText,
ntfy: Bell,
wren: Bird,
stt: Mic,
tts: Volume2,
// The glyph the Devices tab goes by.
device: MonitorSmartphone,
} as const