@tryhamster/gerbil 1.0.0-rc.0 → 1.0.0-rc.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/README.md +79 -14
- package/dist/auto-update-DsWBBnEk.mjs +3 -0
- package/dist/browser/index.d.mts +401 -5
- package/dist/browser/index.d.mts.map +1 -1
- package/dist/browser/index.mjs +1772 -146
- package/dist/browser/index.mjs.map +1 -1
- package/dist/{chrome-backend-CtwPENIW.mjs → chrome-backend-JEPeM2YE.mjs} +1 -1
- package/dist/{chrome-backend-C5Un08O4.mjs → chrome-backend-Y9F7W5VQ.mjs} +514 -73
- package/dist/chrome-backend-Y9F7W5VQ.mjs.map +1 -0
- package/dist/cli.mjs +3359 -646
- package/dist/cli.mjs.map +1 -1
- package/dist/frameworks/express.d.mts +1 -1
- package/dist/frameworks/express.mjs +3 -3
- package/dist/frameworks/fastify.d.mts +1 -1
- package/dist/frameworks/fastify.mjs +3 -3
- package/dist/frameworks/hono.d.mts +1 -1
- package/dist/frameworks/hono.mjs +3 -3
- package/dist/frameworks/next.d.mts +2 -2
- package/dist/frameworks/next.mjs +3 -3
- package/dist/frameworks/react.d.mts +1 -1
- package/dist/frameworks/trpc.d.mts +1 -1
- package/dist/frameworks/trpc.mjs +3 -3
- package/dist/gerbil-DeQlX_Mt.mjs +5 -0
- package/dist/gerbil-POAz8peb.d.mts +431 -0
- package/dist/gerbil-POAz8peb.d.mts.map +1 -0
- package/dist/gerbil-yoSpRHgv.mjs +1463 -0
- package/dist/gerbil-yoSpRHgv.mjs.map +1 -0
- package/dist/index.d.mts +395 -9
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +8 -6
- package/dist/index.mjs.map +1 -1
- package/dist/integrations/ai-sdk.d.mts +122 -4
- package/dist/integrations/ai-sdk.d.mts.map +1 -1
- package/dist/integrations/ai-sdk.mjs +239 -11
- package/dist/integrations/ai-sdk.mjs.map +1 -1
- package/dist/integrations/langchain.d.mts +132 -2
- package/dist/integrations/langchain.d.mts.map +1 -1
- package/dist/integrations/langchain.mjs +176 -8
- package/dist/integrations/langchain.mjs.map +1 -1
- package/dist/integrations/llamaindex.d.mts +1 -1
- package/dist/integrations/llamaindex.mjs +3 -3
- package/dist/integrations/mcp-client.mjs +4 -4
- package/dist/integrations/mcp-client.mjs.map +1 -1
- package/dist/integrations/mcp.d.mts +2 -2
- package/dist/integrations/mcp.d.mts.map +1 -1
- package/dist/integrations/mcp.mjs +6 -6
- package/dist/{mcp-R8kRLIKb.mjs → mcp-Bitg4sjX.mjs} +10 -37
- package/dist/mcp-Bitg4sjX.mjs.map +1 -0
- package/dist/microphone-D-6y9aiE.mjs +3 -0
- package/dist/{models-DKULvhOr.mjs → models-BAtL8qsA.mjs} +42 -7
- package/dist/models-BAtL8qsA.mjs.map +1 -0
- package/dist/{models-De2-_GmQ.d.mts → models-CE0fBq0U.d.mts} +2 -2
- package/dist/models-CE0fBq0U.d.mts.map +1 -0
- package/dist/{one-liner-BUQR0nqq.mjs → one-liner-B1rmFto6.mjs} +2 -2
- package/dist/{one-liner-BUQR0nqq.mjs.map → one-liner-B1rmFto6.mjs.map} +1 -1
- package/dist/repl-D20JO260.mjs +10 -0
- package/dist/skills/index.d.mts +303 -12
- package/dist/skills/index.d.mts.map +1 -1
- package/dist/skills/index.mjs +6 -6
- package/dist/skills-5DxAV-rn.mjs +1435 -0
- package/dist/skills-5DxAV-rn.mjs.map +1 -0
- package/dist/stt-Bv_dum-R.mjs +433 -0
- package/dist/stt-Bv_dum-R.mjs.map +1 -0
- package/dist/stt-KzSoNvwI.mjs +3 -0
- package/dist/{tools-BsiEE6f2.mjs → tools-IYPrqoek.mjs} +6 -7
- package/dist/{tools-BsiEE6f2.mjs.map → tools-IYPrqoek.mjs.map} +1 -1
- package/dist/tts-5yWeP_I0.mjs +3 -0
- package/dist/tts-DG6denWG.mjs +729 -0
- package/dist/tts-DG6denWG.mjs.map +1 -0
- package/dist/types-s6Py2_DL.d.mts +353 -0
- package/dist/types-s6Py2_DL.d.mts.map +1 -0
- package/dist/{utils-7vXqtq2Q.mjs → utils-CkB4Roi6.mjs} +1 -1
- package/dist/{utils-7vXqtq2Q.mjs.map → utils-CkB4Roi6.mjs.map} +1 -1
- package/docs/ai-sdk.md +137 -21
- package/docs/browser.md +241 -2
- package/docs/memory.md +72 -0
- package/docs/stt.md +494 -0
- package/docs/tts.md +569 -0
- package/docs/vision.md +396 -0
- package/package.json +17 -18
- package/dist/auto-update-BbNHbSU1.mjs +0 -3
- package/dist/chrome-backend-C5Un08O4.mjs.map +0 -1
- package/dist/gerbil-BfnsFWRE.mjs +0 -644
- package/dist/gerbil-BfnsFWRE.mjs.map +0 -1
- package/dist/gerbil-BjW-z7Fq.mjs +0 -5
- package/dist/gerbil-DZ1k3ChC.d.mts +0 -138
- package/dist/gerbil-DZ1k3ChC.d.mts.map +0 -1
- package/dist/mcp-R8kRLIKb.mjs.map +0 -1
- package/dist/models-DKULvhOr.mjs.map +0 -1
- package/dist/models-De2-_GmQ.d.mts.map +0 -1
- package/dist/skills-D3CEpgDc.mjs +0 -630
- package/dist/skills-D3CEpgDc.mjs.map +0 -1
- package/dist/types-BS1N92Jt.d.mts +0 -183
- package/dist/types-BS1N92Jt.d.mts.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
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":";;;;;
|
|
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
|
|
2
|
-
import "../
|
|
3
|
-
import
|
|
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()}-${
|
|
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":"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"}
|
|
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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"}
|