webml-kit 0.1.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.
package/dist/device.js ADDED
@@ -0,0 +1,195 @@
1
+ /**
2
+ * WebGPU / WASM device detection and capability probing.
3
+ *
4
+ * Detects the best available backend, extracts GPU adapter info,
5
+ * and recommends a quantization level based on estimated VRAM.
6
+ */
7
+ // ─── VRAM thresholds for dtype recommendation ───
8
+ const VRAM_THRESHOLDS = [
9
+ { min: 8 * 1024 ** 3, dtype: 'fp16' }, // 8 GB+ → fp16
10
+ { min: 4 * 1024 ** 3, dtype: 'q8' }, // 4 GB+ → q8
11
+ { min: 2 * 1024 ** 3, dtype: 'q4' }, // 2 GB+ → q4
12
+ { min: 0, dtype: 'q4' }, // < 2 GB → q4 (safest)
13
+ ];
14
+ /**
15
+ * Check if WebGPU is available and request an adapter.
16
+ * Returns `null` if WebGPU is not supported.
17
+ */
18
+ export async function getGPUAdapter() {
19
+ if (typeof navigator === 'undefined')
20
+ return null;
21
+ if (!('gpu' in navigator))
22
+ return null;
23
+ try {
24
+ const adapter = await navigator.gpu.requestAdapter({
25
+ powerPreference: 'high-performance',
26
+ });
27
+ return adapter;
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ /**
34
+ * Extract GPU info from an adapter.
35
+ */
36
+ export async function getGPUInfo(adapter) {
37
+ // adapterInfo is available synchronously on modern browsers
38
+ const info = adapter.info ?? adapter.requestAdapterInfo?.();
39
+ const resolved = info instanceof Promise ? await info : info;
40
+ // maxBufferSize gives a rough VRAM lower-bound
41
+ const vram = Number(adapter.limits?.maxBufferSize ?? 0);
42
+ return {
43
+ vendor: resolved?.vendor ?? 'unknown',
44
+ architecture: resolved?.architecture ?? 'unknown',
45
+ description: resolved?.description ?? 'unknown',
46
+ vram,
47
+ vramFormatted: formatSize(vram),
48
+ };
49
+ }
50
+ /**
51
+ * Recommend a quantization dtype based on available VRAM.
52
+ */
53
+ export function recommendDtype(vram) {
54
+ for (const { min, dtype } of VRAM_THRESHOLDS) {
55
+ if (vram >= min)
56
+ return dtype;
57
+ }
58
+ return 'q4';
59
+ }
60
+ /**
61
+ * Check if WebGPU is available.
62
+ */
63
+ export async function checkWebGPU() {
64
+ const adapter = await getGPUAdapter();
65
+ return adapter !== null;
66
+ }
67
+ /**
68
+ * Check if WebAssembly is available.
69
+ */
70
+ export function checkWASM() {
71
+ return typeof WebAssembly !== 'undefined';
72
+ }
73
+ /**
74
+ * Detect the best available compute backend and return device info.
75
+ *
76
+ * Priority: WebGPU → WASM → CPU
77
+ *
78
+ * ```ts
79
+ * const info = await detectDevice();
80
+ * console.log(info.backend); // 'webgpu'
81
+ * console.log(info.recommendedDtype); // 'q4'
82
+ * console.log(info.gpu?.vendor); // 'apple'
83
+ * ```
84
+ */
85
+ export async function detectDevice() {
86
+ // Try WebGPU first
87
+ const adapter = await getGPUAdapter();
88
+ if (adapter) {
89
+ const gpu = await getGPUInfo(adapter);
90
+ return {
91
+ backend: 'webgpu',
92
+ gpu,
93
+ recommendedDtype: recommendDtype(gpu.vram),
94
+ };
95
+ }
96
+ // Fall back to WASM
97
+ if (checkWASM()) {
98
+ return {
99
+ backend: 'wasm',
100
+ gpu: null,
101
+ recommendedDtype: 'q4',
102
+ };
103
+ }
104
+ // CPU-only (rare)
105
+ return {
106
+ backend: 'cpu',
107
+ gpu: null,
108
+ recommendedDtype: 'q4',
109
+ };
110
+ }
111
+ // ─── Size parsing / formatting ───
112
+ const SIZE_UNITS = {
113
+ b: 1,
114
+ kb: 1024,
115
+ mb: 1024 ** 2,
116
+ gb: 1024 ** 3,
117
+ tb: 1024 ** 4,
118
+ };
119
+ /**
120
+ * Parse a human-readable size string into bytes.
121
+ *
122
+ * Accepts formats like '4GB', '512 MB', '1.5gb', '256mb'.
123
+ * Also accepts raw numbers (passed through as-is).
124
+ *
125
+ * ```ts
126
+ * parseSize('4GB') // 4294967296
127
+ * parseSize('512MB') // 536870912
128
+ * parseSize('1.5gb') // 1610612736
129
+ * parseSize(1024) // 1024
130
+ * ```
131
+ */
132
+ export function parseSize(input) {
133
+ if (typeof input === 'number')
134
+ return input;
135
+ const match = input.trim().match(/^([\d.]+)\s*(b|kb|mb|gb|tb)$/i);
136
+ if (!match) {
137
+ throw new Error(`Invalid size format: "${input}". Use something like "4GB", "512MB", or a number in bytes.`);
138
+ }
139
+ const value = parseFloat(match[1]);
140
+ const unit = match[2].toLowerCase();
141
+ return Math.round(value * SIZE_UNITS[unit]);
142
+ }
143
+ /**
144
+ * Format bytes into a human-readable string.
145
+ *
146
+ * ```ts
147
+ * formatSize(4294967296) // '4 GB'
148
+ * formatSize(536870912) // '512 MB'
149
+ * formatSize(1536) // '1.5 KB'
150
+ * ```
151
+ */
152
+ export function formatSize(bytes) {
153
+ if (bytes >= 1024 ** 4)
154
+ return `${(bytes / 1024 ** 4).toFixed(1)} TB`;
155
+ if (bytes >= 1024 ** 3)
156
+ return `${(bytes / 1024 ** 3).toFixed(1)} GB`;
157
+ if (bytes >= 1024 ** 2)
158
+ return `${(bytes / 1024 ** 2).toFixed(1)} MB`;
159
+ if (bytes >= 1024)
160
+ return `${(bytes / 1024).toFixed(1)} KB`;
161
+ return `${bytes} B`;
162
+ }
163
+ // ─── canRun ───
164
+ /**
165
+ * Check whether a model of a given size can likely run
166
+ * on the current device without OOM.
167
+ *
168
+ * Accepts human-readable strings or raw byte counts:
169
+ *
170
+ * ```ts
171
+ * await canRun('4GB');
172
+ * await canRun('512MB');
173
+ * await canRun(4_000_000_000);
174
+ * ```
175
+ *
176
+ * This is a heuristic — real limits depend on browser, OS, and
177
+ * other tabs consuming VRAM.
178
+ */
179
+ export async function canRun(estimatedSize) {
180
+ const bytes = parseSize(estimatedSize);
181
+ const device = await detectDevice();
182
+ if (device.backend === 'webgpu' && device.gpu) {
183
+ // Leave ~500MB headroom for browser internals
184
+ const available = device.gpu.vram - 512 * 1024 ** 2;
185
+ if (bytes > available) {
186
+ return {
187
+ ok: false,
188
+ backend: device.backend,
189
+ reason: `Model (~${formatSize(bytes)}) exceeds available VRAM (~${formatSize(available)})`,
190
+ };
191
+ }
192
+ }
193
+ return { ok: true, backend: device.backend };
194
+ }
195
+ //# sourceMappingURL=device.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.js","sourceRoot":"","sources":["../src/device.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * GPU device-lost recovery handler.
3
+ *
4
+ * WebGPU devices can be lost due to TDR resets, VRAM exhaustion, driver
5
+ * updates, or mobile browsers reclaiming resources. This module provides
6
+ * automatic recovery with exponential backoff.
7
+ */
8
+ export type RecoveryState = 'idle' | 'lost' | 'recovering' | 'recovered' | 'failed';
9
+ export interface GPURecoveryEvents {
10
+ 'state-change': RecoveryState;
11
+ 'lost': {
12
+ reason: string;
13
+ };
14
+ 'recovered': {
15
+ adapter: GPUAdapter;
16
+ };
17
+ 'failed': {
18
+ attempts: number;
19
+ lastError: string;
20
+ };
21
+ }
22
+ export type GPURecoveryListener<K extends keyof GPURecoveryEvents> = (data: GPURecoveryEvents[K]) => void;
23
+ /**
24
+ * Monitors a GPU device for loss and attempts automatic recovery.
25
+ *
26
+ * ```ts
27
+ * const recovery = new GPURecovery();
28
+ * recovery.on('lost', ({ reason }) => showBanner('GPU lost: ' + reason));
29
+ * recovery.on('recovered', ({ adapter }) => reinitPipeline(adapter));
30
+ * recovery.on('failed', () => showFallbackUI());
31
+ *
32
+ * const device = await recovery.watchDevice(existingDevice);
33
+ * ```
34
+ */
35
+ export declare class GPURecovery {
36
+ private state;
37
+ private listeners;
38
+ private maxRetries;
39
+ private baseDelay;
40
+ constructor(options?: {
41
+ maxRetries?: number;
42
+ baseDelayMs?: number;
43
+ });
44
+ /** Current recovery state. */
45
+ getState(): RecoveryState;
46
+ /** Register a listener for recovery events. */
47
+ on<K extends keyof GPURecoveryEvents>(event: K, listener: GPURecoveryListener<K>): void;
48
+ /** Remove a listener. */
49
+ off<K extends keyof GPURecoveryEvents>(event: K, listener: GPURecoveryListener<K>): void;
50
+ private emit;
51
+ private setState;
52
+ /**
53
+ * Watch a GPU device for loss. When the device is lost, automatically
54
+ * attempt to re-acquire an adapter.
55
+ *
56
+ * @returns The same device (for chaining)
57
+ */
58
+ watchDevice(device: GPUDevice): GPUDevice;
59
+ private attemptRecovery;
60
+ }
61
+ //# sourceMappingURL=gpu-recovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpu-recovery.d.ts","sourceRoot":"","sources":["../src/gpu-recovery.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEpF,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,aAAa,CAAC;IAC9B,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3B,WAAW,EAAE;QAAE,OAAO,EAAE,UAAU,CAAA;KAAE,CAAC;IACrC,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CACnD;AAED,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,MAAM,iBAAiB,IAC/D,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AAEvC;;;;;;;;;;;GAWG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE;IAKnE,8BAA8B;IAC9B,QAAQ,IAAI,aAAa;IAIzB,+CAA+C;IAC/C,EAAE,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAClC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAC/B,IAAI;IAOP,yBAAyB;IACzB,GAAG,CAAC,CAAC,SAAS,MAAM,iBAAiB,EACnC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAC/B,IAAI;IAIP,OAAO,CAAC,IAAI;IAOZ,OAAO,CAAC,QAAQ;IAKhB;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS;YAmB3B,eAAe;CAqC9B"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * GPU device-lost recovery handler.
3
+ *
4
+ * WebGPU devices can be lost due to TDR resets, VRAM exhaustion, driver
5
+ * updates, or mobile browsers reclaiming resources. This module provides
6
+ * automatic recovery with exponential backoff.
7
+ */
8
+ /**
9
+ * Monitors a GPU device for loss and attempts automatic recovery.
10
+ *
11
+ * ```ts
12
+ * const recovery = new GPURecovery();
13
+ * recovery.on('lost', ({ reason }) => showBanner('GPU lost: ' + reason));
14
+ * recovery.on('recovered', ({ adapter }) => reinitPipeline(adapter));
15
+ * recovery.on('failed', () => showFallbackUI());
16
+ *
17
+ * const device = await recovery.watchDevice(existingDevice);
18
+ * ```
19
+ */
20
+ export class GPURecovery {
21
+ state = 'idle';
22
+ listeners = new Map();
23
+ maxRetries;
24
+ baseDelay;
25
+ constructor(options) {
26
+ this.maxRetries = options?.maxRetries ?? 3;
27
+ this.baseDelay = options?.baseDelayMs ?? 1000;
28
+ }
29
+ /** Current recovery state. */
30
+ getState() {
31
+ return this.state;
32
+ }
33
+ /** Register a listener for recovery events. */
34
+ on(event, listener) {
35
+ if (!this.listeners.has(event)) {
36
+ this.listeners.set(event, new Set());
37
+ }
38
+ this.listeners.get(event).add(listener);
39
+ }
40
+ /** Remove a listener. */
41
+ off(event, listener) {
42
+ this.listeners.get(event)?.delete(listener);
43
+ }
44
+ emit(event, data) {
45
+ this.listeners.get(event)?.forEach(fn => fn(data));
46
+ }
47
+ setState(state) {
48
+ this.state = state;
49
+ this.emit('state-change', state);
50
+ }
51
+ /**
52
+ * Watch a GPU device for loss. When the device is lost, automatically
53
+ * attempt to re-acquire an adapter.
54
+ *
55
+ * @returns The same device (for chaining)
56
+ */
57
+ watchDevice(device) {
58
+ device.lost.then((info) => {
59
+ const reason = info.message || 'unknown';
60
+ // If the device was intentionally destroyed, don't recover
61
+ if (info.reason === 'destroyed') {
62
+ this.setState('idle');
63
+ return;
64
+ }
65
+ this.setState('lost');
66
+ this.emit('lost', { reason });
67
+ this.attemptRecovery(0);
68
+ });
69
+ this.setState('idle');
70
+ return device;
71
+ }
72
+ async attemptRecovery(attempt) {
73
+ if (attempt >= this.maxRetries) {
74
+ this.setState('failed');
75
+ this.emit('failed', {
76
+ attempts: attempt,
77
+ lastError: 'Max retries exceeded',
78
+ });
79
+ return;
80
+ }
81
+ this.setState('recovering');
82
+ // Exponential backoff: 1s, 2s, 4s
83
+ const delay = this.baseDelay * 2 ** attempt;
84
+ await new Promise(r => setTimeout(r, delay));
85
+ try {
86
+ if (typeof navigator === 'undefined' || !('gpu' in navigator)) {
87
+ throw new Error('WebGPU not available');
88
+ }
89
+ const adapter = await navigator.gpu.requestAdapter({
90
+ powerPreference: 'high-performance',
91
+ });
92
+ if (!adapter) {
93
+ throw new Error('No GPU adapter available');
94
+ }
95
+ this.setState('recovered');
96
+ this.emit('recovered', { adapter });
97
+ }
98
+ catch (e) {
99
+ const msg = e instanceof Error ? e.message : String(e);
100
+ // Retry
101
+ this.attemptRecovery(attempt + 1);
102
+ }
103
+ }
104
+ }
105
+ //# sourceMappingURL=gpu-recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpu-recovery.js","sourceRoot":"","sources":["../src/gpu-recovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * webml-kit — Browser ML Made Easy
3
+ *
4
+ * Framework-agnostic utilities for loading and running ML models
5
+ * in the browser via WebGPU/WASM, powered by @huggingface/transformers.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { ModelClient, detectDevice, isCached } from 'webml-kit';
10
+ *
11
+ * // Check device
12
+ * const device = await detectDevice();
13
+ * console.log(device.backend); // 'webgpu'
14
+ *
15
+ * // Check cache
16
+ * if (await isCached('onnx-community/Bonsai-1.7B-ONNX')) {
17
+ * console.log('Model already downloaded!');
18
+ * }
19
+ *
20
+ * // Create client
21
+ * const client = new ModelClient(
22
+ * new URL('./model-worker.js', import.meta.url)
23
+ * );
24
+ *
25
+ * // Load model
26
+ * await client.load({
27
+ * task: 'text-generation',
28
+ * modelId: 'onnx-community/Bonsai-1.7B-ONNX',
29
+ * dtype: 'q4',
30
+ * onProgress: ({ percent }) => console.log(`${percent}%`),
31
+ * });
32
+ *
33
+ * // Stream tokens
34
+ * for await (const { token, tps } of client.stream('Hello!')) {
35
+ * process.stdout.write(token);
36
+ * }
37
+ * ```
38
+ *
39
+ * @packageDocumentation
40
+ */
41
+ export { ModelClient } from './model-client.js';
42
+ export type { LoadOptions, ClientEventType } from './model-client.js';
43
+ export { detectDevice, checkWebGPU, checkWASM, getGPUAdapter, getGPUInfo, recommendDtype, canRun, parseSize, formatSize, } from './device.js';
44
+ export { getCacheBackend, isCached, getCacheSize, listCachedModels, clearCache, } from './cache.js';
45
+ export { TokenStream, collectStream } from './streaming.js';
46
+ export { GPURecovery } from './gpu-recovery.js';
47
+ export type { RecoveryState, GPURecoveryEvents } from './gpu-recovery.js';
48
+ export { PIPELINE_REGISTRY, getPipelineDefaults, supportsStreaming, } from './pipelines/index.js';
49
+ export type { PipelineDefaults } from './pipelines/index.js';
50
+ export type { DeviceBackend, DeviceInfo, GPUInfo, QuantizationType, PipelineTask, ModelConfig, ProgressEvent, ProgressCallback, TokenEvent, ChatMessage, TextGenerationOptions, TextGenerationResult, ClassificationResult, DetectionResult, TranscriptionResult, EmbeddingResult, CaptionResult, TextResult, CacheBackend, CachedModel, } from './types.js';
51
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGtE,OAAO,EACL,YAAY,EACZ,WAAW,EACX,SAAS,EACT,aAAa,EACb,UAAU,EACV,cAAc,EACd,MAAM,EACN,SAAS,EACT,UAAU,GACX,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,UAAU,GACX,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG5D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAG1E,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,YAAY,EACV,aAAa,EACb,UAAU,EACV,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,GACZ,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ /**
2
+ * webml-kit — Browser ML Made Easy
3
+ *
4
+ * Framework-agnostic utilities for loading and running ML models
5
+ * in the browser via WebGPU/WASM, powered by @huggingface/transformers.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { ModelClient, detectDevice, isCached } from 'webml-kit';
10
+ *
11
+ * // Check device
12
+ * const device = await detectDevice();
13
+ * console.log(device.backend); // 'webgpu'
14
+ *
15
+ * // Check cache
16
+ * if (await isCached('onnx-community/Bonsai-1.7B-ONNX')) {
17
+ * console.log('Model already downloaded!');
18
+ * }
19
+ *
20
+ * // Create client
21
+ * const client = new ModelClient(
22
+ * new URL('./model-worker.js', import.meta.url)
23
+ * );
24
+ *
25
+ * // Load model
26
+ * await client.load({
27
+ * task: 'text-generation',
28
+ * modelId: 'onnx-community/Bonsai-1.7B-ONNX',
29
+ * dtype: 'q4',
30
+ * onProgress: ({ percent }) => console.log(`${percent}%`),
31
+ * });
32
+ *
33
+ * // Stream tokens
34
+ * for await (const { token, tps } of client.stream('Hello!')) {
35
+ * process.stdout.write(token);
36
+ * }
37
+ * ```
38
+ *
39
+ * @packageDocumentation
40
+ */
41
+ // ─── Core ───
42
+ export { ModelClient } from './model-client.js';
43
+ // ─── Device Detection ───
44
+ export { detectDevice, checkWebGPU, checkWASM, getGPUAdapter, getGPUInfo, recommendDtype, canRun, parseSize, formatSize, } from './device.js';
45
+ // ─── Cache ───
46
+ export { getCacheBackend, isCached, getCacheSize, listCachedModels, clearCache, } from './cache.js';
47
+ // ─── Streaming ───
48
+ export { TokenStream, collectStream } from './streaming.js';
49
+ // ─── GPU Recovery ───
50
+ export { GPURecovery } from './gpu-recovery.js';
51
+ // ─── Pipelines ───
52
+ export { PIPELINE_REGISTRY, getPipelineDefaults, supportsStreaming, } from './pipelines/index.js';
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,2BAA2B;AAC3B,OAAO,EACL,YAAY,EACZ,WAAW,EACX,SAAS,EACT,aAAa,EACb,UAAU,EACV,cAAc,EACd,MAAM,EACN,SAAS,EACT,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,gBAAgB;AAChB,OAAO,EACL,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,UAAU,GACX,MAAM,YAAY,CAAC;AAEpB,oBAAoB;AACpB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE5D,uBAAuB;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,oBAAoB;AACpB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Main-thread client for communicating with the ML worker.
3
+ *
4
+ * Wraps the Web Worker's postMessage protocol with a promise-based API,
5
+ * AsyncIterable token streaming, and typed events.
6
+ *
7
+ * ```ts
8
+ * import { ModelClient } from 'webml-kit';
9
+ *
10
+ * const client = new ModelClient();
11
+ *
12
+ * // Check device capabilities
13
+ * const device = await client.detect();
14
+ * console.log(device.backend); // 'webgpu'
15
+ *
16
+ * // Load a model
17
+ * await client.load({
18
+ * task: 'text-generation',
19
+ * modelId: 'onnx-community/Bonsai-1.7B-ONNX',
20
+ * dtype: 'q4',
21
+ * onProgress: ({ percent }) => console.log(`${percent}%`),
22
+ * });
23
+ *
24
+ * // Stream text generation
25
+ * for await (const { token, tps } of client.stream('Hello!')) {
26
+ * process.stdout.write(token);
27
+ * }
28
+ *
29
+ * // One-shot inference
30
+ * const labels = await client.run('image-classification', imageBlob);
31
+ * ```
32
+ */
33
+ import type { DeviceInfo, ModelConfig, PipelineTask, ProgressCallback, TextGenerationOptions, TextGenerationResult, ChatMessage } from './types.js';
34
+ import { TokenStream } from './streaming.js';
35
+ export interface LoadOptions extends ModelConfig {
36
+ onProgress?: ProgressCallback;
37
+ }
38
+ export type ClientEventType = 'progress' | 'ready' | 'error' | 'device-lost' | 'device-recovered';
39
+ type Listener = (data: unknown) => void;
40
+ export declare class ModelClient {
41
+ private worker;
42
+ private workerUrl;
43
+ private listeners;
44
+ private pendingRequests;
45
+ private requestCounter;
46
+ private deviceInfo;
47
+ private loadedModels;
48
+ private progressCallback;
49
+ private gpuRecovery;
50
+ /**
51
+ * Create a new ModelClient.
52
+ *
53
+ * @param workerUrl - URL to the model-worker.js file. If omitted,
54
+ * creates a Blob URL from the bundled worker (requires bundler support).
55
+ */
56
+ constructor(workerUrl?: string | URL);
57
+ private getWorker;
58
+ private send;
59
+ private nextId;
60
+ private handleMessage;
61
+ /** Register an event listener. */
62
+ on(event: ClientEventType, listener: Listener): this;
63
+ /** Remove an event listener. */
64
+ off(event: ClientEventType, listener: Listener): this;
65
+ private emit;
66
+ /**
67
+ * Detect the best available compute backend.
68
+ *
69
+ * ```ts
70
+ * const info = await client.detect();
71
+ * console.log(info.backend); // 'webgpu'
72
+ * console.log(info.gpu?.vendor); // 'apple'
73
+ * console.log(info.recommendedDtype); // 'q4'
74
+ * ```
75
+ */
76
+ detect(): Promise<DeviceInfo>;
77
+ /**
78
+ * Load a model pipeline.
79
+ *
80
+ * ```ts
81
+ * await client.load({
82
+ * task: 'text-generation',
83
+ * modelId: 'onnx-community/Bonsai-1.7B-ONNX',
84
+ * dtype: 'q4',
85
+ * onProgress: ({ percent }) => updateUI(percent),
86
+ * });
87
+ * ```
88
+ */
89
+ load(options: LoadOptions): Promise<void>;
90
+ /**
91
+ * Run one-shot inference for any pipeline task.
92
+ *
93
+ * ```ts
94
+ * // Image classification
95
+ * const labels = await client.run('image-classification', imageUrl);
96
+ *
97
+ * // Speech recognition
98
+ * const { text } = await client.run('automatic-speech-recognition', audioBlob);
99
+ *
100
+ * // Embeddings
101
+ * const vectors = await client.run('feature-extraction', 'Hello world');
102
+ * ```
103
+ */
104
+ run<T = unknown>(task: PipelineTask, input: unknown, options?: Record<string, unknown>): Promise<T>;
105
+ /**
106
+ * Generate text with streaming tokens.
107
+ *
108
+ * Returns an `AsyncIterable<TokenEvent>` that yields tokens as they're generated.
109
+ *
110
+ * ```ts
111
+ * for await (const { token, tps } of client.stream('Tell me a joke')) {
112
+ * process.stdout.write(token);
113
+ * }
114
+ * ```
115
+ */
116
+ stream(input: string | ChatMessage[], options?: TextGenerationOptions): TokenStream;
117
+ /**
118
+ * Generate text and wait for the complete result.
119
+ *
120
+ * ```ts
121
+ * const { text, tps, numTokens } = await client.generate('Hello!');
122
+ * ```
123
+ */
124
+ generate(input: string | ChatMessage[], options?: TextGenerationOptions): Promise<TextGenerationResult>;
125
+ /**
126
+ * Interrupt an ongoing text generation.
127
+ */
128
+ interrupt(): void;
129
+ /**
130
+ * Reset the KV cache (start a new conversation).
131
+ */
132
+ reset(): void;
133
+ /**
134
+ * Dispose a loaded model and free memory.
135
+ *
136
+ * @param modelKey - Specific model key (task::modelId), or omit to dispose all.
137
+ */
138
+ dispose(modelKey?: string): void;
139
+ /**
140
+ * Check if a model is currently loaded.
141
+ */
142
+ isLoaded(task: PipelineTask, modelId: string): boolean;
143
+ /**
144
+ * Terminate the worker completely.
145
+ */
146
+ terminate(): void;
147
+ }
148
+ export {};
149
+ //# sourceMappingURL=model-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-client.d.ts","sourceRoot":"","sources":["../src/model-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EAIpB,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,WAAW,EAAiB,MAAM,gBAAgB,CAAC;AAK5D,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED,MAAM,MAAM,eAAe,GACvB,UAAU,GACV,OAAO,GACP,OAAO,GACP,aAAa,GACb,kBAAkB,CAAC;AAEvB,KAAK,QAAQ,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;AAIxC,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,eAAe,CAOnB;IACJ,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,WAAW,CAAc;IAEjC;;;;;OAKG;gBACS,SAAS,CAAC,EAAE,MAAM,GAAG,GAAG;IAcpC,OAAO,CAAC,SAAS;IAsBjB,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,aAAa;IA8ErB,kCAAkC;IAClC,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAQpD,gCAAgC;IAChC,GAAG,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAKrD,OAAO,CAAC,IAAI;IAMZ;;;;;;;;;OASG;IACG,MAAM,IAAI,OAAO,CAAC,UAAU,CAAC;IASnC;;;;;;;;;;;OAWG;IACG,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB/C;;;;;;;;;;;;;OAaG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EACnB,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,OAAO,CAAC,CAAC,CAAC;IASb;;;;;;;;;;OAUG;IACH,MAAM,CACJ,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,EAC7B,OAAO,CAAC,EAAE,qBAAqB,GAC9B,WAAW;IAqBd;;;;;;OAMG;IACG,QAAQ,CACZ,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,EAC7B,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,oBAAoB,CAAC;IAShC;;OAEG;IACH,SAAS,IAAI,IAAI;IAIjB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAShC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IAItD;;OAEG;IACH,SAAS,IAAI,IAAI;CAOlB"}