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/README.md +205 -0
- package/dist/cache.d.ts +46 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +160 -0
- package/dist/cache.js.map +1 -0
- package/dist/device.d.ts +86 -0
- package/dist/device.d.ts.map +1 -0
- package/dist/device.js +195 -0
- package/dist/device.js.map +1 -0
- package/dist/gpu-recovery.d.ts +61 -0
- package/dist/gpu-recovery.d.ts.map +1 -0
- package/dist/gpu-recovery.js +105 -0
- package/dist/gpu-recovery.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/model-client.d.ts +149 -0
- package/dist/model-client.d.ts.map +1 -0
- package/dist/model-client.js +325 -0
- package/dist/model-client.js.map +1 -0
- package/dist/model-worker.d.ts +16 -0
- package/dist/model-worker.d.ts.map +1 -0
- package/dist/model-worker.js +303 -0
- package/dist/model-worker.js.map +1 -0
- package/dist/pipelines/index.d.ts +28 -0
- package/dist/pipelines/index.d.ts.map +1 -0
- package/dist/pipelines/index.js +122 -0
- package/dist/pipelines/index.js.map +1 -0
- package/dist/streaming.d.ts +55 -0
- package/dist/streaming.d.ts.map +1 -0
- package/dist/streaming.js +142 -0
- package/dist/streaming.js.map +1 -0
- package/dist/types.d.ts +186 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +56 -0
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":"AAAA;;;;;;GAMG;AAcH;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,WAAW;IACd,KAAK,GAAkB,MAAM,CAAC;IAC9B,SAAS,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC7C,UAAU,CAAS;IACnB,SAAS,CAAS;IAE1B,YAAY,OAAuD;QACjE,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,WAAW,IAAI,IAAI,CAAC;IAChD,CAAC;IAED,8BAA8B;IAC9B,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,+CAA+C;IAC/C,EAAE,CACA,KAAQ,EACR,QAAgC;QAEhC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QACvC,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED,yBAAyB;IACzB,GAAG,CACD,KAAQ,EACR,QAAgC;QAEhC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAEO,IAAI,CACV,KAAQ,EACR,IAA0B;QAE1B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,CAAE,EAA6B,CAAC,IAAI,CAAC,CAAC,CAAC;IACjF,CAAC;IAEO,QAAQ,CAAC,KAAoB;QACnC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;IAED;;;;;OAKG;IACH,WAAW,CAAC,MAAiB;QAC3B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAuB,EAAE,EAAE;YAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,IAAI,SAAS,CAAC;YAEzC,2DAA2D;YAC3D,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBAChC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACtB,OAAO;YACT,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACtB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAC9B,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACtB,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,eAAe,CAAC,OAAe;QAC3C,IAAI,OAAO,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACxB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;gBAClB,QAAQ,EAAE,OAAO;gBACjB,SAAS,EAAE,sBAAsB;aAClC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAE5B,kCAAkC;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,OAAO,CAAC;QAC5C,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QAE7C,IAAI,CAAC;YACH,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,CAAC,CAAC,KAAK,IAAI,SAAS,CAAC,EAAE,CAAC;gBAC9D,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;YAC1C,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC;gBACjD,eAAe,EAAE,kBAAkB;aACpC,CAAC,CAAC;YAEH,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;YAC9C,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACvD,QAAQ;YACR,IAAI,CAAC,eAAe,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|