klaudio 0.12.1 → 0.12.2

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": "klaudio",
3
- "version": "0.12.1",
3
+ "version": "0.12.2",
4
4
  "description": "Add sound effects to your coding sessions — play sounds when tasks complete, notifications arrive, and more",
5
5
  "type": "module",
6
6
  "bin": {
package/src/installer.js CHANGED
@@ -1,9 +1,13 @@
1
1
  import { readFile, writeFile, mkdir, copyFile } from "node:fs/promises";
2
2
  import { join, basename, extname } from "node:path";
3
3
  import { homedir } from "node:os";
4
+ import { createRequire } from "node:module";
4
5
  import { getHookPlayCommand, processSound } from "./player.js";
5
6
  import { EVENTS } from "./presets.js";
6
7
 
8
+ const _require = createRequire(import.meta.url);
9
+ const KLAUDIO_VERSION = _require("../package.json").version;
10
+
7
11
  /**
8
12
  * Get the target directory based on install scope.
9
13
  */
@@ -84,6 +88,7 @@ export async function install({ scope, sounds, tts = false, voice } = {}) {
84
88
  // Add our hook
85
89
  settings.hooks[hookEvent].push({
86
90
  _klaudio: true,
91
+ _klaudioVersion: KLAUDIO_VERSION,
87
92
  matcher: "",
88
93
  hooks: [
89
94
  {
@@ -253,7 +258,8 @@ export async function getExistingSounds(scope) {
253
258
  const hookEntries = settings.hooks[event.hookEvent];
254
259
  if (!hookEntries) continue;
255
260
  const entry = hookEntries.find((e) => e._klaudio || e._klonk
256
- || e.hooks?.[0]?.command?.includes("klaudio"));
261
+ || e.hooks?.[0]?.command?.includes("klaudio")
262
+ || e.hooks?.[0]?.command?.includes(".claude/sounds/"));
257
263
  if (!entry?.hooks?.[0]?.command) continue;
258
264
 
259
265
  // Extract file path from the play command
@@ -283,16 +289,30 @@ export async function checkHooksOutdated(scope) {
283
289
  const settings = JSON.parse(existing);
284
290
  if (!settings.hooks) return reasons;
285
291
 
292
+ const isOurs = (e) => e._klaudio || e._klonk || e.hooks?.[0]?.command?.includes("klaudio") || e.hooks?.[0]?.command?.includes(".claude/sounds/");
293
+
294
+ // Check if any klaudio hook was installed with an older version
295
+ const allKlaudioHooks = Object.values(settings.hooks).flat().filter(isOurs);
296
+ if (allKlaudioHooks.length > 0) {
297
+ const hasVersionMismatch = allKlaudioHooks.some((e) => e._klaudioVersion !== KLAUDIO_VERSION);
298
+ if (hasVersionMismatch) {
299
+ const installedVer = allKlaudioHooks.find((e) => e._klaudioVersion)?._klaudioVersion;
300
+ reasons.push(installedVer
301
+ ? `Hooks from v${installedVer} → v${KLAUDIO_VERSION}`
302
+ : `Hooks need update to v${KLAUDIO_VERSION}`);
303
+ }
304
+ }
305
+
286
306
  // Check Stop hook for --notify flag
287
307
  const stopEntries = settings.hooks.Stop || [];
288
- const stopHook = stopEntries.find((e) => e._klaudio || e.hooks?.[0]?.command?.includes("klaudio"));
308
+ const stopHook = stopEntries.find(isOurs);
289
309
  if (stopHook?.hooks?.[0]?.command && !stopHook.hooks[0].command.includes("--notify")) {
290
310
  reasons.push("System notifications on task complete");
291
311
  }
292
312
 
293
313
  // Check Notification hook for --notify flag
294
314
  const notifEntries = settings.hooks.Notification || [];
295
- const notifHook = notifEntries.find((e) => e._klaudio || e.hooks?.[0]?.command?.includes("klaudio"));
315
+ const notifHook = notifEntries.find(isOurs);
296
316
  if (notifHook?.hooks?.[0]?.command && !notifHook.hooks[0].command.includes("--notify")) {
297
317
  reasons.push("System notifications on background task");
298
318
  }
@@ -336,7 +356,7 @@ export async function uninstall(scope) {
336
356
  if (settings.hooks) {
337
357
  for (const [event, entries] of Object.entries(settings.hooks)) {
338
358
  settings.hooks[event] = entries.filter(
339
- (entry) => !entry._klaudio && !entry._klonk
359
+ (entry) => !entry._klaudio && !entry._klonk && !entry.hooks?.[0]?.command?.includes(".claude/sounds/")
340
360
  );
341
361
  if (settings.hooks[event].length === 0) {
342
362
  delete settings.hooks[event];
package/src/tts.js CHANGED
@@ -375,11 +375,14 @@ export async function speak(text, options = {}) {
375
375
  : options;
376
376
 
377
377
  // Try Kokoro first (works on all platforms, best quality)
378
- try {
379
- await speakKokoro(text, voice);
380
- return;
381
- } catch {
382
- // Kokoro unavailable — fall through
378
+ // Check availability first to avoid loading native module that may crash
379
+ if (await isKokoroAvailable()) {
380
+ try {
381
+ await speakKokoro(text, voice);
382
+ return;
383
+ } catch {
384
+ // Kokoro failed at runtime — fall through
385
+ }
383
386
  }
384
387
 
385
388
  // macOS: use built-in `say`