@tryhamster/gerbil 1.0.0-rc.0 → 1.0.0-rc.1

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 (94) hide show
  1. package/README.md +79 -14
  2. package/dist/auto-update-DsWBBnEk.mjs +3 -0
  3. package/dist/browser/index.d.mts +401 -5
  4. package/dist/browser/index.d.mts.map +1 -1
  5. package/dist/browser/index.mjs +1772 -146
  6. package/dist/browser/index.mjs.map +1 -1
  7. package/dist/{chrome-backend-CtwPENIW.mjs → chrome-backend-JEPeM2YE.mjs} +1 -1
  8. package/dist/{chrome-backend-C5Un08O4.mjs → chrome-backend-Y9F7W5VQ.mjs} +514 -73
  9. package/dist/chrome-backend-Y9F7W5VQ.mjs.map +1 -0
  10. package/dist/cli.mjs +3359 -646
  11. package/dist/cli.mjs.map +1 -1
  12. package/dist/frameworks/express.d.mts +1 -1
  13. package/dist/frameworks/express.mjs +3 -3
  14. package/dist/frameworks/fastify.d.mts +1 -1
  15. package/dist/frameworks/fastify.mjs +3 -3
  16. package/dist/frameworks/hono.d.mts +1 -1
  17. package/dist/frameworks/hono.mjs +3 -3
  18. package/dist/frameworks/next.d.mts +2 -2
  19. package/dist/frameworks/next.mjs +3 -3
  20. package/dist/frameworks/react.d.mts +1 -1
  21. package/dist/frameworks/trpc.d.mts +1 -1
  22. package/dist/frameworks/trpc.mjs +3 -3
  23. package/dist/gerbil-DeQlX_Mt.mjs +5 -0
  24. package/dist/gerbil-POAz8peb.d.mts +431 -0
  25. package/dist/gerbil-POAz8peb.d.mts.map +1 -0
  26. package/dist/gerbil-yoSpRHgv.mjs +1463 -0
  27. package/dist/gerbil-yoSpRHgv.mjs.map +1 -0
  28. package/dist/index.d.mts +395 -9
  29. package/dist/index.d.mts.map +1 -1
  30. package/dist/index.mjs +8 -6
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/integrations/ai-sdk.d.mts +122 -4
  33. package/dist/integrations/ai-sdk.d.mts.map +1 -1
  34. package/dist/integrations/ai-sdk.mjs +239 -11
  35. package/dist/integrations/ai-sdk.mjs.map +1 -1
  36. package/dist/integrations/langchain.d.mts +132 -2
  37. package/dist/integrations/langchain.d.mts.map +1 -1
  38. package/dist/integrations/langchain.mjs +176 -8
  39. package/dist/integrations/langchain.mjs.map +1 -1
  40. package/dist/integrations/llamaindex.d.mts +1 -1
  41. package/dist/integrations/llamaindex.mjs +3 -3
  42. package/dist/integrations/mcp-client.mjs +4 -4
  43. package/dist/integrations/mcp-client.mjs.map +1 -1
  44. package/dist/integrations/mcp.d.mts +2 -2
  45. package/dist/integrations/mcp.d.mts.map +1 -1
  46. package/dist/integrations/mcp.mjs +6 -6
  47. package/dist/{mcp-R8kRLIKb.mjs → mcp-Bitg4sjX.mjs} +10 -37
  48. package/dist/mcp-Bitg4sjX.mjs.map +1 -0
  49. package/dist/microphone-D-6y9aiE.mjs +3 -0
  50. package/dist/{models-DKULvhOr.mjs → models-BAtL8qsA.mjs} +42 -7
  51. package/dist/models-BAtL8qsA.mjs.map +1 -0
  52. package/dist/{models-De2-_GmQ.d.mts → models-CE0fBq0U.d.mts} +2 -2
  53. package/dist/models-CE0fBq0U.d.mts.map +1 -0
  54. package/dist/{one-liner-BUQR0nqq.mjs → one-liner-B1rmFto6.mjs} +2 -2
  55. package/dist/{one-liner-BUQR0nqq.mjs.map → one-liner-B1rmFto6.mjs.map} +1 -1
  56. package/dist/repl-D20JO260.mjs +10 -0
  57. package/dist/skills/index.d.mts +303 -12
  58. package/dist/skills/index.d.mts.map +1 -1
  59. package/dist/skills/index.mjs +6 -6
  60. package/dist/skills-5DxAV-rn.mjs +1435 -0
  61. package/dist/skills-5DxAV-rn.mjs.map +1 -0
  62. package/dist/stt-Bv_dum-R.mjs +433 -0
  63. package/dist/stt-Bv_dum-R.mjs.map +1 -0
  64. package/dist/stt-KzSoNvwI.mjs +3 -0
  65. package/dist/{tools-BsiEE6f2.mjs → tools-IYPrqoek.mjs} +6 -7
  66. package/dist/{tools-BsiEE6f2.mjs.map → tools-IYPrqoek.mjs.map} +1 -1
  67. package/dist/tts-5yWeP_I0.mjs +3 -0
  68. package/dist/tts-DG6denWG.mjs +729 -0
  69. package/dist/tts-DG6denWG.mjs.map +1 -0
  70. package/dist/types-s6Py2_DL.d.mts +353 -0
  71. package/dist/types-s6Py2_DL.d.mts.map +1 -0
  72. package/dist/{utils-7vXqtq2Q.mjs → utils-CkB4Roi6.mjs} +1 -1
  73. package/dist/{utils-7vXqtq2Q.mjs.map → utils-CkB4Roi6.mjs.map} +1 -1
  74. package/docs/ai-sdk.md +137 -21
  75. package/docs/browser.md +241 -2
  76. package/docs/memory.md +72 -0
  77. package/docs/stt.md +494 -0
  78. package/docs/tts.md +569 -0
  79. package/docs/vision.md +396 -0
  80. package/package.json +17 -18
  81. package/dist/auto-update-BbNHbSU1.mjs +0 -3
  82. package/dist/chrome-backend-C5Un08O4.mjs.map +0 -1
  83. package/dist/gerbil-BfnsFWRE.mjs +0 -644
  84. package/dist/gerbil-BfnsFWRE.mjs.map +0 -1
  85. package/dist/gerbil-BjW-z7Fq.mjs +0 -5
  86. package/dist/gerbil-DZ1k3ChC.d.mts +0 -138
  87. package/dist/gerbil-DZ1k3ChC.d.mts.map +0 -1
  88. package/dist/mcp-R8kRLIKb.mjs.map +0 -1
  89. package/dist/models-DKULvhOr.mjs.map +0 -1
  90. package/dist/models-De2-_GmQ.d.mts.map +0 -1
  91. package/dist/skills-D3CEpgDc.mjs +0 -630
  92. package/dist/skills-D3CEpgDc.mjs.map +0 -1
  93. package/dist/types-BS1N92Jt.d.mts +0 -183
  94. package/dist/types-BS1N92Jt.d.mts.map +0 -1
@@ -1,5 +1,5 @@
1
- import { c as GerbilModelSettings, f as ModelConfig, l as GerbilProviderSettings } from "../types-BS1N92Jt.mjs";
2
- import { LanguageModelV2, LanguageModelV2CallOptions, LanguageModelV2CallWarning, LanguageModelV2Content, LanguageModelV2FinishReason, LanguageModelV2StreamPart, LanguageModelV2Usage } from "@ai-sdk/provider";
1
+ import { b as STTModelConfig, g as ModelConfig, l as GerbilModelSettings, u as GerbilProviderSettings } from "../types-s6Py2_DL.mjs";
2
+ import { LanguageModelV2, LanguageModelV2CallOptions, LanguageModelV2CallWarning, LanguageModelV2Content, LanguageModelV2FinishReason, LanguageModelV2StreamPart, LanguageModelV2Usage, SpeechModelV2, SpeechModelV2CallOptions, SpeechModelV2CallWarning, TranscriptionModelV2, TranscriptionModelV2CallOptions, TranscriptionModelV2CallWarning } from "@ai-sdk/provider";
3
3
 
4
4
  //#region src/integrations/ai-sdk.d.ts
5
5
 
@@ -38,11 +38,85 @@ declare class GerbilLanguageModel implements LanguageModelV2 {
38
38
  };
39
39
  }>;
40
40
  }
41
+ /** Settings for Gerbil speech model */
42
+ interface GerbilSpeechSettings {
43
+ /** Default voice ID (default: "af_heart") */
44
+ voice?: string;
45
+ /** Speech speed multiplier (default: 1.0) */
46
+ speed?: number;
47
+ }
48
+ declare class GerbilSpeechModel implements SpeechModelV2 {
49
+ readonly specificationVersion: "v2";
50
+ readonly provider = "gerbil";
51
+ readonly modelId: string;
52
+ private instance;
53
+ private readonly settings;
54
+ private loadPromise;
55
+ constructor(modelId: string, settings?: GerbilSpeechSettings);
56
+ private ensureLoaded;
57
+ doGenerate(options: SpeechModelV2CallOptions): Promise<{
58
+ audio: Uint8Array;
59
+ warnings: SpeechModelV2CallWarning[];
60
+ request?: {
61
+ body?: unknown;
62
+ };
63
+ response: {
64
+ timestamp: Date;
65
+ modelId: string;
66
+ };
67
+ }>;
68
+ /**
69
+ * Convert Float32Array audio to WAV format Uint8Array
70
+ */
71
+ private float32ToWav;
72
+ }
73
+ /** Settings for Gerbil transcription model */
74
+ interface GerbilTranscriptionSettings {
75
+ /** Default language code (ISO-639-1) for transcription */
76
+ language?: string;
77
+ }
78
+ declare class GerbilTranscriptionModel implements TranscriptionModelV2 {
79
+ readonly specificationVersion: "v2";
80
+ readonly provider = "gerbil";
81
+ readonly modelId: string;
82
+ private instance;
83
+ private readonly settings;
84
+ private loadPromise;
85
+ constructor(modelId: string, settings?: GerbilTranscriptionSettings);
86
+ private ensureLoaded;
87
+ doGenerate(options: TranscriptionModelV2CallOptions): Promise<{
88
+ text: string;
89
+ segments: Array<{
90
+ text: string;
91
+ startSecond: number;
92
+ endSecond: number;
93
+ }>;
94
+ language: string | undefined;
95
+ durationInSeconds: number | undefined;
96
+ warnings: TranscriptionModelV2CallWarning[];
97
+ request?: {
98
+ body?: string;
99
+ };
100
+ response: {
101
+ timestamp: Date;
102
+ modelId: string;
103
+ };
104
+ }>;
105
+ }
41
106
  type GerbilProvider = {
42
107
  (modelId: string, settings?: GerbilModelSettings): GerbilLanguageModel;
43
108
  languageModel(modelId: string, settings?: GerbilModelSettings): GerbilLanguageModel;
109
+ speech(modelId?: string, settings?: GerbilSpeechSettings): GerbilSpeechModel;
110
+ transcription(modelId?: string, settings?: GerbilTranscriptionSettings): GerbilTranscriptionModel;
44
111
  listModels(): ModelConfig[];
45
112
  getModel(modelId: string): ModelConfig | undefined;
113
+ listVoices(): Array<{
114
+ id: string;
115
+ name: string;
116
+ gender: string;
117
+ language: string;
118
+ }>;
119
+ listTranscriptionModels(): STTModelConfig[];
46
120
  };
47
121
  /**
48
122
  * Create a Gerbil provider
@@ -51,17 +125,31 @@ type GerbilProvider = {
51
125
  * ```ts
52
126
  * const local = createGerbil({ device: "gpu", dtype: "q4" });
53
127
  *
128
+ * // Text generation
54
129
  * const { text } = await generateText({
55
130
  * model: local("qwen3-0.6b"),
56
131
  * prompt: "Hello",
57
132
  * });
133
+ *
134
+ * // Speech generation
135
+ * const audio = await generateSpeech({
136
+ * model: local.speech(),
137
+ * text: "Hello world!",
138
+ * voice: "af_heart",
139
+ * });
140
+ *
141
+ * // Transcription
142
+ * const transcript = await transcribe({
143
+ * model: local.transcription(),
144
+ * audio: audioBuffer,
145
+ * });
58
146
  * ```
59
147
  */
60
148
  declare function createGerbil(options?: GerbilProviderSettings): GerbilProvider;
61
149
  /**
62
150
  * Default Gerbil provider
63
151
  *
64
- * @example
152
+ * @example Text Generation
65
153
  * ```ts
66
154
  * import { generateText } from "ai";
67
155
  * import { gerbil } from "gerbil/ai";
@@ -71,8 +159,38 @@ declare function createGerbil(options?: GerbilProviderSettings): GerbilProvider;
71
159
  * prompt: "Hello",
72
160
  * });
73
161
  * ```
162
+ *
163
+ * @example Speech Generation
164
+ * ```ts
165
+ * import { experimental_generateSpeech as generateSpeech } from "ai";
166
+ * import { gerbil } from "gerbil/ai";
167
+ *
168
+ * const audio = await generateSpeech({
169
+ * model: gerbil.speech(),
170
+ * text: "Hello world!",
171
+ * voice: "af_heart", // Or "bf_emma", "am_fenrir", etc.
172
+ * });
173
+ *
174
+ * // Access audio data
175
+ * const audioData = audio.audioData; // Uint8Array (WAV format)
176
+ * ```
177
+ *
178
+ * @example Transcription
179
+ * ```ts
180
+ * import { experimental_transcribe as transcribe } from "ai";
181
+ * import { gerbil } from "gerbil/ai";
182
+ * import { readFile } from "fs/promises";
183
+ *
184
+ * const transcript = await transcribe({
185
+ * model: gerbil.transcription(), // whisper-tiny.en by default
186
+ * audio: await readFile("audio.wav"),
187
+ * });
188
+ *
189
+ * console.log(transcript.text);
190
+ * console.log(transcript.segments); // Timestamped segments
191
+ * ```
74
192
  */
75
193
  declare const gerbil: GerbilProvider;
76
194
  //#endregion
77
- export { GerbilProvider, createGerbil, gerbil as default, gerbil };
195
+ export { GerbilProvider, GerbilSpeechSettings, GerbilTranscriptionSettings, createGerbil, gerbil as default, gerbil };
78
196
  //# sourceMappingURL=ai-sdk.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-sdk.d.mts","names":[],"sources":["../../src/integrations/ai-sdk.ts"],"sourcesContent":[],"mappings":";;;;;cA0CM,mBAAA,YAA+B,eAqIe,CAAA;EArIf,SAAA,oBAAA,EAAA,IAAA;EAAe,SAAA,QAAA,GAAA,QAAA;EAmNxC,SAAA,OAAA,EAAc,MAAA;EACK,SAAA,aAAA,EA9ML,MA8MK,CAAA,MAAA,EA9MU,MA8MV,EAAA,CAAA;EAAsB,QAAA,QAAA;EACT,iBAAA,QAAA;EAAsB,iBAAA,gBAAA;EAClD,QAAA,WAAA;EACa,WAAA,CAAA,OAAA,EAAA,MAAA,EAAA,QAAA,EAxMf,mBAwMe,EAAA,gBAAA,EAvMP,sBAuMO;EAAW,QAAA,YAAA;EAgBxB,QAAA,aAAY;EA4Bf,QAAA,eAAM;sBA7KS,6BAA0B;;;;;;;;;;;;oBA+C5B,6BAA0B;;;;;;;;;;KA8ExC,cAAA;+BACmB,sBAAsB;4CACT,sBAAsB;gBAClD;6BACa;;;;;;;;;;;;;;;iBAgBb,YAAA,WAAsB,yBAA8B;;;;;;;;;;;;;;;cA4BvD,QAAM"}
1
+ {"version":3,"file":"ai-sdk.d.mts","names":[],"sources":["../../src/integrations/ai-sdk.ts"],"sourcesContent":[],"mappings":";;;;;cAwDM,mBAAA,YAA+B,eAsJe,CAAA;EAtJf,SAAA,oBAAA,EAAA,IAAA;EAAe,SAAA,QAAA,GAAA,QAAA;EAsOnC,SAAA,OAAA,EAAA,MAAoB;EAO/B,SAAA,aAAkB,EAvOE,MAuOF,CAAA,MAAA,EAvOiB,MAuOjB,EAAA,CAAA;EASiB,QAAA,QAAA;EAoBb,iBAAA,QAAA;EACjB,iBAAA,gBAAA;EACG,QAAA,WAAA;EAEa,WAAA,CAAA,OAAA,EAAA,MAAA,EAAA,QAAA,EA/Pb,mBA+Pa,EAAA,gBAAA,EA9PL,sBA8PK;EAJ4B,QAAA,YAAA;EA7BpB,QAAA,aAAA;EAAa,QAAA,eAAA;EAoI/B,UAAA,CAAA,OAAA,EA3QW,0BA2QgB,CAAA,EA3QU,OA2QV,CAAA;IAKtC,OAAA,wBAAyB,EAAA;IASU,YAAA,6BAAA;IAoBb,KAAA,sBAAA;IAEd,OAAA,EAAA;MAOA,IAAA,EAAA;QAGG,KAAA,EAAA,MAAA;QAZ6C,MAAA,EAAA,MAAA;MA7BpB,CAAA;IAAoB,CAAA;IAiHlD,QAAA,4BAAc,EAAA;EACK,CAAA,CAAA;EAAsB,QAAA,CAAA,OAAA,EAlV3B,0BAkV2B,CAAA,EAlVD,OAkVC,CAAA;IACT,MAAA,gBAAA,0BAAA,CAAA;IAAsB,OAAA,EAAA;MAC5B,IAAA,EAAA;QAAuB,KAAA,EAAA,MAAA;QAChB,MAAA,EAAA,MAAA;MAA8B,CAAA;IAC3D,CAAA;EACa,CAAA,CAAA;;;AAEc,UAzQ1B,oBAAA,CAyQ0B;EA8B3B;EA4EH,KAAA,CAAA,EAAA,MAAuB;;;;cA5W9B,iBAAA,YAA6B;;;;;;;0CASM;;sBAoBb,2BAA2B;WAC5C;cACG;;;;;iBAEa;;;;;;;;;;UAmGV,2BAAA;;;;cAKX,wBAAA,YAAoC;;;;;;;0CASD;;sBAoBb,kCAAkC;;cAEhD;;;;;;;cAOA;;;;;iBAGG;;;;;KAwEL,cAAA;+BACmB,sBAAsB;4CACT,sBAAsB;sCAC5B,uBAAuB;6CAChB,8BAA8B;gBAC3D;6BACa;gBACb;;;;;;6BACa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8Bb,YAAA,WAAsB,yBAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA4EvD,QAAM"}
@@ -1,11 +1,13 @@
1
- import { t as BUILTIN_MODELS } from "../models-DKULvhOr.mjs";
2
- import "../utils-7vXqtq2Q.mjs";
3
- import { t as Gerbil } from "../gerbil-BfnsFWRE.mjs";
1
+ import { t as Gerbil } from "../gerbil-yoSpRHgv.mjs";
2
+ import { t as BUILTIN_MODELS } from "../models-BAtL8qsA.mjs";
3
+ import "../utils-CkB4Roi6.mjs";
4
+ import { t as WHISPER_MODELS } from "../stt-Bv_dum-R.mjs";
5
+ import { t as KOKORO_VOICES } from "../tts-DG6denWG.mjs";
4
6
 
5
7
  //#region src/integrations/ai-sdk.ts
6
8
  let idCounter = 0;
7
9
  function generateId() {
8
- return `gerbil-${Date.now()}-${++idCounter}`;
10
+ return `gerbil-${Date.now()}-${idCounter += 1}`;
9
11
  }
10
12
  var GerbilLanguageModel = class {
11
13
  specificationVersion = "v2";
@@ -38,15 +40,27 @@ var GerbilLanguageModel = class {
38
40
  convertPrompt(prompt) {
39
41
  let system;
40
42
  let user = "";
43
+ const images = [];
41
44
  for (const msg of prompt) if (msg.role === "system") system = msg.content;
42
45
  else if (msg.role === "user") {
43
46
  for (const part of msg.content) if (part.type === "text") user += part.text;
47
+ else if (part.type === "image") {
48
+ const imgPart = part;
49
+ if (imgPart.image instanceof URL) images.push({ source: imgPart.image.toString() });
50
+ else if (typeof imgPart.image === "string") images.push({ source: imgPart.image });
51
+ else if (imgPart.image instanceof Uint8Array) {
52
+ const base64 = btoa(String.fromCharCode(...imgPart.image));
53
+ const mimeType = imgPart.mimeType || "image/png";
54
+ images.push({ source: `data:${mimeType};base64,${base64}` });
55
+ }
56
+ }
44
57
  } else if (msg.role === "assistant") {
45
58
  for (const part of msg.content) if (part.type === "text") user += `\n\nAssistant: ${part.text}`;
46
59
  } else if (msg.role === "tool") for (const part of msg.content) user += `\n\nTool (${part.toolName}): ${JSON.stringify(part)}`;
47
60
  return {
48
61
  system,
49
- user
62
+ user,
63
+ images
50
64
  };
51
65
  }
52
66
  mapFinishReason(reason) {
@@ -58,7 +72,7 @@ var GerbilLanguageModel = class {
58
72
  async doGenerate(options) {
59
73
  const warnings = [];
60
74
  const g = await this.ensureLoaded();
61
- const { system, user } = this.convertPrompt(options.prompt);
75
+ const { system, user, images } = this.convertPrompt(options.prompt);
62
76
  const result = await g.generate(user, {
63
77
  maxTokens: options.maxOutputTokens,
64
78
  temperature: options.temperature,
@@ -66,7 +80,8 @@ var GerbilLanguageModel = class {
66
80
  topK: options.topK,
67
81
  system,
68
82
  thinking: this.settings.thinking,
69
- stopSequences: options.stopSequences
83
+ stopSequences: options.stopSequences,
84
+ images: images.length > 0 ? images : void 0
70
85
  });
71
86
  const content = [];
72
87
  if (result.thinking) content.push({
@@ -96,7 +111,7 @@ var GerbilLanguageModel = class {
96
111
  async doStream(options) {
97
112
  const warnings = [];
98
113
  const g = await this.ensureLoaded();
99
- const { system, user } = this.convertPrompt(options.prompt);
114
+ const { system, user, images } = this.convertPrompt(options.prompt);
100
115
  const streamGen = g.stream(user, {
101
116
  maxTokens: options.maxOutputTokens,
102
117
  temperature: options.temperature,
@@ -104,7 +119,8 @@ var GerbilLanguageModel = class {
104
119
  topK: options.topK,
105
120
  system,
106
121
  thinking: this.settings.thinking,
107
- stopSequences: options.stopSequences
122
+ stopSequences: options.stopSequences,
123
+ images: images.length > 0 ? images : void 0
108
124
  });
109
125
  let tokens = 0;
110
126
  const textId = generateId();
@@ -120,7 +136,7 @@ var GerbilLanguageModel = class {
120
136
  id: textId
121
137
  });
122
138
  for await (const chunk of streamGen) {
123
- tokens++;
139
+ tokens += 1;
124
140
  controller.enqueue({
125
141
  type: "text-delta",
126
142
  id: textId,
@@ -156,6 +172,163 @@ var GerbilLanguageModel = class {
156
172
  };
157
173
  }
158
174
  };
175
+ var GerbilSpeechModel = class {
176
+ specificationVersion = "v2";
177
+ provider = "gerbil";
178
+ modelId;
179
+ instance = null;
180
+ settings;
181
+ loadPromise = null;
182
+ constructor(modelId, settings = {}) {
183
+ this.modelId = modelId;
184
+ this.settings = settings;
185
+ }
186
+ async ensureLoaded() {
187
+ if (this.instance?.isTTSLoaded()) return this.instance;
188
+ if (this.loadPromise) {
189
+ await this.loadPromise;
190
+ return this.instance;
191
+ }
192
+ this.instance = new Gerbil();
193
+ this.loadPromise = this.instance.ensureTTSLoaded();
194
+ await this.loadPromise;
195
+ return this.instance;
196
+ }
197
+ async doGenerate(options) {
198
+ const warnings = [];
199
+ const g = await this.ensureLoaded();
200
+ let voice = options.voice || this.settings.voice || "af_heart";
201
+ if (!KOKORO_VOICES.find((v) => v.id === voice)) {
202
+ warnings.push({
203
+ type: "unsupported-setting",
204
+ setting: "voice",
205
+ details: `Unknown voice "${voice}", using default "af_heart"`
206
+ });
207
+ voice = "af_heart";
208
+ }
209
+ const speed = options.speed ?? this.settings.speed ?? 1;
210
+ if (options.outputFormat && options.outputFormat !== "wav" && options.outputFormat !== "raw") warnings.push({
211
+ type: "unsupported-setting",
212
+ setting: "outputFormat",
213
+ details: `Gerbil TTS only supports "wav" and "raw" formats, got "${options.outputFormat}"`
214
+ });
215
+ if (options.instructions) warnings.push({
216
+ type: "unsupported-setting",
217
+ setting: "instructions",
218
+ details: "Gerbil TTS does not support instructions parameter"
219
+ });
220
+ const result = await g.speak(options.text, {
221
+ voice,
222
+ speed
223
+ });
224
+ return {
225
+ audio: this.float32ToWav(result.audio, result.sampleRate),
226
+ warnings,
227
+ request: { body: {
228
+ text: options.text,
229
+ voice,
230
+ speed
231
+ } },
232
+ response: {
233
+ timestamp: /* @__PURE__ */ new Date(),
234
+ modelId: this.modelId
235
+ }
236
+ };
237
+ }
238
+ /**
239
+ * Convert Float32Array audio to WAV format Uint8Array
240
+ */
241
+ float32ToWav(audio, sampleRate) {
242
+ const buffer = /* @__PURE__ */ new ArrayBuffer(44 + audio.length * 2);
243
+ const view = new DataView(buffer);
244
+ const writeString = (offset, str) => {
245
+ for (let i = 0; i < str.length; i++) view.setUint8(offset + i, str.charCodeAt(i));
246
+ };
247
+ writeString(0, "RIFF");
248
+ view.setUint32(4, 36 + audio.length * 2, true);
249
+ writeString(8, "WAVE");
250
+ writeString(12, "fmt ");
251
+ view.setUint32(16, 16, true);
252
+ view.setUint16(20, 1, true);
253
+ view.setUint16(22, 1, true);
254
+ view.setUint32(24, sampleRate, true);
255
+ view.setUint32(28, sampleRate * 2, true);
256
+ view.setUint16(32, 2, true);
257
+ view.setUint16(34, 16, true);
258
+ writeString(36, "data");
259
+ view.setUint32(40, audio.length * 2, true);
260
+ for (let i = 0; i < audio.length; i++) {
261
+ const s = Math.max(-1, Math.min(1, audio[i]));
262
+ view.setInt16(44 + i * 2, Math.round(s * 32767), true);
263
+ }
264
+ return new Uint8Array(buffer);
265
+ }
266
+ };
267
+ var GerbilTranscriptionModel = class {
268
+ specificationVersion = "v2";
269
+ provider = "gerbil";
270
+ modelId;
271
+ instance = null;
272
+ settings;
273
+ loadPromise = null;
274
+ constructor(modelId, settings = {}) {
275
+ this.modelId = modelId;
276
+ this.settings = settings;
277
+ }
278
+ async ensureLoaded() {
279
+ if (this.instance?.isSTTLoaded()) return this.instance;
280
+ if (this.loadPromise) {
281
+ await this.loadPromise;
282
+ return this.instance;
283
+ }
284
+ this.instance = new Gerbil();
285
+ this.loadPromise = this.instance.loadSTT(this.modelId);
286
+ await this.loadPromise;
287
+ return this.instance;
288
+ }
289
+ async doGenerate(options) {
290
+ const warnings = [];
291
+ const g = await this.ensureLoaded();
292
+ let audioData;
293
+ if (typeof options.audio === "string") {
294
+ const binaryString = atob(options.audio);
295
+ audioData = new Uint8Array(binaryString.length);
296
+ for (let i = 0; i < binaryString.length; i++) audioData[i] = binaryString.charCodeAt(i);
297
+ } else audioData = options.audio;
298
+ const mediaType = options.mediaType?.toLowerCase() || "";
299
+ if (mediaType && !mediaType.includes("wav") && !mediaType.includes("wave")) warnings.push({
300
+ type: "unsupported-setting",
301
+ setting: "mediaType",
302
+ details: `Gerbil STT natively supports WAV format. Got "${options.mediaType}". Audio may not decode correctly.`
303
+ });
304
+ const language = (options.providerOptions?.gerbil)?.language || this.settings.language;
305
+ const result = await g.transcribe(audioData, {
306
+ language,
307
+ timestamps: true
308
+ });
309
+ const segments = (result.segments || []).map((seg) => ({
310
+ text: seg.text,
311
+ startSecond: seg.start,
312
+ endSecond: seg.end
313
+ }));
314
+ return {
315
+ text: result.text,
316
+ segments,
317
+ language: result.language,
318
+ durationInSeconds: result.duration,
319
+ warnings,
320
+ request: { body: JSON.stringify({
321
+ model: this.modelId,
322
+ mediaType: options.mediaType,
323
+ language
324
+ }) },
325
+ response: {
326
+ timestamp: /* @__PURE__ */ new Date(),
327
+ modelId: this.modelId
328
+ }
329
+ };
330
+ }
331
+ };
159
332
  /**
160
333
  * Create a Gerbil provider
161
334
  *
@@ -163,24 +336,49 @@ var GerbilLanguageModel = class {
163
336
  * ```ts
164
337
  * const local = createGerbil({ device: "gpu", dtype: "q4" });
165
338
  *
339
+ * // Text generation
166
340
  * const { text } = await generateText({
167
341
  * model: local("qwen3-0.6b"),
168
342
  * prompt: "Hello",
169
343
  * });
344
+ *
345
+ * // Speech generation
346
+ * const audio = await generateSpeech({
347
+ * model: local.speech(),
348
+ * text: "Hello world!",
349
+ * voice: "af_heart",
350
+ * });
351
+ *
352
+ * // Transcription
353
+ * const transcript = await transcribe({
354
+ * model: local.transcription(),
355
+ * audio: audioBuffer,
356
+ * });
170
357
  * ```
171
358
  */
172
359
  function createGerbil(options = {}) {
173
360
  const createModel = (modelId, settings = {}) => new GerbilLanguageModel(modelId, settings, options);
361
+ const createSpeechModel = (modelId = "kokoro-82m", settings = {}) => new GerbilSpeechModel(modelId, settings);
362
+ const createTranscriptionModel = (modelId = "whisper-tiny.en", settings = {}) => new GerbilTranscriptionModel(modelId, settings);
174
363
  const provider = ((modelId, settings) => createModel(modelId, settings ?? {}));
175
364
  provider.languageModel = createModel;
365
+ provider.speech = createSpeechModel;
366
+ provider.transcription = createTranscriptionModel;
176
367
  provider.listModels = () => Object.values(BUILTIN_MODELS);
177
368
  provider.getModel = (id) => BUILTIN_MODELS[id];
369
+ provider.listVoices = () => KOKORO_VOICES.map((v) => ({
370
+ id: v.id,
371
+ name: v.name,
372
+ gender: v.gender,
373
+ language: v.language
374
+ }));
375
+ provider.listTranscriptionModels = () => WHISPER_MODELS;
178
376
  return provider;
179
377
  }
180
378
  /**
181
379
  * Default Gerbil provider
182
380
  *
183
- * @example
381
+ * @example Text Generation
184
382
  * ```ts
185
383
  * import { generateText } from "ai";
186
384
  * import { gerbil } from "gerbil/ai";
@@ -190,6 +388,36 @@ function createGerbil(options = {}) {
190
388
  * prompt: "Hello",
191
389
  * });
192
390
  * ```
391
+ *
392
+ * @example Speech Generation
393
+ * ```ts
394
+ * import { experimental_generateSpeech as generateSpeech } from "ai";
395
+ * import { gerbil } from "gerbil/ai";
396
+ *
397
+ * const audio = await generateSpeech({
398
+ * model: gerbil.speech(),
399
+ * text: "Hello world!",
400
+ * voice: "af_heart", // Or "bf_emma", "am_fenrir", etc.
401
+ * });
402
+ *
403
+ * // Access audio data
404
+ * const audioData = audio.audioData; // Uint8Array (WAV format)
405
+ * ```
406
+ *
407
+ * @example Transcription
408
+ * ```ts
409
+ * import { experimental_transcribe as transcribe } from "ai";
410
+ * import { gerbil } from "gerbil/ai";
411
+ * import { readFile } from "fs/promises";
412
+ *
413
+ * const transcript = await transcribe({
414
+ * model: gerbil.transcription(), // whisper-tiny.en by default
415
+ * audio: await readFile("audio.wav"),
416
+ * });
417
+ *
418
+ * console.log(transcript.text);
419
+ * console.log(transcript.segments); // Timestamped segments
420
+ * ```
193
421
  */
194
422
  const gerbil = createGerbil();
195
423
  var ai_sdk_default = gerbil;
@@ -1 +1 @@
1
- {"version":3,"file":"ai-sdk.mjs","names":["system: string | undefined","warnings: LanguageModelV2CallWarning[]","content: LanguageModelV2Content[]","usage: LanguageModelV2Usage"],"sources":["../../src/integrations/ai-sdk.ts"],"sourcesContent":["/**\n * Gerbil AI SDK Provider (V2 Specification)\n *\n * Compatible with AI SDK v5+\n *\n * @example\n * ```ts\n * import { generateText, streamText } from \"ai\";\n * import { gerbil } from \"gerbil/ai\";\n *\n * const { text } = await generateText({\n * model: gerbil(\"qwen3-0.6b\"),\n * prompt: \"Hello world\",\n * });\n * ```\n */\n\nimport type {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2CallWarning,\n LanguageModelV2Content,\n LanguageModelV2FinishReason,\n LanguageModelV2Prompt,\n LanguageModelV2StreamPart,\n LanguageModelV2Usage,\n} from \"@ai-sdk/provider\";\n\nimport { Gerbil } from \"../core/gerbil.js\";\nimport { BUILTIN_MODELS } from \"../core/models.js\";\nimport type { GerbilModelSettings, GerbilProviderSettings, ModelConfig } from \"../core/types.js\";\n\n// Simple ID generator\nlet idCounter = 0;\nfunction generateId(): string {\n return `gerbil-${Date.now()}-${++idCounter}`;\n}\n\n// ============================================\n// Language Model Implementation (V2 Spec)\n// ============================================\n\nclass GerbilLanguageModel implements LanguageModelV2 {\n readonly specificationVersion = \"v2\" as const;\n readonly provider = \"gerbil\";\n readonly modelId: string;\n\n // Gerbil runs locally, no URL support needed\n readonly supportedUrls: Record<string, RegExp[]> = {};\n\n private instance: Gerbil | null = null;\n private readonly settings: GerbilModelSettings;\n private readonly providerSettings: GerbilProviderSettings;\n private loadPromise: Promise<void> | null = null;\n\n constructor(\n modelId: string,\n settings: GerbilModelSettings,\n providerSettings: GerbilProviderSettings,\n ) {\n this.modelId = modelId;\n this.settings = settings;\n this.providerSettings = providerSettings;\n }\n\n private async ensureLoaded(): Promise<Gerbil> {\n if (this.instance?.isLoaded()) {\n return this.instance;\n }\n if (this.loadPromise) {\n await this.loadPromise;\n return this.instance!;\n }\n\n this.instance = new Gerbil();\n this.loadPromise = this.instance.loadModel(this.modelId, {\n device: this.settings.device ?? this.providerSettings.device ?? \"auto\",\n dtype: this.settings.dtype ?? this.providerSettings.dtype ?? \"q4\",\n });\n await this.loadPromise;\n return this.instance;\n }\n\n private convertPrompt(prompt: LanguageModelV2Prompt): {\n system?: string;\n user: string;\n } {\n let system: string | undefined;\n let user = \"\";\n\n for (const msg of prompt) {\n if (msg.role === \"system\") {\n system = msg.content;\n } else if (msg.role === \"user\") {\n for (const part of msg.content) {\n if (part.type === \"text\") {\n user += part.text;\n }\n }\n } else if (msg.role === \"assistant\") {\n for (const part of msg.content) {\n if (part.type === \"text\") {\n user += `\\n\\nAssistant: ${part.text}`;\n }\n }\n } else if (msg.role === \"tool\") {\n for (const part of msg.content) {\n user += `\\n\\nTool (${part.toolName}): ${JSON.stringify(part)}`;\n }\n }\n }\n\n return { system, user };\n }\n\n private mapFinishReason(reason: string): LanguageModelV2FinishReason {\n if (reason === \"stop\") {\n return \"stop\";\n }\n if (reason === \"length\") {\n return \"length\";\n }\n if (reason === \"error\") {\n return \"error\";\n }\n return \"other\";\n }\n\n async doGenerate(options: LanguageModelV2CallOptions) {\n const warnings: LanguageModelV2CallWarning[] = [];\n const g = await this.ensureLoaded();\n const { system, user } = this.convertPrompt(options.prompt);\n\n const result = await g.generate(user, {\n maxTokens: options.maxOutputTokens,\n temperature: options.temperature,\n topP: options.topP,\n topK: options.topK,\n system,\n thinking: this.settings.thinking,\n stopSequences: options.stopSequences,\n });\n\n // Build V2 content array\n const content: LanguageModelV2Content[] = [];\n\n // Add reasoning if thinking mode was enabled\n if (result.thinking) {\n content.push({\n type: \"reasoning\",\n text: result.thinking,\n });\n }\n\n // Add main text response\n content.push({\n type: \"text\",\n text: result.text,\n });\n\n const usage: LanguageModelV2Usage = {\n inputTokens: 0,\n outputTokens: result.tokensGenerated,\n totalTokens: result.tokensGenerated,\n };\n\n return {\n content,\n finishReason: this.mapFinishReason(result.finishReason),\n usage,\n request: { body: { model: this.modelId, prompt: user } },\n warnings,\n };\n }\n\n async doStream(options: LanguageModelV2CallOptions) {\n const warnings: LanguageModelV2CallWarning[] = [];\n const g = await this.ensureLoaded();\n const { system, user } = this.convertPrompt(options.prompt);\n\n const streamGen = g.stream(user, {\n maxTokens: options.maxOutputTokens,\n temperature: options.temperature,\n topP: options.topP,\n topK: options.topK,\n system,\n thinking: this.settings.thinking,\n stopSequences: options.stopSequences,\n });\n\n let tokens = 0;\n const textId = generateId();\n\n const stream = new ReadableStream<LanguageModelV2StreamPart>({\n async start(controller) {\n try {\n // V2: Send stream-start event first\n controller.enqueue({\n type: \"stream-start\",\n warnings,\n });\n\n // V2: Send text-start before text deltas\n controller.enqueue({\n type: \"text-start\",\n id: textId,\n });\n\n for await (const chunk of streamGen) {\n tokens++;\n // V2: Use 'text-delta' with id and delta\n controller.enqueue({\n type: \"text-delta\",\n id: textId,\n delta: chunk,\n });\n }\n\n // V2: Send text-end after all deltas\n controller.enqueue({\n type: \"text-end\",\n id: textId,\n });\n\n // V2: Send finish event\n controller.enqueue({\n type: \"finish\",\n finishReason: \"stop\",\n usage: {\n inputTokens: 0,\n outputTokens: tokens,\n totalTokens: tokens,\n },\n });\n controller.close();\n } catch (error) {\n controller.enqueue({ type: \"error\", error });\n controller.close();\n }\n },\n });\n\n return {\n stream,\n request: { body: { model: this.modelId, prompt: user } },\n };\n }\n}\n\n// ============================================\n// Provider Factory\n// ============================================\n\nexport type GerbilProvider = {\n (modelId: string, settings?: GerbilModelSettings): GerbilLanguageModel;\n languageModel(modelId: string, settings?: GerbilModelSettings): GerbilLanguageModel;\n listModels(): ModelConfig[];\n getModel(modelId: string): ModelConfig | undefined;\n};\n\n/**\n * Create a Gerbil provider\n *\n * @example\n * ```ts\n * const local = createGerbil({ device: \"gpu\", dtype: \"q4\" });\n *\n * const { text } = await generateText({\n * model: local(\"qwen3-0.6b\"),\n * prompt: \"Hello\",\n * });\n * ```\n */\nexport function createGerbil(options: GerbilProviderSettings = {}): GerbilProvider {\n const createModel = (modelId: string, settings: GerbilModelSettings = {}) =>\n new GerbilLanguageModel(modelId, settings, options);\n\n const provider = ((modelId: string, settings?: GerbilModelSettings) =>\n createModel(modelId, settings ?? {})) as GerbilProvider;\n\n provider.languageModel = createModel;\n provider.listModels = () => Object.values(BUILTIN_MODELS);\n provider.getModel = (id: string) => BUILTIN_MODELS[id];\n\n return provider;\n}\n\n/**\n * Default Gerbil provider\n *\n * @example\n * ```ts\n * import { generateText } from \"ai\";\n * import { gerbil } from \"gerbil/ai\";\n *\n * const { text } = await generateText({\n * model: gerbil(\"qwen3-0.6b\"),\n * prompt: \"Hello\",\n * });\n * ```\n */\nexport const gerbil = createGerbil();\n\nexport default gerbil;\n"],"mappings":";;;;;AAiCA,IAAI,YAAY;AAChB,SAAS,aAAqB;AAC5B,QAAO,UAAU,KAAK,KAAK,CAAC,GAAG,EAAE;;AAOnC,IAAM,sBAAN,MAAqD;CACnD,AAAS,uBAAuB;CAChC,AAAS,WAAW;CACpB,AAAS;CAGT,AAAS,gBAA0C,EAAE;CAErD,AAAQ,WAA0B;CAClC,AAAiB;CACjB,AAAiB;CACjB,AAAQ,cAAoC;CAE5C,YACE,SACA,UACA,kBACA;AACA,OAAK,UAAU;AACf,OAAK,WAAW;AAChB,OAAK,mBAAmB;;CAG1B,MAAc,eAAgC;AAC5C,MAAI,KAAK,UAAU,UAAU,CAC3B,QAAO,KAAK;AAEd,MAAI,KAAK,aAAa;AACpB,SAAM,KAAK;AACX,UAAO,KAAK;;AAGd,OAAK,WAAW,IAAI,QAAQ;AAC5B,OAAK,cAAc,KAAK,SAAS,UAAU,KAAK,SAAS;GACvD,QAAQ,KAAK,SAAS,UAAU,KAAK,iBAAiB,UAAU;GAChE,OAAO,KAAK,SAAS,SAAS,KAAK,iBAAiB,SAAS;GAC9D,CAAC;AACF,QAAM,KAAK;AACX,SAAO,KAAK;;CAGd,AAAQ,cAAc,QAGpB;EACA,IAAIA;EACJ,IAAI,OAAO;AAEX,OAAK,MAAM,OAAO,OAChB,KAAI,IAAI,SAAS,SACf,UAAS,IAAI;WACJ,IAAI,SAAS,QACtB;QAAK,MAAM,QAAQ,IAAI,QACrB,KAAI,KAAK,SAAS,OAChB,SAAQ,KAAK;aAGR,IAAI,SAAS,aACtB;QAAK,MAAM,QAAQ,IAAI,QACrB,KAAI,KAAK,SAAS,OAChB,SAAQ,kBAAkB,KAAK;aAG1B,IAAI,SAAS,OACtB,MAAK,MAAM,QAAQ,IAAI,QACrB,SAAQ,aAAa,KAAK,SAAS,KAAK,KAAK,UAAU,KAAK;AAKlE,SAAO;GAAE;GAAQ;GAAM;;CAGzB,AAAQ,gBAAgB,QAA6C;AACnE,MAAI,WAAW,OACb,QAAO;AAET,MAAI,WAAW,SACb,QAAO;AAET,MAAI,WAAW,QACb,QAAO;AAET,SAAO;;CAGT,MAAM,WAAW,SAAqC;EACpD,MAAMC,WAAyC,EAAE;EACjD,MAAM,IAAI,MAAM,KAAK,cAAc;EACnC,MAAM,EAAE,QAAQ,SAAS,KAAK,cAAc,QAAQ,OAAO;EAE3D,MAAM,SAAS,MAAM,EAAE,SAAS,MAAM;GACpC,WAAW,QAAQ;GACnB,aAAa,QAAQ;GACrB,MAAM,QAAQ;GACd,MAAM,QAAQ;GACd;GACA,UAAU,KAAK,SAAS;GACxB,eAAe,QAAQ;GACxB,CAAC;EAGF,MAAMC,UAAoC,EAAE;AAG5C,MAAI,OAAO,SACT,SAAQ,KAAK;GACX,MAAM;GACN,MAAM,OAAO;GACd,CAAC;AAIJ,UAAQ,KAAK;GACX,MAAM;GACN,MAAM,OAAO;GACd,CAAC;EAEF,MAAMC,QAA8B;GAClC,aAAa;GACb,cAAc,OAAO;GACrB,aAAa,OAAO;GACrB;AAED,SAAO;GACL;GACA,cAAc,KAAK,gBAAgB,OAAO,aAAa;GACvD;GACA,SAAS,EAAE,MAAM;IAAE,OAAO,KAAK;IAAS,QAAQ;IAAM,EAAE;GACxD;GACD;;CAGH,MAAM,SAAS,SAAqC;EAClD,MAAMF,WAAyC,EAAE;EACjD,MAAM,IAAI,MAAM,KAAK,cAAc;EACnC,MAAM,EAAE,QAAQ,SAAS,KAAK,cAAc,QAAQ,OAAO;EAE3D,MAAM,YAAY,EAAE,OAAO,MAAM;GAC/B,WAAW,QAAQ;GACnB,aAAa,QAAQ;GACrB,MAAM,QAAQ;GACd,MAAM,QAAQ;GACd;GACA,UAAU,KAAK,SAAS;GACxB,eAAe,QAAQ;GACxB,CAAC;EAEF,IAAI,SAAS;EACb,MAAM,SAAS,YAAY;AAmD3B,SAAO;GACL,QAlDa,IAAI,eAA0C,EAC3D,MAAM,MAAM,YAAY;AACtB,QAAI;AAEF,gBAAW,QAAQ;MACjB,MAAM;MACN;MACD,CAAC;AAGF,gBAAW,QAAQ;MACjB,MAAM;MACN,IAAI;MACL,CAAC;AAEF,gBAAW,MAAM,SAAS,WAAW;AACnC;AAEA,iBAAW,QAAQ;OACjB,MAAM;OACN,IAAI;OACJ,OAAO;OACR,CAAC;;AAIJ,gBAAW,QAAQ;MACjB,MAAM;MACN,IAAI;MACL,CAAC;AAGF,gBAAW,QAAQ;MACjB,MAAM;MACN,cAAc;MACd,OAAO;OACL,aAAa;OACb,cAAc;OACd,aAAa;OACd;MACF,CAAC;AACF,gBAAW,OAAO;aACX,OAAO;AACd,gBAAW,QAAQ;MAAE,MAAM;MAAS;MAAO,CAAC;AAC5C,gBAAW,OAAO;;MAGvB,CAAC;GAIA,SAAS,EAAE,MAAM;IAAE,OAAO,KAAK;IAAS,QAAQ;IAAM,EAAE;GACzD;;;;;;;;;;;;;;;;AA4BL,SAAgB,aAAa,UAAkC,EAAE,EAAkB;CACjF,MAAM,eAAe,SAAiB,WAAgC,EAAE,KACtE,IAAI,oBAAoB,SAAS,UAAU,QAAQ;CAErD,MAAM,aAAa,SAAiB,aAClC,YAAY,SAAS,YAAY,EAAE,CAAC;AAEtC,UAAS,gBAAgB;AACzB,UAAS,mBAAmB,OAAO,OAAO,eAAe;AACzD,UAAS,YAAY,OAAe,eAAe;AAEnD,QAAO;;;;;;;;;;;;;;;;AAiBT,MAAa,SAAS,cAAc;AAEpC,qBAAe"}
1
+ {"version":3,"file":"ai-sdk.mjs","names":["system: string | undefined","images: ImageInput[]","warnings: LanguageModelV2CallWarning[]","content: LanguageModelV2Content[]","usage: LanguageModelV2Usage","warnings: SpeechModelV2CallWarning[]","warnings: TranscriptionModelV2CallWarning[]","audioData: Uint8Array"],"sources":["../../src/integrations/ai-sdk.ts"],"sourcesContent":["/**\n * Gerbil AI SDK Provider (V2 Specification)\n *\n * Compatible with AI SDK v5+\n *\n * @example\n * ```ts\n * import { generateText, streamText } from \"ai\";\n * import { gerbil } from \"gerbil/ai\";\n *\n * const { text } = await generateText({\n * model: gerbil(\"qwen3-0.6b\"),\n * prompt: \"Hello world\",\n * });\n * ```\n */\n\nimport type {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2CallWarning,\n LanguageModelV2Content,\n LanguageModelV2FinishReason,\n LanguageModelV2Prompt,\n LanguageModelV2StreamPart,\n LanguageModelV2Usage,\n SpeechModelV2,\n SpeechModelV2CallOptions,\n SpeechModelV2CallWarning,\n TranscriptionModelV2,\n TranscriptionModelV2CallOptions,\n TranscriptionModelV2CallWarning,\n} from \"@ai-sdk/provider\";\n\nimport { Gerbil } from \"../core/gerbil.js\";\nimport { BUILTIN_MODELS } from \"../core/models.js\";\nimport { WHISPER_MODELS } from \"../core/stt.js\";\nimport { KOKORO_VOICES } from \"../core/tts.js\";\nimport type {\n GerbilModelSettings,\n GerbilProviderSettings,\n ImageInput,\n ModelConfig,\n STTModelConfig,\n} from \"../core/types.js\";\n\n// Simple ID generator\nlet idCounter = 0;\nfunction generateId(): string {\n return `gerbil-${Date.now()}-${(idCounter += 1)}`;\n}\n\n// ============================================\n// Language Model Implementation (V2 Spec)\n// ============================================\n\nclass GerbilLanguageModel implements LanguageModelV2 {\n readonly specificationVersion = \"v2\" as const;\n readonly provider = \"gerbil\";\n readonly modelId: string;\n\n // Gerbil runs locally, no URL support needed\n readonly supportedUrls: Record<string, RegExp[]> = {};\n\n private instance: Gerbil | null = null;\n private readonly settings: GerbilModelSettings;\n private readonly providerSettings: GerbilProviderSettings;\n private loadPromise: Promise<void> | null = null;\n\n constructor(\n modelId: string,\n settings: GerbilModelSettings,\n providerSettings: GerbilProviderSettings,\n ) {\n this.modelId = modelId;\n this.settings = settings;\n this.providerSettings = providerSettings;\n }\n\n private async ensureLoaded(): Promise<Gerbil> {\n if (this.instance?.isLoaded()) {\n return this.instance;\n }\n if (this.loadPromise) {\n await this.loadPromise;\n return this.instance!;\n }\n\n this.instance = new Gerbil();\n this.loadPromise = this.instance.loadModel(this.modelId, {\n device: this.settings.device ?? this.providerSettings.device ?? \"auto\",\n dtype: this.settings.dtype ?? this.providerSettings.dtype ?? \"q4\",\n });\n await this.loadPromise;\n return this.instance;\n }\n\n private convertPrompt(prompt: LanguageModelV2Prompt): {\n system?: string;\n user: string;\n images: ImageInput[];\n } {\n let system: string | undefined;\n let user = \"\";\n const images: ImageInput[] = [];\n\n for (const msg of prompt) {\n if (msg.role === \"system\") {\n system = msg.content;\n } else if (msg.role === \"user\") {\n for (const part of msg.content) {\n if (part.type === \"text\") {\n user += part.text;\n } else if ((part as any).type === \"image\") {\n // AI SDK v5 image part - can be URL, base64, or Uint8Array\n const imgPart = part as any;\n if (imgPart.image instanceof URL) {\n images.push({ source: imgPart.image.toString() });\n } else if (typeof imgPart.image === \"string\") {\n // base64 or URL string\n images.push({ source: imgPart.image });\n } else if (imgPart.image instanceof Uint8Array) {\n // Convert Uint8Array to base64 data URI\n const base64 = btoa(String.fromCharCode(...imgPart.image));\n const mimeType = imgPart.mimeType || \"image/png\";\n images.push({ source: `data:${mimeType};base64,${base64}` });\n }\n }\n }\n } else if (msg.role === \"assistant\") {\n for (const part of msg.content) {\n if (part.type === \"text\") {\n user += `\\n\\nAssistant: ${part.text}`;\n }\n }\n } else if (msg.role === \"tool\") {\n for (const part of msg.content) {\n user += `\\n\\nTool (${part.toolName}): ${JSON.stringify(part)}`;\n }\n }\n }\n\n return { system, user, images };\n }\n\n private mapFinishReason(reason: string): LanguageModelV2FinishReason {\n if (reason === \"stop\") {\n return \"stop\";\n }\n if (reason === \"length\") {\n return \"length\";\n }\n if (reason === \"error\") {\n return \"error\";\n }\n return \"other\";\n }\n\n async doGenerate(options: LanguageModelV2CallOptions) {\n const warnings: LanguageModelV2CallWarning[] = [];\n const g = await this.ensureLoaded();\n const { system, user, images } = this.convertPrompt(options.prompt);\n\n const result = await g.generate(user, {\n maxTokens: options.maxOutputTokens,\n temperature: options.temperature,\n topP: options.topP,\n topK: options.topK,\n system,\n thinking: this.settings.thinking,\n stopSequences: options.stopSequences,\n images: images.length > 0 ? images : undefined,\n });\n\n // Build V2 content array\n const content: LanguageModelV2Content[] = [];\n\n // Add reasoning if thinking mode was enabled\n if (result.thinking) {\n content.push({\n type: \"reasoning\",\n text: result.thinking,\n });\n }\n\n // Add main text response\n content.push({\n type: \"text\",\n text: result.text,\n });\n\n const usage: LanguageModelV2Usage = {\n inputTokens: 0,\n outputTokens: result.tokensGenerated,\n totalTokens: result.tokensGenerated,\n };\n\n return {\n content,\n finishReason: this.mapFinishReason(result.finishReason),\n usage,\n request: { body: { model: this.modelId, prompt: user } },\n warnings,\n };\n }\n\n async doStream(options: LanguageModelV2CallOptions) {\n const warnings: LanguageModelV2CallWarning[] = [];\n const g = await this.ensureLoaded();\n const { system, user, images } = this.convertPrompt(options.prompt);\n\n const streamGen = g.stream(user, {\n maxTokens: options.maxOutputTokens,\n temperature: options.temperature,\n topP: options.topP,\n topK: options.topK,\n system,\n thinking: this.settings.thinking,\n stopSequences: options.stopSequences,\n images: images.length > 0 ? images : undefined,\n });\n\n let tokens = 0;\n const textId = generateId();\n\n const stream = new ReadableStream<LanguageModelV2StreamPart>({\n async start(controller) {\n try {\n // V2: Send stream-start event first\n controller.enqueue({\n type: \"stream-start\",\n warnings,\n });\n\n // V2: Send text-start before text deltas\n controller.enqueue({\n type: \"text-start\",\n id: textId,\n });\n\n for await (const chunk of streamGen) {\n tokens += 1;\n // V2: Use 'text-delta' with id and delta\n controller.enqueue({\n type: \"text-delta\",\n id: textId,\n delta: chunk,\n });\n }\n\n // V2: Send text-end after all deltas\n controller.enqueue({\n type: \"text-end\",\n id: textId,\n });\n\n // V2: Send finish event\n controller.enqueue({\n type: \"finish\",\n finishReason: \"stop\",\n usage: {\n inputTokens: 0,\n outputTokens: tokens,\n totalTokens: tokens,\n },\n });\n controller.close();\n } catch (error) {\n controller.enqueue({ type: \"error\", error });\n controller.close();\n }\n },\n });\n\n return {\n stream,\n request: { body: { model: this.modelId, prompt: user } },\n };\n }\n}\n\n// ============================================\n// Speech Model Implementation (V2 Spec)\n// ============================================\n\n/** Settings for Gerbil speech model */\nexport interface GerbilSpeechSettings {\n /** Default voice ID (default: \"af_heart\") */\n voice?: string;\n /** Speech speed multiplier (default: 1.0) */\n speed?: number;\n}\n\nclass GerbilSpeechModel implements SpeechModelV2 {\n readonly specificationVersion = \"v2\" as const;\n readonly provider = \"gerbil\";\n readonly modelId: string;\n\n private instance: Gerbil | null = null;\n private readonly settings: GerbilSpeechSettings;\n private loadPromise: Promise<void> | null = null;\n\n constructor(modelId: string, settings: GerbilSpeechSettings = {}) {\n this.modelId = modelId;\n this.settings = settings;\n }\n\n private async ensureLoaded(): Promise<Gerbil> {\n if (this.instance?.isTTSLoaded()) {\n return this.instance;\n }\n if (this.loadPromise) {\n await this.loadPromise;\n return this.instance!;\n }\n\n this.instance = new Gerbil();\n this.loadPromise = this.instance.ensureTTSLoaded();\n await this.loadPromise;\n return this.instance;\n }\n\n async doGenerate(options: SpeechModelV2CallOptions): Promise<{\n audio: Uint8Array;\n warnings: SpeechModelV2CallWarning[];\n request?: { body?: unknown };\n response: { timestamp: Date; modelId: string };\n }> {\n const warnings: SpeechModelV2CallWarning[] = [];\n const g = await this.ensureLoaded();\n\n // Determine voice - use options.voice, fall back to settings, then default\n let voice = options.voice || this.settings.voice || \"af_heart\";\n\n // Validate voice exists\n const validVoice = KOKORO_VOICES.find((v) => v.id === voice);\n if (!validVoice) {\n warnings.push({\n type: \"unsupported-setting\",\n setting: \"voice\",\n details: `Unknown voice \"${voice}\", using default \"af_heart\"`,\n });\n voice = \"af_heart\";\n }\n\n // Determine speed\n const speed = options.speed ?? this.settings.speed ?? 1.0;\n\n // Handle unsupported options\n if (options.outputFormat && options.outputFormat !== \"wav\" && options.outputFormat !== \"raw\") {\n warnings.push({\n type: \"unsupported-setting\",\n setting: \"outputFormat\",\n details: `Gerbil TTS only supports \"wav\" and \"raw\" formats, got \"${options.outputFormat}\"`,\n });\n }\n\n if (options.instructions) {\n warnings.push({\n type: \"unsupported-setting\",\n setting: \"instructions\",\n details: \"Gerbil TTS does not support instructions parameter\",\n });\n }\n\n // Generate speech\n const result = await g.speak(options.text, { voice, speed });\n\n // Convert Float32Array to WAV format Uint8Array\n const audioData = this.float32ToWav(result.audio, result.sampleRate);\n\n return {\n audio: audioData,\n warnings,\n request: { body: { text: options.text, voice, speed } },\n response: {\n timestamp: new Date(),\n modelId: this.modelId,\n },\n };\n }\n\n /**\n * Convert Float32Array audio to WAV format Uint8Array\n */\n private float32ToWav(audio: Float32Array, sampleRate: number): Uint8Array {\n const buffer = new ArrayBuffer(44 + audio.length * 2);\n const view = new DataView(buffer);\n\n // WAV header\n const writeString = (offset: number, str: string) => {\n for (let i = 0; i < str.length; i++) {\n view.setUint8(offset + i, str.charCodeAt(i));\n }\n };\n\n writeString(0, \"RIFF\");\n view.setUint32(4, 36 + audio.length * 2, true);\n writeString(8, \"WAVE\");\n writeString(12, \"fmt \");\n view.setUint32(16, 16, true); // Subchunk1Size\n view.setUint16(20, 1, true); // AudioFormat (PCM)\n view.setUint16(22, 1, true); // NumChannels (mono)\n view.setUint32(24, sampleRate, true); // SampleRate\n view.setUint32(28, sampleRate * 2, true); // ByteRate\n view.setUint16(32, 2, true); // BlockAlign\n view.setUint16(34, 16, true); // BitsPerSample\n writeString(36, \"data\");\n view.setUint32(40, audio.length * 2, true);\n\n // Audio data (convert float32 to int16)\n for (let i = 0; i < audio.length; i++) {\n const s = Math.max(-1, Math.min(1, audio[i]));\n view.setInt16(44 + i * 2, Math.round(s * 32767), true);\n }\n\n return new Uint8Array(buffer);\n }\n}\n\n// ============================================\n// Transcription Model Implementation (V2 Spec)\n// ============================================\n\n/** Settings for Gerbil transcription model */\nexport interface GerbilTranscriptionSettings {\n /** Default language code (ISO-639-1) for transcription */\n language?: string;\n}\n\nclass GerbilTranscriptionModel implements TranscriptionModelV2 {\n readonly specificationVersion = \"v2\" as const;\n readonly provider = \"gerbil\";\n readonly modelId: string;\n\n private instance: Gerbil | null = null;\n private readonly settings: GerbilTranscriptionSettings;\n private loadPromise: Promise<void> | null = null;\n\n constructor(modelId: string, settings: GerbilTranscriptionSettings = {}) {\n this.modelId = modelId;\n this.settings = settings;\n }\n\n private async ensureLoaded(): Promise<Gerbil> {\n if (this.instance?.isSTTLoaded()) {\n return this.instance;\n }\n if (this.loadPromise) {\n await this.loadPromise;\n return this.instance!;\n }\n\n this.instance = new Gerbil();\n this.loadPromise = this.instance.loadSTT(this.modelId);\n await this.loadPromise;\n return this.instance;\n }\n\n async doGenerate(options: TranscriptionModelV2CallOptions): Promise<{\n text: string;\n segments: Array<{\n text: string;\n startSecond: number;\n endSecond: number;\n }>;\n language: string | undefined;\n durationInSeconds: number | undefined;\n warnings: TranscriptionModelV2CallWarning[];\n request?: { body?: string };\n response: {\n timestamp: Date;\n modelId: string;\n };\n }> {\n const warnings: TranscriptionModelV2CallWarning[] = [];\n const g = await this.ensureLoaded();\n\n // Convert audio to Uint8Array\n let audioData: Uint8Array;\n if (typeof options.audio === \"string\") {\n // Base64 encoded - decode it\n const binaryString = atob(options.audio);\n audioData = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n audioData[i] = binaryString.charCodeAt(i);\n }\n } else {\n audioData = options.audio;\n }\n\n // Check media type - we only support WAV natively\n const mediaType = options.mediaType?.toLowerCase() || \"\";\n if (mediaType && !mediaType.includes(\"wav\") && !mediaType.includes(\"wave\")) {\n warnings.push({\n type: \"unsupported-setting\",\n setting: \"mediaType\",\n details: `Gerbil STT natively supports WAV format. Got \"${options.mediaType}\". Audio may not decode correctly.`,\n });\n }\n\n // Determine language from provider options or settings\n const providerOpts = options.providerOptions?.gerbil as Record<string, unknown> | undefined;\n const language = (providerOpts?.language as string) || this.settings.language;\n\n // Transcribe with timestamps to get segments\n const result = await g.transcribe(audioData, {\n language,\n timestamps: true,\n });\n\n // Map segments to V2 format\n const segments = (result.segments || []).map((seg) => ({\n text: seg.text,\n startSecond: seg.start,\n endSecond: seg.end,\n }));\n\n return {\n text: result.text,\n segments,\n language: result.language,\n durationInSeconds: result.duration,\n warnings,\n request: {\n body: JSON.stringify({\n model: this.modelId,\n mediaType: options.mediaType,\n language,\n }),\n },\n response: {\n timestamp: new Date(),\n modelId: this.modelId,\n },\n };\n }\n}\n\n// ============================================\n// Provider Factory\n// ============================================\n\nexport type GerbilProvider = {\n (modelId: string, settings?: GerbilModelSettings): GerbilLanguageModel;\n languageModel(modelId: string, settings?: GerbilModelSettings): GerbilLanguageModel;\n speech(modelId?: string, settings?: GerbilSpeechSettings): GerbilSpeechModel;\n transcription(modelId?: string, settings?: GerbilTranscriptionSettings): GerbilTranscriptionModel;\n listModels(): ModelConfig[];\n getModel(modelId: string): ModelConfig | undefined;\n listVoices(): Array<{ id: string; name: string; gender: string; language: string }>;\n listTranscriptionModels(): STTModelConfig[];\n};\n\n/**\n * Create a Gerbil provider\n *\n * @example\n * ```ts\n * const local = createGerbil({ device: \"gpu\", dtype: \"q4\" });\n *\n * // Text generation\n * const { text } = await generateText({\n * model: local(\"qwen3-0.6b\"),\n * prompt: \"Hello\",\n * });\n *\n * // Speech generation\n * const audio = await generateSpeech({\n * model: local.speech(),\n * text: \"Hello world!\",\n * voice: \"af_heart\",\n * });\n *\n * // Transcription\n * const transcript = await transcribe({\n * model: local.transcription(),\n * audio: audioBuffer,\n * });\n * ```\n */\nexport function createGerbil(options: GerbilProviderSettings = {}): GerbilProvider {\n const createModel = (modelId: string, settings: GerbilModelSettings = {}) =>\n new GerbilLanguageModel(modelId, settings, options);\n\n const createSpeechModel = (modelId = \"kokoro-82m\", settings: GerbilSpeechSettings = {}) =>\n new GerbilSpeechModel(modelId, settings);\n\n const createTranscriptionModel = (\n modelId = \"whisper-tiny.en\",\n settings: GerbilTranscriptionSettings = {},\n ) => new GerbilTranscriptionModel(modelId, settings);\n\n const provider = ((modelId: string, settings?: GerbilModelSettings) =>\n createModel(modelId, settings ?? {})) as GerbilProvider;\n\n provider.languageModel = createModel;\n provider.speech = createSpeechModel;\n provider.transcription = createTranscriptionModel;\n provider.listModels = () => Object.values(BUILTIN_MODELS);\n provider.getModel = (id: string) => BUILTIN_MODELS[id];\n provider.listVoices = () =>\n KOKORO_VOICES.map((v) => ({\n id: v.id,\n name: v.name,\n gender: v.gender,\n language: v.language,\n }));\n provider.listTranscriptionModels = () => WHISPER_MODELS;\n\n return provider;\n}\n\n/**\n * Default Gerbil provider\n *\n * @example Text Generation\n * ```ts\n * import { generateText } from \"ai\";\n * import { gerbil } from \"gerbil/ai\";\n *\n * const { text } = await generateText({\n * model: gerbil(\"qwen3-0.6b\"),\n * prompt: \"Hello\",\n * });\n * ```\n *\n * @example Speech Generation\n * ```ts\n * import { experimental_generateSpeech as generateSpeech } from \"ai\";\n * import { gerbil } from \"gerbil/ai\";\n *\n * const audio = await generateSpeech({\n * model: gerbil.speech(),\n * text: \"Hello world!\",\n * voice: \"af_heart\", // Or \"bf_emma\", \"am_fenrir\", etc.\n * });\n *\n * // Access audio data\n * const audioData = audio.audioData; // Uint8Array (WAV format)\n * ```\n *\n * @example Transcription\n * ```ts\n * import { experimental_transcribe as transcribe } from \"ai\";\n * import { gerbil } from \"gerbil/ai\";\n * import { readFile } from \"fs/promises\";\n *\n * const transcript = await transcribe({\n * model: gerbil.transcription(), // whisper-tiny.en by default\n * audio: await readFile(\"audio.wav\"),\n * });\n *\n * console.log(transcript.text);\n * console.log(transcript.segments); // Timestamped segments\n * ```\n */\nexport const gerbil = createGerbil();\n\nexport default gerbil;\n"],"mappings":"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"}