@drakulavich/kesha-voice-kit 1.0.0 → 1.0.3

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/README.md CHANGED
@@ -11,9 +11,9 @@
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>Open-source voice toolkit for Apple Silicon.</b><br>A collection of small, fast, open-source audio models — packaged as CLI tools and an <a href="https://github.com/openclaw/openclaw">OpenClaw</a> skill for LLM agents.</p>
14
+ <p align="center"><b>Open-source voice toolkit.</b> Optimized for Apple Silicon (CoreML), works on any platform (ONNX fallback).<br>A collection of small, fast, open-source audio models — packaged as CLI tools and an <a href="https://github.com/openclaw/openclaw">OpenClaw</a> skill for LLM agents.</p>
15
15
 
16
- - **Speech-to-text** — 25 languages, ~19x faster than Whisper on Apple Silicon
16
+ - **Speech-to-text** — 25 languages, ~19x faster than Whisper on Apple Silicon, ~2.5x on CPU
17
17
  - **Language detection** — 107 languages from audio, text language via NLLanguageRecognizer
18
18
  - **Rust engine** — single 20MB binary, no ffmpeg, no Python, no native Node addons
19
19
  - **OpenClaw-ready** — plug into your LLM agent as a voice processing skill
@@ -28,18 +28,16 @@ kesha audio.ogg # transcript to stdout
28
28
 
29
29
  ## OpenClaw Integration
30
30
 
31
- Kesha Voice Kit is built as a skill for [OpenClaw](https://github.com/openclaw/openclaw) — give your LLM agent ears. No API keys, everything runs locally on your machine.
31
+ Kesha Voice Kit ships as a plugin for [OpenClaw](https://github.com/openclaw/openclaw) — give your LLM agent ears. No API keys, everything runs locally on your machine.
32
32
 
33
- Add to your OpenClaw config:
33
+ **Install the plugin** (requires the `kesha` CLI — see [Quick Start](#quick-start)):
34
34
 
35
- ```json
36
- {
37
- "type": "cli",
38
- "command": "kesha",
39
- "args": ["--json", "{{MediaPath}}"]
40
- }
35
+ ```bash
36
+ openclaw plugins install @drakulavich/kesha-voice-kit
41
37
  ```
42
38
 
39
+ OpenClaw fetches the package from npm, auto-detects [`openclaw.plugin.json`](./openclaw.plugin.json), and wires `kesha --json {{MediaPath}}` as the audio transcription backend under `tools.media.audio`. Manage it afterwards with `openclaw plugins list`, `openclaw plugins disable kesha-voice-kit`, or `openclaw plugins uninstall kesha-voice-kit`.
40
+
43
41
  Your agent receives a voice message in Telegram/WhatsApp/Slack. Kesha transcribes it locally, detects the language, and returns structured JSON:
44
42
 
45
43
  ```json
@@ -0,0 +1,14 @@
1
+ // OpenClaw plugin entry stub for Kesha Voice Kit.
2
+ //
3
+ // The actual wiring lives in openclaw.plugin.json's configPatch, which
4
+ // installs `kesha --json {{MediaPath}}` under tools.media.audio. This
5
+ // file exists only to satisfy OpenClaw's requirement that native
6
+ // plugins declare at least one JavaScript extension in
7
+ // package.json#openclaw.extensions — Kesha has no hooks, tools, or
8
+ // services to register beyond the config patch itself.
9
+ export default {
10
+ id: "kesha-voice-kit",
11
+ register() {
12
+ // intentionally empty — see openclaw.plugin.json
13
+ },
14
+ };
@@ -2,6 +2,7 @@
2
2
  "name": "kesha-voice-kit",
3
3
  "displayName": "Kesha Voice Kit",
4
4
  "description": "Local speech-to-text for voice messages. 25 languages, ~19x faster than Whisper on Apple Silicon. Drop-in replacement for openai-whisper.",
5
+ "configSchema": {},
5
6
  "configPatch": {
6
7
  "tools": {
7
8
  "media": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drakulavich/kesha-voice-kit",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "Open-source voice toolkit for Apple Silicon. Speech-to-text, language detection. 25 languages.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,11 +17,20 @@
17
17
  "package.json",
18
18
  "tsconfig.json",
19
19
  "openclaw.plugin.json",
20
+ "openclaw-plugin.js",
20
21
  "SKILL.md",
21
22
  "scripts/postinstall.cjs",
22
23
  "LICENSE",
23
24
  "README.md"
24
25
  ],
26
+ "openclaw": {
27
+ "extensions": [
28
+ "./openclaw-plugin.js"
29
+ ]
30
+ },
31
+ "keshaEngine": {
32
+ "version": "1.0.2"
33
+ },
25
34
  "scripts": {
26
35
  "test": "bun test",
27
36
  "test:unit": "bun test tests/unit/",
@@ -1,6 +1,6 @@
1
1
  import { dirname } from "path";
2
2
  import { existsSync, mkdirSync, chmodSync } from "fs";
3
- import { getEngineBinPath } from "./engine";
3
+ import { getEngineBinPath, getEngineCapabilities } from "./engine";
4
4
  import { log } from "./log";
5
5
  import { streamResponseToFile } from "./progress";
6
6
 
@@ -25,8 +25,16 @@ export async function downloadEngine(noCache = false, backend?: string): Promise
25
25
  } else {
26
26
  const binaryName = getEngineBinaryName();
27
27
  const pkg = await Bun.file(new URL("../package.json", import.meta.url)).json();
28
- const version = typeof pkg.version === "string" ? pkg.version : "unknown";
29
- const url = `https://github.com/${GITHUB_REPO}/releases/download/v${version}/${binaryName}`;
28
+ // The engine version is tracked separately from the CLI version so
29
+ // CLI-only patch releases don't require cutting a new GitHub release
30
+ // + Rust rebuild. Fall back to the CLI version for backwards compat.
31
+ const engineVersion =
32
+ typeof pkg.keshaEngine?.version === "string"
33
+ ? pkg.keshaEngine.version
34
+ : typeof pkg.version === "string"
35
+ ? pkg.version
36
+ : "unknown";
37
+ const url = `https://github.com/${GITHUB_REPO}/releases/download/v${engineVersion}/${binaryName}`;
30
38
 
31
39
  mkdirSync(dirname(binPath), { recursive: true });
32
40
 
@@ -50,8 +58,17 @@ export async function downloadEngine(noCache = false, backend?: string): Promise
50
58
  log.success("Engine binary downloaded.");
51
59
  }
52
60
 
61
+ if (backend) {
62
+ const caps = await getEngineCapabilities();
63
+ if (caps && caps.backend !== backend) {
64
+ throw new Error(
65
+ `Requested backend "${backend}" is not available: the installed engine for this platform uses "${caps.backend}".\n Fix: omit --${backend} to use the auto-detected backend, or run on a platform that ships the "${backend}" build.`,
66
+ );
67
+ }
68
+ }
69
+
53
70
  log.progress("Installing models...");
54
- const installArgs = ["install", ...(noCache ? ["--no-cache"] : []), ...(backend ? [`--backend=${backend}`] : [])];
71
+ const installArgs = ["install", ...(noCache ? ["--no-cache"] : [])];
55
72
  const proc = Bun.spawnSync([binPath, ...installArgs], {
56
73
  stdout: "pipe",
57
74
  stderr: "pipe",