@tryhamster/gerbil 1.0.0-rc.8 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +247 -84
  3. package/dist/architectures-C1I5V3Dt.mjs +6070 -0
  4. package/dist/architectures-C1I5V3Dt.mjs.map +1 -0
  5. package/dist/browser/index.d.ts +264 -588
  6. package/dist/browser/index.d.ts.map +1 -1
  7. package/dist/browser/index.js +585 -2334
  8. package/dist/browser/index.js.map +1 -1
  9. package/dist/cli.mjs +625 -1098
  10. package/dist/cli.mjs.map +1 -1
  11. package/dist/defaults-9komdrbY.mjs +24 -0
  12. package/dist/defaults-9komdrbY.mjs.map +1 -0
  13. package/dist/frameworks/express.d.mts +1 -3
  14. package/dist/frameworks/express.d.mts.map +1 -1
  15. package/dist/frameworks/express.mjs +7 -7
  16. package/dist/frameworks/express.mjs.map +1 -1
  17. package/dist/frameworks/fastify.d.mts +1 -1
  18. package/dist/frameworks/fastify.d.mts.map +1 -1
  19. package/dist/frameworks/fastify.mjs +3 -3
  20. package/dist/frameworks/fastify.mjs.map +1 -1
  21. package/dist/frameworks/hono.d.mts +1 -1
  22. package/dist/frameworks/hono.d.mts.map +1 -1
  23. package/dist/frameworks/hono.mjs +4 -4
  24. package/dist/frameworks/hono.mjs.map +1 -1
  25. package/dist/frameworks/next.d.mts +3 -2
  26. package/dist/frameworks/next.d.mts.map +1 -1
  27. package/dist/frameworks/next.mjs +4 -4
  28. package/dist/frameworks/next.mjs.map +1 -1
  29. package/dist/frameworks/react.d.mts +1 -1
  30. package/dist/frameworks/trpc.d.mts +1 -1
  31. package/dist/frameworks/trpc.d.mts.map +1 -1
  32. package/dist/frameworks/trpc.mjs +4 -4
  33. package/dist/frameworks/trpc.mjs.map +1 -1
  34. package/dist/gerbil-BHrJJIa4.mjs +1656 -0
  35. package/dist/gerbil-BHrJJIa4.mjs.map +1 -0
  36. package/dist/gerbil-BT9fCydo.d.mts +488 -0
  37. package/dist/gerbil-BT9fCydo.d.mts.map +1 -0
  38. package/dist/gerbil-DomNfIr1.mjs +4 -0
  39. package/dist/gpu/hooks.d.mts +520 -0
  40. package/dist/gpu/hooks.d.mts.map +1 -0
  41. package/dist/gpu/hooks.mjs +1188 -0
  42. package/dist/gpu/hooks.mjs.map +1 -0
  43. package/dist/gpu/index.d.mts +2 -0
  44. package/dist/gpu/index.mjs +6 -0
  45. package/dist/gpu-33qCAtHW.mjs +3615 -0
  46. package/dist/gpu-33qCAtHW.mjs.map +1 -0
  47. package/dist/index-Dgmb2kE3.d.mts +245 -0
  48. package/dist/index-Dgmb2kE3.d.mts.map +1 -0
  49. package/dist/index-jEAL2s-A.d.mts +2022 -0
  50. package/dist/index-jEAL2s-A.d.mts.map +1 -0
  51. package/dist/index.d.mts +22 -487
  52. package/dist/index.d.mts.map +1 -1
  53. package/dist/index.mjs +13 -8
  54. package/dist/index.mjs.map +1 -1
  55. package/dist/indexeddb-store-BWIMtxxH.mjs +103 -0
  56. package/dist/indexeddb-store-BWIMtxxH.mjs.map +1 -0
  57. package/dist/indexeddb-store-ClH12Xnl.mjs +4 -0
  58. package/dist/integrations/ai-sdk.d.mts +75 -6
  59. package/dist/integrations/ai-sdk.d.mts.map +1 -1
  60. package/dist/integrations/ai-sdk.mjs +131 -15
  61. package/dist/integrations/ai-sdk.mjs.map +1 -1
  62. package/dist/integrations/langchain.d.mts +1 -1
  63. package/dist/integrations/langchain.d.mts.map +1 -1
  64. package/dist/integrations/langchain.mjs +5 -5
  65. package/dist/integrations/langchain.mjs.map +1 -1
  66. package/dist/integrations/llamaindex.d.mts +1 -1
  67. package/dist/integrations/llamaindex.d.mts.map +1 -1
  68. package/dist/integrations/llamaindex.mjs +5 -5
  69. package/dist/integrations/llamaindex.mjs.map +1 -1
  70. package/dist/integrations/mcp-client.mjs +3 -3
  71. package/dist/integrations/mcp-client.mjs.map +1 -1
  72. package/dist/integrations/mcp.d.mts +3 -2
  73. package/dist/integrations/mcp.d.mts.map +1 -1
  74. package/dist/integrations/mcp.mjs +5 -5
  75. package/dist/{mcp-BvbriaBy.mjs → mcp-1DaMsaBc.mjs} +4 -4
  76. package/dist/mcp-1DaMsaBc.mjs.map +1 -0
  77. package/dist/memory/index.d.mts +3 -0
  78. package/dist/memory/index.mjs +6 -0
  79. package/dist/memory-D1P7Tmda.mjs +4 -0
  80. package/dist/memory-DVN0MnIG.mjs +132 -0
  81. package/dist/memory-DVN0MnIG.mjs.map +1 -0
  82. package/dist/memory-Dj0J1v88.mjs +294 -0
  83. package/dist/memory-Dj0J1v88.mjs.map +1 -0
  84. package/dist/moonshine-stt-BLyVoRpB.mjs +4 -0
  85. package/dist/moonshine-stt-v_P_Ci_m.mjs +11936 -0
  86. package/dist/moonshine-stt-v_P_Ci_m.mjs.map +1 -0
  87. package/dist/{one-liner-s-lD8rCC.mjs → one-liner-DnQn7HJK.mjs} +14 -16
  88. package/dist/one-liner-DnQn7HJK.mjs.map +1 -0
  89. package/dist/repl-jV5gcJFA.mjs +9 -0
  90. package/dist/skills/index.d.mts +270 -320
  91. package/dist/skills/index.d.mts.map +1 -1
  92. package/dist/skills/index.mjs +5 -5
  93. package/dist/{skills-CD3Orlex.mjs → skills-DX8D59UH.mjs} +187 -32
  94. package/dist/skills-DX8D59UH.mjs.map +1 -0
  95. package/dist/{tools-Bi1P7Xoy.mjs → tools-DQ1mPUw5.mjs} +34 -22
  96. package/dist/tools-DQ1mPUw5.mjs.map +1 -0
  97. package/dist/{types-CiTc7ez3.d.mts → types-D6FiR_oh.d.mts} +106 -12
  98. package/dist/types-D6FiR_oh.d.mts.map +1 -0
  99. package/dist/types-DQBe2lFo.d.mts +165 -0
  100. package/dist/types-DQBe2lFo.d.mts.map +1 -0
  101. package/dist/{utils-CZBZ8dgR.mjs → utils-DKO55ZmZ.mjs} +1 -1
  102. package/dist/{utils-CZBZ8dgR.mjs.map → utils-DKO55ZmZ.mjs.map} +1 -1
  103. package/dist/vector-B0panuy6.mjs +95 -0
  104. package/dist/vector-B0panuy6.mjs.map +1 -0
  105. package/docs/PROJECT-STATE.md +321 -0
  106. package/docs/adding-a-model-family.md +280 -0
  107. package/docs/ai-sdk.md +70 -61
  108. package/docs/architecture/overview.md +17 -7
  109. package/docs/browser.md +203 -8
  110. package/docs/embeddings.md +156 -0
  111. package/docs/gerbil-site-native-migration.md +217 -0
  112. package/docs/gpu-engine/architectures.md +398 -0
  113. package/docs/gpu-engine/ir.md +372 -0
  114. package/docs/gpu-engine/kernels.md +718 -0
  115. package/docs/gpu-engine/paper.html +1759 -0
  116. package/docs/gpu-engine/paper.md +2109 -0
  117. package/docs/gpu-engine/safetensors.md +312 -0
  118. package/docs/gpu-engine/tokenizer.md +302 -0
  119. package/docs/memory-rag.md +91 -0
  120. package/docs/metal-safari-intel.md +190 -0
  121. package/docs/mobile-failure-diagnosis.md +124 -0
  122. package/docs/mobile.md +99 -0
  123. package/docs/observability.md +230 -0
  124. package/docs/onnx-removal-plan.md +339 -0
  125. package/docs/research/autoresearch-portable.md +904 -0
  126. package/docs/research/dispatch-reduction-hivemind.md +84 -0
  127. package/docs/research/ios-safari-model-caching.md +117 -0
  128. package/docs/research/mobile-webgpu-speed-fusion.md +135 -0
  129. package/docs/research/native-stt-model-selection.md +49 -0
  130. package/docs/research/native-tts-model-selection.md +90 -0
  131. package/docs/research/native-vs-chromium-decision.md +152 -0
  132. package/docs/research/nemotron-mamba2-inference.md +910 -0
  133. package/docs/research/qwen35-multimodal.md +293 -0
  134. package/docs/research/qwen36-gemma4-targets.md +337 -0
  135. package/docs/research/sota-embedding-models.md +179 -0
  136. package/docs/research/sota-mobile-models-2026.md +263 -0
  137. package/docs/research/sota-modality-models.md +202 -0
  138. package/docs/research/tps-baselines.md +71 -0
  139. package/docs/research/webgpu-m4-reference.md +104 -0
  140. package/docs/site-update-plan.md +155 -0
  141. package/docs/structured-output.md +123 -0
  142. package/docs/stt.md +63 -446
  143. package/docs/tts.md +77 -499
  144. package/docs/vision.md +100 -338
  145. package/package.json +22 -7
  146. package/dist/chrome-backend-CORwaIyC.mjs +0 -1212
  147. package/dist/chrome-backend-CORwaIyC.mjs.map +0 -1
  148. package/dist/chrome-backend-DIKYoWj-.mjs +0 -3
  149. package/dist/gerbil-CJ3ifloF.mjs +0 -4
  150. package/dist/gerbil-Dw4Qj77e.mjs +0 -1631
  151. package/dist/gerbil-Dw4Qj77e.mjs.map +0 -1
  152. package/dist/gerbil-qOTe1nl2.d.mts +0 -431
  153. package/dist/gerbil-qOTe1nl2.d.mts.map +0 -1
  154. package/dist/kokoro-BNTb6egA.mjs +0 -20210
  155. package/dist/kokoro-BNTb6egA.mjs.map +0 -1
  156. package/dist/kokoro-DFRQ1OeM.js +0 -20212
  157. package/dist/kokoro-DFRQ1OeM.js.map +0 -1
  158. package/dist/mcp-BvbriaBy.mjs.map +0 -1
  159. package/dist/one-liner-s-lD8rCC.mjs.map +0 -1
  160. package/dist/repl-DveXw36T.mjs +0 -9
  161. package/dist/skills-CD3Orlex.mjs.map +0 -1
  162. package/dist/stt-CpLYbGFd.mjs +0 -433
  163. package/dist/stt-CpLYbGFd.mjs.map +0 -1
  164. package/dist/stt-DRPLEEHB.mjs +0 -3
  165. package/dist/stt-Te8Qz-Ay.js +0 -433
  166. package/dist/stt-Te8Qz-Ay.js.map +0 -1
  167. package/dist/tools-Bi1P7Xoy.mjs.map +0 -1
  168. package/dist/transformers.web-DokyH3rP.js +0 -3
  169. package/dist/transformers.web-M6mCnEYJ.js +0 -30382
  170. package/dist/transformers.web-M6mCnEYJ.js.map +0 -1
  171. package/dist/tts-C0xx3CtE.js +0 -724
  172. package/dist/tts-C0xx3CtE.js.map +0 -1
  173. package/dist/tts-DXgsKGCe.mjs +0 -3
  174. package/dist/tts-DeGANMNV.mjs +0 -730
  175. package/dist/tts-DeGANMNV.mjs.map +0 -1
  176. package/dist/types-CiTc7ez3.d.mts.map +0 -1
  177. /package/dist/{auto-update-S9s5-g0C.mjs → auto-update-BVaLXcDE.mjs} +0 -0
  178. /package/dist/{chunk-CkXuGtQK.mjs → chunk-B9cbKln6.mjs} +0 -0
  179. /package/dist/{microphone-DaMZFRuR.mjs → microphone-Bqmoz9_K.mjs} +0 -0
@@ -92,16 +92,47 @@ type EmbedResult = {
92
92
  /** Time in ms */
93
93
  totalTime: number;
94
94
  };
95
+ type SearchResult = {
96
+ /** The matched text */
97
+ text: string;
98
+ /** Similarity score (0-1, higher is more similar) */
99
+ score: number;
100
+ /** Index in the original corpus */
101
+ index: number;
102
+ };
103
+ type SimilarityResult = {
104
+ /** Similarity score (0-1, higher is more similar) */
105
+ score: number;
106
+ /** First text */
107
+ textA: string;
108
+ /** Second text */
109
+ textB: string;
110
+ /** Time in ms */
111
+ totalTime: number;
112
+ };
95
113
  type LoadOptions = {
96
114
  /** Progress callback */
97
115
  onProgress?: (info: ProgressInfo) => void;
98
- /** Device: 'auto', 'gpu', 'cpu', 'webgpu' (default: 'auto') */
99
- device?: "auto" | "gpu" | "cpu" | "webgpu";
100
- /** Quantization: 'q4', 'q8', 'fp16', 'fp32' (default: 'q4') */
116
+ /**
117
+ * Compute device. The only inference backend is the native WebGPU engine
118
+ * (Dawn in Node, WebGPU in the browser); "auto" resolves to "webgpu". There
119
+ * is no CPU/WASM or ONNX path.
120
+ */
121
+ device?: "auto" | "webgpu";
122
+ /**
123
+ * Weight quantization. The engine quantizes to INT4 ("q4") on load; the other
124
+ * values are accepted for forward-compat but currently map to q4.
125
+ */
101
126
  dtype?: "q4" | "q8" | "fp16" | "fp32";
102
127
  /** Override context length */
103
128
  contextLength?: number;
104
129
  };
130
+ type PreloadOptions = {
131
+ /** Progress callback for download status */
132
+ onProgress?: (info: ProgressInfo) => void;
133
+ /** Keep model loaded in memory after preload (default: false - disposes to free memory) */
134
+ keepLoaded?: boolean;
135
+ };
105
136
  type ProgressInfo = {
106
137
  status: string;
107
138
  progress?: number;
@@ -112,14 +143,18 @@ type ProgressInfo = {
112
143
  type GerbilConfig = {
113
144
  /** Default model */
114
145
  model?: string;
115
- /** Default device */
116
- device?: "auto" | "gpu" | "cpu";
117
- /** Default quantization */
146
+ /** Default device (native WebGPU only; "auto" resolves to "webgpu") */
147
+ device?: "auto" | "webgpu";
148
+ /** Default quantization (engine uses INT4 "q4") */
118
149
  dtype?: "q4" | "q8" | "fp16" | "fp32";
119
150
  /** Cache configuration */
120
151
  cache?: CacheConfig;
121
152
  /** Fallback configuration */
122
153
  fallback?: FallbackConfig;
154
+ /** Telemetry hooks for observability (Sentry, logging, etc.) */
155
+ telemetry?: TelemetryConfig;
156
+ /** Concurrency control for request queuing */
157
+ concurrency?: ConcurrencyConfig;
123
158
  };
124
159
  type CacheConfig = {
125
160
  /** Enable caching (default: true) */
@@ -183,14 +218,14 @@ type SystemInfo = {
183
218
  type GerbilModelSettings = {
184
219
  /** Enable thinking mode */
185
220
  thinking?: boolean;
186
- /** Device to use */
187
- device?: "auto" | "gpu" | "cpu";
221
+ /** Device to use (native WebGPU only) */
222
+ device?: "auto" | "webgpu";
188
223
  /** Quantization level */
189
224
  dtype?: "q4" | "q8" | "fp16" | "fp32";
190
225
  };
191
226
  type GerbilProviderSettings = {
192
- /** Default device */
193
- device?: "auto" | "gpu" | "cpu";
227
+ /** Default device (native WebGPU only) */
228
+ device?: "auto" | "webgpu";
194
229
  /** Default quantization */
195
230
  dtype?: "q4" | "q8" | "fp16" | "fp32";
196
231
  };
@@ -348,381 +383,150 @@ type StreamingTranscriptionSession = {
348
383
  /** Reset session (clear buffer and transcript) */
349
384
  reset: () => void;
350
385
  };
351
- //#endregion
352
- //#region src/core/models.d.ts
353
- declare const BUILTIN_MODELS: Record<string, ModelConfig>;
354
- //#endregion
355
- //#region src/browser/index.d.ts
356
-
357
- type WorkerProgress = {
358
- status: "loading" | "downloading" | "ready" | "error";
359
- message?: string;
360
- file?: string;
361
- progress?: number;
362
- /** Number of files being downloaded (0 = loading from cache) */
363
- downloadCount?: number;
364
- /** Total files to process */
365
- totalFiles?: number;
366
- error?: string;
367
- };
368
- type WorkerToken = {
369
- status: "token";
370
- text: string;
371
- state: "thinking" | "answering";
372
- numTokens: number;
373
- tps: number;
374
- };
375
- type WorkerComplete = {
376
- status: "complete";
377
- text: string;
378
- numTokens: number;
379
- totalTime: number;
380
- tps: number;
381
- };
382
- type GerbilWorkerOptions = {
383
- /** Model ID to load (default: "qwen3-0.6b") */
384
- modelId?: string;
385
- /** Called during model loading with progress updates */
386
- onProgress?: (progress: WorkerProgress) => void;
387
- /** Called for each token during streaming generation */
388
- onToken?: (token: WorkerToken) => void;
389
- /** Called when generation is complete */
390
- onComplete?: (result: WorkerComplete) => void;
391
- /** Called on errors */
392
- onError?: (error: string) => void;
393
- /** Worker script URL (auto-detected if not provided) */
394
- workerUrl?: string;
395
- };
396
- type GenerateStreamOptions = {
397
- /** Maximum tokens to generate */
398
- maxTokens?: number;
399
- /** Temperature for sampling (0 = deterministic) */
400
- temperature?: number;
401
- /** Top-p nucleus sampling */
402
- topP?: number;
403
- /** Top-k sampling */
404
- topK?: number;
405
- /** Enable thinking mode (Qwen3) */
406
- thinking?: boolean;
407
- /** System prompt */
408
- system?: string;
409
- /** Image URLs or data URIs (for vision models) */
410
- images?: string[];
411
- /** Conversation history for multi-turn (includes all previous messages) */
412
- history?: Array<{
413
- role: "user" | "assistant" | "system";
414
- content: string;
415
- }>;
416
- };
417
- type GerbilWorker = {
418
- /** Generate text with streaming */
419
- generate: (prompt: string, options?: GenerateStreamOptions) => Promise<string>;
420
- /** Interrupt current generation */
421
- interrupt: () => void;
422
- /** Reset conversation cache */
423
- reset: () => void;
424
- /** Terminate the worker */
425
- terminate: () => void;
426
- /** Check if model is loaded */
427
- isReady: () => boolean;
428
- };
429
386
  /**
430
- * Create a Gerbil worker for streaming WebGPU inference
431
- *
432
- * Uses a Web Worker to keep the UI responsive during model loading
433
- * and text generation, with real-time token streaming.
387
+ * Telemetry hooks for production observability.
388
+ * Pass your own Sentry instance or custom logging functions.
434
389
  */
435
- declare function createGerbilWorker(options?: GerbilWorkerOptions): Promise<GerbilWorker>;
436
- /** Message in a chat conversation */
437
- type Message = {
438
- id: string;
439
- role: "user" | "assistant";
440
- content: string;
441
- thinking?: string;
442
- /** Attached images (URLs or data URIs) - for vision models */
443
- images?: string[];
444
- };
445
- /** Loading progress state */
446
- type LoadingProgress = {
447
- status: "loading" | "downloading" | "ready" | "error";
448
- message?: string;
449
- file?: string;
450
- progress?: number;
451
- /** Number of files being downloaded (0 = loading from cache) */
452
- downloadCount?: number;
453
- /** Total files to process */
454
- totalFiles?: number;
455
- };
456
- /** Options for useChat hook */
457
- type UseChatOptions = {
458
- /** Model ID (default: "qwen3-0.6b") */
459
- model?: string;
460
- /** System prompt */
461
- system?: string;
462
- /** Enable thinking mode (Qwen3) */
463
- thinking?: boolean;
464
- /** Max tokens per response */
465
- maxTokens?: number;
466
- /** Temperature (0-2) */
467
- temperature?: number;
468
- /** Initial messages */
469
- initialMessages?: Message[];
470
- /** Auto-load model on mount (default: false - loads on first generate or load()) */
471
- autoLoad?: boolean;
472
- /** Called when model is ready */
473
- onReady?: () => void;
474
- /** Called on error */
475
- onError?: (error: string) => void;
476
- };
477
- /** Return type for useChat hook */
478
- type UseChatReturn = {
479
- /** Chat messages */
480
- messages: Message[];
481
- /** Current input value */
482
- input: string;
483
- /** Set input value */
484
- setInput: (value: string) => void;
485
- /** Submit current input */
486
- handleSubmit: (e?: {
487
- preventDefault?: () => void;
488
- }) => void;
489
- /** Whether model is loading */
490
- isLoading: boolean;
491
- /** Loading progress */
492
- loadingProgress: LoadingProgress | null;
493
- /** Whether generating a response */
494
- isGenerating: boolean;
495
- /** Current thinking content (streaming) */
496
- thinking: string;
497
- /** Stop generation */
498
- stop: () => void;
499
- /** Clear all messages */
500
- clear: () => void;
501
- /** Current tokens per second */
502
- tps: number;
503
- /** Whether model is ready */
504
- isReady: boolean;
505
- /** Error message if any */
506
- error: string | null;
507
- /** Load the model (only needed if lazy: true) */
508
- load: () => void;
509
- /** Currently attached images (for next message) */
510
- attachedImages: string[];
511
- /** Attach an image to the next message */
512
- attachImage: (imageUrl: string) => void;
513
- /** Remove an attached image */
514
- removeImage: (index: number) => void;
515
- /** Clear all attached images */
516
- clearImages: () => void;
517
- /** Send message with specific images (convenience method) */
518
- sendWithImages: (text: string, images: string[]) => void;
390
+ type TelemetryConfig = {
391
+ /**
392
+ * Called after successful generation with full result and timing.
393
+ * Use for logging, metrics, or analytics.
394
+ */
395
+ onGenerate?: (event: GenerateEvent) => void;
396
+ /**
397
+ * Called when any error occurs during Gerbil operations.
398
+ * Perfect for Sentry.captureException() or similar.
399
+ */
400
+ onError?: (error: Error, context: ErrorContext) => void;
401
+ /**
402
+ * Called after model loading completes (success or failure).
403
+ */
404
+ onModelLoad?: (event: ModelLoadEvent) => void;
405
+ /**
406
+ * Called when a request is queued (if concurrency limit reached).
407
+ */
408
+ onQueueWait?: (waitTimeMs: number) => void;
409
+ };
410
+ type GenerateEvent = {
411
+ /** Model used for generation */
412
+ modelId: string;
413
+ /** Generation result */
414
+ result: GenerateResult;
415
+ /** Whether response came from cache */
416
+ cached: boolean;
417
+ /** Time spent waiting in queue (if any) */
418
+ queueTimeMs?: number;
519
419
  };
520
420
  /**
521
- * React hook for chat with local LLM
522
- *
523
- * @example
524
- * ```tsx
525
- * import { useChat } from "@tryhamster/gerbil/browser";
526
- *
527
- * function Chat() {
528
- * const { messages, input, setInput, handleSubmit, isLoading, isGenerating } = useChat();
529
- *
530
- * if (isLoading) return <div>Loading model...</div>;
531
- *
532
- * return (
533
- * <div>
534
- * {messages.map(m => (
535
- * <div key={m.id}>{m.role}: {m.content}</div>
536
- * ))}
537
- * <form onSubmit={handleSubmit}>
538
- * <input value={input} onChange={e => setInput(e.target.value)} />
539
- * <button disabled={isGenerating}>Send</button>
540
- * </form>
541
- * </div>
542
- * );
543
- * }
544
- * ```
421
+ * Context passed to telemetry onError callback.
422
+ * Flexible record to allow any relevant context data.
545
423
  */
546
- declare function useChat(options?: UseChatOptions): UseChatReturn;
547
- /** Options for useCompletion hook */
548
- type UseCompletionOptions = {
549
- /** Model ID (default: "qwen3-0.6b") */
550
- model?: string;
551
- /** System prompt */
552
- system?: string;
553
- /** Enable thinking mode (Qwen3) */
554
- thinking?: boolean;
555
- /** Max tokens */
556
- maxTokens?: number;
557
- /** Temperature (0-2) */
558
- temperature?: number;
559
- /** Auto-load model on mount (default: false - loads on first complete() or load()) */
560
- autoLoad?: boolean;
561
- /** Called when model is ready */
562
- onReady?: () => void;
563
- /** Called on error */
564
- onError?: (error: string) => void;
424
+ type ErrorContext = Record<string, unknown>;
425
+ type ModelLoadEvent = {
426
+ /** Model that was loaded */
427
+ modelId: string;
428
+ /** Time to load in ms */
429
+ loadTimeMs: number;
430
+ /** Whether loaded from cache */
431
+ fromCache: boolean;
432
+ /** Device used */
433
+ device: "webgpu" | "cpu" | "wasm";
434
+ /** Whether load succeeded */
435
+ success: boolean;
436
+ /** Error message if failed */
437
+ error?: string;
565
438
  };
566
- /** Options for single completion call */
567
- type CompleteOptions = {
568
- /** Image URLs or data URIs to analyze (for vision models) */
569
- images?: string[];
570
- };
571
- /** Return type for useCompletion hook */
572
- type UseCompletionReturn = {
573
- /** Generated completion */
574
- completion: string;
575
- /** Thinking content (if enabled) */
576
- thinking: string;
577
- /** Generate completion (optionally with images for vision models) */
578
- complete: (prompt: string, options?: CompleteOptions) => Promise<string>;
579
- /** Whether model is loading */
580
- isLoading: boolean;
581
- /** Loading progress */
582
- loadingProgress: LoadingProgress | null;
583
- /** Whether generating */
584
- isGenerating: boolean;
585
- /** Stop generation */
586
- stop: () => void;
587
- /** Current tokens per second */
588
- tps: number;
589
- /** Whether model is ready */
590
- isReady: boolean;
591
- /** Error message if any */
592
- error: string | null;
593
- /** Load the model (only needed if lazy: true) */
594
- load: () => void;
439
+ type ConcurrencyConfig = {
440
+ /** Maximum concurrent generation requests (default: 1 for LLM) */
441
+ maxConcurrent?: number;
442
+ /** Request timeout in ms (default: 300000 = 5 min) */
443
+ timeout?: number;
595
444
  };
445
+ //#endregion
446
+ //#region src/core/models.d.ts
447
+ declare const BUILTIN_MODELS: Record<string, ModelConfig>;
448
+ //#endregion
449
+ //#region src/browser/pwa.d.ts
596
450
  /**
597
- * React hook for text completion with local LLM
451
+ * Mobile / PWA storage helpers.
598
452
  *
599
- * @example
600
- * ```tsx
601
- * import { useCompletion } from "@tryhamster/gerbil/browser";
453
+ * On-device models are large (a 4-bit 0.8B is ~400 MB; vision/larger models are
454
+ * GBs). Mobile browsers — iOS Safari especially — wall a web origin off from the
455
+ * real disk with TWO independent ceilings:
602
456
  *
603
- * function App() {
604
- * const { complete, completion, isLoading, isGenerating } = useCompletion();
457
+ * 1. **Storage quota** (disk for the model cache). An *uninstalled* Safari tab
458
+ * gets only ~1 GB, best-effort and evictable, regardless of how much free
459
+ * disk the device has. Exceed it and every cache write fails → the model
460
+ * re-downloads on every visit.
461
+ * 2. **Tab memory** (RAM during load/inference) — a separate, smaller ceiling.
605
462
  *
606
- * if (isLoading) return <div>Loading...</div>;
463
+ * The unlock for the storage ceiling is **persistent storage**, which iOS Safari
464
+ * grants when the site is **installed to the Home Screen** (a PWA). Installed, the
465
+ * quota jumps to a large fraction of actual disk and is never evicted — so models
466
+ * cache once and stay. These helpers let an app surface that to its users and
467
+ * request it, so on-device AI is actually practical on mobile.
607
468
  *
608
- * return (
609
- * <div>
610
- * <button onClick={() => complete("Write a haiku")}>Generate</button>
611
- * <p>{completion}</p>
612
- * </div>
613
- * );
614
- * }
615
- * ```
469
+ * All functions are SSR/Node-safe (guarded; return conservative defaults).
616
470
  */
617
- declare function useCompletion(options?: UseCompletionOptions): UseCompletionReturn;
618
- /** TTS loading progress */
619
- type TTSProgress = {
620
- status: "idle" | "loading" | "downloading" | "ready" | "error";
621
- message?: string;
622
- file?: string;
623
- progress?: number;
624
- error?: string;
625
- };
626
- /** Available TTS models */
627
- type TTSModelId = "kokoro-82m" | "supertonic-66m";
628
- /** Voice info for TTS models */
629
- type BrowserVoiceInfo = {
630
- id: string;
631
- name: string;
632
- gender: "male" | "female";
633
- language: string;
634
- description: string;
635
- };
636
- /** Options for useSpeech hook */
637
- type UseSpeechOptions = {
638
- /** TTS model to use (default: "kokoro-82m") */
639
- model?: TTSModelId;
640
- /** Default voice ID (default: model's default voice) */
641
- voice?: string;
642
- /** Speech speed multiplier (default: 1.0) */
643
- speed?: number;
644
- /** Auto-load TTS model on mount (default: false) */
645
- autoLoad?: boolean;
646
- /** Called when model is ready */
647
- onReady?: () => void;
648
- /** Called on error */
649
- onError?: (error: string) => void;
650
- /** Called when speech starts */
651
- onStart?: () => void;
652
- /** Called when speech ends */
653
- onEnd?: () => void;
654
- };
655
- /** Return type for useSpeech hook */
656
- type UseSpeechReturn = {
657
- /** Speak text aloud */
658
- speak: (text: string, options?: {
659
- voice?: string;
660
- speed?: number;
661
- }) => Promise<void>;
662
- /** Stop current speech */
663
- stop: () => void;
664
- /** Whether TTS model is loading */
665
- isLoading: boolean;
666
- /** Loading progress */
667
- loadingProgress: TTSProgress | null;
668
- /** Whether currently speaking */
669
- isSpeaking: boolean;
670
- /** Whether TTS model is ready */
671
- isReady: boolean;
672
- /** Load the TTS model */
673
- load: () => void;
674
- /** Error message if any */
675
- error: string | null;
676
- /** List available voices for current model */
677
- listVoices: () => BrowserVoiceInfo[];
678
- /** Current voice ID */
679
- currentVoice: string;
680
- /** Set current voice */
681
- setVoice: (voiceId: string) => void;
682
- /** Current speed */
683
- currentSpeed: number;
684
- /** Set speed */
685
- setSpeed: (speed: number) => void;
686
- /** Current TTS model ID */
687
- currentModel: TTSModelId;
688
- /** Sample rate for current model (24000 for Kokoro, 44100 for Supertonic) */
689
- sampleRate: number;
471
+ /** True when the page is running as an installed/standalone PWA (Home Screen). */
472
+ declare function isStandalone(): boolean;
473
+ /** True when running on iOS/iPadOS (where install is the quota unlock and the
474
+ * install flow is manual: Share Add to Home Screen). iPadOS masquerades as
475
+ * macOS, so we also treat touch-capable WebKit-on-Mac as iOS. */
476
+ declare function isIOS(): boolean;
477
+ type StorageStatus = {
478
+ /** Total quota granted to this origin, in MB (best-effort estimate). */
479
+ quotaMB: number;
480
+ /** Bytes currently used by this origin, in MB. */
481
+ usageMB: number;
482
+ /** quota usage, in MB. */
483
+ availableMB: number;
484
+ /** Storage is persistent (exempt from eviction). On iOS this is effectively
485
+ * only true once the site is installed to the Home Screen. */
486
+ persisted: boolean;
487
+ /** Running as an installed/standalone PWA. */
488
+ installed: boolean;
489
+ /** Platform is iOS/iPadOS (install is the quota unlock here). */
490
+ ios: boolean;
491
+ };
492
+ /** Snapshot of the origin's storage situation — quota, usage, persistence, and
493
+ * whether the app is installed. Use it to decide whether to recommend install
494
+ * before downloading a large model. */
495
+ declare function getStorageStatus(): Promise<StorageStatus>;
496
+ /**
497
+ * Request persistent storage (exempt from eviction). Returns whether the origin
498
+ * is persistent afterwards. Browsers grant this based on engagement/installation;
499
+ * on iOS Safari it is effectively granted only to an installed (Home Screen) PWA,
500
+ * so call this AND guide users to install when it returns false on iOS.
501
+ */
502
+ declare function requestPersistentStorage(): Promise<boolean>;
503
+ type ModelFit = {
504
+ /** The model likely fits in the currently-available quota. */
505
+ fits: boolean;
506
+ availableMB: number;
507
+ /** Caching durably would benefit from installing to the Home Screen — true when
508
+ * not installed on iOS, or when the model doesn't fit the current quota. */
509
+ recommendInstall: boolean;
690
510
  };
691
511
  /**
692
- * React hook for text-to-speech with Web Audio API playback
693
- *
694
- * Supports both Kokoro (24kHz, high quality) and Supertonic (44.1kHz, faster).
695
- *
696
- * @example
697
- * ```tsx
698
- * import { useSpeech } from "@tryhamster/gerbil/browser";
699
- *
700
- * function App() {
701
- * // Default: Kokoro TTS
702
- * const { speak, stop, isLoading, isSpeaking, listVoices, setVoice } = useSpeech();
703
- *
704
- * // Or use Supertonic (44.1kHz, faster)
705
- * // const { speak, listVoices } = useSpeech({ model: "supertonic-66m" });
706
- *
707
- * if (isLoading) return <div>Loading TTS...</div>;
708
- *
709
- * return (
710
- * <div>
711
- * <select onChange={e => setVoice(e.target.value)}>
712
- * {listVoices().map(v => (
713
- * <option key={v.id} value={v.id}>{v.name}</option>
714
- * ))}
715
- * </select>
716
- * <button onClick={() => speak("Hello world!")}>
717
- * {isSpeaking ? "Speaking..." : "Speak"}
718
- * </button>
719
- * {isSpeaking && <button onClick={stop}>Stop</button>}
720
- * </div>
721
- * );
722
- * }
723
- * ```
512
+ * Estimate whether a model of `sizeMB` will cache in the current quota, and
513
+ * whether you should recommend installing to the Home Screen first. Pair with a
514
+ * one-time "Install for offline use" prompt before a large download on mobile.
515
+ */
516
+ declare function canCacheModel(sizeMB: number): Promise<ModelFit>;
517
+ /**
518
+ * Platform-appropriate install guidance. iOS Safari has NO programmatic install
519
+ * prompt — installation is manual (Share → Add to Home Screen), so apps should
520
+ * show these instructions. Other platforms (Android/Chrome) fire
521
+ * `beforeinstallprompt`, which apps can capture for a one-tap button.
724
522
  */
725
- declare function useSpeech(options?: UseSpeechOptions): UseSpeechReturn;
523
+ declare function getInstallGuidance(): {
524
+ installed: boolean;
525
+ manual: boolean;
526
+ steps: string;
527
+ };
528
+ //#endregion
529
+ //#region src/browser/audio.d.ts
726
530
  /**
727
531
  * Play audio from Float32Array using Web Audio API
728
532
  *
@@ -763,247 +567,119 @@ declare function createAudioPlayer(sampleRate?: number): {
763
567
  stop: () => void;
764
568
  isPlaying: () => boolean;
765
569
  };
570
+ //#endregion
571
+ //#region src/browser/device-guards.d.ts
766
572
  /**
767
- * Progress info for STT loading
573
+ * Approximate on-device (INT4) memory footprint in MB for the models the native
574
+ * engine actually ships. Used for memory-aware selection and messaging.
768
575
  */
769
- type STTProgress = {
770
- status: "downloading" | "loading" | "ready" | "error";
771
- message?: string;
772
- progress?: number;
773
- file?: string;
774
- };
576
+ declare const MODEL_SIZES: Record<string, number>;
775
577
  /**
776
- * Options for useVoiceInput hook
578
+ * Check if a model is safe to load on the current device.
579
+ * Returns guidance specific to iOS memory constraints. Matches on the real
580
+ * native-engine repo ids (MLX 4-bit / upstream Qwen / Liquid).
777
581
  */
778
- type UseVoiceInputOptions = {
779
- /** STT model ID (default: whisper-tiny.en) */
780
- model?: string;
781
- /** Auto-load model on mount (default: false) */
782
- autoLoad?: boolean;
783
- /** Callback when model is ready */
784
- onReady?: () => void;
785
- /** Callback when transcription completes (or for each chunk in streaming mode) */
786
- onTranscript?: (text: string) => void;
787
- /** Callback on error */
788
- onError?: (error: string) => void;
789
- /** Callback during loading */
790
- onProgress?: (progress: STTProgress) => void;
791
- /** Enable streaming transcription - transcribes audio in chunks as you speak */
792
- streaming?: boolean;
793
- /** Chunk duration in ms for streaming mode (default: 3000 = 3 seconds) */
794
- chunkDuration?: number;
795
- /** Callback for each streaming chunk with partial transcript */
796
- onChunk?: (text: string, chunkIndex: number) => void;
582
+ declare function isModelSafeForDevice(modelId: string): {
583
+ safe: boolean;
584
+ reason: string;
585
+ recommendation?: string;
586
+ maxSafeModel?: string;
797
587
  };
798
588
  /**
799
- * Return type for useVoiceInput hook
589
+ * Get recommended models based on device memory and capabilities.
590
+ * Helps prevent OOM crashes on low-memory mobile devices.
800
591
  */
801
- type UseVoiceInputReturn = {
802
- /** Start recording audio */
803
- startRecording: () => Promise<void>;
804
- /** Stop recording and transcribe */
805
- stopRecording: () => Promise<string>;
806
- /** Cancel recording without transcribing */
807
- cancelRecording: () => void;
808
- /** Transcribe raw audio data (Float32Array at 16kHz) */
809
- transcribe: (audio: Float32Array) => Promise<string>;
810
- /** Whether currently recording */
811
- isRecording: boolean;
812
- /** Whether transcribing */
813
- isTranscribing: boolean;
814
- /** Whether model is loading */
815
- isLoading: boolean;
816
- /** Whether model is ready */
817
- isReady: boolean;
818
- /** Latest transcription result (full transcript in streaming mode) */
819
- transcript: string;
820
- /** Current streaming chunk being transcribed (streaming mode only) */
821
- streamingChunk: string;
822
- /** Number of chunks transcribed so far (streaming mode only) */
823
- chunkCount: number;
824
- /** Loading progress */
825
- loadingProgress: STTProgress | null;
826
- /** Error message */
827
- error: string | null;
828
- /** Manually load the model */
829
- load: () => void;
592
+ declare function getRecommendedModels(): {
593
+ chat: string;
594
+ tts: string;
595
+ stt: string;
596
+ embedding: string;
597
+ reason: string;
598
+ deviceMemory: number | null;
599
+ isMobile: boolean;
600
+ };
601
+ type DownloadPhase = "idle" | "downloading" | "caching" | "initializing" | "ready" | "error";
602
+ declare const SESSION_STORAGE_KEY = "gerbil_session_phase";
603
+ type SessionState = {
604
+ phase: DownloadPhase;
605
+ modelId: string | null;
606
+ sessionId: string;
607
+ timestamp: number;
608
+ bytesDownloaded?: number;
609
+ totalBytes?: number;
830
610
  };
831
611
  /**
832
- * React hook for voice input with browser microphone
833
- *
834
- * Uses MediaRecorder to capture audio and Whisper for transcription.
835
- * Supports both one-shot and streaming transcription modes.
836
- *
837
- * @example Basic usage (one-shot)
838
- * ```tsx
839
- * function VoiceInput() {
840
- * const { startRecording, stopRecording, isRecording, transcript } = useVoiceInput({
841
- * onTranscript: (text) => console.log("User said:", text),
842
- * });
843
- *
844
- * return (
845
- * <button onClick={isRecording ? stopRecording : startRecording}>
846
- * {isRecording ? "Stop" : "Record"}
847
- * </button>
848
- * );
849
- * }
850
- * ```
851
- *
852
- * @example Streaming transcription (real-time)
853
- * ```tsx
854
- * function LiveTranscription() {
855
- * const { startRecording, stopRecording, isRecording, transcript, streamingChunk } = useVoiceInput({
856
- * streaming: true, // Enable streaming mode
857
- * chunkDuration: 1500, // Transcribe every 1.5 seconds (default)
858
- * onChunk: (text, idx) => console.log(`Chunk ${idx}: ${text}`),
859
- * });
860
- *
861
- * return (
862
- * <div>
863
- * <button onClick={isRecording ? stopRecording : startRecording}>
864
- * {isRecording ? "Stop" : "Start Live Transcription"}
865
- * </button>
866
- * <p>Current chunk: {streamingChunk}</p>
867
- * <p>Full transcript: {transcript}</p>
868
- * </div>
869
- * );
870
- * }
871
- * ```
612
+ * Set the current download/initialization phase.
613
+ * Used to detect if a reload happened during a critical operation.
872
614
  */
873
- declare function useVoiceInput(options?: UseVoiceInputOptions): UseVoiceInputReturn;
615
+ declare function setDownloadPhase(phase: DownloadPhase, modelId?: string, progress?: {
616
+ bytesDownloaded: number;
617
+ totalBytes: number;
618
+ }): void;
874
619
  /**
875
- * Options for useVoiceChat hook
620
+ * Get the last known download phase from storage.
876
621
  */
877
- type UseVoiceChatOptions = {
878
- /** LLM model ID (default: qwen3-0.6b) */
879
- llmModel?: string;
880
- /** STT model ID (default: whisper-tiny.en) */
881
- sttModel?: string;
882
- /** TTS model ID (default: kokoro-82m, also supports supertonic-66m) */
883
- ttsModel?: TTSModelId;
884
- /** System prompt for LLM */
885
- system?: string;
886
- /** Enable thinking mode (default: false) */
887
- thinking?: boolean;
888
- /** TTS voice ID (default: model's default voice) */
889
- voice?: string;
890
- /** TTS speech speed (default: 1.0) */
891
- speed?: number;
892
- /** Auto-load all models on mount (default: false) */
893
- autoLoad?: boolean;
894
- /** Callback when user speaks */
895
- onUserSpeak?: (text: string) => void;
896
- /** Callback when assistant responds */
897
- onAssistantSpeak?: (text: string) => void;
898
- /** Callback on error */
899
- onError?: (error: string) => void;
900
- };
622
+ declare function getDownloadPhase(): SessionState | null;
901
623
  /**
902
- * Message in voice chat
624
+ * Detect if the page reloaded during a model download/initialization.
625
+ * This typically indicates an iOS memory crash.
626
+ *
627
+ * @returns Detection result with recommended action
903
628
  */
904
- type VoiceChatMessage = {
905
- id: string;
906
- role: "user" | "assistant";
907
- content: string;
908
- thinking?: string;
909
- audioUrl?: string;
629
+ declare function detectMemoryCrash(): {
630
+ crashed: boolean;
631
+ phase?: DownloadPhase;
632
+ modelId?: string;
633
+ timeSinceCrash?: number;
634
+ recommendation?: string;
910
635
  };
911
636
  /**
912
- * Return type for useVoiceChat hook
637
+ * Clear session phase (call when model loads successfully).
913
638
  */
914
- type UseVoiceChatReturn = {
915
- /** Messages in the conversation */
916
- messages: VoiceChatMessage[];
917
- /** Start recording user speech */
918
- startListening: () => Promise<void>;
919
- /** Stop recording and process (STT LLM → TTS) */
920
- stopListening: () => Promise<void>;
921
- /** Cancel current operation */
922
- cancel: () => void;
923
- /** Clear conversation history */
924
- clear: () => void;
925
- /** Whether recording user speech */
926
- isListening: boolean;
927
- /** Whether processing (STT/LLM/TTS) */
928
- isProcessing: boolean;
929
- /** Whether assistant is speaking */
930
- isSpeaking: boolean;
931
- /** Current stage: idle, listening, transcribing, thinking, speaking */
932
- stage: "idle" | "listening" | "transcribing" | "thinking" | "speaking";
933
- /** Whether all models are loaded */
934
- isReady: boolean;
935
- /** Whether loading models */
936
- isLoading: boolean;
937
- /** Loading progress message */
938
- loadingMessage: string;
939
- /** Error message */
940
- error: string | null;
941
- /** Manually load all models */
942
- load: () => void;
943
- };
639
+ declare function clearDownloadPhase(): void;
640
+ //#endregion
641
+ //#region src/browser/download.d.ts
642
+ /** Chunk size for downloads: 1.5MB (safe for iOS IndexedDB transactions) */
643
+ declare const CHUNK_SIZE_BYTES: number;
644
+ /** IndexedDB database name for chunked downloads */
645
+ declare const DOWNLOAD_DB_NAME = "gerbil-model-chunks";
944
646
  /**
945
- * React hook for voice conversation with STT + LLM + TTS
946
- *
947
- * Complete voice-to-voice conversation loop:
948
- * 1. User presses button to speak
949
- * 2. Speech is transcribed (Whisper)
950
- * 3. LLM generates response
951
- * 4. Response is spoken aloud (Kokoro or Supertonic TTS)
952
- *
953
- * @example
954
- * ```tsx
955
- * function VoiceChat() {
956
- * const {
957
- * messages,
958
- * startListening,
959
- * stopListening,
960
- * isListening,
961
- * isSpeaking,
962
- * stage,
963
- * } = useVoiceChat({
964
- * system: "You are a helpful voice assistant.",
965
- * voice: "af_bella",
966
- * // Or use Supertonic for faster synthesis:
967
- * // ttsModel: "supertonic-66m",
968
- * // voice: "F1",
969
- * });
970
- *
971
- * return (
972
- * <div>
973
- * {messages.map(m => (
974
- * <div key={m.id}>{m.role}: {m.content}</div>
975
- * ))}
976
- * <button
977
- * onMouseDown={startListening}
978
- * onMouseUp={stopListening}
979
- * >
980
- * {stage === "idle" ? "🎤 Hold to Speak" : stage}
981
- * </button>
982
- * </div>
983
- * );
984
- * }
985
- * ```
647
+ * Chunked resumable downloader for large model files.
648
+ * Downloads in 1.5MB chunks to avoid iOS memory pressure.
986
649
  */
987
- declare function useVoiceChat(options?: UseVoiceChatOptions): UseVoiceChatReturn;
650
+ declare function downloadModelChunked(url: string, modelId: string, options?: {
651
+ onProgress?: (info: {
652
+ phase: string;
653
+ bytesDownloaded: number;
654
+ totalBytes: number;
655
+ percent: number;
656
+ }) => void;
657
+ signal?: AbortSignal;
658
+ }): Promise<ArrayBuffer>;
988
659
  /**
989
- * Check if WebGPU is supported
660
+ * Check if a model has an incomplete download.
990
661
  */
991
- declare function isWebGPUSupported(): boolean;
662
+ declare function hasIncompleteDownload(modelId: string): Promise<{
663
+ incomplete: boolean;
664
+ bytesDownloaded?: number;
665
+ totalBytes?: number;
666
+ percent?: number;
667
+ }>;
992
668
  /**
993
- * Get WebGPU adapter info
669
+ * Clear incomplete download data for a model.
994
670
  */
995
- declare function getWebGPUInfo(): Promise<{
996
- supported: boolean;
997
- adapter?: string;
998
- device?: string;
999
- } | null>;
1000
- declare const _default: {
1001
- isWebGPUSupported: typeof isWebGPUSupported;
1002
- getWebGPUInfo: typeof getWebGPUInfo;
1003
- createGerbilWorker: typeof createGerbilWorker;
1004
- playAudio: typeof playAudio;
1005
- createAudioPlayer: typeof createAudioPlayer;
1006
- };
671
+ declare function clearIncompleteDownload(modelId: string): Promise<void>;
672
+ /**
673
+ * Check if there's enough storage quota for a model download.
674
+ * Returns estimated available space and whether download should proceed.
675
+ */
676
+ declare function checkStorageQuota(requiredMB?: number): Promise<{
677
+ ok: boolean;
678
+ availableMB: number;
679
+ usedMB: number;
680
+ quotaMB: number;
681
+ message?: string;
682
+ }>;
1007
683
  //#endregion
1008
- export { AudioChunk, BUILTIN_MODELS, BrowserVoiceInfo, CacheConfig, CompleteOptions, EmbedOptions, EmbedResult, FallbackConfig, GenerateOptions, GenerateResult, GenerateStreamOptions, GerbilConfig, GerbilModelSettings, GerbilProviderSettings, GerbilWorker, GerbilWorkerOptions, ImageInput, JsonOptions, LoadOptions, LoadSTTOptions, LoadTTSOptions, LoadingProgress, Message, ModelConfig, ModelSource, ModelStats, ProgressInfo, STTModelConfig, STTProgress, SessionStats, SpeakOptions, SpeakResult, StreamingTranscriptionOptions, StreamingTranscriptionSession, SystemInfo, TTSModelConfig, TTSModelId, TTSProgress, TranscribeOptions, TranscribeResult, TranscribeSegment, UseChatOptions, UseChatReturn, UseCompletionOptions, UseCompletionReturn, UseSpeechOptions, UseSpeechReturn, UseVoiceChatOptions, UseVoiceChatReturn, UseVoiceInputOptions, UseVoiceInputReturn, VoiceChatMessage, VoiceInfo, WorkerComplete, WorkerProgress, WorkerToken, createAudioPlayer, createGerbilWorker, _default as default, getWebGPUInfo, isWebGPUSupported, playAudio, useChat, useCompletion, useSpeech, useVoiceChat, useVoiceInput };
684
+ export { AudioChunk, BUILTIN_MODELS, CHUNK_SIZE_BYTES, CacheConfig, ConcurrencyConfig, DOWNLOAD_DB_NAME, EmbedOptions, EmbedResult, ErrorContext, FallbackConfig, GenerateEvent, GenerateOptions, GenerateResult, GerbilConfig, GerbilModelSettings, GerbilProviderSettings, ImageInput, JsonOptions, LoadOptions, LoadSTTOptions, LoadTTSOptions, MODEL_SIZES, ModelConfig, type ModelFit, ModelLoadEvent, ModelSource, ModelStats, PreloadOptions, ProgressInfo, SESSION_STORAGE_KEY, STTModelConfig, SearchResult, type SessionState, SessionStats, SimilarityResult, SpeakOptions, SpeakResult, type StorageStatus, StreamingTranscriptionOptions, StreamingTranscriptionSession, SystemInfo, TTSModelConfig, TelemetryConfig, TranscribeOptions, TranscribeResult, TranscribeSegment, VoiceInfo, canCacheModel, checkStorageQuota, clearDownloadPhase, clearIncompleteDownload, createAudioPlayer, detectMemoryCrash, downloadModelChunked, getDownloadPhase, getInstallGuidance, getRecommendedModels, getStorageStatus, hasIncompleteDownload, isIOS, isModelSafeForDevice, isStandalone, playAudio, requestPersistentStorage, setDownloadPhase };
1009
685
  //# sourceMappingURL=index.d.ts.map