@drakulavich/kesha-voice-kit 1.24.2 → 1.24.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drakulavich/kesha-voice-kit",
3
- "version": "1.24.2",
3
+ "version": "1.24.4",
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": {
@@ -38,7 +38,7 @@
38
38
  }
39
39
  },
40
40
  "keshaEngine": {
41
- "version": "1.24.2"
41
+ "version": "1.24.4"
42
42
  },
43
43
  "scripts": {
44
44
  "test": "bun test",
@@ -99,5 +99,8 @@
99
99
  "picocolors": "^1.1.1",
100
100
  "tinyld": "^1.3.4",
101
101
  "zod": "^4.4.3"
102
+ },
103
+ "overrides": {
104
+ "hono": "^4.12.25"
102
105
  }
103
106
  }
@@ -46,9 +46,7 @@ function isFalsey(v: string): boolean {
46
46
  return FALSEY_VALUES.has(v.trim().toLowerCase());
47
47
  }
48
48
 
49
- // Whether the process was launched with NO_COLOR already forced on. Captured
50
- // once at import (before any runCli) so re-enabling colors never clobbers an
51
- // externally-set NO_COLOR — we only clear the var on re-enable when WE set it.
49
+ // Captured at import so re-enabling colors never clobbers a user-exported NO_COLOR.
52
50
  const USER_FORCED_NO_COLOR =
53
51
  process.env.NO_COLOR !== undefined && !isFalsey(process.env.NO_COLOR);
54
52
 
@@ -105,47 +103,72 @@ export function resolveQuietMode(rawArgs: string[]): { quiet: boolean; rawArgs:
105
103
  return { quiet: value, rawArgs: cleaned };
106
104
  }
107
105
 
108
- export async function runCli(rawArgs = process.argv.slice(2)): Promise<void> {
109
- // Global flags resolved before citty so they apply to every command (and help
110
- // output) and never reach a subcommand's arg schema.
111
- const color = resolveColorMode(rawArgs);
112
- // Reset on EVERY invocation (not just the disable path): an earlier
113
- // --no-color / CI call must not leave colors permanently off for later
114
- // in-process calls (unit tests, `kesha mcp`). picocolors already honors
115
- // NO_COLOR at startup; setting the env var also propagates to the engine.
116
- setColorEnabled(!color.disableColor);
117
- // Keep NO_COLOR symmetric so it doesn't leak to engine subprocesses spawned
118
- // by a later in-process call: set it when WE disable, clear it on re-enable —
119
- // but never clear a NO_COLOR the user exported themselves.
120
- if (color.disableColor) {
106
+ /**
107
+ * Sync NO_COLOR with the resolved color decision so engine subprocesses inherit
108
+ * the right value. Separated from setColorEnabled so it can be tested without
109
+ * picocolors side-effects.
110
+ *
111
+ * Never clears a NO_COLOR the user exported before this process started
112
+ * (USER_FORCED_NO_COLOR guard).
113
+ */
114
+ export function applyColorEnv(disableColor: boolean): void {
115
+ if (disableColor) {
121
116
  process.env.NO_COLOR = "1";
122
117
  } else if (!USER_FORCED_NO_COLOR) {
123
118
  delete process.env.NO_COLOR;
124
119
  }
120
+ }
121
+
122
+ /**
123
+ * Classify the first positional arg for routing.
124
+ *
125
+ * - `"subcommand"` — exact match in the known subcommand set
126
+ * - `"unknown"` — bare token that looks like a typo (not a flag, not path-like)
127
+ * - `"main"` — flags, path-like args, or no arg (→ transcribe / help)
128
+ */
129
+ export function classifyFirstArg(
130
+ firstArg: string | undefined,
131
+ subcommandKeys: string[],
132
+ ): "subcommand" | "unknown" | "main" {
133
+ if (!firstArg) return "main";
134
+ if (subcommandKeys.includes(firstArg)) return "subcommand";
135
+ // Flags and path-like tokens fall through to the main transcribe command.
136
+ if (firstArg.startsWith("-") || isPathLike(firstArg)) return "main";
137
+ return "unknown";
138
+ }
139
+
140
+ export async function runCli(rawArgs = process.argv.slice(2)): Promise<void> {
141
+ // Global flags resolved before citty so they apply to every command and never reach a subcommand's arg schema.
142
+ const color = resolveColorMode(rawArgs);
143
+ // Reset on every invocation so an earlier --no-color/CI call doesn't leave colors off for later in-process calls (unit tests, `kesha mcp`).
144
+ setColorEnabled(!color.disableColor);
145
+ applyColorEnv(color.disableColor);
125
146
 
126
147
  const quiet = resolveQuietMode(color.rawArgs);
127
148
  log.quietEnabled = quiet.quiet;
128
149
 
129
150
  rawArgs = quiet.rawArgs;
130
151
  const [firstArg, ...restArgs] = rawArgs;
152
+ const subcommandKeys = Object.keys(SUBCOMMANDS);
131
153
 
132
- if (firstArg && Object.hasOwn(SUBCOMMANDS, firstArg)) {
133
- await runMain(SUBCOMMANDS[firstArg], { rawArgs: restArgs });
134
- return;
135
- }
154
+ switch (classifyFirstArg(firstArg, subcommandKeys)) {
155
+ case "subcommand":
156
+ await runMain(SUBCOMMANDS[firstArg!], { rawArgs: restArgs });
157
+ return;
136
158
 
137
- // Check for unknown subcommands (non-flag, non-file-path args).
138
- // Extensionless existing files remain valid transcription inputs; missing
139
- // bare tokens are more likely command typos and should not start the engine.
140
- if (firstArg && !firstArg.startsWith("-") && !isPathLike(firstArg)) {
141
- const suggestion = suggestCommand(firstArg, Object.keys(SUBCOMMANDS));
142
- log.error(`unknown command '${firstArg}'`);
143
- if (suggestion && suggestion !== firstArg) {
144
- log.warn(`(Did you mean ${suggestion}?)`);
159
+ case "unknown": {
160
+ // Extensionless existing files are valid transcription inputs; bare non-path tokens are likely command typos.
161
+ const suggestion = suggestCommand(firstArg!, subcommandKeys);
162
+ log.error(`unknown command '${firstArg}'`);
163
+ if (suggestion && suggestion !== firstArg) {
164
+ log.warn(`(Did you mean ${suggestion}?)`);
165
+ }
166
+ log.warn(`If this is an audio file, pass a path like './${firstArg}'.`);
167
+ process.exit(1);
168
+ break;
145
169
  }
146
- log.warn(`If this is an audio file, pass a path like './${firstArg}'.`);
147
- process.exit(1);
148
- }
149
170
 
150
- await runMain(mainCommand, { rawArgs });
171
+ default:
172
+ await runMain(mainCommand, { rawArgs });
173
+ }
151
174
  }
package/src/cli/init.ts CHANGED
@@ -5,12 +5,8 @@ import { multiselect, isCancel, cancel } from "@clack/prompts";
5
5
  import { renderInstallPlan } from "../install-plan";
6
6
  import { log } from "../log";
7
7
  import { getEngineCapabilities } from "../engine";
8
- import {
9
- performInstall,
10
- resolveBackendFlag,
11
- resolveNoCacheFlag,
12
- TTS_LANG_FALLBACK,
13
- } from "./install";
8
+ import { performInstall, resolveBackendFlag, resolveNoCacheFlag, TTS_LANG_FALLBACK } from "./install";
9
+ import type { SharedInstallArgs } from "./types";
14
10
 
15
11
  const TTS_LANG_LABELS: Record<string, string> = {
16
12
  en: "English (Kokoro)",
@@ -44,16 +40,7 @@ async function promptTtsLangs(preselect: string[]): Promise<string[]> {
44
40
  return selected as string[];
45
41
  }
46
42
 
47
- export interface InitCommandArgs {
48
- coreml: boolean;
49
- onnx: boolean;
50
- "no-cache": boolean;
51
- noCache?: boolean;
52
- no_cache?: boolean;
53
- tts: boolean;
54
- vad: boolean;
55
- diarize: boolean;
56
- plan: boolean;
43
+ export interface InitCommandArgs extends SharedInstallArgs {
57
44
  yes: boolean;
58
45
  }
59
46
 
@@ -7,19 +7,11 @@ import { maybeAskForStar } from "../star";
7
7
  import { log } from "../log";
8
8
  import { packageVersion } from "../package-info";
9
9
  import { createDiagnosticLogSession, type DiagnosticLogSession } from "../diagnostic-log";
10
+ import type { SharedInstallArgs } from "./types";
10
11
 
11
- export interface InstallCommandArgs {
12
+ export interface InstallCommandArgs extends SharedInstallArgs {
12
13
  /** Positional args after `install` — candidate TTS language codes. */
13
14
  _?: string[];
14
- coreml: boolean;
15
- onnx: boolean;
16
- "no-cache": boolean;
17
- noCache?: boolean;
18
- no_cache?: boolean;
19
- tts: boolean;
20
- vad: boolean;
21
- diarize: boolean;
22
- plan: boolean;
23
15
  }
24
16
 
25
17
  /**
@@ -30,9 +22,7 @@ export interface InstallCommandArgs {
30
22
  export const TTS_LANG_FALLBACK = ["en", "es", "fr", "it", "pt", "ru"];
31
23
 
32
24
  export interface TtsArgInput {
33
- /** Whether --tts was passed. */
34
25
  tts: boolean;
35
- /** Positional args after the install command (candidate language codes). */
36
26
  positionals: string[];
37
27
  }
38
28