@moxxy/plugin-stt-whisper 0.28.0 → 0.29.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.
@@ -1 +1 @@
1
- {"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../src/audio.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD;;;;;iEAKiE;AACjE,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAElC;;;;;;;;;0EAS0E;AAC1E,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYlE,CAAC;AAEL,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,UAAU,GAAG,WAAW,EAC/B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,cAAc,CAAC,EAAE,MAAM,GACtB,qBAAqB,CA8BvB;AAWD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,GAAG,WAAW,EAAE,UAAU,SAAS,GAAG,UAAU,CAgC7F"}
1
+ {"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../src/audio.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAiB,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEnE;;;;;iEAKiE;AACjE,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAElC;;;;;;;;;0EAS0E;AAC1E,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYlE,CAAC;AAEL,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,UAAU,GAAG,WAAW,EAC/B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,cAAc,CAAC,EAAE,MAAM,GACtB,qBAAqB,CAgCvB;AAWD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,GAAG,WAAW,EAAE,UAAU,SAAS,GAAG,UAAU,CAgC7F"}
package/dist/audio.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * (filename inference from MIME, raw PCM16 → WAV wrapping). Centralizing
6
6
  * them here keeps the wrapper plugins thin.
7
7
  */
8
- import { MOXXY_PCM16_24KHZ_MIME } from '@moxxy/sdk';
8
+ import { assertDefined, MOXXY_PCM16_24KHZ_MIME } from '@moxxy/sdk';
9
9
  /** A custom MIME tag used by the TUI voice recorder to flag raw PCM16
10
10
  * mono @ 24kHz bytes (ffmpeg's `-f s16le` output) so the transcriber
11
11
  * knows to wrap them in a WAV header before upload. Public so other
@@ -61,7 +61,9 @@ export function normalizeWhisperUpload(audio, mimeType, filenamePrefix) {
61
61
  // Guard the runtime type so `.toLowerCase()` can't throw on hostile input —
62
62
  // anything non-string degrades to the default rather than crashing the path.
63
63
  const rawMime = typeof mimeType === 'string' ? mimeType : '';
64
- const mt = (rawMime || 'audio/wav').toLowerCase().split(';')[0].trim();
64
+ const firstSegment = (rawMime || 'audio/wav').toLowerCase().split(';')[0];
65
+ assertDefined(firstSegment, 'String.split always yields at least one element');
66
+ const mt = firstSegment.trim();
65
67
  if (mt === MOXXY_PCM16_24KHZ_MIME) {
66
68
  return {
67
69
  bytes: pcm16MonoToWav(bytes, 24_000),
package/dist/audio.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"audio.js","sourceRoot":"","sources":["../src/audio.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"audio.js","sourceRoot":"","sources":["../src/audio.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moxxy/plugin-stt-whisper",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "OpenAI Whisper Transcriber for moxxy. Audio bytes → text + segments. Plugs into the session's TranscriberRegistry; channels with audio input (Telegram voice, HTTP multipart) consume it transparently.",
5
5
  "keywords": [
6
6
  "moxxy",
@@ -44,14 +44,14 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "openai": "^4.80.0",
47
- "@moxxy/sdk": "0.28.0"
47
+ "@moxxy/sdk": "0.29.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/node": "^22.10.0",
51
51
  "typescript": "^5.7.3",
52
52
  "vitest": "^2.1.8",
53
- "@moxxy/vitest-preset": "0.0.0",
54
- "@moxxy/tsconfig": "0.0.0"
53
+ "@moxxy/tsconfig": "0.0.0",
54
+ "@moxxy/vitest-preset": "0.0.0"
55
55
  },
56
56
  "scripts": {
57
57
  "build": "tsc -p tsconfig.json",
package/src/audio.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * them here keeps the wrapper plugins thin.
7
7
  */
8
8
 
9
- import { MOXXY_PCM16_24KHZ_MIME } from '@moxxy/sdk';
9
+ import { assertDefined, MOXXY_PCM16_24KHZ_MIME } from '@moxxy/sdk';
10
10
 
11
11
  /** A custom MIME tag used by the TUI voice recorder to flag raw PCM16
12
12
  * mono @ 24kHz bytes (ffmpeg's `-f s16le` output) so the transcriber
@@ -75,7 +75,9 @@ export function normalizeWhisperUpload(
75
75
  // Guard the runtime type so `.toLowerCase()` can't throw on hostile input —
76
76
  // anything non-string degrades to the default rather than crashing the path.
77
77
  const rawMime = typeof mimeType === 'string' ? mimeType : '';
78
- const mt = (rawMime || 'audio/wav').toLowerCase().split(';')[0]!.trim();
78
+ const firstSegment = (rawMime || 'audio/wav').toLowerCase().split(';')[0];
79
+ assertDefined(firstSegment, 'String.split always yields at least one element');
80
+ const mt = firstSegment.trim();
79
81
  if (mt === MOXXY_PCM16_24KHZ_MIME) {
80
82
  return {
81
83
  bytes: pcm16MonoToWav(bytes, 24_000),
@@ -4,6 +4,7 @@ import { APIError, APIConnectionError, APIUserAbortError } from 'openai';
4
4
  import { WhisperTranscriber } from './whisper.js';
5
5
  import { buildWhisperPlugin } from './index.js';
6
6
  import { MOXXY_PCM16_24KHZ_MIME, normalizeWhisperUpload, pcm16MonoToWav } from './audio.js';
7
+ import { assertDefined } from '@moxxy/sdk';
7
8
 
8
9
  const fakeOpenAI = (impl: (req: unknown) => unknown): OpenAI =>
9
10
  ({
@@ -52,7 +53,9 @@ describe('WhisperTranscriber', () => {
52
53
  const client = { audio: { transcriptions: { create } } } as unknown as OpenAI;
53
54
  const t = new WhisperTranscriber({ client, language: 'pl' });
54
55
  await t.transcribe(new Uint8Array(), { mimeType: 'audio/ogg', prompt: 'jargon-list' });
55
- const req = create.mock.calls[0]![0] as { language: string; prompt: string; response_format: string };
56
+ const call = create.mock.calls[0];
57
+ assertDefined(call, 'transcribe invokes the OpenAI create() exactly once');
58
+ const req = call[0] as { language: string; prompt: string; response_format: string };
56
59
  expect(req.language).toBe('pl');
57
60
  expect(req.prompt).toBe('jargon-list');
58
61
  expect(req.response_format).toBe('verbose_json');
@@ -63,7 +66,9 @@ describe('WhisperTranscriber', () => {
63
66
  const client = { audio: { transcriptions: { create } } } as unknown as OpenAI;
64
67
  const t = new WhisperTranscriber({ client, language: 'pl' });
65
68
  await t.transcribe(new Uint8Array(), { language: 'en' });
66
- const req = create.mock.calls[0]![0] as { language: string };
69
+ const call = create.mock.calls[0];
70
+ assertDefined(call, 'transcribe invokes the OpenAI create() exactly once');
71
+ const req = call[0] as { language: string };
67
72
  expect(req.language).toBe('en');
68
73
  });
69
74
 
@@ -73,14 +78,19 @@ describe('WhisperTranscriber', () => {
73
78
  const t = new WhisperTranscriber({ client, model: 'gpt-4o-transcribe' });
74
79
  const out = await t.transcribe(new Uint8Array(), { mimeType: 'audio/wav' });
75
80
  expect(out.text).toBe('plain');
76
- const req = create.mock.calls[0]![0] as { response_format?: string };
81
+ const call = create.mock.calls[0];
82
+ assertDefined(call, 'transcribe invokes the OpenAI create() exactly once');
83
+ const req = call[0] as { response_format?: string };
77
84
  expect(req.response_format).toBeUndefined();
78
85
  });
79
86
 
80
87
  it('plugin registers a transcriber whose createClient yields the right name', () => {
81
88
  const plugin = buildWhisperPlugin({});
82
89
  expect(plugin.transcribers).toHaveLength(1);
83
- const def = plugin.transcribers![0]!;
90
+ const transcribers = plugin.transcribers;
91
+ assertDefined(transcribers, 'buildWhisperPlugin always registers transcribers');
92
+ const def = transcribers[0];
93
+ assertDefined(def, 'the plugin registers at least one transcriber');
84
94
  expect(def.name).toBe('openai-whisper-1');
85
95
  expect(def.displayName).toBe('OpenAI whisper-1');
86
96
  const inst = def.createClient({ apiKey: 'sk-test' });
@@ -95,7 +105,9 @@ describe('WhisperTranscriber', () => {
95
105
  const raw = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]);
96
106
  await t.transcribe(raw, { mimeType: MOXXY_PCM16_24KHZ_MIME });
97
107
 
98
- const req = create.mock.calls[0]![0] as { file: File };
108
+ const call = create.mock.calls[0];
109
+ assertDefined(call, 'transcribe invokes the OpenAI create() exactly once');
110
+ const req = call[0] as { file: File };
99
111
  expect(req.file.type).toBe('audio/wav');
100
112
  const header = new Uint8Array(await req.file.arrayBuffer());
101
113
  const ascii = (s: number, e: number): string =>
@@ -108,7 +120,11 @@ describe('WhisperTranscriber', () => {
108
120
 
109
121
  it('plugin honors a non-default model name', () => {
110
122
  const plugin = buildWhisperPlugin({ model: 'gpt-4o-mini-transcribe' });
111
- expect(plugin.transcribers![0]!.name).toBe('openai-gpt-4o-mini-transcribe');
123
+ const transcribers = plugin.transcribers;
124
+ assertDefined(transcribers, 'buildWhisperPlugin always registers transcribers');
125
+ const def = transcribers[0];
126
+ assertDefined(def, 'the plugin registers at least one transcriber');
127
+ expect(def.name).toBe('openai-gpt-4o-mini-transcribe');
112
128
  });
113
129
 
114
130
  it('throws PROVIDER_UNKNOWN_RESPONSE when verbose_json lacks a string text', async () => {
@@ -180,7 +196,9 @@ describe('WhisperTranscriber', () => {
180
196
  mimeType: 123 as unknown as string,
181
197
  });
182
198
  expect(result.text).toBe('ok');
183
- const req = create.mock.calls[0]![0] as { file: File };
199
+ const call = create.mock.calls[0];
200
+ assertDefined(call, 'transcribe invokes the OpenAI create() exactly once');
201
+ const req = call[0] as { file: File };
184
202
  // Defaults to the audio/wav fallback filename rather than crashing.
185
203
  expect(req.file.name).toBe('audio.wav');
186
204
  });