@tryhamster/gerbil 1.0.0-rc.23 → 1.0.0-rc.25

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 (55) hide show
  1. package/dist/browser/index.d.ts +146 -2
  2. package/dist/browser/index.d.ts.map +1 -1
  3. package/dist/browser/index.js +507 -22
  4. package/dist/browser/index.js.map +1 -1
  5. package/dist/cli.mjs +7 -7
  6. package/dist/cli.mjs.map +1 -1
  7. package/dist/frameworks/express.d.mts +1 -3
  8. package/dist/frameworks/express.d.mts.map +1 -1
  9. package/dist/frameworks/express.mjs +3 -3
  10. package/dist/frameworks/express.mjs.map +1 -1
  11. package/dist/frameworks/fastify.d.mts +1 -1
  12. package/dist/frameworks/fastify.mjs +1 -1
  13. package/dist/frameworks/hono.d.mts +1 -1
  14. package/dist/frameworks/hono.mjs +1 -1
  15. package/dist/frameworks/next.d.mts +2 -2
  16. package/dist/frameworks/next.mjs +1 -1
  17. package/dist/frameworks/react.d.mts +1 -1
  18. package/dist/frameworks/react.d.mts.map +1 -1
  19. package/dist/frameworks/trpc.d.mts +1 -1
  20. package/dist/frameworks/trpc.mjs +1 -1
  21. package/dist/{gerbil-DJygY0sJ.d.mts → gerbil-CbnV_cG5.d.mts} +9 -2
  22. package/dist/gerbil-CbnV_cG5.d.mts.map +1 -0
  23. package/dist/{gerbil-PzPtcdeM.mjs → gerbil-DODVGr-u.mjs} +1 -1
  24. package/dist/{gerbil-DzZ-L6n8.mjs → gerbil-jO9anIh_.mjs} +90 -3
  25. package/dist/gerbil-jO9anIh_.mjs.map +1 -0
  26. package/dist/index.d.mts +3 -3
  27. package/dist/index.d.mts.map +1 -1
  28. package/dist/index.mjs +2 -2
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/integrations/ai-sdk.d.mts +1 -1
  31. package/dist/integrations/ai-sdk.mjs +1 -1
  32. package/dist/integrations/langchain.d.mts +1 -1
  33. package/dist/integrations/langchain.mjs +1 -1
  34. package/dist/integrations/llamaindex.d.mts +1 -1
  35. package/dist/integrations/llamaindex.mjs +1 -1
  36. package/dist/integrations/mcp.d.mts +2 -2
  37. package/dist/integrations/mcp.mjs +4 -4
  38. package/dist/{mcp-D161vL_C.mjs → mcp-tavZtFY1.mjs} +3 -3
  39. package/dist/{mcp-D161vL_C.mjs.map → mcp-tavZtFY1.mjs.map} +1 -1
  40. package/dist/{one-liner-C-pRqDK2.mjs → one-liner-Ba58M_6j.mjs} +2 -2
  41. package/dist/{one-liner-C-pRqDK2.mjs.map → one-liner-Ba58M_6j.mjs.map} +1 -1
  42. package/dist/{repl-D9x3TnQc.mjs → repl-BGly-o_e.mjs} +3 -3
  43. package/dist/skills/index.d.mts +3 -3
  44. package/dist/skills/index.d.mts.map +1 -1
  45. package/dist/skills/index.mjs +3 -3
  46. package/dist/{skills-D14RwyUN.mjs → skills-BKxP2pex.mjs} +2 -2
  47. package/dist/{skills-D14RwyUN.mjs.map → skills-BKxP2pex.mjs.map} +1 -1
  48. package/dist/{types-evP8RShr.d.mts → types-6uG8lC7u.d.mts} +65 -2
  49. package/dist/types-6uG8lC7u.d.mts.map +1 -0
  50. package/docs/architecture/overview.md +2 -0
  51. package/docs/observability.md +230 -0
  52. package/package.json +5 -4
  53. package/dist/gerbil-DJygY0sJ.d.mts.map +0 -1
  54. package/dist/gerbil-DzZ-L6n8.mjs.map +0 -1
  55. package/dist/types-evP8RShr.d.mts.map +0 -1
@@ -144,6 +144,10 @@ type GerbilConfig = {
144
144
  cache?: CacheConfig;
145
145
  /** Fallback configuration */
146
146
  fallback?: FallbackConfig;
147
+ /** Telemetry hooks for observability (Sentry, logging, etc.) */
148
+ telemetry?: TelemetryConfig;
149
+ /** Concurrency control for request queuing */
150
+ concurrency?: ConcurrencyConfig;
147
151
  };
148
152
  type CacheConfig = {
149
153
  /** Enable caching (default: true) */
@@ -372,6 +376,65 @@ type StreamingTranscriptionSession = {
372
376
  /** Reset session (clear buffer and transcript) */
373
377
  reset: () => void;
374
378
  };
379
+ /**
380
+ * Telemetry hooks for production observability.
381
+ * Pass your own Sentry instance or custom logging functions.
382
+ */
383
+ type TelemetryConfig = {
384
+ /**
385
+ * Called after successful generation with full result and timing.
386
+ * Use for logging, metrics, or analytics.
387
+ */
388
+ onGenerate?: (event: GenerateEvent) => void;
389
+ /**
390
+ * Called when any error occurs during Gerbil operations.
391
+ * Perfect for Sentry.captureException() or similar.
392
+ */
393
+ onError?: (error: Error, context: ErrorContext) => void;
394
+ /**
395
+ * Called after model loading completes (success or failure).
396
+ */
397
+ onModelLoad?: (event: ModelLoadEvent) => void;
398
+ /**
399
+ * Called when a request is queued (if concurrency limit reached).
400
+ */
401
+ onQueueWait?: (waitTimeMs: number) => void;
402
+ };
403
+ type GenerateEvent = {
404
+ /** Model used for generation */
405
+ modelId: string;
406
+ /** Generation result */
407
+ result: GenerateResult;
408
+ /** Whether response came from cache */
409
+ cached: boolean;
410
+ /** Time spent waiting in queue (if any) */
411
+ queueTimeMs?: number;
412
+ };
413
+ /**
414
+ * Context passed to telemetry onError callback.
415
+ * Flexible record to allow any relevant context data.
416
+ */
417
+ type ErrorContext = Record<string, unknown>;
418
+ type ModelLoadEvent = {
419
+ /** Model that was loaded */
420
+ modelId: string;
421
+ /** Time to load in ms */
422
+ loadTimeMs: number;
423
+ /** Whether loaded from cache */
424
+ fromCache: boolean;
425
+ /** Device used */
426
+ device: "webgpu" | "cpu" | "wasm";
427
+ /** Whether load succeeded */
428
+ success: boolean;
429
+ /** Error message if failed */
430
+ error?: string;
431
+ };
432
+ type ConcurrencyConfig = {
433
+ /** Maximum concurrent generation requests (default: 1 for LLM) */
434
+ maxConcurrent?: number;
435
+ /** Request timeout in ms (default: 300000 = 5 min) */
436
+ timeout?: number;
437
+ };
375
438
  //#endregion
376
- export { TTSModelConfig as A, SessionStats as C, StreamingTranscriptionOptions as D, SpeakResult as E, TranscribeResult as M, TranscribeSegment as N, StreamingTranscriptionSession as O, VoiceInfo as P, SearchResult as S, SpeakOptions as T, ModelSource as _, FallbackConfig as a, ProgressInfo as b, GerbilConfig as c, ImageInput as d, JsonOptions as f, ModelConfig as g, LoadTTSOptions as h, EmbedResult as i, TranscribeOptions as j, SystemInfo as k, GerbilModelSettings as l, LoadSTTOptions as m, CacheConfig as n, GenerateOptions as o, LoadOptions as p, EmbedOptions as r, GenerateResult as s, AudioChunk as t, GerbilProviderSettings as u, ModelStats as v, SimilarityResult as w, STTModelConfig as x, PreloadOptions as y };
377
- //# sourceMappingURL=types-evP8RShr.d.mts.map
439
+ export { SpeakResult as A, PreloadOptions as C, SessionStats as D, SearchResult as E, TelemetryConfig as F, TranscribeOptions as I, TranscribeResult as L, StreamingTranscriptionSession as M, SystemInfo as N, SimilarityResult as O, TTSModelConfig as P, TranscribeSegment as R, ModelStats as S, STTModelConfig as T, LoadSTTOptions as _, EmbedResult as a, ModelLoadEvent as b, GenerateEvent as c, GerbilConfig as d, GerbilModelSettings as f, LoadOptions as g, JsonOptions as h, EmbedOptions as i, StreamingTranscriptionOptions as j, SpeakOptions as k, GenerateOptions as l, ImageInput as m, CacheConfig as n, ErrorContext as o, GerbilProviderSettings as p, ConcurrencyConfig as r, FallbackConfig as s, AudioChunk as t, GenerateResult as u, LoadTTSOptions as v, ProgressInfo as w, ModelSource as x, ModelConfig as y, VoiceInfo as z };
440
+ //# sourceMappingURL=types-6uG8lC7u.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-6uG8lC7u.d.mts","names":[],"sources":["../src/core/types.ts"],"sourcesContent":[],"mappings":";;;;AAyBY,KAfA,WAAA,GAeW;EASX,EAAA,EAAA,MAAA;EAWA,IAAA,EAAA,MAAA;EAmCA,WAAA,EAAA,MAAc;EA8Bd,IAAA,EAAA,MAAA;EAkBA,aAAA,EAAY,MAAA;EAQZ,gBAAW,EAAA,OAAA;EAWX,YAAA,EAAA,OAAY;EAWZ;EAkBA,cAAW,CAAA,EAAA,OAAA;EAcX;EAOA,iBAAY,CAAA,EAAA,MAAA;EAYZ,MAAA,EAAA,MAAA,GAAY,QAAA,GAAA,KAAA,GAAA,SAAA,GAAA,OAAA,GAAA,OAAA;CAWd;AAGG,KAtMD,WAAA,GAsMC;EAGC,IAAA,EAAA,SAAA,GAAA,aAAA,GAAA,OAAA;EAGE,IAAA,EAAA,MAAA;CAAiB;AAGrB,KAtMA,UAAA,GAsMW;EAiBX;EAqBA,MAAA,EAAA,MAAA;EAUA;EAOA,GAAA,CAAA,EAAA,MAAA;AAyBZ,CAAA;AAWY,KAtRA,eAAA,GAsRsB;EAYtB;EAeA,SAAA,CAAA,EAAA,MAAc;EAmBd;EAWA,WAAA,CAAA,EAAU,MAAA;EAWV;EAaA,IAAA,CAAA,EAAA,MAAA;EAWA;EAiBA,IAAA,CAAA,EAAA,MAAA;EASA;EASA,aAAA,CAAA,EAAA,MAAgB,EAAA;EAahB;EAWA,MAAA,CAAA,EAAA,MAAA;EAeA;EAES,QAAA,CAAA,EAAA,OAAA;EAEN;EAID,OAAA,CAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAO;EAqBT,MAAA,CAAA,EA/bD,UA+bgB,EAAA;EAKJ;EAMH,KAAA,CAAA,EAAA,OAAA;EAAgB;EAKZ,QAAA,CAAA,EAAA,MAAA;CAAc;AAQ1B,KA9cA,cAAA,GA8ca;EAeb;EAEA,IAAA,EAAA,MAAA;EAmBA;;;;;;;;;;;;;;;KApdA;;UAEF,CAAA,CAAE,QAAQ;;;;;;;;KAgBR,YAAA;;;;;;KAQA,WAAA;;;;;;;;KAWA,YAAA;;;;;;;;KAWA,gBAAA;;;;;;;;;;KAkBA,WAAA;;sBAEU;;;;;;;;KAYV,cAAA;;sBAEU;;;;KAKV,YAAA;;;;;;;KAYA,YAAA;;;;;;;;UAWF;;aAGG;;cAGC;;gBAGE;;KAGJ,WAAA;;;;;;;;;;;;KAiBA,cAAA;;;;;;;;;;;;KAqBA,YAAA;;;;;;;;;KAUA,UAAA;;;;;;KAOA,UAAA;;SAEH;;;;;;;;;;;;;;;;;;KAuBG,mBAAA;;;;;;;;KAWA,sBAAA;;;;;;KAYA,SAAA;;;;;;;;;;;;;;KAeA,cAAA;;;;;;;;;;;;UAYF;;;;;;KAOE,YAAA;;;;;;sBAMU;;yBAEG;;KAGb,UAAA;;WAED;;;;;;;;KASC,WAAA;;SAEH;;;;;;;;;;KAWG,cAAA;;sBAEU;;;;KASV,cAAA;;;;;;;;;;;;;;;;KAiBA,iBAAA;;;;;;sBAMU;;KAGV,iBAAA;;;;;;;;KASA,gBAAA;;;;;;aAMC;;;;;;KAOD,cAAA;;sBAEU;;;;KASV,6BAAA;;;;;;;;;;;;;;KAeA,6BAAA;;qBAES;;eAEN;;;;cAID;;;;;;;;;;;;;;;;KAqBF,eAAA;;;;;uBAKW;;;;;oBAMH,gBAAgB;;;;wBAKZ;;;;;;KAQZ,aAAA;;;;UAIF;;;;;;;;;;KAWE,YAAA,GAAe;KAEf,cAAA;;;;;;;;;;;;;;KAmBA,iBAAA"}
@@ -20,6 +20,8 @@ Responsibilities:
20
20
  - Generation orchestration
21
21
  - Streaming coordination
22
22
  - Session statistics
23
+ - Request queue (concurrency control)
24
+ - Telemetry hooks for observability
23
25
 
24
26
  ### 2. Model Registry (`src/core/models.ts`)
25
27
 
@@ -0,0 +1,230 @@
1
+ # Production Observability
2
+
3
+ Gerbil includes built-in support for production observability through telemetry hooks and request queuing.
4
+
5
+ ## Telemetry Hooks
6
+
7
+ Configure telemetry hooks to integrate with Sentry, DataDog, or any monitoring system:
8
+
9
+ ```typescript
10
+ import { Gerbil } from "@tryhamster/gerbil";
11
+ import * as Sentry from "@sentry/node";
12
+
13
+ const g = new Gerbil({
14
+ telemetry: {
15
+ // Called on any error (model load, generation, etc.)
16
+ onError: (error, context) => {
17
+ Sentry.captureException(error, {
18
+ extra: context,
19
+ tags: { operation: context.operation },
20
+ });
21
+ },
22
+
23
+ // Called after successful generation
24
+ onGenerate: (event) => {
25
+ console.log(`Generated ${event.result.tokensGenerated} tokens`);
26
+ // Track in your metrics system
27
+ metrics.histogram("gerbil.tokens_generated", event.result.tokensGenerated);
28
+ metrics.histogram("gerbil.tokens_per_second", event.result.tokensPerSecond);
29
+ },
30
+
31
+ // Called after model loading (success or failure)
32
+ onModelLoad: (event) => {
33
+ if (event.success) {
34
+ console.log(`Loaded ${event.modelId} in ${event.loadTimeMs}ms on ${event.device}`);
35
+ } else {
36
+ console.error(`Failed to load ${event.modelId}: ${event.error}`);
37
+ }
38
+ },
39
+
40
+ // Called when requests wait in queue (>100ms)
41
+ onQueueWait: (waitTimeMs) => {
42
+ metrics.histogram("gerbil.queue_wait_ms", waitTimeMs);
43
+ },
44
+ },
45
+ });
46
+ ```
47
+
48
+ ### Telemetry Events
49
+
50
+ #### `onError(error, context)`
51
+
52
+ Called whenever an error occurs during Gerbil operations.
53
+
54
+ ```typescript
55
+ type ErrorContext = {
56
+ operation: "generate" | "load" | "embed" | "speak" | "transcribe" | "json";
57
+ modelId?: string;
58
+ extra?: Record<string, unknown>;
59
+ };
60
+ ```
61
+
62
+ #### `onGenerate(event)`
63
+
64
+ Called after successful text generation.
65
+
66
+ ```typescript
67
+ type GenerateEvent = {
68
+ modelId: string;
69
+ result: GenerateResult;
70
+ cached: boolean;
71
+ queueTimeMs?: number; // Only if waited >100ms
72
+ };
73
+ ```
74
+
75
+ #### `onModelLoad(event)`
76
+
77
+ Called after model loading completes (success or failure).
78
+
79
+ ```typescript
80
+ type ModelLoadEvent = {
81
+ modelId: string;
82
+ loadTimeMs: number;
83
+ fromCache: boolean;
84
+ device: "webgpu" | "cpu" | "wasm";
85
+ success: boolean;
86
+ error?: string;
87
+ };
88
+ ```
89
+
90
+ #### `onQueueWait(waitTimeMs)`
91
+
92
+ Called when a request waits in the queue for more than 100ms. Useful for detecting congestion.
93
+
94
+ ## Request Queue
95
+
96
+ Gerbil uses a request queue to prevent GPU OOM errors under concurrent load. LLM inference can only run one request at a time on the GPU.
97
+
98
+ ### Default Behavior
99
+
100
+ - **Concurrency**: 1 (single request at a time)
101
+ - **Timeout**: 5 minutes (300,000ms)
102
+ - Requests are processed in FIFO order
103
+ - Timeout errors are thrown if exceeded
104
+
105
+ ### Custom Configuration
106
+
107
+ ```typescript
108
+ const g = new Gerbil({
109
+ concurrency: {
110
+ maxConcurrent: 1, // Max parallel requests (default: 1)
111
+ timeout: 300_000, // Request timeout in ms (default: 5 min)
112
+ },
113
+ });
114
+ ```
115
+
116
+ ### Why Queue?
117
+
118
+ LLM inference on GPU is:
119
+ 1. **Memory-bound**: Models consume most of GPU VRAM
120
+ 2. **Non-concurrent**: Running multiple inferences simultaneously causes OOM
121
+ 3. **Variable duration**: Generation time depends on output length
122
+
123
+ The queue ensures:
124
+ - Predictable memory usage
125
+ - No OOM crashes under load
126
+ - Fair request ordering
127
+
128
+ ## Rate Limiting
129
+
130
+ Gerbil does **not** include rate limiting. This is intentional—rate limiting is best handled at the application layer using middleware specific to your framework:
131
+
132
+ ```typescript
133
+ // Express
134
+ import rateLimit from "express-rate-limit";
135
+ import { gerbil } from "@tryhamster/gerbil/express";
136
+
137
+ app.use("/ai", rateLimit({ windowMs: 60000, max: 10 }));
138
+ app.use("/ai", gerbil());
139
+
140
+ // Next.js
141
+ import { Ratelimit } from "@upstash/ratelimit";
142
+ import { Redis } from "@upstash/redis";
143
+
144
+ const ratelimit = new Ratelimit({
145
+ redis: Redis.fromEnv(),
146
+ limiter: Ratelimit.slidingWindow(10, "60s"),
147
+ });
148
+
149
+ export async function POST(req: Request) {
150
+ const ip = req.headers.get("x-forwarded-for") ?? "anonymous";
151
+ const { success } = await ratelimit.limit(ip);
152
+ if (!success) return Response.json({ error: "Rate limited" }, { status: 429 });
153
+
154
+ // Continue with Gerbil...
155
+ }
156
+ ```
157
+
158
+ ## Example: Full Production Setup
159
+
160
+ ```typescript
161
+ import { Gerbil } from "@tryhamster/gerbil";
162
+ import * as Sentry from "@sentry/node";
163
+
164
+ Sentry.init({ dsn: process.env.SENTRY_DSN });
165
+
166
+ const g = new Gerbil({
167
+ model: "qwen3-0.6b",
168
+
169
+ telemetry: {
170
+ onError: (error, context) => {
171
+ Sentry.captureException(error, { extra: context });
172
+ },
173
+
174
+ onGenerate: ({ result, queueTimeMs }) => {
175
+ // Log slow generations
176
+ if (result.totalTime > 10000) {
177
+ console.warn(`Slow generation: ${result.totalTime}ms`);
178
+ }
179
+
180
+ // Track queue congestion
181
+ if (queueTimeMs && queueTimeMs > 5000) {
182
+ Sentry.captureMessage("High queue wait time", {
183
+ level: "warning",
184
+ extra: { queueTimeMs },
185
+ });
186
+ }
187
+ },
188
+
189
+ onModelLoad: (event) => {
190
+ if (!event.success) {
191
+ Sentry.captureMessage(`Model load failed: ${event.error}`, {
192
+ level: "error",
193
+ extra: event,
194
+ });
195
+ }
196
+ },
197
+ },
198
+
199
+ concurrency: {
200
+ maxConcurrent: 1,
201
+ timeout: 120_000, // 2 minute timeout for your use case
202
+ },
203
+ });
204
+
205
+ // Preload model on startup
206
+ await g.loadModel();
207
+ console.log("Gerbil ready for production");
208
+ ```
209
+
210
+ ## Health Checks
211
+
212
+ For production deployments, implement a health check endpoint:
213
+
214
+ ```typescript
215
+ // Express
216
+ app.get("/health", async (req, res) => {
217
+ try {
218
+ const info = g.getInfo();
219
+ res.json({
220
+ status: "ok",
221
+ model: info.model?.id,
222
+ device: info.device.backend,
223
+ ready: info.device.status === "ready",
224
+ });
225
+ } catch (error) {
226
+ res.status(503).json({ status: "error", message: String(error) });
227
+ }
228
+ });
229
+ ```
230
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tryhamster/gerbil",
3
- "version": "1.0.0-rc.23",
3
+ "version": "1.0.0-rc.25",
4
4
  "description": "Local LLM inference for Node.js. GPU-accelerated. Zero config. Works standalone or with Vercel AI SDK.",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -72,6 +72,7 @@
72
72
  "cli-progress": "^3.12.0",
73
73
  "commander": "^12.1.0",
74
74
  "ora": "^8.0.1",
75
+ "p-queue": "^9.0.1",
75
76
  "puppeteer-core": "^24.31.0",
76
77
  "react": "^19.0.0",
77
78
  "webgpu": "^0.3.8",
@@ -127,11 +128,9 @@
127
128
  "devDependencies": {
128
129
  "@ai-sdk/provider": "^2.0.0",
129
130
  "@biomejs/biome": "^2.3.8",
130
- "@huggingface/transformers": "^3.8.0",
131
- "kokoro-js": "^1.2.1",
132
- "onnxruntime-web": "^1.21.0-dev.20250114-228dd16893",
133
131
  "@changesets/changelog-github": "^0.5.1",
134
132
  "@changesets/cli": "^2.28.1",
133
+ "@huggingface/transformers": "^3.8.0",
135
134
  "@types/cli-progress": "^3.11.6",
136
135
  "@types/express": "^4.17.21",
137
136
  "@types/ink-big-text": "^1.2.4",
@@ -145,7 +144,9 @@
145
144
  "ink-select-input": "^6.2.0",
146
145
  "ink-spinner": "^5.0.0",
147
146
  "ink-text-input": "^6.0.0",
147
+ "kokoro-js": "^1.2.1",
148
148
  "lefthook": "^2.0.5",
149
+ "onnxruntime-web": "^1.21.0-dev.20250114-228dd16893",
149
150
  "tsdown": "^0.17.0-beta.3",
150
151
  "tsx": "^4.15.0",
151
152
  "typescript": "^5.4.5",
@@ -1 +0,0 @@
1
- {"version":3,"file":"gerbil-DJygY0sJ.d.mts","names":[],"sources":["../src/core/gerbil.ts"],"sourcesContent":[],"mappings":"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"}