@drakulavich/kesha-voice-kit 1.27.0 → 1.28.0

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.
Files changed (50) hide show
  1. package/README.md +48 -26
  2. package/SKILL.md +5 -3
  3. package/completions/kesha.bash +3 -3
  4. package/completions/kesha.fish +9 -3
  5. package/completions/kesha.zsh +11 -4
  6. package/man/kesha.1 +21 -3
  7. package/model-plan.json +6 -6
  8. package/openclaw-plugin.cjs +20 -59
  9. package/package.json +10 -5
  10. package/src/asset-modules.d.ts +20 -0
  11. package/src/cache-layout.ts +44 -0
  12. package/src/cli/completions.ts +10 -7
  13. package/src/cli/dispatch.ts +23 -1
  14. package/src/cli/init.ts +2 -11
  15. package/src/cli/install.ts +7 -2
  16. package/src/cli/main.ts +110 -77
  17. package/src/cli/manpage.ts +4 -3
  18. package/src/cli/record.ts +132 -11
  19. package/src/cli/say.ts +28 -34
  20. package/src/cli.ts +1 -0
  21. package/src/diagnostic-log.ts +2 -1
  22. package/src/doctor.ts +96 -85
  23. package/src/engine-health.ts +107 -6
  24. package/src/engine-install.ts +245 -101
  25. package/src/engine-targets.ts +19 -3
  26. package/src/engine.ts +281 -20
  27. package/src/error-codes.ts +3 -3
  28. package/src/fluid-asr-cache.ts +24 -30
  29. package/src/fluid-roots.ts +159 -0
  30. package/src/format.ts +3 -2
  31. package/src/install-lock.ts +261 -0
  32. package/src/install-plan.ts +23 -25
  33. package/src/kokoro-ane.ts +92 -0
  34. package/src/lib.ts +3 -3
  35. package/src/log.ts +3 -1
  36. package/src/mcp/tools.ts +9 -2
  37. package/src/mcp/voices.ts +19 -10
  38. package/src/progress.ts +15 -11
  39. package/src/star.ts +64 -36
  40. package/src/stats.ts +1 -1
  41. package/src/status.ts +66 -72
  42. package/src/stdout-pipe.ts +26 -0
  43. package/src/suggest-command.ts +2 -2
  44. package/src/synth.ts +72 -13
  45. package/src/toon.ts +9 -5
  46. package/src/transcribe.ts +22 -2
  47. package/src/types.ts +21 -1
  48. package/src/voice-routing.ts +32 -3
  49. package/tsconfig.json +7 -0
  50. package/src/fluid-kokoro-cache.ts +0 -47
package/README.md CHANGED
@@ -11,12 +11,12 @@
11
11
  <a href="https://bun.sh"><img src="https://img.shields.io/badge/runtime-Bun-f9f1e1?logo=bun" alt="Bun"></a>
12
12
  </p>
13
13
 
14
- <p align="center"><b>Give your local tools and LLM agents a voice.</b><br>Fast speech-to-text, text-to-speech, voice-activity detection, and language detection in one local-first CLI: Apple Silicon CoreML first, ONNX fallback on supported Linux/Windows builds.</p>
14
+ <p align="center"><b>Give your local tools and LLM agents a voice.</b><br>Fast speech-to-text, text-to-speech, voice-activity detection, and language detection in one local-first CLI — CoreML on Apple Silicon, ONNX on Linux and Windows.</p>
15
15
 
16
16
  - **Transcribe locally** — [25 languages](docs/languages.md#speech-to-text-25), up to ~19x faster than Whisper on Apple Silicon, ~2.5x on CPU
17
17
  - **Speak back** — text-to-speech in [9 languages](docs/languages.md#text-to-speech)
18
18
  - **Plug into agents** — ship voice workflows as CLI commands, an MCP server, an <a href="docs/openclaw.md">OpenClaw</a> skill, or a <a href="docs/hermes.md">Hermes</a> agent
19
- - **Small Rust engine** — single ~60MB binary, no ffmpeg, no Python, no native Node addons
19
+ - **Small Rust engine** — single ~65MB binary, no ffmpeg, no Python, no native Node addons
20
20
 
21
21
  <p align="center">
22
22
  <img src="https://github.com/drakulavich/kesha-voice-kit/raw/main/demo.gif" alt="kesha demo — English + Russian transcription with automatic language detection" width="800">
@@ -24,30 +24,46 @@
24
24
 
25
25
  ## Quick Start
26
26
 
27
- Runtime: **[Bun](https://bun.sh)** >= 1.3.0 · Platforms: macOS arm64, Linux x64, Windows x64. Linux and Windows run the ONNX engine — everything except microphone capture (`kesha record`), macOS system voices, speaker diarization, and text language detection, which need Apple frameworks.
27
+ Runtime: **[Bun](https://bun.sh)** >= 1.3.0.
28
28
 
29
29
  ```bash
30
- # 1. Install Bun (skip if you have it) — Linux & macOS:
31
- curl -fsSL https://bun.sh/install | bash # or: brew install oven-sh/bun/bun
32
- # Windows: powershell -c "irm bun.sh/install.ps1 | iex"
33
- # if `bun --version` fails, reload PATH: exec $SHELL -l
30
+ # 1. Install Bun (skip if you have it)
31
+ curl -fsSL https://bun.sh/install | bash # macOS/Linux — or: brew install oven-sh/bun/bun
32
+ powershell -c "irm bun.sh/install.ps1 | iex" # Windows
34
33
 
35
- # 2. Install Kesha:
34
+ # 2. Install Kesha
36
35
  bun add -g @drakulavich/kesha-voice-kit
37
36
  kesha --version # confirms `kesha` resolved on PATH
38
- kesha install --plan # preview exact download/disk sizes first — downloads nothing
39
- kesha install # ~2.5 GB on Linux/Windows; ~0.6 GB on Apple Silicon, whose CoreML
40
- # engine uses a different, smaller model set. Explicit — never automatic.
41
- # No progress bar during the model step; can take several minutes.
42
- # Prefer a guided wizard? `kesha init` walks through the same choices interactively.
43
-
44
- # 3. Transcribe:
45
- kesha audio.ogg # transcript to stdout
37
+
38
+ # 3. Download the engine and models — pick one path
39
+ kesha init # guided: backend, languages, TTS voices
40
+ kesha install --plan && kesha install # manual: preview the sizes, then download
41
+
42
+ # 4. Transcribe
43
+ kesha audio.ogg # transcript to stdout
46
44
  ```
47
45
 
48
- Prefer Homebrew, Docker, or Nix? See [Other install methods](#other-install-methods).
46
+ `kesha install` pulls ~2.5 GB on Linux/Windows and ~0.6 GB on Apple Silicon, whose CoreML engine reads a smaller model set. It is always explicit — nothing downloads behind your back — and the model step has no progress bar, so expect a few quiet minutes. If `bun --version` fails right after step 1, reload your PATH: `exec $SHELL -l`.
47
+
48
+ Prefer Homebrew or Docker? See [Other install methods](#other-install-methods).
49
49
  Air-gapped or behind a corporate mirror? See [docs/model-mirror.md](docs/model-mirror.md).
50
50
 
51
+ ### Platform support
52
+
53
+ All three targets transcribe, detect the spoken language, run VAD, and speak. The macOS-only rows need Apple frameworks — they are not a missing port. Windows is a tested path rather than a published binary nobody ran: CI does a cold `kesha install` on `windows-latest`, transcribes a fixture, and round-trips a synthesis ([#216](https://github.com/drakulavich/kesha-voice-kit/issues/216), [#667](https://github.com/drakulavich/kesha-voice-kit/pull/667)).
54
+
55
+ | | macOS arm64 | Linux x64 | Windows x64 |
56
+ |---|:---:|:---:|:---:|
57
+ | Transcribe · audio language ID · [VAD](docs/vad.md) | CoreML / ANE | ONNX CPU | ONNX CPU |
58
+ | TTS — `en` `ru` `es` `fr` `it` `pt` | ✅ | ✅ | ✅ |
59
+ | TTS — `hi` `ja` `zh` and macOS system voices | ✅ | — | — |
60
+ | Mic capture and live dictation (`kesha record`) | ✅ | — | — |
61
+ | Speaker diarization (`--speakers`) | ✅ | — | — |
62
+ | Word-level timestamps (`words` in `--json`) | ✅ | ✅ | ✅ |
63
+ | Voice auto-routing from the text's language | ✅ | pass `--lang` | pass `--lang` |
64
+
65
+ Intel Macs get no published engine binary. Full matrix with maturity labels: [docs/product-positioning.md](docs/product-positioning.md#platform-matrix).
66
+
51
67
  ## Speech-to-text
52
68
 
53
69
  ```bash
@@ -55,6 +71,7 @@ kesha audio.ogg # transcribe (plain text)
55
71
  kesha --format transcript audio.ogg # text + language/confidence
56
72
  kesha --format json audio.ogg # full JSON with lang fields
57
73
  kesha --json --timestamps audio.ogg # JSON with timestamped segments
74
+ kesha --itn audio.ogg # spelled-out numbers -> digits
58
75
  kesha --toon audio.ogg # compact LLM-friendly TOON
59
76
  kesha status # show installed backend info
60
77
  kesha status --disk # + recursive cache disk usage
@@ -73,18 +90,22 @@ $ kesha freedom.ogg tahiti.ogg
73
90
  ```
74
91
 
75
92
  - **Record from the mic (macOS):** `kesha record --out hello.wav` writes microphone audio to a WAV file (`kesha hello.wav` transcribes it). macOS prompts for microphone access on first use — grant it under System Settings → Privacy & Security → Microphone if it was denied. On Linux/Windows or headless boxes, pass any existing audio file straight to `kesha` instead.
93
+ - **Dictate straight to text (darwin-arm64):** `kesha record --live` transcribes the mic as it captures and prints the transcript to stdout — no WAV in between, so it pipes (`kesha record --live | pbcopy`). Progress goes to stderr. Other platforms keep the two-step `record --out` + transcribe flow. An interruption is recoverable: Ctrl-C (or SIGTERM) stops the session, still prints what you dictated, and exits 130/143, and the audio is spilled to a recovery WAV under `~/.cache/kesha/recordings/` — named on stderr when the session starts, deleted once the transcript has actually been delivered, kept if anything — a signal, a crash, a closed terminal, a dead pipe — got in the way first ([#962](https://github.com/drakulavich/kesha-voice-kit/issues/962)).
76
94
  - **Long / silence-heavy audio:** install VAD (`kesha install --vad`); Kesha auto-uses it past 120 s. Without VAD, long audio falls back to fixed ASR chunks. See [docs/vad.md](docs/vad.md).
77
95
  - **Speaker diarization** (darwin-arm64): `kesha install --diarize` (which installs VAD too), then `kesha --json --speakers meeting.m4a` stamps each segment with a `speaker` id. `--speakers` engages VAD windowing itself at any duration, so it cannot be combined with `--no-vad`. Linux/Windows return a clear "darwin-arm64 only" error ([#199](https://github.com/drakulavich/kesha-voice-kit/issues/199)).
96
+ - **Word-level timestamps** (every platform): `kesha --json --timestamps audio.ogg` adds a `words` array to each segment — `{ "word": "email", "start": 0.72, "end": 1.12 }` — on the same file-relative clock as the segment, so a word always lies inside the segment carrying it. Read them off the decoder's own frame grid, so: times are quantised to 0.08 s, consecutive spans may overlap (each `end` is a per-word duration prediction, not the next word's `start`), `end >= start` rather than strictly greater, and punctuation stays attached to its word. The key is simply absent where a segment has none — any segment `--itn` rewrote, for one — so check the `transcribe.words` capability rather than expecting an empty array ([#720](https://github.com/drakulavich/kesha-voice-kit/issues/720)).
97
+ - **Written-form numbers:** `--itn` rewrites what the model spells out — `"two hundred thirty two"` → `"232"`, `"five dollars and fifty cents"` → `"$5.50"`. Opt-in, every platform, timestamps untouched. English-only in practice; Russian and the rest pass through unchanged. Spoken punctuation names stay words (`"dot"`, `"comma"`, `"the period of growth"`) because Kesha transcribes speech rather than dictation — so `"example dot com"` keeps its words too ([#822](https://github.com/drakulavich/kesha-voice-kit/issues/822)). A sentence `"and"` survives the number that follows it (`"cats and three dogs"` → `"cats and 3 dogs"`), while an `"and"` the number owns still joins it (`"three hundred and five"` → `"305"`) ([#1000](https://github.com/drakulavich/kesha-voice-kit/issues/1000)) — and no longer splits the number around it (`"two hundred and thirty two"` → `"232"`, not `"230 2"`) ([#1006](https://github.com/drakulavich/kesha-voice-kit/issues/1006)). A hyphenated number reads the same as the spaced form (`"twenty-five apples"` → `"25 apples"`), while a hyphen between ordinary words is left alone (`"well-known"`, `"state-of-the-art"`, `"twenty-something"`) ([#1004](https://github.com/drakulavich/kesha-voice-kit/issues/1004)).
78
98
 
79
99
  ## Text-to-speech
80
100
 
81
- Kesha speaks back in [9 languages](docs/languages.md#text-to-speech), auto-picking the voice from the text's language. Override with `--lang <code>` or `--voice <id>`.
101
+ Kesha speaks back in [9 languages](docs/languages.md#text-to-speech). On macOS it picks the voice from the text's own language; on Linux and Windows text detection needs Apple frameworks, so state the language with `--lang <code>` (or the voice with `--voice <id>`) — otherwise the engine default speaks.
82
102
 
83
103
  ```bash
84
104
  kesha install --tts # English voices; sizes differ per platform — preview: kesha install --plan
85
105
  kesha install --tts en ru # + Russian (+~890 MB, Vosk)
86
106
  kesha say "Hello, world" > hello.wav
87
- kesha say "Привет, мир" > privet.wav # auto-routes by language
107
+ kesha say "Привет, мир" > privet.wav # auto-routes by language (macOS)
108
+ kesha say --lang ru "Привет, мир" > privet.wav # explicit — the Linux/Windows path
88
109
  kesha say --voice ru-vosk-m02 "Голос в текст." > ru.wav
89
110
  ```
90
111
 
@@ -100,7 +121,7 @@ kesha say "Hello" --format flac --out hi.flac # FLAC — lossless, plays in
100
121
 
101
122
  ## Languages
102
123
 
103
- **Speech-to-text** spans 25 languages and **text-to-speech** covers English, Russian, and select multilingual voices — full tables with codes and flags in **[docs/languages.md](docs/languages.md)**. Audio language detection identifies [107 languages](https://huggingface.co/speechbrain/lang-id-voxlingua107-ecapa).
124
+ **Speech-to-text** spans 25 languages and **text-to-speech** 9 — full tables with codes, flags, and per-platform availability in **[docs/languages.md](docs/languages.md)**. Audio language detection identifies [107 languages](https://huggingface.co/speechbrain/lang-id-voxlingua107-ecapa).
104
125
 
105
126
  ## Performance
106
127
 
@@ -110,16 +131,16 @@ Compared against Whisper `large-v3-turbo`, all engines auto-detecting language:
110
131
 
111
132
  ![Benchmark: openai-whisper vs faster-whisper vs Kesha Voice Kit](https://github.com/drakulavich/kesha-voice-kit/raw/main/docs/assets/benchmark.svg)
112
133
 
113
- Full per-file breakdown (Russian + English): [BENCHMARK.md](BENCHMARK.md).
134
+ Full per-file breakdown (Russian + English): [BENCHMARK.md](BENCHMARK.md). The CPU figure is the ONNX engine on an M2's CPU cores; no x86 numbers are published yet.
114
135
 
115
136
  ## Other install methods
116
137
 
117
- All of these install the Bun CLI wrapper; engine + models still download explicitly via `kesha install`.
138
+ All of these install the Bun CLI wrapper; engine + models still download explicitly via `kesha install`. (Nix is the exception — it currently builds only the engine from source; see below.)
118
139
 
119
140
  - **Homebrew** — `brew install drakulavich/tap/kesha-voice-kit` · [docs/homebrew.md](docs/homebrew.md)
120
- - **Linux packages** (`.deb`/`.rpm`, x64) — not currently published, see [docs/linux-packages.md](docs/linux-packages.md)
141
+ - **Linux packages** (`.deb`/`.rpm`, x64) — published on CLI releases, see [docs/linux-packages.md](docs/linux-packages.md)
121
142
  - **Docker** (GHCR image) — [docs/docker.md](docs/docker.md)
122
- - **Nix** (`aarch64-darwin` / `x86_64-linux`) — `nix run github:drakulavich/kesha-voice-kit -- install` · [docs/nix-install.md](docs/nix-install.md)
143
+ - **Nix** (`aarch64-darwin` / `x86_64-linux`) — builds the engine from source (`nix build github:drakulavich/kesha-voice-kit#kesha-engine`). The full `kesha` CLI via `nix run` / `nix profile install` is **not yet available** — it needs a maintainer with Nix to populate a build hash ([#946](https://github.com/drakulavich/kesha-voice-kit/issues/946)). · [docs/nix-install.md](docs/nix-install.md)
123
144
  - **Shell completions + manpage** — `kesha completions bash|zsh|fish` and `kesha manpage` print the packaged files to install wherever your shell expects them.
124
145
 
125
146
  ## Integrations
@@ -135,13 +156,14 @@ All of these install the Bun CLI wrapper; engine + models still download explici
135
156
  - [Architecture](docs/architecture.md) — runtime data flow, the models that ship, the CLI ↔ Rust engine boundary, model pinning, and where tests live.
136
157
  - [Use cases](docs/use-cases.md) — copy-paste recipes (transcribe a meeting, speak from OpenClaw, run offline, move the cache).
137
158
  - [Product positioning](docs/product-positioning.md) — supported workflows, non-goals, maturity labels, platform matrix.
159
+ - [Changelog](CHANGELOG.md) — every release, with the behaviour changes spelled out.
138
160
  - **Diagnostics:** `kesha doctor`, `kesha support-bundle` (redacted `.tar.gz` for issues), and `kesha logs` produce local, content-free diagnostics — see [docs/diagnostic-logs.md](docs/diagnostic-logs.md). Every failure prints a stable `error [CODE]: …` line and a documented [process exit code](docs/errors.md#process-exit-codes).
139
- - **Scripting & CI:** `--json` (or `--toon`) for machine-readable output, `--quiet`/`-q` to silence progress, and `--no-color` (or `NO_COLOR=1`) for plain logs. Colors switch off automatically when `CI=true`.
161
+ - **Scripting & CI:** `--json` (or `--toon`) for machine-readable output, `--include-errors` (with either) to get per-file failures on stdout alongside the results, `--quiet`/`-q` to silence progress, and `--no-color` (or `NO_COLOR=1`) for plain logs. Colors switch off automatically when `CI=true`.
140
162
  - **Privacy / Local Stats:** Stats are **off by default** and fully local. Opt in with `kesha stats enable` to record content-free operational metrics in a local SQLite database — never networked, never storing audio, transcripts, text, or paths. Full commands & lifecycle: [docs/local-stats.md](docs/local-stats.md).
141
163
 
142
164
  ## Contributing
143
165
 
144
- See [CONTRIBUTING.md](CONTRIBUTING.md), the [Roadmap](ROADMAP.md) (Now / Next / Later), and the [Decision log](docs/decision-log.md) (why platform/model choices were made — and reversed). Dev setup: `make dev-setup` (Bun, Rust, nextest, platform libs).
166
+ See [CONTRIBUTING.md](CONTRIBUTING.md), the [Roadmap](ROADMAP.md) (Now / Next / Later), and the [Decision log](docs/decision-log.md) (why platform/model choices were made — and reversed). Dev setup: `just dev-setup` (Bun, Rust, nextest, platform libs).
145
167
 
146
168
  ## License
147
169
 
package/SKILL.md CHANGED
@@ -130,12 +130,14 @@ kesha --json voice.ogg
130
130
  "text": "Привет, как дела?",
131
131
  "lang": "ru",
132
132
  "audioLanguage": { "code": "ru", "confidence": 0.98 },
133
- "textLanguage": { "code": "ru", "confidence": 0.99 }
133
+ "textLanguage": { "code": "ru", "confidence": 0.99, "source": "engine" }
134
134
  }]
135
135
  ```
136
136
 
137
137
  Use `lang` (or the more detailed `audioLanguage`/`textLanguage`) to decide how to respond.
138
138
 
139
+ **Read `textLanguage.source` before you compare its `confidence` to a threshold.** `"engine"` (macOS `NLLanguageRecognizer`) and `"tinyld"` (the CLI fallback used on Linux/Windows) score on different scales — the same correct detection reads ~0.98 from the engine and ~0.2 from `tinyld`, so a fixed `> 0.5` gate discards every correct fallback result. `audioLanguage` has one detector and carries no `source`.
140
+
139
141
  Need timestamped transcript segments for navigation, chapters, or downstream editing:
140
142
 
141
143
  ```bash
@@ -196,7 +198,7 @@ Format is also inferred from `--out` extension (`.ogg` / `.opus` / `.oga` → OG
196
198
 
197
199
  **Russian abbreviations** (`ru-vosk-*`): all-uppercase Cyrillic 2-5-char tokens auto-expand letter-by-letter when not pronounceable as a Russian syllable (ФСБ → "эф-эс-бэ", ВОЗ → "воз"). Disable with `--no-expand-abbrev`. See [docs/tts.md#russian-abbreviation-auto-expansion](docs/tts.md#russian-abbreviation-auto-expansion).
198
200
 
199
- **English acronyms** (`en-*`, Kokoro): three-table mechanism (letter-spell rule + STOP_LIST + IPA_LEXICON) auto-expands FBI → "ef bee eye" and gives EPAM/JSON/Anthropic the right IPA. Disable letter-spell with `--no-expand-abbrev`. See [docs/tts.md#english-acronym-auto-expansion](docs/tts.md#english-acronym-auto-expansion).
201
+ **English acronyms** (`en-*`, Kokoro): three-table mechanism (letter-spell rule + STOP_LIST + IPA_LEXICON) auto-expands FBI → "ef bee eye" and gives EPAM/JSON/Anthropic the right IPA. Disable letter-spell with `--no-expand-abbrev` — honored on ONNX builds only; the released darwin-arm64 binary spells initialisms inside FluidAudio's own G2P and warns that the flag is a no-op ([#842](https://github.com/drakulavich/kesha-voice-kit/issues/842)). See [docs/tts.md#english-acronym-auto-expansion](docs/tts.md#english-acronym-auto-expansion).
200
202
 
201
203
  **Russian word stress** (`ru-vosk-*` only): `<emphasis>сл+ово</emphasis>` shifts stress to the vowel marked with `+`. `<emphasis level="none">сл+ово</emphasis>` strips the `+` (cancel inherited emphasis). Other voices (`en-*`, `macos-*`) silently strip the `+` and warn once per process. Auto-stress dictionary not provided — caller writes the `+` manually. Closes [#233](https://github.com/drakulavich/kesha-voice-kit/issues/233).
202
204
 
@@ -204,7 +206,7 @@ Format is also inferred from `--out` extension (`.ogg` / `.opus` / `.oga` → OG
204
206
 
205
207
  ## Language detection standalone
206
208
 
207
- `kesha --json audio.ogg` includes both audio-based (`audioLanguage`) and text-based (`textLanguage`) detection. Use audio detection to identify the language before running language-specific logic.
209
+ `kesha --json audio.ogg` includes both audio-based (`audioLanguage`) and text-based (`textLanguage`) detection. Use audio detection to identify the language before running language-specific logic. `textLanguage` also names its detector in `source` — see the threshold rule under [STT](#stt-transcribe-audio).
208
210
 
209
211
  ## Install
210
212
 
@@ -10,7 +10,7 @@ _kesha_completion() {
10
10
 
11
11
  if [[ "$COMP_CWORD" -eq 1 ]]; then
12
12
  if [[ "$cur" == -* ]]; then
13
- COMPREPLY=( $(compgen -W "--help -h --version -v --json --toon --timestamps --speakers --include-errors --verbose --format --lang --debug --vad --no-vad --quiet --no-color" -- "$cur") )
13
+ COMPREPLY=( $(compgen -W "--help -h --version -v --json --toon --timestamps --speakers --itn --include-errors --verbose --format --lang --debug --vad --no-vad --quiet --no-color" -- "$cur") )
14
14
  else
15
15
  COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
16
16
  fi
@@ -25,12 +25,12 @@ _kesha_completion() {
25
25
  logs) opts="--help -h --json" ;;
26
26
  manpage) opts="--help -h" ;;
27
27
  mcp) opts="--help -h" ;;
28
- record) opts="--help -h --out --max-seconds --debug" ;;
28
+ record) opts="--help -h --out --live --max-seconds --auto-stop --auto-stop-silence-ms --auto-stop-threshold --auto-stop-min-speech-ms --debug" ;;
29
29
  say) opts="--help -h --voice --lang --out --rate --list-voices --ssml --format --bitrate --sample-rate --no-expand-abbrev --verbose --debug" ;;
30
30
  stats) opts="--help -h --format" ;;
31
31
  status) opts="--help -h --disk --json" ;;
32
32
  support-bundle) opts="--help -h --output --include-logs" ;;
33
- *) opts="--help -h --version -v --json --toon --timestamps --speakers --include-errors --verbose --format --lang --debug --vad --no-vad --quiet --no-color" ;;
33
+ *) opts="--help -h --version -v --json --toon --timestamps --speakers --itn --include-errors --verbose --format --lang --debug --vad --no-vad --quiet --no-color" ;;
34
34
  esac
35
35
 
36
36
  if [[ "$cur" == -* ]]; then
@@ -7,7 +7,7 @@ complete -c kesha -n '__fish_use_subcommand' -a 'install' -d 'Download inference
7
7
  complete -c kesha -n '__fish_use_subcommand' -a 'logs' -d 'Manage local privacy-safe diagnostic logs'
8
8
  complete -c kesha -n '__fish_use_subcommand' -a 'manpage' -d 'Print the kesha(1) manpage'
9
9
  complete -c kesha -n '__fish_use_subcommand' -a 'mcp' -d 'Run a Model Context Protocol server over stdio (transcribe_audio, synthesize_speech, list_voices, list_languages). Configure an MCP client with: { command: \'kesha\', args: [\'mcp\'] }.'
10
- complete -c kesha -n '__fish_use_subcommand' -a 'record' -d 'Record microphone audio to a WAV file'
10
+ complete -c kesha -n '__fish_use_subcommand' -a 'record' -d 'Record microphone audio to a WAV file, or transcribe it live'
11
11
  complete -c kesha -n '__fish_use_subcommand' -a 'say' -d 'Synthesize speech from text (TTS). Writes audio to stdout (or --out file). Defaults to WAV; use --format ogg-opus for messenger-ready voice notes.'
12
12
  complete -c kesha -n '__fish_use_subcommand' -a 'stats' -d 'Manage local anonymous Kesha Stats'
13
13
  complete -c kesha -n '__fish_use_subcommand' -a 'status' -d 'Show backend installation status'
@@ -20,7 +20,8 @@ complete -c kesha -n '__fish_use_subcommand' -l json -d 'Output results as JSON'
20
20
  complete -c kesha -n '__fish_use_subcommand' -l toon -d 'Output results as TOON (compact, LLM-friendly encoding of the same data as --json)'
21
21
  complete -c kesha -n '__fish_use_subcommand' -l timestamps -d 'Include timestamped transcript segments in JSON/TOON output'
22
22
  complete -c kesha -n '__fish_use_subcommand' -l speakers -d 'Include speaker labels in segments. Needs --json/--toon and darwin-arm64; run `kesha install --diarize` first (it installs VAD too). Implies --timestamps, and engages VAD windowing at any duration (so it cannot be combined with --no-vad).'
23
- complete -c kesha -n '__fish_use_subcommand' -l include-errors -d 'With --json, output { results, errors } so scripts can read per-file failures without parsing stderr'
23
+ complete -c kesha -n '__fish_use_subcommand' -l itn -d 'Rewrite spoken-form numbers, money, dates and times to written form ("two hundred thirty two" -> "232"). English-only; other languages pass through unchanged.'
24
+ complete -c kesha -n '__fish_use_subcommand' -l include-errors -d 'With --json or --toon, output { results, errors } so scripts can read per-file failures without parsing stderr'
24
25
  complete -c kesha -n '__fish_use_subcommand' -l verbose -d 'Show language detection details'
25
26
  complete -c kesha -n '__fish_use_subcommand' -l format -r -d 'Output format: transcript | json | toon (long-form alias for --json / --toon)'
26
27
  complete -c kesha -n '__fish_use_subcommand' -l lang -r -d 'Expected language code, e.g. en or en-us (see docs/languages.md); warn if mismatch'
@@ -65,7 +66,12 @@ complete -c kesha -n '__fish_seen_subcommand_from mcp' -s h -d 'Show help'
65
66
  complete -c kesha -n '__fish_seen_subcommand_from record' -l help -d 'Show help'
66
67
  complete -c kesha -n '__fish_seen_subcommand_from record' -s h -d 'Show help'
67
68
  complete -c kesha -n '__fish_seen_subcommand_from record' -l out -r -d 'Write recorded WAV audio to this path'
69
+ complete -c kesha -n '__fish_seen_subcommand_from record' -l live -d 'Transcribe the microphone live and print the transcript to stdout (CoreML on Apple Silicon only)'
68
70
  complete -c kesha -n '__fish_seen_subcommand_from record' -l max-seconds -r -d 'Maximum recording duration in seconds'
71
+ complete -c kesha -n '__fish_seen_subcommand_from record' -l auto-stop -d 'End a live recording after trailing silence (requires `kesha install --vad`)'
72
+ complete -c kesha -n '__fish_seen_subcommand_from record' -l auto-stop-silence-ms -r -d 'Trailing silence before auto-stop (default: 1000)'
73
+ complete -c kesha -n '__fish_seen_subcommand_from record' -l auto-stop-threshold -r -d 'Silero speech threshold for auto-stop (default: 0.5)'
74
+ complete -c kesha -n '__fish_seen_subcommand_from record' -l auto-stop-min-speech-ms -r -d 'Minimum speech before auto-stop may end a recording (default: 250)'
69
75
  complete -c kesha -n '__fish_seen_subcommand_from record' -l debug -d 'Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)'
70
76
  complete -c kesha -n '__fish_seen_subcommand_from say' -l help -d 'Show help'
71
77
  complete -c kesha -n '__fish_seen_subcommand_from say' -s h -d 'Show help'
@@ -78,7 +84,7 @@ complete -c kesha -n '__fish_seen_subcommand_from say' -l ssml -d 'Parse input a
78
84
  complete -c kesha -n '__fish_seen_subcommand_from say' -l format -r -d 'Output format: wav (default), ogg-opus (Telegram-ready voice note), or flac (lossless, plays in all browsers incl. Safari). Inferred from --out extension when omitted.'
79
85
  complete -c kesha -n '__fish_seen_subcommand_from say' -l bitrate -r -d 'Opus bitrate in bits/sec (e.g. 32000). Only with --format ogg-opus.'
80
86
  complete -c kesha -n '__fish_seen_subcommand_from say' -l sample-rate -r -d 'Opus encoder sample rate (8000/12000/16000/24000/48000). Only with --format ogg-opus.'
81
- complete -c kesha -n '__fish_seen_subcommand_from say' -l no-expand-abbrev -d 'Disable Russian acronym auto-expansion (ВОЗ → \'вэ о зэ\') for ru-vosk-* voices. <say-as interpret-as=\'characters\'> still works. Applies to Russian (ru-vosk-*) and English (en-*) voices.'
87
+ complete -c kesha -n '__fish_seen_subcommand_from say' -l no-expand-abbrev -d 'Disable acronym auto-expansion on ru-vosk-* voices (ВОЗ → \'вэ о зэ\') and English on ONNX engine builds (FBI → \'ef bee eye\'). No effect on macOS arm64 FluidAudio, macos-* or non-English voices, which spell initialisms in their own G2P; the engine warns when the flag is ignored. <say-as interpret-as=\'characters\'> still works.'
82
88
  complete -c kesha -n '__fish_seen_subcommand_from say' -l verbose -d 'Log TTS synthesis time to stderr'
83
89
  complete -c kesha -n '__fish_seen_subcommand_from say' -l debug -d 'Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)'
84
90
  complete -c kesha -n '__fish_seen_subcommand_from stats' -l help -d 'Show help'
@@ -11,7 +11,7 @@ _kesha() {
11
11
  'logs:Manage local privacy-safe diagnostic logs'
12
12
  'manpage:Print the kesha(1) manpage'
13
13
  'mcp:Run a Model Context Protocol server over stdio (transcribe_audio, synthesize_speech, list_voices, list_languages). Configure an MCP client with: { command: '\''kesha'\'', args: \['\''mcp'\''\] }.'
14
- 'record:Record microphone audio to a WAV file'
14
+ 'record:Record microphone audio to a WAV file, or transcribe it live'
15
15
  'say:Synthesize speech from text (TTS). Writes audio to stdout (or --out file). Defaults to WAV; use --format ogg-opus for messenger-ready voice notes.'
16
16
  'stats:Manage local anonymous Kesha Stats'
17
17
  'status:Show backend installation status'
@@ -28,7 +28,8 @@ _kesha() {
28
28
  '--toon[Output results as TOON (compact, LLM-friendly encoding of the same data as --json)]' \
29
29
  '--timestamps[Include timestamped transcript segments in JSON/TOON output]' \
30
30
  '--speakers[Include speaker labels in segments. Needs --json/--toon and darwin-arm64; run `kesha install --diarize` first (it installs VAD too). Implies --timestamps, and engages VAD windowing at any duration (so it cannot be combined with --no-vad).]' \
31
- '--include-errors[With --json, output { results, errors } so scripts can read per-file failures without parsing stderr]' \
31
+ '--itn[Rewrite spoken-form numbers, money, dates and times to written form ("two hundred thirty two" -> "232"). English-only; other languages pass through unchanged.]' \
32
+ '--include-errors[With --json or --toon, output { results, errors } so scripts can read per-file failures without parsing stderr]' \
32
33
  '--verbose[Show language detection details]' \
33
34
  '--format=[Output format: transcript | json | toon (long-form alias for --json / --toon)]:format:' \
34
35
  '--lang=[Expected language code, e.g. en or en-us (see docs/languages.md); warn if mismatch]:lang:' \
@@ -95,7 +96,12 @@ _kesha() {
95
96
  _arguments '--help[Show help]' \
96
97
  '-h[Show help]' \
97
98
  '--out=[Write recorded WAV audio to this path]:out:' \
99
+ '--live[Transcribe the microphone live and print the transcript to stdout (CoreML on Apple Silicon only)]' \
98
100
  '--max-seconds=[Maximum recording duration in seconds]:max seconds:' \
101
+ '--auto-stop[End a live recording after trailing silence (requires `kesha install --vad`)]' \
102
+ '--auto-stop-silence-ms=[Trailing silence before auto-stop (default: 1000)]:auto stop silence ms:' \
103
+ '--auto-stop-threshold=[Silero speech threshold for auto-stop (default: 0.5)]:auto stop threshold:' \
104
+ '--auto-stop-min-speech-ms=[Minimum speech before auto-stop may end a recording (default: 250)]:auto stop min speech ms:' \
99
105
  '--debug[Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)]'
100
106
  ;;
101
107
  say)
@@ -110,7 +116,7 @@ _kesha() {
110
116
  '--format=[Output format: wav (default), ogg-opus (Telegram-ready voice note), or flac (lossless, plays in all browsers incl. Safari). Inferred from --out extension when omitted.]:format:' \
111
117
  '--bitrate=[Opus bitrate in bits/sec (e.g. 32000). Only with --format ogg-opus.]:bitrate:' \
112
118
  '--sample-rate=[Opus encoder sample rate (8000/12000/16000/24000/48000). Only with --format ogg-opus.]:sample rate:' \
113
- '--no-expand-abbrev[Disable Russian acronym auto-expansion (ВОЗ → '\''вэ о зэ'\'') for ru-vosk-* voices. <say-as interpret-as='\''characters'\''> still works. Applies to Russian (ru-vosk-*) and English (en-*) voices.]' \
119
+ '--no-expand-abbrev[Disable acronym auto-expansion on ru-vosk-* voices (ВОЗ → '\''вэ о зэ'\'') and English on ONNX engine builds (FBI → '\''ef bee eye'\''). No effect on macOS arm64 FluidAudio, macos-* or non-English voices, which spell initialisms in their own G2P; the engine warns when the flag is ignored. <say-as interpret-as='\''characters'\''> still works.]' \
114
120
  '--verbose[Log TTS synthesis time to stderr]' \
115
121
  '--debug[Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)]'
116
122
  ;;
@@ -140,7 +146,8 @@ _kesha() {
140
146
  '--toon[Output results as TOON (compact, LLM-friendly encoding of the same data as --json)]' \
141
147
  '--timestamps[Include timestamped transcript segments in JSON/TOON output]' \
142
148
  '--speakers[Include speaker labels in segments. Needs --json/--toon and darwin-arm64; run `kesha install --diarize` first (it installs VAD too). Implies --timestamps, and engages VAD windowing at any duration (so it cannot be combined with --no-vad).]' \
143
- '--include-errors[With --json, output { results, errors } so scripts can read per-file failures without parsing stderr]' \
149
+ '--itn[Rewrite spoken-form numbers, money, dates and times to written form ("two hundred thirty two" -> "232"). English-only; other languages pass through unchanged.]' \
150
+ '--include-errors[With --json or --toon, output { results, errors } so scripts can read per-file failures without parsing stderr]' \
144
151
  '--verbose[Show language detection details]' \
145
152
  '--format=[Output format: transcript | json | toon (long-form alias for --json / --toon)]:format:' \
146
153
  '--lang=[Expected language code, e.g. en or en-us (see docs/languages.md); warn if mismatch]:lang:' \
package/man/kesha.1 CHANGED
@@ -33,7 +33,7 @@ Print the kesha(1) manpage
33
33
  Run a Model Context Protocol server over stdio (transcribe_audio, synthesize_speech, list_voices, list_languages). Configure an MCP client with: { command: 'kesha', args: ['mcp'] }.
34
34
  .TP
35
35
  .B record
36
- Record microphone audio to a WAV file
36
+ Record microphone audio to a WAV file, or transcribe it live
37
37
  .TP
38
38
  .B say
39
39
  Synthesize speech from text (TTS). Writes audio to stdout (or \-\-out file). Defaults to WAV; use \-\-format ogg\-opus for messenger\-ready voice notes.
@@ -60,8 +60,11 @@ Include timestamped transcript segments in JSON/TOON output
60
60
  .B \-\-speakers
61
61
  Include speaker labels in segments. Needs \-\-json/\-\-toon and darwin\-arm64; run `kesha install \-\-diarize` first (it installs VAD too). Implies \-\-timestamps, and engages VAD windowing at any duration (so it cannot be combined with \-\-no\-vad).
62
62
  .TP
63
+ .B \-\-itn
64
+ Rewrite spoken\-form numbers, money, dates and times to written form ("two hundred thirty two" \-> "232"). English\-only; other languages pass through unchanged.
65
+ .TP
63
66
  .B \-\-include\-errors
64
- With \-\-json, output { results, errors } so scripts can read per\-file failures without parsing stderr
67
+ With \-\-json or \-\-toon, output { results, errors } so scripts can read per\-file failures without parsing stderr
65
68
  .TP
66
69
  .B \-\-verbose
67
70
  Show language detection details
@@ -153,9 +156,24 @@ Output status as JSON
153
156
  .B \-\-out
154
157
  Write recorded WAV audio to this path
155
158
  .TP
159
+ .B \-\-live
160
+ Transcribe the microphone live and print the transcript to stdout (CoreML on Apple Silicon only)
161
+ .TP
156
162
  .B \-\-max\-seconds
157
163
  Maximum recording duration in seconds
158
164
  .TP
165
+ .B \-\-auto\-stop
166
+ End a live recording after trailing silence (requires `kesha install \-\-vad`)
167
+ .TP
168
+ .B \-\-auto\-stop\-silence\-ms
169
+ Trailing silence before auto\-stop (default: 1000)
170
+ .TP
171
+ .B \-\-auto\-stop\-threshold
172
+ Silero speech threshold for auto\-stop (default: 0.5)
173
+ .TP
174
+ .B \-\-auto\-stop\-min\-speech\-ms
175
+ Minimum speech before auto\-stop may end a recording (default: 250)
176
+ .TP
159
177
  .B \-\-debug
160
178
  Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)
161
179
  .SS say
@@ -188,7 +206,7 @@ Opus bitrate in bits/sec (e.g. 32000). Only with \-\-format ogg\-opus.
188
206
  Opus encoder sample rate (8000/12000/16000/24000/48000). Only with \-\-format ogg\-opus.
189
207
  .TP
190
208
  .B \-\-no\-expand\-abbrev
191
- Disable Russian acronym auto\-expansion (ВОЗ → 'вэ о зэ') for ru\-vosk\-* voices. <say\-as interpret\-as='characters'> still works. Applies to Russian (ru\-vosk\-*) and English (en\-*) voices.
209
+ Disable acronym auto\-expansion on ru\-vosk\-* voices (ВОЗ → 'вэ о зэ') and English on ONNX engine builds (FBI → 'ef bee eye'). No effect on macOS arm64 FluidAudio, macos\-* or non\-English voices, which spell initialisms in their own G2P; the engine warns when the flag is ignored. <say\-as interpret\-as='characters'> still works.
192
210
  .TP
193
211
  .B \-\-verbose
194
212
  Log TTS synthesis time to stderr
package/model-plan.json CHANGED
@@ -15,9 +15,9 @@
15
15
  { "relPath": "models/silero-vad/silero_vad.onnx", "sizeBytes": 2327524 }
16
16
  ],
17
17
  "g2pCharsiu": [
18
- { "relPath": "models/g2p/byt5-tiny/encoder_model.onnx", "sizeBytes": 12478704 },
19
- { "relPath": "models/g2p/byt5-tiny/decoder_model.onnx", "sizeBytes": 11983268 },
20
- { "relPath": "models/g2p/byt5-tiny/decoder_with_past_model.onnx", "sizeBytes": 5427260 }
18
+ { "relPath": "models/g2p/byt5-tiny/encoder_model.onnx", "sizeBytes": 57234020 },
19
+ { "relPath": "models/g2p/byt5-tiny/decoder_model.onnx", "sizeBytes": 26118052 },
20
+ { "relPath": "models/g2p/byt5-tiny/decoder_with_past_model.onnx", "sizeBytes": 22960684 }
21
21
  ],
22
22
  "kokoroGraph": { "relPath": "models/kokoro-82m/model.onnx", "sizeBytes": 325532387 },
23
23
  "kokoroVoices": {
@@ -36,8 +36,8 @@
36
36
  ],
37
37
  "diarize": [
38
38
  { "relPath": "models/diarize/SortformerNvidiaLow_v2.mlpackage/Manifest.json", "sizeBytes": 617 },
39
- { "relPath": "models/diarize/SortformerNvidiaLow_v2.mlpackage/Data/com.apple.CoreML/model.mlmodel", "sizeBytes": 7080357 },
40
- { "relPath": "models/diarize/SortformerNvidiaLow_v2.mlpackage/Data/com.apple.CoreML/weights/0-weight.bin", "sizeBytes": 5930400 },
41
- { "relPath": "models/diarize/SortformerNvidiaLow_v2.mlpackage/Data/com.apple.CoreML/weights/1-weight.bin", "sizeBytes": 232161600 }
39
+ { "relPath": "models/diarize/SortformerNvidiaLow_v2.mlpackage/Data/com.apple.CoreML/model.mlmodel", "sizeBytes": 856521 },
40
+ { "relPath": "models/diarize/SortformerNvidiaLow_v2.mlpackage/Data/com.apple.CoreML/weights/0-weight.bin", "sizeBytes": 8948544 },
41
+ { "relPath": "models/diarize/SortformerNvidiaLow_v2.mlpackage/Data/com.apple.CoreML/weights/1-weight.bin", "sizeBytes": 235580992 }
42
42
  ]
43
43
  }
@@ -1,74 +1,36 @@
1
1
  // Kesha Voice Kit — OpenClaw plugin entry.
2
2
  //
3
- // Registers the locally-installed `kesha` CLI as an audio transcription
4
- // provider so OpenClaw routes voice messages from any connected channel
5
- // through Kesha (Parakeet TDT via CoreML on Apple Silicon, ONNX elsewhere).
6
- // 25 languages, no cloud, ~19x faster than Whisper.
3
+ // Declares the locally-installed `kesha` CLI as an audio media-understanding
4
+ // provider so it is discoverable in `openclaw plugins inspect`
5
+ // (Shape: plain-capability) — Parakeet TDT via CoreML on Apple Silicon, ONNX
6
+ // elsewhere, 25 languages, no cloud.
7
+ //
8
+ // This registration is declaration-only and does NOT transcribe. OpenClaw only
9
+ // routes audio to a media-understanding provider once model auth resolves for it
10
+ // (an API key), which a local, keyless CLI cannot satisfy on any sane config, so
11
+ // this provider is never selected to run. Real transcription is wired by the
12
+ // user through the documented `type: "cli"` entry in tools.media.audio.models,
13
+ // which runs `kesha {{MediaPath}}` directly and reads its stdout — see
14
+ // docs/openclaw.md and docs/runbooks/openclaw-plugin.md.
7
15
  //
8
16
  // The same `kesha` CLI also produces messenger-ready voice notes via
9
- // `kesha say "..." --format ogg-opus --out reply.ogg` (Telegram /
10
- // Discord ingest OGG/Opus directly — no transcoding needed). Not wired into
11
- // OpenClaw's media-understanding capability here; invoke it from a hook or
12
- // agent tool when you want Kesha to speak.
17
+ // `kesha say "..." --format ogg-opus --out reply.ogg` (Telegram / Discord ingest
18
+ // OGG/Opus directly — no transcoding needed). Not wired into OpenClaw's
19
+ // media-understanding capability here; invoke it from a hook or agent tool when
20
+ // you want Kesha to speak.
13
21
  //
14
22
  // Prerequisite: the `kesha` binary must be on PATH. Install it with:
15
23
  // bun add -g @drakulavich/kesha-voice-kit
16
24
  // kesha install # ASR models
17
25
  // kesha install --tts # TTS models (Kokoro + Vosk-TTS), only if you use `kesha say`
18
26
  //
19
- // The module specifier below is split across `+` on purpose — see the
20
- // OpenClaw skill-scanner rule "dangerous-exec" in
21
- // src/security/skill-scanner.ts. It gates on a per-file substring match,
22
- // and splitting the specifier keeps that substring out of this source so
23
- // the rule does not fire on this legitimate local-CLI wrapper.
24
- const { spawnSync } = require("node:child_" + "process");
25
- const fs = require("node:fs");
26
- const os = require("node:os");
27
- const path = require("node:path");
27
+ // Editing note: OpenClaw's `dangerous-exec` scanner is a naive per-file regex
28
+ // that also reads comments. Do not name the forbidden Node runtime module or a
29
+ // bare command-running call anywhere in this file — see
30
+ // docs/runbooks/openclaw-plugin.md.
28
31
 
29
- const DEFAULT_TIMEOUT_MS = 60_000;
30
32
  const MODEL_ID = "parakeet-tdt-0.6b-v3";
31
33
 
32
- function tempAudioPath(fileName) {
33
- const ext = (fileName && path.extname(fileName)) || ".ogg";
34
- return path.join(os.tmpdir(), `kesha-${process.pid}-${Date.now()}${ext}`);
35
- }
36
-
37
- async function transcribeAudio(req) {
38
- if (!req || !req.buffer) {
39
- return { text: "" };
40
- }
41
-
42
- const tmp = tempAudioPath(req.fileName);
43
- fs.writeFileSync(tmp, req.buffer);
44
-
45
- try {
46
- const result = spawnSync("kesha", ["--json", tmp], {
47
- encoding: "utf8",
48
- timeout: req.timeoutMs ?? DEFAULT_TIMEOUT_MS,
49
- });
50
-
51
- if (result.error || result.status !== 0) {
52
- return { text: "" };
53
- }
54
-
55
- const parsed = JSON.parse(result.stdout || "[]");
56
- const text = Array.isArray(parsed) && parsed[0] && typeof parsed[0].text === "string"
57
- ? parsed[0].text
58
- : "";
59
-
60
- return { text, model: MODEL_ID };
61
- } catch {
62
- return { text: "" };
63
- } finally {
64
- try {
65
- fs.unlinkSync(tmp);
66
- } catch {
67
- // best effort cleanup
68
- }
69
- }
70
- }
71
-
72
34
  module.exports = {
73
35
  id: "kesha-voice-kit",
74
36
  name: "Kesha Voice Kit",
@@ -78,7 +40,6 @@ module.exports = {
78
40
  capabilities: ["audio"],
79
41
  defaultModels: { audio: MODEL_ID },
80
42
  autoPriority: { audio: 50 },
81
- transcribeAudio,
82
43
  });
83
44
  },
84
45
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drakulavich/kesha-voice-kit",
3
- "version": "1.27.0",
3
+ "version": "1.28.0",
4
4
  "description": "Give your tools a voice — speech to text and back, 25 languages, up to ~19× faster than Whisper. On your machine.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -40,13 +40,14 @@
40
40
  }
41
41
  },
42
42
  "keshaEngine": {
43
- "version": "1.24.9"
43
+ "version": "1.24.10"
44
44
  },
45
45
  "scripts": {
46
46
  "test": "bun test --timeout 30000",
47
+ "conveyor": "bun scripts/backlog.ts",
47
48
  "test:watch": "bun test --timeout 30000 --watch",
48
49
  "test:unit": "bun test --timeout 30000 tests/unit/",
49
- "test:cli-fast": "bun test --timeout 30000 tests/unit/ tests/integration/cli-contracts.test.ts tests/integration/e2e-cli.test.ts tests/integration/say.test.ts",
50
+ "test:cli-fast": "bun test --timeout 30000 tests/unit/ tests/integration/cli-contracts.test.ts tests/integration/error-codes-cli.test.ts tests/integration/say.test.ts",
50
51
  "test:integration": "bun test --timeout 30000 tests/integration/",
51
52
  "coverage:ts": "bun run test:cli-fast --coverage --coverage-reporter=text --coverage-reporter=lcov --coverage-dir=coverage/ts",
52
53
  "coverage:check:ts": "bun .github/scripts/check-coverage.ts --preset=ts --lcov=coverage/ts/lcov.info --summary=coverage/ts/summary.md",
@@ -54,12 +55,14 @@
54
55
  "coverage:check:rust": "bun .github/scripts/check-coverage.ts --preset=rust --lcov=coverage/rust/lcov.info --summary=coverage/rust/summary.md",
55
56
  "generate:shell-artifacts": "bun scripts/generate-shell-artifacts.ts",
56
57
  "lint": "bunx tsc --noEmit",
57
- "check": "bun run lint && bun run check:versions && bun run test:cli-fast",
58
+ "check": "bun run lint && bun run check:versions && bun run check:recipes && bun run test:cli-fast",
58
59
  "check:workflows": "bun .github/scripts/check-workflows.ts",
60
+ "check:recipes": "bun .github/scripts/check-recipes.ts",
59
61
  "check:specs": "bunx @fission-ai/openspec@1.4.1 validate --specs --strict",
60
62
  "check:release-manifest": "bun .github/scripts/release-manifest.mjs --check",
61
63
  "check:versions": "bun .github/scripts/check-versions.ts",
62
- "check:engine-targets": "bun .github/scripts/check-engine-targets.ts"
64
+ "check:engine-targets": "bun .github/scripts/check-engine-targets.ts",
65
+ "mutants:ts": "bun scripts/mutants-ts.ts"
63
66
  },
64
67
  "keywords": [
65
68
  "asr",
@@ -87,6 +90,8 @@
87
90
  "bun": ">=1.3.0"
88
91
  },
89
92
  "devDependencies": {
93
+ "@hughescr/stryker-bun-runner": "^1.3.8",
94
+ "@stryker-mutator/core": "^9.6.1",
90
95
  "@types/bun": "latest",
91
96
  "fast-xml-parser": "^5.8.0",
92
97
  "typescript": "^7.0.2",
@@ -0,0 +1,20 @@
1
+ // Bun's `with { type: "text" }` imports; tsc has no loader for these extensions.
2
+ declare module "*.bash" {
3
+ const content: string;
4
+ export default content;
5
+ }
6
+
7
+ declare module "*.zsh" {
8
+ const content: string;
9
+ export default content;
10
+ }
11
+
12
+ declare module "*.fish" {
13
+ const content: string;
14
+ export default content;
15
+ }
16
+
17
+ declare module "*.1" {
18
+ const content: string;
19
+ export default content;
20
+ }