localm-web 0.2.0 → 0.4.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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/core/load-phase.ts","../src/core/exceptions.ts","../src/core/webllm-engine.ts","../src/worker/protocol.ts","../src/core/worker-engine.ts","../src/presets/models.ts","../src/worker/create-worker.ts","../src/tasks/lm-task.ts","../src/results.ts","../src/tasks/chat.ts","../src/tasks/completion.ts","../src/cache/model-cache.ts","../src/streaming/token-stream.ts","../src/index.ts"],"sourcesContent":["import type { ModelLoadPhase } from \"../types\";\n\nconst DOWNLOAD_PATTERN: RegExp = /\\b(fetch|download|loading from cache|cache hit|param)/i;\nconst COMPILE_PATTERN: RegExp = /\\b(compil|shader|kernel|tensor|init|allocat|warm)/i;\n\n/**\n * Classify a runtime status text into a {@link ModelLoadPhase}.\n *\n * Heuristic: match download-related verbs first (network or cache hits are\n * treated as `downloading`), then compile-related verbs. Anything else falls\n * back to the generic `loading` bucket. The `ready` phase is never returned\n * here — callers emit it explicitly when the load resolves.\n *\n * @param text - The raw status string from the runtime.\n * @returns The classified phase.\n */\nexport function classifyLoadPhase(text: string): ModelLoadPhase {\n if (DOWNLOAD_PATTERN.test(text)) return \"downloading\";\n if (COMPILE_PATTERN.test(text)) return \"compiling\";\n return \"loading\";\n}\n","/**\n * Error hierarchy for localm-web.\n *\n * All errors thrown by the SDK extend `LocalmWebError` so consumers can\n * distinguish SDK errors from unrelated runtime errors with a single\n * `instanceof` check.\n */\n\n/** Base class for every error raised by localm-web. */\nexport class LocalmWebError extends Error {\n /**\n * @param message - Human-readable description of the error.\n * @param cause - Underlying error, if any.\n */\n constructor(\n message: string,\n public readonly cause?: unknown\n ) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** Thrown when WebGPU is required but not available in the host browser. */\nexport class WebGPUUnavailableError extends LocalmWebError {}\n\n/** Thrown when a model fails to load (network, parsing, runtime init). */\nexport class ModelLoadError extends LocalmWebError {}\n\n/** Thrown when an inference call is made before a model has loaded. */\nexport class ModelNotLoadedError extends LocalmWebError {}\n\n/** Thrown when a model id is not present in the curated registry. */\nexport class UnknownModelError extends LocalmWebError {}\n\n/** Thrown when generation is aborted via an `AbortSignal`. */\nexport class GenerationAbortedError extends LocalmWebError {}\n\n/** Thrown when the browser denies storage quota for the model cache. */\nexport class QuotaExceededError extends LocalmWebError {}\n\n/** Thrown when no usable backend is available on the current platform. */\nexport class BackendNotAvailableError extends LocalmWebError {}\n","import type { Engine } from \"./engine\";\nimport { classifyLoadPhase } from \"./load-phase\";\nimport type { GenerationOptions, Message, ProgressCallback, TokenChunk } from \"../types\";\nimport {\n GenerationAbortedError,\n ModelLoadError,\n ModelNotLoadedError,\n WebGPUUnavailableError,\n} from \"./exceptions\";\n\ntype WebLLMModule = typeof import(\"@mlc-ai/web-llm\");\ntype MLCEngine = import(\"@mlc-ai/web-llm\").MLCEngineInterface;\ntype ChatCompletionMessageParam = import(\"@mlc-ai/web-llm\").ChatCompletionMessageParam;\n\nlet webllmModulePromise: Promise<WebLLMModule> | null = null;\n\nasync function loadWebLLM(): Promise<WebLLMModule> {\n if (!webllmModulePromise) {\n webllmModulePromise = import(\"@mlc-ai/web-llm\");\n }\n return webllmModulePromise;\n}\n\nfunction isWebGPUAvailable(): boolean {\n return typeof navigator !== \"undefined\" && \"gpu\" in navigator;\n}\n\ninterface SamplingParams {\n max_tokens?: number;\n temperature?: number;\n top_p?: number;\n}\n\nfunction buildSamplingParams(options: GenerationOptions): SamplingParams {\n const params: SamplingParams = {};\n if (options.maxTokens !== undefined) params.max_tokens = options.maxTokens;\n if (options.temperature !== undefined) params.temperature = options.temperature;\n if (options.topP !== undefined) params.top_p = options.topP;\n return params;\n}\n\nfunction toChatMessages(messages: Message[]): ChatCompletionMessageParam[] {\n return messages.map((m): ChatCompletionMessageParam => {\n switch (m.role) {\n case \"system\":\n return { role: \"system\", content: m.content };\n case \"user\":\n return { role: \"user\", content: m.content };\n case \"assistant\":\n return { role: \"assistant\", content: m.content };\n case \"tool\":\n return { role: \"tool\", content: m.content, tool_call_id: m.name ?? \"\" };\n }\n });\n}\n\n/**\n * Inference engine backed by [WebLLM (MLC)](https://github.com/mlc-ai/web-llm).\n *\n * Requires WebGPU. The fallback path planned for v0.5 will route to ORT-Web\n * when WebGPU is missing.\n */\nexport class WebLLMEngine implements Engine {\n private engine: MLCEngine | null = null;\n\n isLoaded(): boolean {\n return this.engine !== null;\n }\n\n async load(modelId: string, onProgress?: ProgressCallback): Promise<void> {\n if (!isWebGPUAvailable()) {\n throw new WebGPUUnavailableError(\n \"WebGPU is not available in this browser. The ORT-Web fallback is planned for v0.5.\"\n );\n }\n const webllm = await loadWebLLM();\n try {\n this.engine = await webllm.CreateMLCEngine(modelId, {\n initProgressCallback: (report): void => {\n onProgress?.({\n progress: report.progress,\n text: report.text,\n loaded: 0,\n total: 0,\n phase: classifyLoadPhase(report.text),\n });\n },\n });\n onProgress?.({\n progress: 1,\n text: \"Model ready.\",\n loaded: 0,\n total: 0,\n phase: \"ready\",\n });\n } catch (err) {\n throw new ModelLoadError(`Failed to load model \"${modelId}\".`, err);\n }\n }\n\n async generate(messages: Message[], options: GenerationOptions = {}): Promise<string> {\n const engine = this.requireEngine();\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted before start.\");\n }\n const completion = await engine.chat.completions.create({\n ...buildSamplingParams(options),\n messages: toChatMessages(messages),\n stream: false,\n });\n return completion.choices[0]?.message?.content ?? \"\";\n }\n\n async *stream(messages: Message[], options: GenerationOptions = {}): AsyncIterable<TokenChunk> {\n const engine = this.requireEngine();\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted before start.\");\n }\n const completion = await engine.chat.completions.create({\n ...buildSamplingParams(options),\n messages: toChatMessages(messages),\n stream: true,\n });\n let index: number = 0;\n let finished: boolean = false;\n try {\n for await (const chunk of completion) {\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted by signal.\");\n }\n const choice = chunk.choices[0];\n const delta = choice?.delta?.content ?? \"\";\n if (delta) {\n yield { text: delta, index, done: false };\n index += 1;\n }\n if (choice?.finish_reason) {\n finished = true;\n yield { text: \"\", index, done: true };\n index += 1;\n }\n }\n if (!finished) {\n yield { text: \"\", index, done: true };\n }\n } catch (err) {\n if (err instanceof GenerationAbortedError) throw err;\n throw new ModelLoadError(\"Streaming generation failed.\", err);\n }\n }\n\n async complete(prompt: string, options: GenerationOptions = {}): Promise<string> {\n const engine = this.requireEngine();\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted before start.\");\n }\n const completion = await engine.completions.create({\n ...buildSamplingParams(options),\n prompt,\n stream: false,\n });\n return completion.choices[0]?.text ?? \"\";\n }\n\n async *streamCompletion(\n prompt: string,\n options: GenerationOptions = {}\n ): AsyncIterable<TokenChunk> {\n const engine = this.requireEngine();\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted before start.\");\n }\n const completion = await engine.completions.create({\n ...buildSamplingParams(options),\n prompt,\n stream: true,\n });\n let index: number = 0;\n let finished: boolean = false;\n try {\n for await (const chunk of completion) {\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted by signal.\");\n }\n const choice = chunk.choices[0];\n const delta = choice?.text ?? \"\";\n if (delta) {\n yield { text: delta, index, done: false };\n index += 1;\n }\n if (choice?.finish_reason) {\n finished = true;\n yield { text: \"\", index, done: true };\n index += 1;\n }\n }\n if (!finished) {\n yield { text: \"\", index, done: true };\n }\n } catch (err) {\n if (err instanceof GenerationAbortedError) throw err;\n throw new ModelLoadError(\"Streaming completion failed.\", err);\n }\n }\n\n async unload(): Promise<void> {\n if (this.engine) {\n await this.engine.unload();\n this.engine = null;\n }\n }\n\n private requireEngine(): MLCEngine {\n if (!this.engine) {\n throw new ModelNotLoadedError(\"Engine not loaded. Call load() before generation.\");\n }\n return this.engine;\n }\n}\n","import type { GenerationOptions, Message, ModelLoadProgress, TokenChunk } from \"../types\";\n\n/**\n * Subset of {@link GenerationOptions} that survives `postMessage`.\n *\n * `AbortSignal` cannot be cloned across the worker boundary, so it is replaced\n * by a separate {@link AbortRequest} message keyed on the same operation id.\n */\nexport type SerializableGenerationOptions = Omit<GenerationOptions, \"signal\">;\n\n/** Strip `signal` from a {@link GenerationOptions} before posting it. */\nexport function toSerializableOptions(\n options: GenerationOptions = {}\n): SerializableGenerationOptions {\n const { signal: _signal, ...rest } = options;\n void _signal;\n return rest;\n}\n\n/** Operation request sent from the main thread to the worker. */\nexport type WorkerRequest =\n | { op: \"load\"; id: number; modelId: string }\n | {\n op: \"generate\";\n id: number;\n messages: Message[];\n options: SerializableGenerationOptions;\n }\n | {\n op: \"stream\";\n id: number;\n messages: Message[];\n options: SerializableGenerationOptions;\n }\n | {\n op: \"complete\";\n id: number;\n prompt: string;\n options: SerializableGenerationOptions;\n }\n | {\n op: \"stream-completion\";\n id: number;\n prompt: string;\n options: SerializableGenerationOptions;\n }\n | { op: \"abort\"; id: number }\n | { op: \"unload\"; id: number }\n | { op: \"isLoaded\"; id: number };\n\n/** Operation response sent from the worker back to the main thread. */\nexport type WorkerResponse =\n | { op: \"loaded\"; id: number }\n | { op: \"generated\"; id: number; text: string }\n | { op: \"progress\"; id: number; payload: ModelLoadProgress }\n | { op: \"token\"; id: number; chunk: TokenChunk }\n | { op: \"stream-end\"; id: number }\n | { op: \"error\"; id: number; name: string; message: string }\n | { op: \"unloaded\"; id: number }\n | { op: \"is-loaded\"; id: number; value: boolean };\n\n/** Subset of `Worker` we depend on. Lets tests inject a mock. */\nexport interface WorkerLike {\n postMessage(message: WorkerRequest): void;\n addEventListener(type: \"message\", listener: (event: MessageEvent<WorkerResponse>) => void): void;\n removeEventListener(\n type: \"message\",\n listener: (event: MessageEvent<WorkerResponse>) => void\n ): void;\n terminate(): void;\n}\n\n/** Internal alias used when the message direction is irrelevant (logging, debug). */\nexport type AbortRequest = Extract<WorkerRequest, { op: \"abort\" }>;\n","import { GenerationAbortedError, ModelLoadError, ModelNotLoadedError } from \"./exceptions\";\nimport type { Engine } from \"./engine\";\nimport type { GenerationOptions, Message, ProgressCallback, TokenChunk } from \"../types\";\nimport {\n toSerializableOptions,\n type WorkerLike,\n type WorkerRequest,\n type WorkerResponse,\n} from \"../worker/protocol\";\n\ninterface PendingGenerate {\n resolve: (text: string) => void;\n reject: (err: Error) => void;\n}\n\ninterface PendingStream {\n push: (chunk: TokenChunk) => void;\n end: () => void;\n fail: (err: Error) => void;\n}\n\n/**\n * Engine implementation that proxies all calls to a Web Worker.\n *\n * The worker holds the actual {@link WebLLMEngine}; this class is a thin RPC\n * shell that serializes requests, tracks pending operations by a numeric id,\n * and turns worker responses back into Promises and async iterables.\n *\n * Use {@link createInferenceWorker} to obtain a real worker. Tests can pass a\n * {@link WorkerLike} mock implementing the same `postMessage` /\n * `addEventListener` surface.\n */\nexport class WorkerEngine implements Engine {\n private nextId: number = 1;\n private loaded: boolean = false;\n private currentLoad: { resolve: () => void; reject: (e: Error) => void } | null = null;\n private currentLoadId: number = 0;\n private currentLoadProgress: ProgressCallback | undefined = undefined;\n private currentUnload: { resolve: () => void; reject: (e: Error) => void } | null = null;\n private currentUnloadId: number = 0;\n private pendingGenerates: Map<number, PendingGenerate> = new Map();\n private pendingStreams: Map<number, PendingStream> = new Map();\n\n private readonly listener: (event: MessageEvent<WorkerResponse>) => void;\n\n constructor(private readonly worker: WorkerLike) {\n this.listener = (event): void => this.handleMessage(event.data);\n this.worker.addEventListener(\"message\", this.listener);\n }\n\n isLoaded(): boolean {\n return this.loaded;\n }\n\n async load(modelId: string, onProgress?: ProgressCallback): Promise<void> {\n if (this.currentLoad) {\n throw new ModelLoadError(\"Another load is already in progress.\");\n }\n const id: number = this.allocateId();\n this.currentLoadId = id;\n this.currentLoadProgress = onProgress;\n return new Promise<void>((resolve, reject) => {\n this.currentLoad = { resolve, reject };\n this.send({ op: \"load\", id, modelId });\n });\n }\n\n async generate(messages: Message[], options: GenerationOptions = {}): Promise<string> {\n const id: number = this.allocateId();\n return new Promise<string>((resolve, reject) => {\n this.pendingGenerates.set(id, { resolve, reject });\n this.send({\n op: \"generate\",\n id,\n messages,\n options: toSerializableOptions(options),\n });\n options.signal?.addEventListener(\"abort\", () => this.send({ op: \"abort\", id }));\n });\n }\n\n async *stream(messages: Message[], options: GenerationOptions = {}): AsyncIterable<TokenChunk> {\n const id: number = this.allocateId();\n const queue: TokenChunk[] = [];\n let done: boolean = false;\n let error: Error | null = null;\n let notify: (() => void) | null = null;\n\n const wakeup = (): void => {\n if (notify) {\n const fn = notify;\n notify = null;\n fn();\n }\n };\n\n this.pendingStreams.set(id, {\n push: (chunk): void => {\n queue.push(chunk);\n wakeup();\n },\n end: (): void => {\n done = true;\n wakeup();\n },\n fail: (err): void => {\n error = err;\n done = true;\n wakeup();\n },\n });\n\n this.send({\n op: \"stream\",\n id,\n messages,\n options: toSerializableOptions(options),\n });\n options.signal?.addEventListener(\"abort\", () => this.send({ op: \"abort\", id }));\n\n try {\n while (true) {\n if (queue.length > 0) {\n const chunk = queue.shift();\n if (chunk) yield chunk;\n continue;\n }\n if (error) throw error;\n if (done) return;\n await new Promise<void>((r) => {\n notify = r;\n });\n }\n } finally {\n this.pendingStreams.delete(id);\n }\n }\n\n async complete(prompt: string, options: GenerationOptions = {}): Promise<string> {\n const id: number = this.allocateId();\n return new Promise<string>((resolve, reject) => {\n this.pendingGenerates.set(id, { resolve, reject });\n this.send({\n op: \"complete\",\n id,\n prompt,\n options: toSerializableOptions(options),\n });\n options.signal?.addEventListener(\"abort\", () => this.send({ op: \"abort\", id }));\n });\n }\n\n async *streamCompletion(\n prompt: string,\n options: GenerationOptions = {}\n ): AsyncIterable<TokenChunk> {\n const id: number = this.allocateId();\n const queue: TokenChunk[] = [];\n let done: boolean = false;\n let error: Error | null = null;\n let notify: (() => void) | null = null;\n\n const wakeup = (): void => {\n if (notify) {\n const fn = notify;\n notify = null;\n fn();\n }\n };\n\n this.pendingStreams.set(id, {\n push: (chunk): void => {\n queue.push(chunk);\n wakeup();\n },\n end: (): void => {\n done = true;\n wakeup();\n },\n fail: (err): void => {\n error = err;\n done = true;\n wakeup();\n },\n });\n\n this.send({\n op: \"stream-completion\",\n id,\n prompt,\n options: toSerializableOptions(options),\n });\n options.signal?.addEventListener(\"abort\", () => this.send({ op: \"abort\", id }));\n\n try {\n while (true) {\n if (queue.length > 0) {\n const chunk = queue.shift();\n if (chunk) yield chunk;\n continue;\n }\n if (error) throw error;\n if (done) return;\n await new Promise<void>((r) => {\n notify = r;\n });\n }\n } finally {\n this.pendingStreams.delete(id);\n }\n }\n\n async unload(): Promise<void> {\n if (!this.loaded) return;\n if (this.currentUnload) {\n throw new ModelLoadError(\"Another unload is already in progress.\");\n }\n const id: number = this.allocateId();\n this.currentUnloadId = id;\n return new Promise<void>((resolve, reject) => {\n this.currentUnload = { resolve, reject };\n this.send({ op: \"unload\", id });\n });\n }\n\n /** Tear down the underlying worker. The engine is unusable after this. */\n terminate(): void {\n this.worker.removeEventListener(\"message\", this.listener);\n this.worker.terminate();\n this.loaded = false;\n }\n\n private allocateId(): number {\n const id = this.nextId;\n this.nextId += 1;\n return id;\n }\n\n private send(req: WorkerRequest): void {\n this.worker.postMessage(req);\n }\n\n private handleMessage(msg: WorkerResponse): void {\n switch (msg.op) {\n case \"loaded\":\n if (this.currentLoad && msg.id === this.currentLoadId) {\n this.loaded = true;\n this.currentLoad.resolve();\n this.currentLoad = null;\n this.currentLoadProgress = undefined;\n }\n return;\n case \"progress\":\n if (msg.id === this.currentLoadId) {\n this.currentLoadProgress?.(msg.payload);\n }\n return;\n case \"generated\": {\n const pending = this.pendingGenerates.get(msg.id);\n if (pending) {\n pending.resolve(msg.text);\n this.pendingGenerates.delete(msg.id);\n }\n return;\n }\n case \"token\": {\n const stream = this.pendingStreams.get(msg.id);\n stream?.push(msg.chunk);\n return;\n }\n case \"stream-end\": {\n const stream = this.pendingStreams.get(msg.id);\n stream?.end();\n return;\n }\n case \"unloaded\":\n if (this.currentUnload && msg.id === this.currentUnloadId) {\n this.loaded = false;\n this.currentUnload.resolve();\n this.currentUnload = null;\n }\n return;\n case \"is-loaded\":\n return;\n case \"error\": {\n const err = mapError(msg.name, msg.message);\n if (this.currentLoad && msg.id === this.currentLoadId) {\n this.currentLoad.reject(err);\n this.currentLoad = null;\n this.currentLoadProgress = undefined;\n return;\n }\n if (this.currentUnload && msg.id === this.currentUnloadId) {\n this.currentUnload.reject(err);\n this.currentUnload = null;\n return;\n }\n const generate = this.pendingGenerates.get(msg.id);\n if (generate) {\n generate.reject(err);\n this.pendingGenerates.delete(msg.id);\n return;\n }\n const stream = this.pendingStreams.get(msg.id);\n if (stream) {\n stream.fail(err);\n return;\n }\n return;\n }\n }\n }\n}\n\nfunction mapError(name: string, message: string): Error {\n switch (name) {\n case \"ModelLoadError\":\n return new ModelLoadError(message);\n case \"ModelNotLoadedError\":\n return new ModelNotLoadedError(message);\n case \"GenerationAbortedError\":\n return new GenerationAbortedError(message);\n default: {\n const err = new Error(message);\n err.name = name;\n return err;\n }\n }\n}\n","import type { ModelPreset } from \"../types\";\nimport { UnknownModelError } from \"../core/exceptions\";\n\n/**\n * Curated registry of supported models for v0.1.\n *\n * Each entry maps a friendly id (e.g. `\"phi-3.5-mini-int4\"`) to the underlying\n * runtime identifier and metadata. Friendly ids are stable; backend ids may\n * change as upstream MLC packages evolve.\n *\n * Only models that have been validated to load in browsers with WebGPU and\n * that fit the SLM target (≤ 4B parameters at INT4) are included.\n */\nexport const MODEL_PRESETS: Readonly<Record<string, ModelPreset>> = Object.freeze({\n \"phi-3.5-mini-int4\": {\n id: \"phi-3.5-mini-int4\",\n family: \"Phi-3.5\",\n parameters: \"3.8B\",\n quantization: \"q4f16_1\",\n webllmId: \"Phi-3.5-mini-instruct-q4f16_1-MLC\",\n contextWindow: 4096,\n description: \"Microsoft Phi-3.5 mini, INT4 quantized for browser inference.\",\n },\n \"llama-3.2-1b-int4\": {\n id: \"llama-3.2-1b-int4\",\n family: \"Llama-3.2\",\n parameters: \"1B\",\n quantization: \"q4f16_1\",\n webllmId: \"Llama-3.2-1B-Instruct-q4f16_1-MLC\",\n contextWindow: 4096,\n description: \"Meta Llama 3.2 1B Instruct, INT4 quantized.\",\n },\n \"qwen2.5-1.5b-int4\": {\n id: \"qwen2.5-1.5b-int4\",\n family: \"Qwen2.5\",\n parameters: \"1.5B\",\n quantization: \"q4f16_1\",\n webllmId: \"Qwen2.5-1.5B-Instruct-q4f16_1-MLC\",\n contextWindow: 4096,\n description: \"Alibaba Qwen 2.5 1.5B Instruct, INT4 quantized.\",\n },\n});\n\n/**\n * Resolve a friendly model id to its full preset metadata.\n *\n * @param modelId - Friendly id (e.g. `\"phi-3.5-mini-int4\"`).\n * @returns The matching preset.\n * @throws UnknownModelError if no preset matches.\n */\nexport function resolveModelPreset(modelId: string): ModelPreset {\n const preset = MODEL_PRESETS[modelId];\n if (!preset) {\n const available = Object.keys(MODEL_PRESETS).join(\", \");\n throw new UnknownModelError(`Unknown model \"${modelId}\". Available models: ${available}.`);\n }\n return preset;\n}\n\n/** Return the list of supported friendly model ids. */\nexport function listSupportedModels(): string[] {\n return Object.keys(MODEL_PRESETS);\n}\n","import type { WorkerLike } from \"./protocol\";\n\n/**\n * Spawn a new inference Web Worker.\n *\n * Uses Vite/webpack-friendly `new Worker(new URL(...), { type: \"module\" })`\n * syntax. The bundler emits the worker as a separate ES module chunk.\n *\n * Consumers normally do not call this directly — `LMTask.create()` invokes it\n * when `inWorker: true` is set. It is exported for advanced scenarios (custom\n * worker management, pooling, lifecycle integration with a host app).\n *\n * @returns A {@link WorkerLike}-compatible Worker instance.\n */\nexport function createInferenceWorker(): WorkerLike {\n return new Worker(new URL(\"./inference.worker.ts\", import.meta.url), {\n type: \"module\",\n }) as unknown as WorkerLike;\n}\n","import type { Engine } from \"../core/engine\";\nimport { WebLLMEngine } from \"../core/webllm-engine\";\nimport { WorkerEngine } from \"../core/worker-engine\";\nimport { resolveModelPreset } from \"../presets/models\";\nimport { createInferenceWorker } from \"../worker/create-worker\";\nimport type { ModelPreset, ProgressCallback } from \"../types\";\n\n/** Common options accepted by every task's `create()` factory. */\nexport interface LMTaskCreateOptions {\n /** Optional callback for model load progress updates. */\n onProgress?: ProgressCallback;\n /**\n * Override the engine used for inference. Intended for testing.\n * Production callers should let the SDK pick a backend automatically.\n */\n engine?: Engine;\n /**\n * Run inference inside a Web Worker, isolating the UI thread from\n * tokenization and generation. Defaults to `false` in v0.2 (opt-in) and\n * will flip to `true` in v0.3 once the Cache API / OPFS integration\n * (also v0.2) has been validated against worker-thread storage access.\n *\n * Ignored when {@link engine} is provided.\n */\n inWorker?: boolean;\n}\n\n/** Internal payload returned by {@link LMTask.createEngine}. */\nexport interface ResolvedEngine {\n engine: Engine;\n preset: ModelPreset;\n}\n\n/**\n * Base class shared by all language-model tasks (`Chat` for v0.1; `Completion`,\n * `Embeddings` and `Reranker` planned for later versions).\n *\n * The base owns:\n * - resolving a friendly model id to a {@link ModelPreset};\n * - selecting and loading an {@link Engine} (defaulting to WebLLM);\n * - exposing `unload()` for cleanup.\n *\n * Subclasses add task-specific public methods (`send`, `stream`, etc.).\n */\nexport abstract class LMTask {\n protected constructor(\n /** Engine used for inference. */\n protected readonly engine: Engine,\n /** Resolved metadata for the loaded model. */\n public readonly preset: ModelPreset\n ) {}\n\n /**\n * Load a model into a backend and return the wired-up engine + preset.\n *\n * Subclasses call this from their static `create()` factories.\n *\n * @param modelId - Friendly model id from the registry.\n * @param options - Task creation options.\n */\n protected static async createEngine(\n modelId: string,\n options: LMTaskCreateOptions = {}\n ): Promise<ResolvedEngine> {\n const preset = resolveModelPreset(modelId);\n const engine = options.engine ?? LMTask.defaultEngine(options);\n if (!engine.isLoaded()) {\n await engine.load(preset.webllmId, options.onProgress);\n }\n return { engine, preset };\n }\n\n private static defaultEngine(options: LMTaskCreateOptions): Engine {\n if (options.inWorker) {\n return new WorkerEngine(createInferenceWorker());\n }\n return new WebLLMEngine();\n }\n\n /** Release engine resources. Safe to call multiple times. */\n async unload(): Promise<void> {\n await this.engine.unload();\n }\n\n /** Whether the underlying engine has a loaded model. */\n isLoaded(): boolean {\n return this.engine.isLoaded();\n }\n}\n","import type { FinishReason, Message } from \"./types\";\n\n/**\n * Result returned by `Chat.send()`.\n *\n * Holds the assistant's textual reply, the structured assistant message\n * (already appended to the chat history), and metadata about the generation.\n */\nexport class ChatReply {\n constructor(\n /** The assistant's reply text. */\n public readonly text: string,\n /** The structured assistant message (already appended to chat history). */\n public readonly message: Message,\n /** Number of tokens generated. 0 when the engine does not report it. */\n public readonly tokensGenerated: number,\n /** Why the generation loop stopped. */\n public readonly finishReason: FinishReason\n ) {}\n}\n\n/**\n * Result returned by `Completion.predict()`.\n *\n * Holds the generated continuation text (the prompt itself is not included)\n * plus metadata about the generation loop.\n */\nexport class CompletionResult {\n constructor(\n /** The generated text (continuation only, prompt excluded). */\n public readonly text: string,\n /** The original prompt that was fed to the model. */\n public readonly prompt: string,\n /** Number of tokens generated. 0 when the engine does not report it. */\n public readonly tokensGenerated: number,\n /** Why the generation loop stopped. */\n public readonly finishReason: FinishReason\n ) {}\n}\n","import { LMTask, type LMTaskCreateOptions } from \"./lm-task\";\nimport type { Engine } from \"../core/engine\";\nimport { ChatReply } from \"../results\";\nimport type { GenerationOptions, Message, ModelPreset, TokenChunk } from \"../types\";\n\n/**\n * Multi-turn chat task.\n *\n * Maintains an in-memory conversation history and applies the chat template\n * configured for the loaded model. Use {@link Chat.create} to construct an\n * instance — the constructor is private.\n *\n * @example\n * ```ts\n * const chat = await Chat.create(\"phi-3.5-mini-int4\");\n * const reply = await chat.send(\"Explain ONNX in one sentence.\");\n * console.log(reply.text);\n * ```\n *\n * @example Streaming\n * ```ts\n * const controller = new AbortController();\n * for await (const token of chat.stream(\"Explain ONNX.\", { signal: controller.signal })) {\n * process.stdout.write(token.text);\n * }\n * ```\n */\nexport class Chat extends LMTask {\n private readonly history: Message[] = [];\n private systemPrompt: string | null = null;\n\n private constructor(engine: Engine, preset: ModelPreset) {\n super(engine, preset);\n }\n\n /**\n * Create and load a `Chat` task for the given model.\n *\n * @param modelId - Friendly model id from the registry (e.g. `\"phi-3.5-mini-int4\"`).\n * @param options - Optional creation options (progress callback, engine override).\n */\n static async create(modelId: string, options: LMTaskCreateOptions = {}): Promise<Chat> {\n const { engine, preset } = await LMTask.createEngine(modelId, options);\n return new Chat(engine, preset);\n }\n\n /** Set or replace the system prompt prepended to every conversation. */\n setSystemPrompt(prompt: string): void {\n this.systemPrompt = prompt;\n }\n\n /** Clear the system prompt. */\n clearSystemPrompt(): void {\n this.systemPrompt = null;\n }\n\n /** Reset the conversation history. The system prompt is preserved. */\n resetHistory(): void {\n this.history.length = 0;\n }\n\n /** A read-only snapshot of the conversation history. */\n getHistory(): readonly Message[] {\n return this.history.slice();\n }\n\n /**\n * Send a user message and await the full assistant reply.\n *\n * The user message and the assistant reply are appended to the history.\n *\n * @param message - The user-facing message text.\n * @param options - Generation options.\n * @returns A {@link ChatReply} with the assistant's reply.\n */\n async send(message: string, options: GenerationOptions = {}): Promise<ChatReply> {\n const messages = this.buildMessages(message);\n const text = await this.engine.generate(messages, options);\n const userMsg: Message = { role: \"user\", content: message };\n const assistantMsg: Message = { role: \"assistant\", content: text };\n this.history.push(userMsg, assistantMsg);\n return new ChatReply(text, assistantMsg, 0, \"stop\");\n }\n\n /**\n * Stream the assistant reply token-by-token as an async iterable.\n *\n * The full reply is appended to the history when the stream completes\n * normally. If the stream is aborted, neither message is appended.\n *\n * @param message - The user-facing message text.\n * @param options - Generation options including an optional `signal`.\n */\n async *stream(message: string, options: GenerationOptions = {}): AsyncIterable<TokenChunk> {\n const messages = this.buildMessages(message);\n const userMsg: Message = { role: \"user\", content: message };\n let acc: string = \"\";\n for await (const chunk of this.engine.stream(messages, options)) {\n acc += chunk.text;\n yield chunk;\n }\n const assistantMsg: Message = { role: \"assistant\", content: acc };\n this.history.push(userMsg, assistantMsg);\n }\n\n private buildMessages(userMessage: string): Message[] {\n const messages: Message[] = [];\n if (this.systemPrompt) {\n messages.push({ role: \"system\", content: this.systemPrompt });\n }\n messages.push(...this.history);\n messages.push({ role: \"user\", content: userMessage });\n return messages;\n }\n}\n","import { LMTask, type LMTaskCreateOptions } from \"./lm-task\";\nimport type { Engine } from \"../core/engine\";\nimport { CompletionResult } from \"../results\";\nimport type { GenerationOptions, ModelPreset, TokenChunk } from \"../types\";\n\n/**\n * Raw text-completion task.\n *\n * Unlike {@link Chat}, `Completion` does not maintain a conversation history\n * and does not apply a chat template. The prompt is fed to the model verbatim\n * and the model continues it. Useful for \"Once upon a time…\" style generation,\n * code completion, or any scenario where chat formatting would interfere.\n *\n * Use {@link Completion.create} to construct an instance — the constructor is\n * private.\n *\n * @example\n * ```ts\n * const comp = await Completion.create(\"qwen2.5-1.5b-int4\");\n * const result = await comp.predict(\"Once upon a time\", { maxTokens: 50 });\n * console.log(result.text);\n * ```\n *\n * @example Streaming\n * ```ts\n * const controller = new AbortController();\n * for await (const token of comp.stream(\"def fibonacci(n):\", { signal: controller.signal })) {\n * process.stdout.write(token.text);\n * }\n * ```\n */\nexport class Completion extends LMTask {\n private constructor(engine: Engine, preset: ModelPreset) {\n super(engine, preset);\n }\n\n /**\n * Create and load a `Completion` task for the given model.\n *\n * @param modelId - Friendly model id from the registry (e.g. `\"qwen2.5-1.5b-int4\"`).\n * @param options - Optional creation options (progress callback, engine override).\n */\n static async create(modelId: string, options: LMTaskCreateOptions = {}): Promise<Completion> {\n const { engine, preset } = await LMTask.createEngine(modelId, options);\n return new Completion(engine, preset);\n }\n\n /**\n * Generate a continuation for the given prompt.\n *\n * @param prompt - Raw text fed to the model.\n * @param options - Generation options.\n * @returns A {@link CompletionResult} with the generated continuation.\n */\n async predict(prompt: string, options: GenerationOptions = {}): Promise<CompletionResult> {\n const text = await this.engine.complete(prompt, options);\n return new CompletionResult(text, prompt, 0, \"stop\");\n }\n\n /**\n * Stream a continuation for the given prompt as an async iterable of token\n * chunks.\n *\n * @param prompt - Raw text fed to the model.\n * @param options - Generation options including an optional `signal`.\n */\n async *stream(prompt: string, options: GenerationOptions = {}): AsyncIterable<TokenChunk> {\n for await (const chunk of this.engine.streamCompletion(prompt, options)) {\n yield chunk;\n }\n }\n}\n","import { MODEL_PRESETS, resolveModelPreset } from \"../presets/models\";\nimport { UnknownModelError } from \"../core/exceptions\";\n\n/** Snapshot of a single cached model's metadata. */\nexport interface CachedModelEntry {\n /** Friendly id from the registry (e.g. `\"llama-3.2-1b-int4\"`). */\n id: string;\n /** Backend-specific id (e.g. WebLLM `webllmId`). */\n backendId: string;\n /** Human-readable family name. */\n family: string;\n /** Approx parameter count, e.g. `\"1B\"`. */\n parameters: string;\n}\n\n/** Aggregate storage usage reported by the browser. */\nexport interface CacheUsage {\n /** Bytes used by the entire origin's storage (not just our cache). */\n usage: number;\n /** Bytes the browser is willing to give the origin. */\n quota: number;\n}\n\n/**\n * Hooks the {@link ModelCache} uses to talk to the underlying runtime and\n * the browser. Tests inject mocks; production code leaves them undefined,\n * letting `ModelCache` resolve the real `@mlc-ai/web-llm` helpers and\n * `navigator.storage.estimate()` lazily.\n */\nexport interface ModelCacheOptions {\n /** Override `hasModelInCache` from the runtime. */\n hasModel?: (backendId: string) => Promise<boolean>;\n /** Override `deleteModelInCache` from the runtime. */\n deleteModel?: (backendId: string) => Promise<void>;\n /** Override `navigator.storage.estimate()`. */\n estimate?: () => Promise<CacheUsage>;\n}\n\ntype WebLLMCacheModule = {\n hasModelInCache: (id: string) => Promise<boolean>;\n deleteModelInCache: (id: string) => Promise<void>;\n};\n\nlet webllmCachePromise: Promise<WebLLMCacheModule> | null = null;\n\nasync function loadWebLLMCacheHelpers(): Promise<WebLLMCacheModule> {\n if (!webllmCachePromise) {\n webllmCachePromise = import(\"@mlc-ai/web-llm\").then((m) => ({\n hasModelInCache: m.hasModelInCache,\n deleteModelInCache: m.deleteModelInCache,\n }));\n }\n return webllmCachePromise;\n}\n\nasync function defaultEstimate(): Promise<CacheUsage> {\n if (typeof navigator === \"undefined\" || !navigator.storage?.estimate) {\n return { usage: 0, quota: 0 };\n }\n const estimate = await navigator.storage.estimate();\n return {\n usage: estimate.usage ?? 0,\n quota: estimate.quota ?? 0,\n };\n}\n\n/**\n * Inspect and manage cached model weights.\n *\n * `localm-web` does not download or cache weights itself — that work is owned\n * by `@mlc-ai/web-llm`, which writes to the browser Cache API. `ModelCache`\n * is a thin wrapper that lets a consuming app surface cache state in its UI:\n * \"this model is downloaded\", \"you have 1.4 GB cached, free up space?\",\n * \"clear all models on logout\".\n *\n * @example\n * ```ts\n * const cache = new ModelCache();\n * if (await cache.has(\"llama-3.2-1b-int4\")) {\n * console.log(\"ready offline\");\n * }\n * const cached = await cache.list();\n * await cache.delete(\"phi-3.5-mini-int4\");\n * const usage = await cache.estimateUsage();\n * console.log(`${usage.usage} / ${usage.quota} bytes`);\n * ```\n */\nexport class ModelCache {\n private readonly hasModelHook: ((id: string) => Promise<boolean>) | undefined;\n private readonly deleteModelHook: ((id: string) => Promise<void>) | undefined;\n private readonly estimateHook: () => Promise<CacheUsage>;\n\n constructor(options: ModelCacheOptions = {}) {\n this.hasModelHook = options.hasModel;\n this.deleteModelHook = options.deleteModel;\n this.estimateHook = options.estimate ?? defaultEstimate;\n }\n\n /**\n * Whether the model's weights are present in the browser cache.\n *\n * @param modelId - Friendly id from the registry.\n * @throws UnknownModelError if `modelId` is not in the registry.\n */\n async has(modelId: string): Promise<boolean> {\n const backendId: string = resolveModelPreset(modelId).webllmId;\n const fn = this.hasModelHook ?? (await loadWebLLMCacheHelpers()).hasModelInCache;\n return fn(backendId);\n }\n\n /**\n * Delete a single model's weights from the browser cache. No-op when the\n * model is not cached.\n *\n * @param modelId - Friendly id from the registry.\n * @throws UnknownModelError if `modelId` is not in the registry.\n */\n async delete(modelId: string): Promise<void> {\n const backendId: string = resolveModelPreset(modelId).webllmId;\n const fn = this.deleteModelHook ?? (await loadWebLLMCacheHelpers()).deleteModelInCache;\n await fn(backendId);\n }\n\n /**\n * List the registry models that are currently cached.\n *\n * Iterates `MODEL_PRESETS` and probes each one. Only returns models known\n * to the SDK — models cached by external WebLLM calls outside our registry\n * are not included.\n *\n * @returns Empty list when nothing is cached.\n */\n async list(): Promise<CachedModelEntry[]> {\n const fn = this.hasModelHook ?? (await loadWebLLMCacheHelpers()).hasModelInCache;\n const probes = await Promise.all(\n Object.values(MODEL_PRESETS).map(async (preset) => {\n const cached: boolean = await fn(preset.webllmId);\n if (!cached) return null;\n const entry: CachedModelEntry = {\n id: preset.id,\n backendId: preset.webllmId,\n family: preset.family,\n parameters: preset.parameters,\n };\n return entry;\n })\n );\n return probes.filter((p): p is CachedModelEntry => p !== null);\n }\n\n /**\n * Delete every registry model from the cache. Useful for logout flows or\n * \"reset\" buttons. Models cached outside the registry are not touched.\n */\n async clear(): Promise<void> {\n const fn = this.deleteModelHook ?? (await loadWebLLMCacheHelpers()).deleteModelInCache;\n await Promise.all(Object.values(MODEL_PRESETS).map((p) => fn(p.webllmId)));\n }\n\n /**\n * Aggregate storage stats from the browser. Returned numbers cover the\n * entire origin (Cache API + IndexedDB + Service Workers + OPFS), not\n * just our model cache — use it for \"you have X of Y available\" hints.\n */\n async estimateUsage(): Promise<CacheUsage> {\n return this.estimateHook();\n }\n\n /**\n * Throw a descriptive error if the given id is not in the registry.\n * Exposed for code paths that want to validate before calling other\n * methods (those already throw on their own).\n *\n * @throws UnknownModelError\n */\n static assertKnown(modelId: string): void {\n if (!(modelId in MODEL_PRESETS)) {\n const available = Object.keys(MODEL_PRESETS).join(\", \");\n throw new UnknownModelError(`Unknown model \"${modelId}\". Available models: ${available}.`);\n }\n }\n}\n","import type { TokenChunk } from \"../types\";\n\n/**\n * Drain an async iterable of token chunks into a single string.\n *\n * Useful in tests, for non-streaming consumers, and as a one-line way to\n * reconstruct the final text from a `Chat.stream(...)` call.\n *\n * @param stream - The token-chunk async iterable to consume.\n * @returns The concatenation of every chunk's `text` field.\n */\nexport async function collectStream(stream: AsyncIterable<TokenChunk>): Promise<string> {\n let acc: string = \"\";\n for await (const chunk of stream) {\n acc += chunk.text;\n }\n return acc;\n}\n\n/**\n * Wrap an async iterable so that each `TokenChunk` is also passed to a\n * caller-supplied side-effect callback before being yielded downstream.\n *\n * This is intentionally a passthrough — it does not buffer.\n *\n * @param stream - The upstream token-chunk async iterable.\n * @param onChunk - Side-effect invoked for every chunk.\n * @returns A new async iterable yielding the same chunks.\n */\nexport async function* tap(\n stream: AsyncIterable<TokenChunk>,\n onChunk: (chunk: TokenChunk) => void\n): AsyncIterable<TokenChunk> {\n for await (const chunk of stream) {\n onChunk(chunk);\n yield chunk;\n }\n}\n","/**\n * localm-web — browser-only TypeScript SDK for running LLMs and SLMs locally.\n *\n * Public API surface for v0.1.\n *\n * @packageDocumentation\n */\n\nexport { Chat } from \"./tasks/chat\";\nexport { Completion } from \"./tasks/completion\";\nexport { LMTask } from \"./tasks/lm-task\";\nexport type { LMTaskCreateOptions } from \"./tasks/lm-task\";\n\nexport { ChatReply, CompletionResult } from \"./results\";\n\nexport { MODEL_PRESETS, resolveModelPreset, listSupportedModels } from \"./presets/models\";\n\nexport {\n LocalmWebError,\n WebGPUUnavailableError,\n ModelLoadError,\n ModelNotLoadedError,\n UnknownModelError,\n GenerationAbortedError,\n QuotaExceededError,\n BackendNotAvailableError,\n} from \"./core/exceptions\";\n\nexport type { Engine } from \"./core/engine\";\nexport { WorkerEngine } from \"./core/worker-engine\";\nexport { createInferenceWorker } from \"./worker/create-worker\";\nexport type { WorkerLike } from \"./worker/protocol\";\n\nexport { ModelCache } from \"./cache\";\nexport type { CachedModelEntry, CacheUsage, ModelCacheOptions } from \"./cache\";\n\nexport { collectStream, tap } from \"./streaming/token-stream\";\n\nexport type {\n Role,\n FinishReason,\n Message,\n GenerationOptions,\n ModelLoadProgress,\n ModelLoadPhase,\n ProgressCallback,\n TokenChunk,\n ModelPreset,\n} from \"./types\";\n\n/** Current package version. Updated at release time. */\nexport const VERSION: string = \"0.2.0\";\n"],"names":[],"mappings":"AAEA,MAAM,mBAA2B;AACjC,MAAM,kBAA0B;AAazB,SAAS,kBAAkB,MAA8B;AAC9D,MAAI,iBAAiB,KAAK,IAAI,EAAG,QAAO;AACxC,MAAI,gBAAgB,KAAK,IAAI,EAAG,QAAO;AACvC,SAAO;AACT;ACXO,MAAM,uBAAuB,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxC,YACE,SACgB,OAChB;AACA,UAAM,OAAO;AAFG,SAAA,QAAA;AAGhB,SAAK,OAAO,WAAW;AAAA,EACzB;AACF;AAGO,MAAM,+BAA+B,eAAe;AAAC;AAGrD,MAAM,uBAAuB,eAAe;AAAC;AAG7C,MAAM,4BAA4B,eAAe;AAAC;AAGlD,MAAM,0BAA0B,eAAe;AAAC;AAGhD,MAAM,+BAA+B,eAAe;AAAC;AAGrD,MAAM,2BAA2B,eAAe;AAAC;AAGjD,MAAM,iCAAiC,eAAe;AAAC;AC5B9D,IAAI,sBAAoD;AAExD,eAAe,aAAoC;AACjD,MAAI,CAAC,qBAAqB;AACxB,0BAAsB,OAAO,iBAAiB;AAAA,EAChD;AACA,SAAO;AACT;AAEA,SAAS,oBAA6B;AACpC,SAAO,OAAO,cAAc,eAAe,SAAS;AACtD;AAQA,SAAS,oBAAoB,SAA4C;AACvE,QAAM,SAAyB,CAAA;AAC/B,MAAI,QAAQ,cAAc,OAAW,QAAO,aAAa,QAAQ;AACjE,MAAI,QAAQ,gBAAgB,OAAW,QAAO,cAAc,QAAQ;AACpE,MAAI,QAAQ,SAAS,OAAW,QAAO,QAAQ,QAAQ;AACvD,SAAO;AACT;AAEA,SAAS,eAAe,UAAmD;AACzE,SAAO,SAAS,IAAI,CAAC,MAAkC;AACrD,YAAQ,EAAE,MAAA;AAAA,MACR,KAAK;AACH,eAAO,EAAE,MAAM,UAAU,SAAS,EAAE,QAAA;AAAA,MACtC,KAAK;AACH,eAAO,EAAE,MAAM,QAAQ,SAAS,EAAE,QAAA;AAAA,MACpC,KAAK;AACH,eAAO,EAAE,MAAM,aAAa,SAAS,EAAE,QAAA;AAAA,MACzC,KAAK;AACH,eAAO,EAAE,MAAM,QAAQ,SAAS,EAAE,SAAS,cAAc,EAAE,QAAQ,GAAA;AAAA,IAAG;AAAA,EAE5E,CAAC;AACH;AAQO,MAAM,aAA+B;AAAA,EAClC,SAA2B;AAAA,EAEnC,WAAoB;AAClB,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA,EAEA,MAAM,KAAK,SAAiB,YAA8C;AACxE,QAAI,CAAC,qBAAqB;AACxB,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AACA,UAAM,SAAS,MAAM,WAAA;AACrB,QAAI;AACF,WAAK,SAAS,MAAM,OAAO,gBAAgB,SAAS;AAAA,QAClD,sBAAsB,CAAC,WAAiB;AACtC,uBAAa;AAAA,YACX,UAAU,OAAO;AAAA,YACjB,MAAM,OAAO;AAAA,YACb,QAAQ;AAAA,YACR,OAAO;AAAA,YACP,OAAO,kBAAkB,OAAO,IAAI;AAAA,UAAA,CACrC;AAAA,QACH;AAAA,MAAA,CACD;AACD,mBAAa;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,OAAO;AAAA,MAAA,CACR;AAAA,IACH,SAAS,KAAK;AACZ,YAAM,IAAI,eAAe,yBAAyB,OAAO,MAAM,GAAG;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,UAAqB,UAA6B,IAAqB;AACpF,UAAM,SAAS,KAAK,cAAA;AACpB,QAAI,QAAQ,QAAQ,SAAS;AAC3B,YAAM,IAAI,uBAAuB,kCAAkC;AAAA,IACrE;AACA,UAAM,aAAa,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,MACtD,GAAG,oBAAoB,OAAO;AAAA,MAC9B,UAAU,eAAe,QAAQ;AAAA,MACjC,QAAQ;AAAA,IAAA,CACT;AACD,WAAO,WAAW,QAAQ,CAAC,GAAG,SAAS,WAAW;AAAA,EACpD;AAAA,EAEA,OAAO,OAAO,UAAqB,UAA6B,IAA+B;AAC7F,UAAM,SAAS,KAAK,cAAA;AACpB,QAAI,QAAQ,QAAQ,SAAS;AAC3B,YAAM,IAAI,uBAAuB,kCAAkC;AAAA,IACrE;AACA,UAAM,aAAa,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,MACtD,GAAG,oBAAoB,OAAO;AAAA,MAC9B,UAAU,eAAe,QAAQ;AAAA,MACjC,QAAQ;AAAA,IAAA,CACT;AACD,QAAI,QAAgB;AACpB,QAAI,WAAoB;AACxB,QAAI;AACF,uBAAiB,SAAS,YAAY;AACpC,YAAI,QAAQ,QAAQ,SAAS;AAC3B,gBAAM,IAAI,uBAAuB,+BAA+B;AAAA,QAClE;AACA,cAAM,SAAS,MAAM,QAAQ,CAAC;AAC9B,cAAM,QAAQ,QAAQ,OAAO,WAAW;AACxC,YAAI,OAAO;AACT,gBAAM,EAAE,MAAM,OAAO,OAAO,MAAM,MAAA;AAClC,mBAAS;AAAA,QACX;AACA,YAAI,QAAQ,eAAe;AACzB,qBAAW;AACX,gBAAM,EAAE,MAAM,IAAI,OAAO,MAAM,KAAA;AAC/B,mBAAS;AAAA,QACX;AAAA,MACF;AACA,UAAI,CAAC,UAAU;AACb,cAAM,EAAE,MAAM,IAAI,OAAO,MAAM,KAAA;AAAA,MACjC;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,uBAAwB,OAAM;AACjD,YAAM,IAAI,eAAe,gCAAgC,GAAG;AAAA,IAC9D;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,QAAgB,UAA6B,IAAqB;AAC/E,UAAM,SAAS,KAAK,cAAA;AACpB,QAAI,QAAQ,QAAQ,SAAS;AAC3B,YAAM,IAAI,uBAAuB,kCAAkC;AAAA,IACrE;AACA,UAAM,aAAa,MAAM,OAAO,YAAY,OAAO;AAAA,MACjD,GAAG,oBAAoB,OAAO;AAAA,MAC9B;AAAA,MACA,QAAQ;AAAA,IAAA,CACT;AACD,WAAO,WAAW,QAAQ,CAAC,GAAG,QAAQ;AAAA,EACxC;AAAA,EAEA,OAAO,iBACL,QACA,UAA6B,IACF;AAC3B,UAAM,SAAS,KAAK,cAAA;AACpB,QAAI,QAAQ,QAAQ,SAAS;AAC3B,YAAM,IAAI,uBAAuB,kCAAkC;AAAA,IACrE;AACA,UAAM,aAAa,MAAM,OAAO,YAAY,OAAO;AAAA,MACjD,GAAG,oBAAoB,OAAO;AAAA,MAC9B;AAAA,MACA,QAAQ;AAAA,IAAA,CACT;AACD,QAAI,QAAgB;AACpB,QAAI,WAAoB;AACxB,QAAI;AACF,uBAAiB,SAAS,YAAY;AACpC,YAAI,QAAQ,QAAQ,SAAS;AAC3B,gBAAM,IAAI,uBAAuB,+BAA+B;AAAA,QAClE;AACA,cAAM,SAAS,MAAM,QAAQ,CAAC;AAC9B,cAAM,QAAQ,QAAQ,QAAQ;AAC9B,YAAI,OAAO;AACT,gBAAM,EAAE,MAAM,OAAO,OAAO,MAAM,MAAA;AAClC,mBAAS;AAAA,QACX;AACA,YAAI,QAAQ,eAAe;AACzB,qBAAW;AACX,gBAAM,EAAE,MAAM,IAAI,OAAO,MAAM,KAAA;AAC/B,mBAAS;AAAA,QACX;AAAA,MACF;AACA,UAAI,CAAC,UAAU;AACb,cAAM,EAAE,MAAM,IAAI,OAAO,MAAM,KAAA;AAAA,MACjC;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,uBAAwB,OAAM;AACjD,YAAM,IAAI,eAAe,gCAAgC,GAAG;AAAA,IAC9D;AAAA,EACF;AAAA,EAEA,MAAM,SAAwB;AAC5B,QAAI,KAAK,QAAQ;AACf,YAAM,KAAK,OAAO,OAAA;AAClB,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA,EAEQ,gBAA2B;AACjC,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,oBAAoB,mDAAmD;AAAA,IACnF;AACA,WAAO,KAAK;AAAA,EACd;AACF;AC/MO,SAAS,sBACd,UAA6B,IACE;AAC/B,QAAM,EAAE,QAAQ,SAAS,GAAG,SAAS;AAErC,SAAO;AACT;ACeO,MAAM,aAA+B;AAAA,EAa1C,YAA6B,QAAoB;AAApB,SAAA,SAAA;AAC3B,SAAK,WAAW,CAAC,UAAgB,KAAK,cAAc,MAAM,IAAI;AAC9D,SAAK,OAAO,iBAAiB,WAAW,KAAK,QAAQ;AAAA,EACvD;AAAA,EAfQ,SAAiB;AAAA,EACjB,SAAkB;AAAA,EAClB,cAA0E;AAAA,EAC1E,gBAAwB;AAAA,EACxB,sBAAoD;AAAA,EACpD,gBAA4E;AAAA,EAC5E,kBAA0B;AAAA,EAC1B,uCAAqD,IAAA;AAAA,EACrD,qCAAiD,IAAA;AAAA,EAExC;AAAA,EAOjB,WAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,KAAK,SAAiB,YAA8C;AACxE,QAAI,KAAK,aAAa;AACpB,YAAM,IAAI,eAAe,sCAAsC;AAAA,IACjE;AACA,UAAM,KAAa,KAAK,WAAA;AACxB,SAAK,gBAAgB;AACrB,SAAK,sBAAsB;AAC3B,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,WAAK,cAAc,EAAE,SAAS,OAAA;AAC9B,WAAK,KAAK,EAAE,IAAI,QAAQ,IAAI,SAAS;AAAA,IACvC,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,SAAS,UAAqB,UAA6B,IAAqB;AACpF,UAAM,KAAa,KAAK,WAAA;AACxB,WAAO,IAAI,QAAgB,CAAC,SAAS,WAAW;AAC9C,WAAK,iBAAiB,IAAI,IAAI,EAAE,SAAS,QAAQ;AACjD,WAAK,KAAK;AAAA,QACR,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA,SAAS,sBAAsB,OAAO;AAAA,MAAA,CACvC;AACD,cAAQ,QAAQ,iBAAiB,SAAS,MAAM,KAAK,KAAK,EAAE,IAAI,SAAS,GAAA,CAAI,CAAC;AAAA,IAChF,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,OAAO,UAAqB,UAA6B,IAA+B;AAC7F,UAAM,KAAa,KAAK,WAAA;AACxB,UAAM,QAAsB,CAAA;AAC5B,QAAI,OAAgB;AACpB,QAAI,QAAsB;AAC1B,QAAI,SAA8B;AAElC,UAAM,SAAS,MAAY;AACzB,UAAI,QAAQ;AACV,cAAM,KAAK;AACX,iBAAS;AACT,WAAA;AAAA,MACF;AAAA,IACF;AAEA,SAAK,eAAe,IAAI,IAAI;AAAA,MAC1B,MAAM,CAAC,UAAgB;AACrB,cAAM,KAAK,KAAK;AAChB,eAAA;AAAA,MACF;AAAA,MACA,KAAK,MAAY;AACf,eAAO;AACP,eAAA;AAAA,MACF;AAAA,MACA,MAAM,CAAC,QAAc;AACnB,gBAAQ;AACR,eAAO;AACP,eAAA;AAAA,MACF;AAAA,IAAA,CACD;AAED,SAAK,KAAK;AAAA,MACR,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA,SAAS,sBAAsB,OAAO;AAAA,IAAA,CACvC;AACD,YAAQ,QAAQ,iBAAiB,SAAS,MAAM,KAAK,KAAK,EAAE,IAAI,SAAS,GAAA,CAAI,CAAC;AAE9E,QAAI;AACF,aAAO,MAAM;AACX,YAAI,MAAM,SAAS,GAAG;AACpB,gBAAM,QAAQ,MAAM,MAAA;AACpB,cAAI,MAAO,OAAM;AACjB;AAAA,QACF;AACA,YAAI,MAAO,OAAM;AACjB,YAAI,KAAM;AACV,cAAM,IAAI,QAAc,CAAC,MAAM;AAC7B,mBAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF,UAAA;AACE,WAAK,eAAe,OAAO,EAAE;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,QAAgB,UAA6B,IAAqB;AAC/E,UAAM,KAAa,KAAK,WAAA;AACxB,WAAO,IAAI,QAAgB,CAAC,SAAS,WAAW;AAC9C,WAAK,iBAAiB,IAAI,IAAI,EAAE,SAAS,QAAQ;AACjD,WAAK,KAAK;AAAA,QACR,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA,SAAS,sBAAsB,OAAO;AAAA,MAAA,CACvC;AACD,cAAQ,QAAQ,iBAAiB,SAAS,MAAM,KAAK,KAAK,EAAE,IAAI,SAAS,GAAA,CAAI,CAAC;AAAA,IAChF,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,iBACL,QACA,UAA6B,IACF;AAC3B,UAAM,KAAa,KAAK,WAAA;AACxB,UAAM,QAAsB,CAAA;AAC5B,QAAI,OAAgB;AACpB,QAAI,QAAsB;AAC1B,QAAI,SAA8B;AAElC,UAAM,SAAS,MAAY;AACzB,UAAI,QAAQ;AACV,cAAM,KAAK;AACX,iBAAS;AACT,WAAA;AAAA,MACF;AAAA,IACF;AAEA,SAAK,eAAe,IAAI,IAAI;AAAA,MAC1B,MAAM,CAAC,UAAgB;AACrB,cAAM,KAAK,KAAK;AAChB,eAAA;AAAA,MACF;AAAA,MACA,KAAK,MAAY;AACf,eAAO;AACP,eAAA;AAAA,MACF;AAAA,MACA,MAAM,CAAC,QAAc;AACnB,gBAAQ;AACR,eAAO;AACP,eAAA;AAAA,MACF;AAAA,IAAA,CACD;AAED,SAAK,KAAK;AAAA,MACR,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA,SAAS,sBAAsB,OAAO;AAAA,IAAA,CACvC;AACD,YAAQ,QAAQ,iBAAiB,SAAS,MAAM,KAAK,KAAK,EAAE,IAAI,SAAS,GAAA,CAAI,CAAC;AAE9E,QAAI;AACF,aAAO,MAAM;AACX,YAAI,MAAM,SAAS,GAAG;AACpB,gBAAM,QAAQ,MAAM,MAAA;AACpB,cAAI,MAAO,OAAM;AACjB;AAAA,QACF;AACA,YAAI,MAAO,OAAM;AACjB,YAAI,KAAM;AACV,cAAM,IAAI,QAAc,CAAC,MAAM;AAC7B,mBAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF,UAAA;AACE,WAAK,eAAe,OAAO,EAAE;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAM,SAAwB;AAC5B,QAAI,CAAC,KAAK,OAAQ;AAClB,QAAI,KAAK,eAAe;AACtB,YAAM,IAAI,eAAe,wCAAwC;AAAA,IACnE;AACA,UAAM,KAAa,KAAK,WAAA;AACxB,SAAK,kBAAkB;AACvB,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,WAAK,gBAAgB,EAAE,SAAS,OAAA;AAChC,WAAK,KAAK,EAAE,IAAI,UAAU,IAAI;AAAA,IAChC,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,YAAkB;AAChB,SAAK,OAAO,oBAAoB,WAAW,KAAK,QAAQ;AACxD,SAAK,OAAO,UAAA;AACZ,SAAK,SAAS;AAAA,EAChB;AAAA,EAEQ,aAAqB;AAC3B,UAAM,KAAK,KAAK;AAChB,SAAK,UAAU;AACf,WAAO;AAAA,EACT;AAAA,EAEQ,KAAK,KAA0B;AACrC,SAAK,OAAO,YAAY,GAAG;AAAA,EAC7B;AAAA,EAEQ,cAAc,KAA2B;AAC/C,YAAQ,IAAI,IAAA;AAAA,MACV,KAAK;AACH,YAAI,KAAK,eAAe,IAAI,OAAO,KAAK,eAAe;AACrD,eAAK,SAAS;AACd,eAAK,YAAY,QAAA;AACjB,eAAK,cAAc;AACnB,eAAK,sBAAsB;AAAA,QAC7B;AACA;AAAA,MACF,KAAK;AACH,YAAI,IAAI,OAAO,KAAK,eAAe;AACjC,eAAK,sBAAsB,IAAI,OAAO;AAAA,QACxC;AACA;AAAA,MACF,KAAK,aAAa;AAChB,cAAM,UAAU,KAAK,iBAAiB,IAAI,IAAI,EAAE;AAChD,YAAI,SAAS;AACX,kBAAQ,QAAQ,IAAI,IAAI;AACxB,eAAK,iBAAiB,OAAO,IAAI,EAAE;AAAA,QACrC;AACA;AAAA,MACF;AAAA,MACA,KAAK,SAAS;AACZ,cAAM,SAAS,KAAK,eAAe,IAAI,IAAI,EAAE;AAC7C,gBAAQ,KAAK,IAAI,KAAK;AACtB;AAAA,MACF;AAAA,MACA,KAAK,cAAc;AACjB,cAAM,SAAS,KAAK,eAAe,IAAI,IAAI,EAAE;AAC7C,gBAAQ,IAAA;AACR;AAAA,MACF;AAAA,MACA,KAAK;AACH,YAAI,KAAK,iBAAiB,IAAI,OAAO,KAAK,iBAAiB;AACzD,eAAK,SAAS;AACd,eAAK,cAAc,QAAA;AACnB,eAAK,gBAAgB;AAAA,QACvB;AACA;AAAA,MACF,KAAK;AACH;AAAA,MACF,KAAK,SAAS;AACZ,cAAM,MAAM,SAAS,IAAI,MAAM,IAAI,OAAO;AAC1C,YAAI,KAAK,eAAe,IAAI,OAAO,KAAK,eAAe;AACrD,eAAK,YAAY,OAAO,GAAG;AAC3B,eAAK,cAAc;AACnB,eAAK,sBAAsB;AAC3B;AAAA,QACF;AACA,YAAI,KAAK,iBAAiB,IAAI,OAAO,KAAK,iBAAiB;AACzD,eAAK,cAAc,OAAO,GAAG;AAC7B,eAAK,gBAAgB;AACrB;AAAA,QACF;AACA,cAAM,WAAW,KAAK,iBAAiB,IAAI,IAAI,EAAE;AACjD,YAAI,UAAU;AACZ,mBAAS,OAAO,GAAG;AACnB,eAAK,iBAAiB,OAAO,IAAI,EAAE;AACnC;AAAA,QACF;AACA,cAAM,SAAS,KAAK,eAAe,IAAI,IAAI,EAAE;AAC7C,YAAI,QAAQ;AACV,iBAAO,KAAK,GAAG;AACf;AAAA,QACF;AACA;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AACF;AAEA,SAAS,SAAS,MAAc,SAAwB;AACtD,UAAQ,MAAA;AAAA,IACN,KAAK;AACH,aAAO,IAAI,eAAe,OAAO;AAAA,IACnC,KAAK;AACH,aAAO,IAAI,oBAAoB,OAAO;AAAA,IACxC,KAAK;AACH,aAAO,IAAI,uBAAuB,OAAO;AAAA,IAC3C,SAAS;AACP,YAAM,MAAM,IAAI,MAAM,OAAO;AAC7B,UAAI,OAAO;AACX,aAAO;AAAA,IACT;AAAA,EAAA;AAEJ;AC3TO,MAAM,gBAAuD,OAAO,OAAO;AAAA,EAChF,qBAAqB;AAAA,IACnB,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,UAAU;AAAA,IACV,eAAe;AAAA,IACf,aAAa;AAAA,EAAA;AAAA,EAEf,qBAAqB;AAAA,IACnB,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,UAAU;AAAA,IACV,eAAe;AAAA,IACf,aAAa;AAAA,EAAA;AAAA,EAEf,qBAAqB;AAAA,IACnB,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,UAAU;AAAA,IACV,eAAe;AAAA,IACf,aAAa;AAAA,EAAA;AAEjB,CAAC;AASM,SAAS,mBAAmB,SAA8B;AAC/D,QAAM,SAAS,cAAc,OAAO;AACpC,MAAI,CAAC,QAAQ;AACX,UAAM,YAAY,OAAO,KAAK,aAAa,EAAE,KAAK,IAAI;AACtD,UAAM,IAAI,kBAAkB,kBAAkB,OAAO,wBAAwB,SAAS,GAAG;AAAA,EAC3F;AACA,SAAO;AACT;AAGO,SAAS,sBAAgC;AAC9C,SAAO,OAAO,KAAK,aAAa;AAClC;AChDO,SAAS,wBAAoC;AAClD,SAAO,IAAI,OAAO,IAAA;AAAA;AAAA,IAAA;AAAA,IAAA,YAAA;AAAA,EAAA,GAAmD;AAAA,IACnE,MAAM;AAAA,EAAA,CACP;AACH;AC0BO,MAAe,OAAO;AAAA,EACjB,YAEW,QAEH,QAChB;AAHmB,SAAA,SAAA;AAEH,SAAA,SAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUH,aAAuB,aACrB,SACA,UAA+B,IACN;AACzB,UAAM,SAAS,mBAAmB,OAAO;AACzC,UAAM,SAAS,QAAQ,UAAU,OAAO,cAAc,OAAO;AAC7D,QAAI,CAAC,OAAO,YAAY;AACtB,YAAM,OAAO,KAAK,OAAO,UAAU,QAAQ,UAAU;AAAA,IACvD;AACA,WAAO,EAAE,QAAQ,OAAA;AAAA,EACnB;AAAA,EAEA,OAAe,cAAc,SAAsC;AACjE,QAAI,QAAQ,UAAU;AACpB,aAAO,IAAI,aAAa,uBAAuB;AAAA,IACjD;AACA,WAAO,IAAI,aAAA;AAAA,EACb;AAAA;AAAA,EAGA,MAAM,SAAwB;AAC5B,UAAM,KAAK,OAAO,OAAA;AAAA,EACpB;AAAA;AAAA,EAGA,WAAoB;AAClB,WAAO,KAAK,OAAO,SAAA;AAAA,EACrB;AACF;AChFO,MAAM,UAAU;AAAA,EACrB,YAEkB,MAEA,SAEA,iBAEA,cAChB;AAPgB,SAAA,OAAA;AAEA,SAAA,UAAA;AAEA,SAAA,kBAAA;AAEA,SAAA,eAAA;AAAA,EACf;AACL;AAQO,MAAM,iBAAiB;AAAA,EAC5B,YAEkB,MAEA,QAEA,iBAEA,cAChB;AAPgB,SAAA,OAAA;AAEA,SAAA,SAAA;AAEA,SAAA,kBAAA;AAEA,SAAA,eAAA;AAAA,EACf;AACL;ACXO,MAAM,aAAa,OAAO;AAAA,EACd,UAAqB,CAAA;AAAA,EAC9B,eAA8B;AAAA,EAE9B,YAAY,QAAgB,QAAqB;AACvD,UAAM,QAAQ,MAAM;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,OAAO,SAAiB,UAA+B,IAAmB;AACrF,UAAM,EAAE,QAAQ,OAAA,IAAW,MAAM,OAAO,aAAa,SAAS,OAAO;AACrE,WAAO,IAAI,KAAK,QAAQ,MAAM;AAAA,EAChC;AAAA;AAAA,EAGA,gBAAgB,QAAsB;AACpC,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA,EAGA,oBAA0B;AACxB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA,EAGA,eAAqB;AACnB,SAAK,QAAQ,SAAS;AAAA,EACxB;AAAA;AAAA,EAGA,aAAiC;AAC/B,WAAO,KAAK,QAAQ,MAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,KAAK,SAAiB,UAA6B,IAAwB;AAC/E,UAAM,WAAW,KAAK,cAAc,OAAO;AAC3C,UAAM,OAAO,MAAM,KAAK,OAAO,SAAS,UAAU,OAAO;AACzD,UAAM,UAAmB,EAAE,MAAM,QAAQ,SAAS,QAAA;AAClD,UAAM,eAAwB,EAAE,MAAM,aAAa,SAAS,KAAA;AAC5D,SAAK,QAAQ,KAAK,SAAS,YAAY;AACvC,WAAO,IAAI,UAAU,MAAM,cAAc,GAAG,MAAM;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,OAAO,SAAiB,UAA6B,IAA+B;AACzF,UAAM,WAAW,KAAK,cAAc,OAAO;AAC3C,UAAM,UAAmB,EAAE,MAAM,QAAQ,SAAS,QAAA;AAClD,QAAI,MAAc;AAClB,qBAAiB,SAAS,KAAK,OAAO,OAAO,UAAU,OAAO,GAAG;AAC/D,aAAO,MAAM;AACb,YAAM;AAAA,IACR;AACA,UAAM,eAAwB,EAAE,MAAM,aAAa,SAAS,IAAA;AAC5D,SAAK,QAAQ,KAAK,SAAS,YAAY;AAAA,EACzC;AAAA,EAEQ,cAAc,aAAgC;AACpD,UAAM,WAAsB,CAAA;AAC5B,QAAI,KAAK,cAAc;AACrB,eAAS,KAAK,EAAE,MAAM,UAAU,SAAS,KAAK,cAAc;AAAA,IAC9D;AACA,aAAS,KAAK,GAAG,KAAK,OAAO;AAC7B,aAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,aAAa;AACpD,WAAO;AAAA,EACT;AACF;ACnFO,MAAM,mBAAmB,OAAO;AAAA,EAC7B,YAAY,QAAgB,QAAqB;AACvD,UAAM,QAAQ,MAAM;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,OAAO,SAAiB,UAA+B,IAAyB;AAC3F,UAAM,EAAE,QAAQ,OAAA,IAAW,MAAM,OAAO,aAAa,SAAS,OAAO;AACrE,WAAO,IAAI,WAAW,QAAQ,MAAM;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,QAAgB,UAA6B,IAA+B;AACxF,UAAM,OAAO,MAAM,KAAK,OAAO,SAAS,QAAQ,OAAO;AACvD,WAAO,IAAI,iBAAiB,MAAM,QAAQ,GAAG,MAAM;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,OAAO,QAAgB,UAA6B,IAA+B;AACxF,qBAAiB,SAAS,KAAK,OAAO,iBAAiB,QAAQ,OAAO,GAAG;AACvE,YAAM;AAAA,IACR;AAAA,EACF;AACF;AC5BA,IAAI,qBAAwD;AAE5D,eAAe,yBAAqD;AAClE,MAAI,CAAC,oBAAoB;AACvB,yBAAqB,OAAO,iBAAiB,EAAE,KAAK,CAAC,OAAO;AAAA,MAC1D,iBAAiB,EAAE;AAAA,MACnB,oBAAoB,EAAE;AAAA,IAAA,EACtB;AAAA,EACJ;AACA,SAAO;AACT;AAEA,eAAe,kBAAuC;AACpD,MAAI,OAAO,cAAc,eAAe,CAAC,UAAU,SAAS,UAAU;AACpE,WAAO,EAAE,OAAO,GAAG,OAAO,EAAA;AAAA,EAC5B;AACA,QAAM,WAAW,MAAM,UAAU,QAAQ,SAAA;AACzC,SAAO;AAAA,IACL,OAAO,SAAS,SAAS;AAAA,IACzB,OAAO,SAAS,SAAS;AAAA,EAAA;AAE7B;AAuBO,MAAM,WAAW;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,UAA6B,IAAI;AAC3C,SAAK,eAAe,QAAQ;AAC5B,SAAK,kBAAkB,QAAQ;AAC/B,SAAK,eAAe,QAAQ,YAAY;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAI,SAAmC;AAC3C,UAAM,YAAoB,mBAAmB,OAAO,EAAE;AACtD,UAAM,KAAK,KAAK,iBAAiB,MAAM,0BAA0B;AACjE,WAAO,GAAG,SAAS;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAO,SAAgC;AAC3C,UAAM,YAAoB,mBAAmB,OAAO,EAAE;AACtD,UAAM,KAAK,KAAK,oBAAoB,MAAM,0BAA0B;AACpE,UAAM,GAAG,SAAS;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,OAAoC;AACxC,UAAM,KAAK,KAAK,iBAAiB,MAAM,0BAA0B;AACjE,UAAM,SAAS,MAAM,QAAQ;AAAA,MAC3B,OAAO,OAAO,aAAa,EAAE,IAAI,OAAO,WAAW;AACjD,cAAM,SAAkB,MAAM,GAAG,OAAO,QAAQ;AAChD,YAAI,CAAC,OAAQ,QAAO;AACpB,cAAM,QAA0B;AAAA,UAC9B,IAAI,OAAO;AAAA,UACX,WAAW,OAAO;AAAA,UAClB,QAAQ,OAAO;AAAA,UACf,YAAY,OAAO;AAAA,QAAA;AAErB,eAAO;AAAA,MACT,CAAC;AAAA,IAAA;AAEH,WAAO,OAAO,OAAO,CAAC,MAA6B,MAAM,IAAI;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAuB;AAC3B,UAAM,KAAK,KAAK,oBAAoB,MAAM,0BAA0B;AACpE,UAAM,QAAQ,IAAI,OAAO,OAAO,aAAa,EAAE,IAAI,CAAC,MAAM,GAAG,EAAE,QAAQ,CAAC,CAAC;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,gBAAqC;AACzC,WAAO,KAAK,aAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,YAAY,SAAuB;AACxC,QAAI,EAAE,WAAW,gBAAgB;AAC/B,YAAM,YAAY,OAAO,KAAK,aAAa,EAAE,KAAK,IAAI;AACtD,YAAM,IAAI,kBAAkB,kBAAkB,OAAO,wBAAwB,SAAS,GAAG;AAAA,IAC3F;AAAA,EACF;AACF;AC1KA,eAAsB,cAAc,QAAoD;AACtF,MAAI,MAAc;AAClB,mBAAiB,SAAS,QAAQ;AAChC,WAAO,MAAM;AAAA,EACf;AACA,SAAO;AACT;AAYA,gBAAuB,IACrB,QACA,SAC2B;AAC3B,mBAAiB,SAAS,QAAQ;AAChC,YAAQ,KAAK;AACb,UAAM;AAAA,EACR;AACF;ACcO,MAAM,UAAkB;"}
1
+ {"version":3,"file":"index.js","sources":["../src/core/load-phase.ts","../src/core/exceptions.ts","../src/structured/json-schema.ts","../src/core/webllm-engine.ts","../src/worker/protocol.ts","../src/core/worker-engine.ts","../src/presets/models.ts","../src/worker/create-worker.ts","../src/tasks/lm-task.ts","../src/results.ts","../src/tasks/chat.ts","../src/tasks/completion.ts","../src/tasks/embeddings.ts","../src/tasks/reranker.ts","../src/cache/model-cache.ts","../src/streaming/token-stream.ts","../src/index.ts"],"sourcesContent":["import type { ModelLoadPhase } from \"../types\";\n\nconst DOWNLOAD_PATTERN: RegExp = /\\b(fetch|download|loading from cache|cache hit|param)/i;\nconst COMPILE_PATTERN: RegExp = /\\b(compil|shader|kernel|tensor|init|allocat|warm)/i;\n\n/**\n * Classify a runtime status text into a {@link ModelLoadPhase}.\n *\n * Heuristic: match download-related verbs first (network or cache hits are\n * treated as `downloading`), then compile-related verbs. Anything else falls\n * back to the generic `loading` bucket. The `ready` phase is never returned\n * here — callers emit it explicitly when the load resolves.\n *\n * @param text - The raw status string from the runtime.\n * @returns The classified phase.\n */\nexport function classifyLoadPhase(text: string): ModelLoadPhase {\n if (DOWNLOAD_PATTERN.test(text)) return \"downloading\";\n if (COMPILE_PATTERN.test(text)) return \"compiling\";\n return \"loading\";\n}\n","/**\n * Error hierarchy for localm-web.\n *\n * All errors thrown by the SDK extend `LocalmWebError` so consumers can\n * distinguish SDK errors from unrelated runtime errors with a single\n * `instanceof` check.\n */\n\n/** Base class for every error raised by localm-web. */\nexport class LocalmWebError extends Error {\n /**\n * @param message - Human-readable description of the error.\n * @param cause - Underlying error, if any.\n */\n constructor(\n message: string,\n public readonly cause?: unknown\n ) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** Thrown when WebGPU is required but not available in the host browser. */\nexport class WebGPUUnavailableError extends LocalmWebError {}\n\n/** Thrown when a model fails to load (network, parsing, runtime init). */\nexport class ModelLoadError extends LocalmWebError {}\n\n/** Thrown when an inference call is made before a model has loaded. */\nexport class ModelNotLoadedError extends LocalmWebError {}\n\n/** Thrown when a model id is not present in the curated registry. */\nexport class UnknownModelError extends LocalmWebError {}\n\n/** Thrown when generation is aborted via an `AbortSignal`. */\nexport class GenerationAbortedError extends LocalmWebError {}\n\n/** Thrown when the browser denies storage quota for the model cache. */\nexport class QuotaExceededError extends LocalmWebError {}\n\n/** Thrown when no usable backend is available on the current platform. */\nexport class BackendNotAvailableError extends LocalmWebError {}\n\n/**\n * Thrown when structured output (JSON mode or JSON Schema constrained\n * decoding) fails to parse as valid JSON.\n *\n * Wraps the underlying `SyntaxError` from `JSON.parse` so consumers can\n * distinguish SDK-issued failures from unrelated runtime exceptions.\n */\nexport class StructuredOutputError extends LocalmWebError {}\n","/**\n * JSON Schema helpers for structured output.\n *\n * The SDK delegates the actual constrained decoding to the underlying\n * runtime (xgrammar inside WebLLM today, ORT-Web equivalent later). These\n * helpers normalize user input — turning a JS object schema into the\n * JSON-string shape that WebLLM's `response_format.schema` expects — and\n * parse the runtime's textual output back into typed JSON.\n */\n\nimport { StructuredOutputError } from \"../core/exceptions\";\n\n/**\n * Minimal structural sanity check for a JSON Schema.\n *\n * Does not validate the schema against the JSON Schema meta-schema. The goal\n * is to fail fast on obvious mistakes (passing a string, an array, `null`)\n * before handing the value off to the runtime, where errors surface much\n * later and with much worse messages.\n *\n * @param schema - Candidate JSON Schema object.\n * @throws StructuredOutputError when `schema` is not a plain object or has\n * no recognizable schema shape (`type`, `$ref`, `oneOf`, `anyOf`, `allOf`,\n * `enum`).\n */\nexport function assertJsonSchema(schema: unknown): asserts schema is object {\n if (schema === null || typeof schema !== \"object\" || Array.isArray(schema)) {\n throw new StructuredOutputError(\"jsonSchema must be a plain object describing a JSON Schema.\");\n }\n const keys: string[] = Object.keys(schema);\n const recognized: readonly string[] = [\n \"type\",\n \"$ref\",\n \"oneOf\",\n \"anyOf\",\n \"allOf\",\n \"enum\",\n \"const\",\n \"properties\",\n ];\n if (!keys.some((key) => recognized.includes(key))) {\n throw new StructuredOutputError(\n \"jsonSchema does not look like a JSON Schema (missing type/$ref/oneOf/anyOf/allOf/enum/const/properties).\"\n );\n }\n}\n\n/**\n * Serialize a JSON Schema object for the WebLLM `response_format.schema`\n * field.\n *\n * WebLLM expects the schema as a JSON-encoded string (xgrammar parses it\n * server-side). Validates the shape via {@link assertJsonSchema} first.\n *\n * @param schema - JSON Schema object.\n * @returns The schema serialized as a JSON string.\n * @throws StructuredOutputError when `schema` is not a recognizable JSON\n * Schema shape.\n */\nexport function serializeJsonSchema(schema: unknown): string {\n assertJsonSchema(schema);\n return JSON.stringify(schema);\n}\n\n/**\n * Parse the textual output of a structured-decoding generation as JSON.\n *\n * @typeParam T - The expected parsed shape. The function does not validate\n * the parsed value against `T`; that is the caller's responsibility.\n * @param text - Raw text returned by the engine.\n * @returns The parsed JSON value cast to `T`.\n * @throws StructuredOutputError when the text is not valid JSON.\n */\nexport function parseStructuredOutput<T = unknown>(text: string): T {\n try {\n return JSON.parse(text) as T;\n } catch (err) {\n throw new StructuredOutputError(\n \"Engine output is not valid JSON. The model may have ignored the constrained decoding directive.\",\n err\n );\n }\n}\n","import type { Engine } from \"./engine\";\nimport { classifyLoadPhase } from \"./load-phase\";\nimport type { GenerationOptions, Message, ProgressCallback, TokenChunk } from \"../types\";\nimport {\n GenerationAbortedError,\n ModelLoadError,\n ModelNotLoadedError,\n WebGPUUnavailableError,\n} from \"./exceptions\";\nimport { serializeJsonSchema } from \"../structured/json-schema\";\n\ntype WebLLMModule = typeof import(\"@mlc-ai/web-llm\");\ntype MLCEngine = import(\"@mlc-ai/web-llm\").MLCEngineInterface;\ntype ChatCompletionMessageParam = import(\"@mlc-ai/web-llm\").ChatCompletionMessageParam;\ntype ResponseFormat = import(\"@mlc-ai/web-llm\").ResponseFormat;\n\nlet webllmModulePromise: Promise<WebLLMModule> | null = null;\n\nasync function loadWebLLM(): Promise<WebLLMModule> {\n if (!webllmModulePromise) {\n webllmModulePromise = import(\"@mlc-ai/web-llm\");\n }\n return webllmModulePromise;\n}\n\nfunction isWebGPUAvailable(): boolean {\n return typeof navigator !== \"undefined\" && \"gpu\" in navigator;\n}\n\ninterface SamplingParams {\n max_tokens?: number;\n temperature?: number;\n top_p?: number;\n}\n\nfunction buildSamplingParams(options: GenerationOptions): SamplingParams {\n const params: SamplingParams = {};\n if (options.maxTokens !== undefined) params.max_tokens = options.maxTokens;\n if (options.temperature !== undefined) params.temperature = options.temperature;\n if (options.topP !== undefined) params.top_p = options.topP;\n return params;\n}\n\n/**\n * Build the WebLLM `response_format` payload from generation options.\n *\n * Returns `undefined` when the caller has not requested structured output —\n * letting WebLLM use its default free-text decoding path. When `jsonSchema`\n * is set it takes priority and is serialized into the `schema` field\n * (xgrammar parses it server-side). When only `json` is set the payload\n * carries `{ type: \"json_object\" }` for unconstrained-but-valid JSON.\n */\nfunction buildResponseFormat(options: GenerationOptions): ResponseFormat | undefined {\n if (options.jsonSchema !== undefined) {\n return { type: \"json_object\", schema: serializeJsonSchema(options.jsonSchema) };\n }\n if (options.json) {\n return { type: \"json_object\" };\n }\n return undefined;\n}\n\nfunction toChatMessages(messages: Message[]): ChatCompletionMessageParam[] {\n return messages.map((m): ChatCompletionMessageParam => {\n switch (m.role) {\n case \"system\":\n return { role: \"system\", content: m.content };\n case \"user\":\n return { role: \"user\", content: m.content };\n case \"assistant\":\n return { role: \"assistant\", content: m.content };\n case \"tool\":\n return { role: \"tool\", content: m.content, tool_call_id: m.name ?? \"\" };\n }\n });\n}\n\n/**\n * Inference engine backed by [WebLLM (MLC)](https://github.com/mlc-ai/web-llm).\n *\n * Requires WebGPU. The fallback path planned for v0.5 will route to ORT-Web\n * when WebGPU is missing.\n */\nexport class WebLLMEngine implements Engine {\n private engine: MLCEngine | null = null;\n\n isLoaded(): boolean {\n return this.engine !== null;\n }\n\n async load(modelId: string, onProgress?: ProgressCallback): Promise<void> {\n if (!isWebGPUAvailable()) {\n throw new WebGPUUnavailableError(\n \"WebGPU is not available in this browser. The ORT-Web fallback is planned for v0.5.\"\n );\n }\n const webllm = await loadWebLLM();\n try {\n this.engine = await webllm.CreateMLCEngine(modelId, {\n initProgressCallback: (report): void => {\n onProgress?.({\n progress: report.progress,\n text: report.text,\n loaded: 0,\n total: 0,\n phase: classifyLoadPhase(report.text),\n });\n },\n });\n onProgress?.({\n progress: 1,\n text: \"Model ready.\",\n loaded: 0,\n total: 0,\n phase: \"ready\",\n });\n } catch (err) {\n throw new ModelLoadError(`Failed to load model \"${modelId}\".`, err);\n }\n }\n\n async generate(messages: Message[], options: GenerationOptions = {}): Promise<string> {\n const engine = this.requireEngine();\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted before start.\");\n }\n const responseFormat = buildResponseFormat(options);\n const completion = await engine.chat.completions.create({\n ...buildSamplingParams(options),\n messages: toChatMessages(messages),\n stream: false,\n ...(responseFormat ? { response_format: responseFormat } : {}),\n });\n return completion.choices[0]?.message?.content ?? \"\";\n }\n\n async *stream(messages: Message[], options: GenerationOptions = {}): AsyncIterable<TokenChunk> {\n const engine = this.requireEngine();\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted before start.\");\n }\n const responseFormat = buildResponseFormat(options);\n const completion = await engine.chat.completions.create({\n ...buildSamplingParams(options),\n messages: toChatMessages(messages),\n stream: true,\n ...(responseFormat ? { response_format: responseFormat } : {}),\n });\n let index: number = 0;\n let finished: boolean = false;\n try {\n for await (const chunk of completion) {\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted by signal.\");\n }\n const choice = chunk.choices[0];\n const delta = choice?.delta?.content ?? \"\";\n if (delta) {\n yield { text: delta, index, done: false };\n index += 1;\n }\n if (choice?.finish_reason) {\n finished = true;\n yield { text: \"\", index, done: true };\n index += 1;\n }\n }\n if (!finished) {\n yield { text: \"\", index, done: true };\n }\n } catch (err) {\n if (err instanceof GenerationAbortedError) throw err;\n throw new ModelLoadError(\"Streaming generation failed.\", err);\n }\n }\n\n async complete(prompt: string, options: GenerationOptions = {}): Promise<string> {\n const engine = this.requireEngine();\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted before start.\");\n }\n const responseFormat = buildResponseFormat(options);\n const completion = await engine.completions.create({\n ...buildSamplingParams(options),\n prompt,\n stream: false,\n ...(responseFormat ? { response_format: responseFormat } : {}),\n });\n return completion.choices[0]?.text ?? \"\";\n }\n\n async *streamCompletion(\n prompt: string,\n options: GenerationOptions = {}\n ): AsyncIterable<TokenChunk> {\n const engine = this.requireEngine();\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted before start.\");\n }\n const responseFormat = buildResponseFormat(options);\n const completion = await engine.completions.create({\n ...buildSamplingParams(options),\n prompt,\n stream: true,\n ...(responseFormat ? { response_format: responseFormat } : {}),\n });\n let index: number = 0;\n let finished: boolean = false;\n try {\n for await (const chunk of completion) {\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted by signal.\");\n }\n const choice = chunk.choices[0];\n const delta = choice?.text ?? \"\";\n if (delta) {\n yield { text: delta, index, done: false };\n index += 1;\n }\n if (choice?.finish_reason) {\n finished = true;\n yield { text: \"\", index, done: true };\n index += 1;\n }\n }\n if (!finished) {\n yield { text: \"\", index, done: true };\n }\n } catch (err) {\n if (err instanceof GenerationAbortedError) throw err;\n throw new ModelLoadError(\"Streaming completion failed.\", err);\n }\n }\n\n async unload(): Promise<void> {\n if (this.engine) {\n await this.engine.unload();\n this.engine = null;\n }\n }\n\n private requireEngine(): MLCEngine {\n if (!this.engine) {\n throw new ModelNotLoadedError(\"Engine not loaded. Call load() before generation.\");\n }\n return this.engine;\n }\n}\n","import type { GenerationOptions, Message, ModelLoadProgress, TokenChunk } from \"../types\";\n\n/**\n * Subset of {@link GenerationOptions} that survives `postMessage`.\n *\n * `AbortSignal` cannot be cloned across the worker boundary, so it is replaced\n * by a separate {@link AbortRequest} message keyed on the same operation id.\n */\nexport type SerializableGenerationOptions = Omit<GenerationOptions, \"signal\">;\n\n/** Strip `signal` from a {@link GenerationOptions} before posting it. */\nexport function toSerializableOptions(\n options: GenerationOptions = {}\n): SerializableGenerationOptions {\n const { signal: _signal, ...rest } = options;\n void _signal;\n return rest;\n}\n\n/** Operation request sent from the main thread to the worker. */\nexport type WorkerRequest =\n | { op: \"load\"; id: number; modelId: string }\n | {\n op: \"generate\";\n id: number;\n messages: Message[];\n options: SerializableGenerationOptions;\n }\n | {\n op: \"stream\";\n id: number;\n messages: Message[];\n options: SerializableGenerationOptions;\n }\n | {\n op: \"complete\";\n id: number;\n prompt: string;\n options: SerializableGenerationOptions;\n }\n | {\n op: \"stream-completion\";\n id: number;\n prompt: string;\n options: SerializableGenerationOptions;\n }\n | { op: \"abort\"; id: number }\n | { op: \"unload\"; id: number }\n | { op: \"isLoaded\"; id: number };\n\n/** Operation response sent from the worker back to the main thread. */\nexport type WorkerResponse =\n | { op: \"loaded\"; id: number }\n | { op: \"generated\"; id: number; text: string }\n | { op: \"progress\"; id: number; payload: ModelLoadProgress }\n | { op: \"token\"; id: number; chunk: TokenChunk }\n | { op: \"stream-end\"; id: number }\n | { op: \"error\"; id: number; name: string; message: string }\n | { op: \"unloaded\"; id: number }\n | { op: \"is-loaded\"; id: number; value: boolean };\n\n/** Subset of `Worker` we depend on. Lets tests inject a mock. */\nexport interface WorkerLike {\n postMessage(message: WorkerRequest): void;\n addEventListener(type: \"message\", listener: (event: MessageEvent<WorkerResponse>) => void): void;\n removeEventListener(\n type: \"message\",\n listener: (event: MessageEvent<WorkerResponse>) => void\n ): void;\n terminate(): void;\n}\n\n/** Internal alias used when the message direction is irrelevant (logging, debug). */\nexport type AbortRequest = Extract<WorkerRequest, { op: \"abort\" }>;\n","import { GenerationAbortedError, ModelLoadError, ModelNotLoadedError } from \"./exceptions\";\nimport type { Engine } from \"./engine\";\nimport type { GenerationOptions, Message, ProgressCallback, TokenChunk } from \"../types\";\nimport {\n toSerializableOptions,\n type WorkerLike,\n type WorkerRequest,\n type WorkerResponse,\n} from \"../worker/protocol\";\n\ninterface PendingGenerate {\n resolve: (text: string) => void;\n reject: (err: Error) => void;\n}\n\ninterface PendingStream {\n push: (chunk: TokenChunk) => void;\n end: () => void;\n fail: (err: Error) => void;\n}\n\n/**\n * Engine implementation that proxies all calls to a Web Worker.\n *\n * The worker holds the actual {@link WebLLMEngine}; this class is a thin RPC\n * shell that serializes requests, tracks pending operations by a numeric id,\n * and turns worker responses back into Promises and async iterables.\n *\n * Use {@link createInferenceWorker} to obtain a real worker. Tests can pass a\n * {@link WorkerLike} mock implementing the same `postMessage` /\n * `addEventListener` surface.\n */\nexport class WorkerEngine implements Engine {\n private nextId: number = 1;\n private loaded: boolean = false;\n private currentLoad: { resolve: () => void; reject: (e: Error) => void } | null = null;\n private currentLoadId: number = 0;\n private currentLoadProgress: ProgressCallback | undefined = undefined;\n private currentUnload: { resolve: () => void; reject: (e: Error) => void } | null = null;\n private currentUnloadId: number = 0;\n private pendingGenerates: Map<number, PendingGenerate> = new Map();\n private pendingStreams: Map<number, PendingStream> = new Map();\n\n private readonly listener: (event: MessageEvent<WorkerResponse>) => void;\n\n constructor(private readonly worker: WorkerLike) {\n this.listener = (event): void => this.handleMessage(event.data);\n this.worker.addEventListener(\"message\", this.listener);\n }\n\n isLoaded(): boolean {\n return this.loaded;\n }\n\n async load(modelId: string, onProgress?: ProgressCallback): Promise<void> {\n if (this.currentLoad) {\n throw new ModelLoadError(\"Another load is already in progress.\");\n }\n const id: number = this.allocateId();\n this.currentLoadId = id;\n this.currentLoadProgress = onProgress;\n return new Promise<void>((resolve, reject) => {\n this.currentLoad = { resolve, reject };\n this.send({ op: \"load\", id, modelId });\n });\n }\n\n async generate(messages: Message[], options: GenerationOptions = {}): Promise<string> {\n const id: number = this.allocateId();\n return new Promise<string>((resolve, reject) => {\n this.pendingGenerates.set(id, { resolve, reject });\n this.send({\n op: \"generate\",\n id,\n messages,\n options: toSerializableOptions(options),\n });\n options.signal?.addEventListener(\"abort\", () => this.send({ op: \"abort\", id }));\n });\n }\n\n async *stream(messages: Message[], options: GenerationOptions = {}): AsyncIterable<TokenChunk> {\n const id: number = this.allocateId();\n const queue: TokenChunk[] = [];\n let done: boolean = false;\n let error: Error | null = null;\n let notify: (() => void) | null = null;\n\n const wakeup = (): void => {\n if (notify) {\n const fn = notify;\n notify = null;\n fn();\n }\n };\n\n this.pendingStreams.set(id, {\n push: (chunk): void => {\n queue.push(chunk);\n wakeup();\n },\n end: (): void => {\n done = true;\n wakeup();\n },\n fail: (err): void => {\n error = err;\n done = true;\n wakeup();\n },\n });\n\n this.send({\n op: \"stream\",\n id,\n messages,\n options: toSerializableOptions(options),\n });\n options.signal?.addEventListener(\"abort\", () => this.send({ op: \"abort\", id }));\n\n try {\n while (true) {\n if (queue.length > 0) {\n const chunk = queue.shift();\n if (chunk) yield chunk;\n continue;\n }\n if (error) throw error;\n if (done) return;\n await new Promise<void>((r) => {\n notify = r;\n });\n }\n } finally {\n this.pendingStreams.delete(id);\n }\n }\n\n async complete(prompt: string, options: GenerationOptions = {}): Promise<string> {\n const id: number = this.allocateId();\n return new Promise<string>((resolve, reject) => {\n this.pendingGenerates.set(id, { resolve, reject });\n this.send({\n op: \"complete\",\n id,\n prompt,\n options: toSerializableOptions(options),\n });\n options.signal?.addEventListener(\"abort\", () => this.send({ op: \"abort\", id }));\n });\n }\n\n async *streamCompletion(\n prompt: string,\n options: GenerationOptions = {}\n ): AsyncIterable<TokenChunk> {\n const id: number = this.allocateId();\n const queue: TokenChunk[] = [];\n let done: boolean = false;\n let error: Error | null = null;\n let notify: (() => void) | null = null;\n\n const wakeup = (): void => {\n if (notify) {\n const fn = notify;\n notify = null;\n fn();\n }\n };\n\n this.pendingStreams.set(id, {\n push: (chunk): void => {\n queue.push(chunk);\n wakeup();\n },\n end: (): void => {\n done = true;\n wakeup();\n },\n fail: (err): void => {\n error = err;\n done = true;\n wakeup();\n },\n });\n\n this.send({\n op: \"stream-completion\",\n id,\n prompt,\n options: toSerializableOptions(options),\n });\n options.signal?.addEventListener(\"abort\", () => this.send({ op: \"abort\", id }));\n\n try {\n while (true) {\n if (queue.length > 0) {\n const chunk = queue.shift();\n if (chunk) yield chunk;\n continue;\n }\n if (error) throw error;\n if (done) return;\n await new Promise<void>((r) => {\n notify = r;\n });\n }\n } finally {\n this.pendingStreams.delete(id);\n }\n }\n\n async unload(): Promise<void> {\n if (!this.loaded) return;\n if (this.currentUnload) {\n throw new ModelLoadError(\"Another unload is already in progress.\");\n }\n const id: number = this.allocateId();\n this.currentUnloadId = id;\n return new Promise<void>((resolve, reject) => {\n this.currentUnload = { resolve, reject };\n this.send({ op: \"unload\", id });\n });\n }\n\n /** Tear down the underlying worker. The engine is unusable after this. */\n terminate(): void {\n this.worker.removeEventListener(\"message\", this.listener);\n this.worker.terminate();\n this.loaded = false;\n }\n\n private allocateId(): number {\n const id = this.nextId;\n this.nextId += 1;\n return id;\n }\n\n private send(req: WorkerRequest): void {\n this.worker.postMessage(req);\n }\n\n private handleMessage(msg: WorkerResponse): void {\n switch (msg.op) {\n case \"loaded\":\n if (this.currentLoad && msg.id === this.currentLoadId) {\n this.loaded = true;\n this.currentLoad.resolve();\n this.currentLoad = null;\n this.currentLoadProgress = undefined;\n }\n return;\n case \"progress\":\n if (msg.id === this.currentLoadId) {\n this.currentLoadProgress?.(msg.payload);\n }\n return;\n case \"generated\": {\n const pending = this.pendingGenerates.get(msg.id);\n if (pending) {\n pending.resolve(msg.text);\n this.pendingGenerates.delete(msg.id);\n }\n return;\n }\n case \"token\": {\n const stream = this.pendingStreams.get(msg.id);\n stream?.push(msg.chunk);\n return;\n }\n case \"stream-end\": {\n const stream = this.pendingStreams.get(msg.id);\n stream?.end();\n return;\n }\n case \"unloaded\":\n if (this.currentUnload && msg.id === this.currentUnloadId) {\n this.loaded = false;\n this.currentUnload.resolve();\n this.currentUnload = null;\n }\n return;\n case \"is-loaded\":\n return;\n case \"error\": {\n const err = mapError(msg.name, msg.message);\n if (this.currentLoad && msg.id === this.currentLoadId) {\n this.currentLoad.reject(err);\n this.currentLoad = null;\n this.currentLoadProgress = undefined;\n return;\n }\n if (this.currentUnload && msg.id === this.currentUnloadId) {\n this.currentUnload.reject(err);\n this.currentUnload = null;\n return;\n }\n const generate = this.pendingGenerates.get(msg.id);\n if (generate) {\n generate.reject(err);\n this.pendingGenerates.delete(msg.id);\n return;\n }\n const stream = this.pendingStreams.get(msg.id);\n if (stream) {\n stream.fail(err);\n return;\n }\n return;\n }\n }\n }\n}\n\nfunction mapError(name: string, message: string): Error {\n switch (name) {\n case \"ModelLoadError\":\n return new ModelLoadError(message);\n case \"ModelNotLoadedError\":\n return new ModelNotLoadedError(message);\n case \"GenerationAbortedError\":\n return new GenerationAbortedError(message);\n default: {\n const err = new Error(message);\n err.name = name;\n return err;\n }\n }\n}\n","import type { ModelPreset } from \"../types\";\nimport { UnknownModelError } from \"../core/exceptions\";\n\n/**\n * Curated registry of supported models for v0.1.\n *\n * Each entry maps a friendly id (e.g. `\"phi-3.5-mini-int4\"`) to the underlying\n * runtime identifier and metadata. Friendly ids are stable; backend ids may\n * change as upstream MLC packages evolve.\n *\n * Only models that have been validated to load in browsers with WebGPU and\n * that fit the SLM target (≤ 4B parameters at INT4) are included.\n */\nexport const MODEL_PRESETS: Readonly<Record<string, ModelPreset>> = Object.freeze({\n \"phi-3.5-mini-int4\": {\n id: \"phi-3.5-mini-int4\",\n family: \"Phi-3.5\",\n parameters: \"3.8B\",\n quantization: \"q4f16_1\",\n webllmId: \"Phi-3.5-mini-instruct-q4f16_1-MLC\",\n contextWindow: 4096,\n description: \"Microsoft Phi-3.5 mini, INT4 quantized for browser inference.\",\n },\n \"llama-3.2-1b-int4\": {\n id: \"llama-3.2-1b-int4\",\n family: \"Llama-3.2\",\n parameters: \"1B\",\n quantization: \"q4f16_1\",\n webllmId: \"Llama-3.2-1B-Instruct-q4f16_1-MLC\",\n contextWindow: 4096,\n description: \"Meta Llama 3.2 1B Instruct, INT4 quantized.\",\n },\n \"qwen2.5-1.5b-int4\": {\n id: \"qwen2.5-1.5b-int4\",\n family: \"Qwen2.5\",\n parameters: \"1.5B\",\n quantization: \"q4f16_1\",\n webllmId: \"Qwen2.5-1.5B-Instruct-q4f16_1-MLC\",\n contextWindow: 4096,\n description: \"Alibaba Qwen 2.5 1.5B Instruct, INT4 quantized.\",\n },\n});\n\n/**\n * Resolve a friendly model id to its full preset metadata.\n *\n * @param modelId - Friendly id (e.g. `\"phi-3.5-mini-int4\"`).\n * @returns The matching preset.\n * @throws UnknownModelError if no preset matches.\n */\nexport function resolveModelPreset(modelId: string): ModelPreset {\n const preset = MODEL_PRESETS[modelId];\n if (!preset) {\n const available = Object.keys(MODEL_PRESETS).join(\", \");\n throw new UnknownModelError(`Unknown model \"${modelId}\". Available models: ${available}.`);\n }\n return preset;\n}\n\n/** Return the list of supported friendly model ids. */\nexport function listSupportedModels(): string[] {\n return Object.keys(MODEL_PRESETS);\n}\n\n/** Curated metadata for a supported embedding model. */\nexport interface EmbeddingPreset {\n /** Friendly identifier (e.g. `\"bge-small-en-v1.5\"`). */\n id: string;\n /** Family name (e.g. `\"BGE\"`). */\n family: string;\n /** Embedding dimension. */\n dimension: number;\n /** Maximum input length in tokens. */\n maxTokens: number;\n /** Identifier passed to `@huggingface/transformers`. */\n transformersId: string;\n /** Approximate quantization scheme (e.g. `\"fp32\"`, `\"int8\"`). */\n quantization: string;\n /** Short human description. */\n description: string;\n}\n\n/**\n * Curated registry of supported embedding models for v0.3.\n *\n * Each entry maps a friendly id to the underlying transformers.js model id.\n */\nexport const EMBEDDING_PRESETS: Readonly<Record<string, EmbeddingPreset>> = Object.freeze({\n \"bge-small-en-v1.5\": {\n id: \"bge-small-en-v1.5\",\n family: \"BGE\",\n dimension: 384,\n maxTokens: 512,\n transformersId: \"Xenova/bge-small-en-v1.5\",\n quantization: \"fp32\",\n description: \"BAAI BGE small English v1.5, 384-dim sentence embeddings.\",\n },\n \"bge-base-en-v1.5\": {\n id: \"bge-base-en-v1.5\",\n family: \"BGE\",\n dimension: 768,\n maxTokens: 512,\n transformersId: \"Xenova/bge-base-en-v1.5\",\n quantization: \"fp32\",\n description: \"BAAI BGE base English v1.5, 768-dim sentence embeddings.\",\n },\n});\n\n/**\n * Resolve a friendly embedding model id to its full preset metadata.\n *\n * @param modelId - Friendly id (e.g. `\"bge-small-en-v1.5\"`).\n * @returns The matching preset.\n * @throws UnknownModelError if no preset matches.\n */\nexport function resolveEmbeddingPreset(modelId: string): EmbeddingPreset {\n const preset = EMBEDDING_PRESETS[modelId];\n if (!preset) {\n const available = Object.keys(EMBEDDING_PRESETS).join(\", \");\n throw new UnknownModelError(\n `Unknown embedding model \"${modelId}\". Available models: ${available}.`\n );\n }\n return preset;\n}\n\n/** Return the list of supported embedding model ids. */\nexport function listSupportedEmbeddingModels(): string[] {\n return Object.keys(EMBEDDING_PRESETS);\n}\n\n/** Curated metadata for a supported reranker (cross-encoder) model. */\nexport interface RerankerPreset {\n /** Friendly identifier (e.g. `\"bge-reranker-base\"`). */\n id: string;\n /** Family name (e.g. `\"BGE Reranker\"`). */\n family: string;\n /** Maximum input length in tokens (combined query + document). */\n maxTokens: number;\n /** Identifier passed to `@huggingface/transformers`. */\n transformersId: string;\n /** Approximate quantization (e.g. `\"fp32\"`). */\n quantization: string;\n /** Short human description. */\n description: string;\n}\n\n/**\n * Curated registry of supported reranker models for v0.3.\n */\nexport const RERANKER_PRESETS: Readonly<Record<string, RerankerPreset>> = Object.freeze({\n \"bge-reranker-base\": {\n id: \"bge-reranker-base\",\n family: \"BGE Reranker\",\n maxTokens: 512,\n transformersId: \"Xenova/bge-reranker-base\",\n quantization: \"fp32\",\n description: \"BAAI BGE reranker base — multilingual cross-encoder.\",\n },\n});\n\n/**\n * Resolve a friendly reranker model id to its full preset metadata.\n *\n * @param modelId - Friendly id (e.g. `\"bge-reranker-base\"`).\n * @throws UnknownModelError if no preset matches.\n */\nexport function resolveRerankerPreset(modelId: string): RerankerPreset {\n const preset = RERANKER_PRESETS[modelId];\n if (!preset) {\n const available = Object.keys(RERANKER_PRESETS).join(\", \");\n throw new UnknownModelError(\n `Unknown reranker model \"${modelId}\". Available models: ${available}.`\n );\n }\n return preset;\n}\n\n/** Return the list of supported reranker model ids. */\nexport function listSupportedRerankerModels(): string[] {\n return Object.keys(RERANKER_PRESETS);\n}\n","import type { WorkerLike } from \"./protocol\";\n\n/**\n * Spawn a new inference Web Worker.\n *\n * Uses Vite/webpack-friendly `new Worker(new URL(...), { type: \"module\" })`\n * syntax. The bundler emits the worker as a separate ES module chunk.\n *\n * Consumers normally do not call this directly — `LMTask.create()` invokes it\n * when `inWorker: true` is set. It is exported for advanced scenarios (custom\n * worker management, pooling, lifecycle integration with a host app).\n *\n * @returns A {@link WorkerLike}-compatible Worker instance.\n */\nexport function createInferenceWorker(): WorkerLike {\n return new Worker(new URL(\"./inference.worker.ts\", import.meta.url), {\n type: \"module\",\n }) as unknown as WorkerLike;\n}\n","import type { Engine } from \"../core/engine\";\nimport { WebLLMEngine } from \"../core/webllm-engine\";\nimport { WorkerEngine } from \"../core/worker-engine\";\nimport { resolveModelPreset } from \"../presets/models\";\nimport { createInferenceWorker } from \"../worker/create-worker\";\nimport type { ModelPreset, ProgressCallback } from \"../types\";\n\n/** Common options accepted by every task's `create()` factory. */\nexport interface LMTaskCreateOptions {\n /** Optional callback for model load progress updates. */\n onProgress?: ProgressCallback;\n /**\n * Override the engine used for inference. Intended for testing.\n * Production callers should let the SDK pick a backend automatically.\n */\n engine?: Engine;\n /**\n * Run inference inside a Web Worker, isolating the UI thread from\n * tokenization and generation. **Default `true` from v0.3** — the\n * `WorkerEngine` is the recommended path. Pass `false` to keep\n * inference on the main thread (useful for environments without\n * `Worker` support or when debugging the runtime directly).\n *\n * Ignored when {@link engine} is provided.\n */\n inWorker?: boolean;\n}\n\n/** Internal payload returned by {@link LMTask.createEngine}. */\nexport interface ResolvedEngine {\n engine: Engine;\n preset: ModelPreset;\n}\n\n/**\n * Base class shared by all language-model tasks (`Chat` for v0.1; `Completion`,\n * `Embeddings` and `Reranker` planned for later versions).\n *\n * The base owns:\n * - resolving a friendly model id to a {@link ModelPreset};\n * - selecting and loading an {@link Engine} (defaulting to WebLLM);\n * - exposing `unload()` for cleanup.\n *\n * Subclasses add task-specific public methods (`send`, `stream`, etc.).\n */\nexport abstract class LMTask {\n protected constructor(\n /** Engine used for inference. */\n protected readonly engine: Engine,\n /** Resolved metadata for the loaded model. */\n public readonly preset: ModelPreset\n ) {}\n\n /**\n * Load a model into a backend and return the wired-up engine + preset.\n *\n * Subclasses call this from their static `create()` factories.\n *\n * @param modelId - Friendly model id from the registry.\n * @param options - Task creation options.\n */\n protected static async createEngine(\n modelId: string,\n options: LMTaskCreateOptions = {}\n ): Promise<ResolvedEngine> {\n const preset = resolveModelPreset(modelId);\n const engine = options.engine ?? LMTask.defaultEngine(options);\n if (!engine.isLoaded()) {\n await engine.load(preset.webllmId, options.onProgress);\n }\n return { engine, preset };\n }\n\n private static defaultEngine(options: LMTaskCreateOptions): Engine {\n const useWorker: boolean = options.inWorker ?? true;\n if (useWorker) {\n return new WorkerEngine(createInferenceWorker());\n }\n return new WebLLMEngine();\n }\n\n /** Release engine resources. Safe to call multiple times. */\n async unload(): Promise<void> {\n await this.engine.unload();\n }\n\n /** Whether the underlying engine has a loaded model. */\n isLoaded(): boolean {\n return this.engine.isLoaded();\n }\n}\n","import { parseStructuredOutput } from \"./structured/json-schema\";\nimport type { FinishReason, Message } from \"./types\";\n\n/**\n * Result returned by `Chat.send()`.\n *\n * Holds the assistant's textual reply, the structured assistant message\n * (already appended to the chat history), and metadata about the generation.\n */\nexport class ChatReply {\n constructor(\n /** The assistant's reply text. */\n public readonly text: string,\n /** The structured assistant message (already appended to chat history). */\n public readonly message: Message,\n /** Number of tokens generated. 0 when the engine does not report it. */\n public readonly tokensGenerated: number,\n /** Why the generation loop stopped. */\n public readonly finishReason: FinishReason\n ) {}\n\n /**\n * Parse {@link ChatReply.text} as JSON.\n *\n * Intended for replies generated with `json: true` or `jsonSchema`.\n * The result is cast to `T` without runtime validation; pair with Zod /\n * Ajv on the call site if you need to verify the schema.\n *\n * @typeParam T - Expected parsed shape.\n * @returns The parsed JSON value.\n * @throws StructuredOutputError if the text is not valid JSON.\n */\n json<T = unknown>(): T {\n return parseStructuredOutput<T>(this.text);\n }\n}\n\n/**\n * Result returned by `Completion.predict()`.\n *\n * Holds the generated continuation text (the prompt itself is not included)\n * plus metadata about the generation loop.\n */\nexport class CompletionResult {\n constructor(\n /** The generated text (continuation only, prompt excluded). */\n public readonly text: string,\n /** The original prompt that was fed to the model. */\n public readonly prompt: string,\n /** Number of tokens generated. 0 when the engine does not report it. */\n public readonly tokensGenerated: number,\n /** Why the generation loop stopped. */\n public readonly finishReason: FinishReason\n ) {}\n\n /**\n * Parse {@link CompletionResult.text} as JSON.\n *\n * Intended for completions generated with `json: true` or `jsonSchema`.\n * The result is cast to `T` without runtime validation.\n *\n * @typeParam T - Expected parsed shape.\n * @returns The parsed JSON value.\n * @throws StructuredOutputError if the text is not valid JSON.\n */\n json<T = unknown>(): T {\n return parseStructuredOutput<T>(this.text);\n }\n}\n","import { LMTask, type LMTaskCreateOptions } from \"./lm-task\";\nimport type { Engine } from \"../core/engine\";\nimport { ChatReply } from \"../results\";\nimport type { GenerationOptions, Message, ModelPreset, TokenChunk } from \"../types\";\n\n/**\n * Multi-turn chat task.\n *\n * Maintains an in-memory conversation history and applies the chat template\n * configured for the loaded model. Use {@link Chat.create} to construct an\n * instance — the constructor is private.\n *\n * @example\n * ```ts\n * const chat = await Chat.create(\"phi-3.5-mini-int4\");\n * const reply = await chat.send(\"Explain ONNX in one sentence.\");\n * console.log(reply.text);\n * ```\n *\n * @example Streaming\n * ```ts\n * const controller = new AbortController();\n * for await (const token of chat.stream(\"Explain ONNX.\", { signal: controller.signal })) {\n * process.stdout.write(token.text);\n * }\n * ```\n */\nexport class Chat extends LMTask {\n private readonly history: Message[] = [];\n private systemPrompt: string | null = null;\n\n private constructor(engine: Engine, preset: ModelPreset) {\n super(engine, preset);\n }\n\n /**\n * Create and load a `Chat` task for the given model.\n *\n * @param modelId - Friendly model id from the registry (e.g. `\"phi-3.5-mini-int4\"`).\n * @param options - Optional creation options (progress callback, engine override).\n */\n static async create(modelId: string, options: LMTaskCreateOptions = {}): Promise<Chat> {\n const { engine, preset } = await LMTask.createEngine(modelId, options);\n return new Chat(engine, preset);\n }\n\n /** Set or replace the system prompt prepended to every conversation. */\n setSystemPrompt(prompt: string): void {\n this.systemPrompt = prompt;\n }\n\n /** Clear the system prompt. */\n clearSystemPrompt(): void {\n this.systemPrompt = null;\n }\n\n /** Reset the conversation history. The system prompt is preserved. */\n resetHistory(): void {\n this.history.length = 0;\n }\n\n /** A read-only snapshot of the conversation history. */\n getHistory(): readonly Message[] {\n return this.history.slice();\n }\n\n /**\n * Send a user message and await the full assistant reply.\n *\n * The user message and the assistant reply are appended to the history.\n *\n * @param message - The user-facing message text.\n * @param options - Generation options.\n * @returns A {@link ChatReply} with the assistant's reply.\n */\n async send(message: string, options: GenerationOptions = {}): Promise<ChatReply> {\n const messages = this.buildMessages(message);\n const text = await this.engine.generate(messages, options);\n const userMsg: Message = { role: \"user\", content: message };\n const assistantMsg: Message = { role: \"assistant\", content: text };\n this.history.push(userMsg, assistantMsg);\n return new ChatReply(text, assistantMsg, 0, \"stop\");\n }\n\n /**\n * Stream the assistant reply token-by-token as an async iterable.\n *\n * The full reply is appended to the history when the stream completes\n * normally. If the stream is aborted, neither message is appended.\n *\n * @param message - The user-facing message text.\n * @param options - Generation options including an optional `signal`.\n */\n async *stream(message: string, options: GenerationOptions = {}): AsyncIterable<TokenChunk> {\n const messages = this.buildMessages(message);\n const userMsg: Message = { role: \"user\", content: message };\n let acc: string = \"\";\n for await (const chunk of this.engine.stream(messages, options)) {\n acc += chunk.text;\n yield chunk;\n }\n const assistantMsg: Message = { role: \"assistant\", content: acc };\n this.history.push(userMsg, assistantMsg);\n }\n\n private buildMessages(userMessage: string): Message[] {\n const messages: Message[] = [];\n if (this.systemPrompt) {\n messages.push({ role: \"system\", content: this.systemPrompt });\n }\n messages.push(...this.history);\n messages.push({ role: \"user\", content: userMessage });\n return messages;\n }\n}\n","import { LMTask, type LMTaskCreateOptions } from \"./lm-task\";\nimport type { Engine } from \"../core/engine\";\nimport { CompletionResult } from \"../results\";\nimport type { GenerationOptions, ModelPreset, TokenChunk } from \"../types\";\n\n/**\n * Raw text-completion task.\n *\n * Unlike {@link Chat}, `Completion` does not maintain a conversation history\n * and does not apply a chat template. The prompt is fed to the model verbatim\n * and the model continues it. Useful for \"Once upon a time…\" style generation,\n * code completion, or any scenario where chat formatting would interfere.\n *\n * Use {@link Completion.create} to construct an instance — the constructor is\n * private.\n *\n * @example\n * ```ts\n * const comp = await Completion.create(\"qwen2.5-1.5b-int4\");\n * const result = await comp.predict(\"Once upon a time\", { maxTokens: 50 });\n * console.log(result.text);\n * ```\n *\n * @example Streaming\n * ```ts\n * const controller = new AbortController();\n * for await (const token of comp.stream(\"def fibonacci(n):\", { signal: controller.signal })) {\n * process.stdout.write(token.text);\n * }\n * ```\n */\nexport class Completion extends LMTask {\n private constructor(engine: Engine, preset: ModelPreset) {\n super(engine, preset);\n }\n\n /**\n * Create and load a `Completion` task for the given model.\n *\n * @param modelId - Friendly model id from the registry (e.g. `\"qwen2.5-1.5b-int4\"`).\n * @param options - Optional creation options (progress callback, engine override).\n */\n static async create(modelId: string, options: LMTaskCreateOptions = {}): Promise<Completion> {\n const { engine, preset } = await LMTask.createEngine(modelId, options);\n return new Completion(engine, preset);\n }\n\n /**\n * Generate a continuation for the given prompt.\n *\n * @param prompt - Raw text fed to the model.\n * @param options - Generation options.\n * @returns A {@link CompletionResult} with the generated continuation.\n */\n async predict(prompt: string, options: GenerationOptions = {}): Promise<CompletionResult> {\n const text = await this.engine.complete(prompt, options);\n return new CompletionResult(text, prompt, 0, \"stop\");\n }\n\n /**\n * Stream a continuation for the given prompt as an async iterable of token\n * chunks.\n *\n * @param prompt - Raw text fed to the model.\n * @param options - Generation options including an optional `signal`.\n */\n async *stream(prompt: string, options: GenerationOptions = {}): AsyncIterable<TokenChunk> {\n for await (const chunk of this.engine.streamCompletion(prompt, options)) {\n yield chunk;\n }\n }\n}\n","import { ModelLoadError, ModelNotLoadedError } from \"../core/exceptions\";\nimport { resolveEmbeddingPreset, type EmbeddingPreset } from \"../presets/models\";\nimport type { ProgressCallback } from \"../types\";\n\n/** Options accepted by {@link Embeddings.create}. */\nexport interface EmbeddingsCreateOptions {\n /** Optional callback for model load progress updates. */\n onProgress?: ProgressCallback;\n /** Override the embedding pipeline. Intended for testing. */\n pipeline?: EmbedPipeline;\n}\n\n/** Options accepted by {@link Embeddings.embed}. */\nexport interface EmbedOptions {\n /** L2-normalize each vector. Recommended for cosine similarity downstream. Default `true`. */\n normalize?: boolean;\n /** Pooling strategy. BGE-style models use `\"cls\"`. Most sentence-transformers use `\"mean\"`. Default `\"mean\"`. */\n pooling?: \"mean\" | \"cls\";\n}\n\n/**\n * Minimal pipeline contract that {@link Embeddings} depends on.\n *\n * The default implementation wraps `@huggingface/transformers`. Tests inject\n * a fake satisfying the same shape — they never load the real runtime.\n */\nexport interface EmbedPipeline {\n /**\n * Run the encoder on a batch of inputs and return raw vectors.\n *\n * @param texts - Input strings.\n * @param options - Pooling + normalization passed to the underlying pipeline.\n */\n embed(texts: string[], options: Required<EmbedOptions>): Promise<number[][]>;\n /** Release pipeline resources. */\n unload?(): Promise<void>;\n}\n\ntype TransformersModule = typeof import(\"@huggingface/transformers\");\n\nlet transformersModulePromise: Promise<TransformersModule> | null = null;\n\nasync function loadTransformers(): Promise<TransformersModule> {\n if (!transformersModulePromise) {\n transformersModulePromise = import(\"@huggingface/transformers\");\n }\n return transformersModulePromise;\n}\n\nasync function buildDefaultPipeline(\n preset: EmbeddingPreset,\n onProgress?: ProgressCallback\n): Promise<EmbedPipeline> {\n const transformers = await loadTransformers();\n try {\n const pipe = await transformers.pipeline(\"feature-extraction\", preset.transformersId, {\n progress_callback: (report: unknown): void => {\n if (!onProgress) return;\n const r = report as { progress?: number; status?: string };\n onProgress({\n progress: typeof r.progress === \"number\" ? r.progress / 100 : 0,\n text: r.status ?? \"\",\n loaded: 0,\n total: 0,\n phase: \"downloading\",\n });\n },\n });\n return {\n async embed(texts, options): Promise<number[][]> {\n const output = await pipe(texts, {\n pooling: options.pooling,\n normalize: options.normalize,\n });\n return output.tolist();\n },\n async unload(): Promise<void> {\n if (typeof (pipe as { dispose?: () => Promise<void> }).dispose === \"function\") {\n await (pipe as unknown as { dispose: () => Promise<void> }).dispose();\n }\n },\n };\n } catch (err) {\n throw new ModelLoadError(`Failed to load embedding model \"${preset.id}\".`, err);\n }\n}\n\n/**\n * Sentence embedding task backed by `@huggingface/transformers`.\n *\n * Use {@link Embeddings.create} to construct an instance — the constructor is\n * private. The default backend lazy-loads the transformers.js runtime; tests\n * inject a {@link EmbedPipeline} mock instead.\n *\n * @example\n * ```ts\n * const emb = await Embeddings.create(\"bge-small-en-v1.5\");\n * const vectors = await emb.embed([\"hello world\", \"another sentence\"]);\n * console.log(vectors[0].length); // 384\n * ```\n */\nexport class Embeddings {\n private constructor(\n private readonly pipeline: EmbedPipeline,\n /** Resolved metadata for the loaded model. */\n public readonly preset: EmbeddingPreset\n ) {}\n\n /**\n * Create and load an `Embeddings` task for the given model.\n *\n * @param modelId - Friendly id from the embedding registry.\n * @param options - Optional creation options.\n * @throws UnknownModelError if `modelId` is not in the registry.\n * @throws ModelLoadError if the underlying pipeline fails to load.\n */\n static async create(modelId: string, options: EmbeddingsCreateOptions = {}): Promise<Embeddings> {\n const preset = resolveEmbeddingPreset(modelId);\n const pipeline = options.pipeline ?? (await buildDefaultPipeline(preset, options.onProgress));\n return new Embeddings(pipeline, preset);\n }\n\n /**\n * Encode an array of strings into dense vectors.\n *\n * Returns one vector per input, in the same order. Empty input array\n * returns an empty array (no error).\n *\n * @param texts - Input strings.\n * @param options - Pooling + normalization. Defaults: `pooling: \"mean\"`, `normalize: true`.\n */\n async embed(texts: string[], options: EmbedOptions = {}): Promise<number[][]> {\n if (texts.length === 0) return [];\n if (!this.pipeline) {\n throw new ModelNotLoadedError(\"Embeddings pipeline not initialized.\");\n }\n const merged: Required<EmbedOptions> = {\n normalize: options.normalize ?? true,\n pooling: options.pooling ?? \"mean\",\n };\n return this.pipeline.embed(texts, merged);\n }\n\n /**\n * Convenience: encode a single string and return its vector.\n *\n * @param text - Input string.\n * @param options - Forwarded to {@link Embeddings.embed}.\n */\n async embedSingle(text: string, options: EmbedOptions = {}): Promise<number[]> {\n const [vec] = await this.embed([text], options);\n if (!vec) {\n throw new ModelLoadError(\"Embedding pipeline returned no result.\");\n }\n return vec;\n }\n\n /** Embedding dimension exposed by the loaded model. */\n get dimension(): number {\n return this.preset.dimension;\n }\n\n /** Release pipeline resources. Safe to call multiple times. */\n async unload(): Promise<void> {\n await this.pipeline.unload?.();\n }\n}\n","import { ModelLoadError, ModelNotLoadedError } from \"../core/exceptions\";\nimport { resolveRerankerPreset, type RerankerPreset } from \"../presets/models\";\nimport type { ProgressCallback } from \"../types\";\n\n/** Options accepted by {@link Reranker.create}. */\nexport interface RerankerCreateOptions {\n /** Optional callback for model load progress updates. */\n onProgress?: ProgressCallback;\n /** Override the rerank pipeline. Intended for testing. */\n pipeline?: RerankPipeline;\n}\n\n/** Options accepted by {@link Reranker.score}. */\nexport interface RerankOptions {\n /**\n * Apply sigmoid to logits to map scores into `[0, 1]`. Recommended when the\n * downstream code uses scores as probabilities. Default `false` (raw logits).\n */\n sigmoid?: boolean;\n}\n\n/** A document paired with its score, for {@link Reranker.rank}. */\nexport interface RankedDocument {\n /** The document text. */\n text: string;\n /** Score from the cross-encoder. */\n score: number;\n /** Original index of the document in the input array. */\n index: number;\n}\n\n/**\n * Minimal pipeline contract that {@link Reranker} depends on.\n *\n * The default implementation wraps `@huggingface/transformers`. Tests inject\n * a fake satisfying the same shape — they never load the real runtime.\n */\nexport interface RerankPipeline {\n /**\n * Score `(query, doc)` pairs. One score per doc, in the same order.\n *\n * @param query - Single query string.\n * @param docs - Documents to score against the query.\n */\n score(query: string, docs: string[]): Promise<number[]>;\n /** Release pipeline resources. */\n unload?(): Promise<void>;\n}\n\ntype TransformersModule = typeof import(\"@huggingface/transformers\");\n\nlet transformersModulePromise: Promise<TransformersModule> | null = null;\n\nasync function loadTransformers(): Promise<TransformersModule> {\n if (!transformersModulePromise) {\n transformersModulePromise = import(\"@huggingface/transformers\");\n }\n return transformersModulePromise;\n}\n\nfunction sigmoidValue(x: number): number {\n return 1 / (1 + Math.exp(-x));\n}\n\nasync function buildDefaultPipeline(\n preset: RerankerPreset,\n onProgress?: ProgressCallback\n): Promise<RerankPipeline> {\n const transformers = await loadTransformers();\n try {\n const tokenizer = await transformers.AutoTokenizer.from_pretrained(preset.transformersId, {\n progress_callback: (report: unknown): void => {\n if (!onProgress) return;\n const r = report as { progress?: number; status?: string };\n onProgress({\n progress: typeof r.progress === \"number\" ? r.progress / 100 : 0,\n text: r.status ?? \"\",\n loaded: 0,\n total: 0,\n phase: \"downloading\",\n });\n },\n });\n const model = await transformers.AutoModelForSequenceClassification.from_pretrained(\n preset.transformersId,\n {\n progress_callback: (report: unknown): void => {\n if (!onProgress) return;\n const r = report as { progress?: number; status?: string };\n onProgress({\n progress: typeof r.progress === \"number\" ? r.progress / 100 : 0,\n text: r.status ?? \"\",\n loaded: 0,\n total: 0,\n phase: \"downloading\",\n });\n },\n }\n );\n return {\n async score(query, docs): Promise<number[]> {\n if (docs.length === 0) return [];\n const queries: string[] = docs.map(() => query);\n // `transformers.js` AutoTokenizer accepts `(text, options)` where\n // `options.text_pair` carries the second sequence; pair-input typing\n // isn't exported, so we cast through `unknown`.\n const tokenize = tokenizer as unknown as (\n text: string[],\n options: Record<string, unknown>\n ) => Record<string, unknown>;\n const inputs = tokenize(queries, {\n text_pair: docs,\n padding: true,\n truncation: true,\n max_length: preset.maxTokens,\n });\n const callModel = model as unknown as (\n inputs: Record<string, unknown>\n ) => Promise<{ logits: { tolist: () => number[][] } }>;\n const outputs = await callModel(inputs);\n const logits: number[][] = outputs.logits.tolist();\n return logits.map((row) => row[0] ?? 0);\n },\n async unload(): Promise<void> {\n const m = model as unknown as { dispose?: () => Promise<unknown> };\n if (typeof m.dispose === \"function\") await m.dispose();\n },\n };\n } catch (err) {\n throw new ModelLoadError(`Failed to load reranker model \"${preset.id}\".`, err);\n }\n}\n\n/**\n * Cross-encoder reranking task backed by `@huggingface/transformers`.\n *\n * Use {@link Reranker.create} to construct an instance — the constructor is\n * private. Useful as a second-stage step in a retrieve-then-rerank pipeline:\n * pull top-K candidates with a fast embedding similarity, then rerank with\n * a cross-encoder for higher precision.\n *\n * @example\n * ```ts\n * const rerank = await Reranker.create(\"bge-reranker-base\");\n * const scores = await rerank.score(\"what is webgpu?\", [\n * \"WebGPU is a modern graphics API\",\n * \"Bananas grow on trees\",\n * ]);\n * // scores[0] >> scores[1]\n * ```\n *\n * @example Ranked output sorted by score\n * ```ts\n * const ranked = await rerank.rank(\"what is webgpu?\", docs);\n * for (const r of ranked) console.log(r.score, r.text);\n * ```\n */\nexport class Reranker {\n private constructor(\n private readonly pipeline: RerankPipeline,\n /** Resolved metadata for the loaded model. */\n public readonly preset: RerankerPreset\n ) {}\n\n /**\n * Create and load a `Reranker` task for the given model.\n *\n * @param modelId - Friendly id from the reranker registry.\n * @param options - Optional creation options.\n * @throws UnknownModelError if `modelId` is not in the registry.\n * @throws ModelLoadError if the underlying pipeline fails to load.\n */\n static async create(modelId: string, options: RerankerCreateOptions = {}): Promise<Reranker> {\n const preset = resolveRerankerPreset(modelId);\n const pipeline = options.pipeline ?? (await buildDefaultPipeline(preset, options.onProgress));\n return new Reranker(pipeline, preset);\n }\n\n /**\n * Score each document against the query. Returns one score per doc, in\n * the same order. Empty `docs` returns `[]` (no error).\n *\n * @param query - Query string.\n * @param docs - Documents to score.\n * @param options - `sigmoid: true` maps logits into `[0, 1]`.\n */\n async score(query: string, docs: string[], options: RerankOptions = {}): Promise<number[]> {\n if (docs.length === 0) return [];\n if (!this.pipeline) {\n throw new ModelNotLoadedError(\"Reranker pipeline not initialized.\");\n }\n const raw = await this.pipeline.score(query, docs);\n return options.sigmoid ? raw.map(sigmoidValue) : raw;\n }\n\n /**\n * Score and sort documents by score in descending order. Returns a list of\n * {@link RankedDocument}s carrying the original index.\n *\n * @param query - Query string.\n * @param docs - Documents to rank.\n * @param options - Forwarded to {@link Reranker.score}.\n */\n async rank(\n query: string,\n docs: string[],\n options: RerankOptions = {}\n ): Promise<RankedDocument[]> {\n const scores = await this.score(query, docs, options);\n const ranked: RankedDocument[] = scores.map((score, index) => {\n const text: string = docs[index] ?? \"\";\n return { text, score, index };\n });\n ranked.sort((a, b) => b.score - a.score);\n return ranked;\n }\n\n /** Release pipeline resources. Safe to call multiple times. */\n async unload(): Promise<void> {\n await this.pipeline.unload?.();\n }\n}\n","import { MODEL_PRESETS, resolveModelPreset } from \"../presets/models\";\nimport { UnknownModelError } from \"../core/exceptions\";\n\n/** Snapshot of a single cached model's metadata. */\nexport interface CachedModelEntry {\n /** Friendly id from the registry (e.g. `\"llama-3.2-1b-int4\"`). */\n id: string;\n /** Backend-specific id (e.g. WebLLM `webllmId`). */\n backendId: string;\n /** Human-readable family name. */\n family: string;\n /** Approx parameter count, e.g. `\"1B\"`. */\n parameters: string;\n}\n\n/** Aggregate storage usage reported by the browser. */\nexport interface CacheUsage {\n /** Bytes used by the entire origin's storage (not just our cache). */\n usage: number;\n /** Bytes the browser is willing to give the origin. */\n quota: number;\n}\n\n/**\n * Hooks the {@link ModelCache} uses to talk to the underlying runtime and\n * the browser. Tests inject mocks; production code leaves them undefined,\n * letting `ModelCache` resolve the real `@mlc-ai/web-llm` helpers and\n * `navigator.storage.estimate()` lazily.\n */\nexport interface ModelCacheOptions {\n /** Override `hasModelInCache` from the runtime. */\n hasModel?: (backendId: string) => Promise<boolean>;\n /** Override `deleteModelInCache` from the runtime. */\n deleteModel?: (backendId: string) => Promise<void>;\n /** Override `navigator.storage.estimate()`. */\n estimate?: () => Promise<CacheUsage>;\n}\n\ntype WebLLMCacheModule = {\n hasModelInCache: (id: string) => Promise<boolean>;\n deleteModelInCache: (id: string) => Promise<void>;\n};\n\nlet webllmCachePromise: Promise<WebLLMCacheModule> | null = null;\n\nasync function loadWebLLMCacheHelpers(): Promise<WebLLMCacheModule> {\n if (!webllmCachePromise) {\n webllmCachePromise = import(\"@mlc-ai/web-llm\").then((m) => ({\n hasModelInCache: m.hasModelInCache,\n deleteModelInCache: m.deleteModelInCache,\n }));\n }\n return webllmCachePromise;\n}\n\nasync function defaultEstimate(): Promise<CacheUsage> {\n if (typeof navigator === \"undefined\" || !navigator.storage?.estimate) {\n return { usage: 0, quota: 0 };\n }\n const estimate = await navigator.storage.estimate();\n return {\n usage: estimate.usage ?? 0,\n quota: estimate.quota ?? 0,\n };\n}\n\n/**\n * Inspect and manage cached model weights.\n *\n * `localm-web` does not download or cache weights itself — that work is owned\n * by `@mlc-ai/web-llm`, which writes to the browser Cache API. `ModelCache`\n * is a thin wrapper that lets a consuming app surface cache state in its UI:\n * \"this model is downloaded\", \"you have 1.4 GB cached, free up space?\",\n * \"clear all models on logout\".\n *\n * @example\n * ```ts\n * const cache = new ModelCache();\n * if (await cache.has(\"llama-3.2-1b-int4\")) {\n * console.log(\"ready offline\");\n * }\n * const cached = await cache.list();\n * await cache.delete(\"phi-3.5-mini-int4\");\n * const usage = await cache.estimateUsage();\n * console.log(`${usage.usage} / ${usage.quota} bytes`);\n * ```\n */\nexport class ModelCache {\n private readonly hasModelHook: ((id: string) => Promise<boolean>) | undefined;\n private readonly deleteModelHook: ((id: string) => Promise<void>) | undefined;\n private readonly estimateHook: () => Promise<CacheUsage>;\n\n constructor(options: ModelCacheOptions = {}) {\n this.hasModelHook = options.hasModel;\n this.deleteModelHook = options.deleteModel;\n this.estimateHook = options.estimate ?? defaultEstimate;\n }\n\n /**\n * Whether the model's weights are present in the browser cache.\n *\n * @param modelId - Friendly id from the registry.\n * @throws UnknownModelError if `modelId` is not in the registry.\n */\n async has(modelId: string): Promise<boolean> {\n const backendId: string = resolveModelPreset(modelId).webllmId;\n const fn = this.hasModelHook ?? (await loadWebLLMCacheHelpers()).hasModelInCache;\n return fn(backendId);\n }\n\n /**\n * Delete a single model's weights from the browser cache. No-op when the\n * model is not cached.\n *\n * @param modelId - Friendly id from the registry.\n * @throws UnknownModelError if `modelId` is not in the registry.\n */\n async delete(modelId: string): Promise<void> {\n const backendId: string = resolveModelPreset(modelId).webllmId;\n const fn = this.deleteModelHook ?? (await loadWebLLMCacheHelpers()).deleteModelInCache;\n await fn(backendId);\n }\n\n /**\n * List the registry models that are currently cached.\n *\n * Iterates `MODEL_PRESETS` and probes each one. Only returns models known\n * to the SDK — models cached by external WebLLM calls outside our registry\n * are not included.\n *\n * @returns Empty list when nothing is cached.\n */\n async list(): Promise<CachedModelEntry[]> {\n const fn = this.hasModelHook ?? (await loadWebLLMCacheHelpers()).hasModelInCache;\n const probes = await Promise.all(\n Object.values(MODEL_PRESETS).map(async (preset) => {\n const cached: boolean = await fn(preset.webllmId);\n if (!cached) return null;\n const entry: CachedModelEntry = {\n id: preset.id,\n backendId: preset.webllmId,\n family: preset.family,\n parameters: preset.parameters,\n };\n return entry;\n })\n );\n return probes.filter((p): p is CachedModelEntry => p !== null);\n }\n\n /**\n * Delete every registry model from the cache. Useful for logout flows or\n * \"reset\" buttons. Models cached outside the registry are not touched.\n */\n async clear(): Promise<void> {\n const fn = this.deleteModelHook ?? (await loadWebLLMCacheHelpers()).deleteModelInCache;\n await Promise.all(Object.values(MODEL_PRESETS).map((p) => fn(p.webllmId)));\n }\n\n /**\n * Aggregate storage stats from the browser. Returned numbers cover the\n * entire origin (Cache API + IndexedDB + Service Workers + OPFS), not\n * just our model cache — use it for \"you have X of Y available\" hints.\n */\n async estimateUsage(): Promise<CacheUsage> {\n return this.estimateHook();\n }\n\n /**\n * Throw a descriptive error if the given id is not in the registry.\n * Exposed for code paths that want to validate before calling other\n * methods (those already throw on their own).\n *\n * @throws UnknownModelError\n */\n static assertKnown(modelId: string): void {\n if (!(modelId in MODEL_PRESETS)) {\n const available = Object.keys(MODEL_PRESETS).join(\", \");\n throw new UnknownModelError(`Unknown model \"${modelId}\". Available models: ${available}.`);\n }\n }\n}\n","import type { TokenChunk } from \"../types\";\n\n/**\n * Drain an async iterable of token chunks into a single string.\n *\n * Useful in tests, for non-streaming consumers, and as a one-line way to\n * reconstruct the final text from a `Chat.stream(...)` call.\n *\n * @param stream - The token-chunk async iterable to consume.\n * @returns The concatenation of every chunk's `text` field.\n */\nexport async function collectStream(stream: AsyncIterable<TokenChunk>): Promise<string> {\n let acc: string = \"\";\n for await (const chunk of stream) {\n acc += chunk.text;\n }\n return acc;\n}\n\n/**\n * Wrap an async iterable so that each `TokenChunk` is also passed to a\n * caller-supplied side-effect callback before being yielded downstream.\n *\n * This is intentionally a passthrough — it does not buffer.\n *\n * @param stream - The upstream token-chunk async iterable.\n * @param onChunk - Side-effect invoked for every chunk.\n * @returns A new async iterable yielding the same chunks.\n */\nexport async function* tap(\n stream: AsyncIterable<TokenChunk>,\n onChunk: (chunk: TokenChunk) => void\n): AsyncIterable<TokenChunk> {\n for await (const chunk of stream) {\n onChunk(chunk);\n yield chunk;\n }\n}\n","/**\n * localm-web — browser-only TypeScript SDK for running LLMs and SLMs locally.\n *\n * Public API surface for v0.1.\n *\n * @packageDocumentation\n */\n\nexport { Chat } from \"./tasks/chat\";\nexport { Completion } from \"./tasks/completion\";\nexport { Embeddings } from \"./tasks/embeddings\";\nexport type { EmbeddingsCreateOptions, EmbedOptions, EmbedPipeline } from \"./tasks/embeddings\";\nexport { Reranker } from \"./tasks/reranker\";\nexport type {\n RerankerCreateOptions,\n RerankOptions,\n RerankPipeline,\n RankedDocument,\n} from \"./tasks/reranker\";\nexport { LMTask } from \"./tasks/lm-task\";\nexport type { LMTaskCreateOptions } from \"./tasks/lm-task\";\n\nexport { ChatReply, CompletionResult } from \"./results\";\n\nexport {\n MODEL_PRESETS,\n resolveModelPreset,\n listSupportedModels,\n EMBEDDING_PRESETS,\n resolveEmbeddingPreset,\n listSupportedEmbeddingModels,\n RERANKER_PRESETS,\n resolveRerankerPreset,\n listSupportedRerankerModels,\n} from \"./presets/models\";\nexport type { EmbeddingPreset, RerankerPreset } from \"./presets/models\";\n\nexport {\n LocalmWebError,\n WebGPUUnavailableError,\n ModelLoadError,\n ModelNotLoadedError,\n UnknownModelError,\n GenerationAbortedError,\n QuotaExceededError,\n BackendNotAvailableError,\n StructuredOutputError,\n} from \"./core/exceptions\";\n\nexport {\n assertJsonSchema,\n serializeJsonSchema,\n parseStructuredOutput,\n} from \"./structured/json-schema\";\n\nexport type { Engine } from \"./core/engine\";\nexport { WorkerEngine } from \"./core/worker-engine\";\nexport { createInferenceWorker } from \"./worker/create-worker\";\nexport type { WorkerLike } from \"./worker/protocol\";\n\nexport { ModelCache } from \"./cache\";\nexport type { CachedModelEntry, CacheUsage, ModelCacheOptions } from \"./cache\";\n\nexport { collectStream, tap } from \"./streaming/token-stream\";\n\nexport type {\n Role,\n FinishReason,\n Message,\n GenerationOptions,\n ModelLoadProgress,\n ModelLoadPhase,\n ProgressCallback,\n TokenChunk,\n ModelPreset,\n} from \"./types\";\n\n/** Current package version. Updated at release time. */\nexport const VERSION: string = \"0.4.0\";\n"],"names":["transformersModulePromise","loadTransformers","buildDefaultPipeline"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "localm-web",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Browser-only TypeScript SDK for running LLMs and SLMs locally with WebGPU. Ultralytics-style DX, Vite-first.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -31,9 +31,16 @@
31
31
  "clean": "rm -rf dist"
32
32
  },
33
33
  "peerDependencies": {
34
+ "@huggingface/transformers": "^4.2.0",
34
35
  "@mlc-ai/web-llm": "^0.2.79"
35
36
  },
37
+ "peerDependenciesMeta": {
38
+ "@huggingface/transformers": {
39
+ "optional": true
40
+ }
41
+ },
36
42
  "devDependencies": {
43
+ "@huggingface/transformers": "^4.2.0",
37
44
  "@mlc-ai/web-llm": "^0.2.79",
38
45
  "@types/node": "^22.10.0",
39
46
  "@typescript-eslint/eslint-plugin": "^8.18.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"inference.worker-CwvQtobb.js","sources":["../src/core/load-phase.ts","../src/core/exceptions.ts","../src/core/webllm-engine.ts","../src/worker/inference.worker.ts"],"sourcesContent":["import type { ModelLoadPhase } from \"../types\";\n\nconst DOWNLOAD_PATTERN: RegExp = /\\b(fetch|download|loading from cache|cache hit|param)/i;\nconst COMPILE_PATTERN: RegExp = /\\b(compil|shader|kernel|tensor|init|allocat|warm)/i;\n\n/**\n * Classify a runtime status text into a {@link ModelLoadPhase}.\n *\n * Heuristic: match download-related verbs first (network or cache hits are\n * treated as `downloading`), then compile-related verbs. Anything else falls\n * back to the generic `loading` bucket. The `ready` phase is never returned\n * here — callers emit it explicitly when the load resolves.\n *\n * @param text - The raw status string from the runtime.\n * @returns The classified phase.\n */\nexport function classifyLoadPhase(text: string): ModelLoadPhase {\n if (DOWNLOAD_PATTERN.test(text)) return \"downloading\";\n if (COMPILE_PATTERN.test(text)) return \"compiling\";\n return \"loading\";\n}\n","/**\n * Error hierarchy for localm-web.\n *\n * All errors thrown by the SDK extend `LocalmWebError` so consumers can\n * distinguish SDK errors from unrelated runtime errors with a single\n * `instanceof` check.\n */\n\n/** Base class for every error raised by localm-web. */\nexport class LocalmWebError extends Error {\n /**\n * @param message - Human-readable description of the error.\n * @param cause - Underlying error, if any.\n */\n constructor(\n message: string,\n public readonly cause?: unknown\n ) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** Thrown when WebGPU is required but not available in the host browser. */\nexport class WebGPUUnavailableError extends LocalmWebError {}\n\n/** Thrown when a model fails to load (network, parsing, runtime init). */\nexport class ModelLoadError extends LocalmWebError {}\n\n/** Thrown when an inference call is made before a model has loaded. */\nexport class ModelNotLoadedError extends LocalmWebError {}\n\n/** Thrown when a model id is not present in the curated registry. */\nexport class UnknownModelError extends LocalmWebError {}\n\n/** Thrown when generation is aborted via an `AbortSignal`. */\nexport class GenerationAbortedError extends LocalmWebError {}\n\n/** Thrown when the browser denies storage quota for the model cache. */\nexport class QuotaExceededError extends LocalmWebError {}\n\n/** Thrown when no usable backend is available on the current platform. */\nexport class BackendNotAvailableError extends LocalmWebError {}\n","import type { Engine } from \"./engine\";\nimport { classifyLoadPhase } from \"./load-phase\";\nimport type { GenerationOptions, Message, ProgressCallback, TokenChunk } from \"../types\";\nimport {\n GenerationAbortedError,\n ModelLoadError,\n ModelNotLoadedError,\n WebGPUUnavailableError,\n} from \"./exceptions\";\n\ntype WebLLMModule = typeof import(\"@mlc-ai/web-llm\");\ntype MLCEngine = import(\"@mlc-ai/web-llm\").MLCEngineInterface;\ntype ChatCompletionMessageParam = import(\"@mlc-ai/web-llm\").ChatCompletionMessageParam;\n\nlet webllmModulePromise: Promise<WebLLMModule> | null = null;\n\nasync function loadWebLLM(): Promise<WebLLMModule> {\n if (!webllmModulePromise) {\n webllmModulePromise = import(\"@mlc-ai/web-llm\");\n }\n return webllmModulePromise;\n}\n\nfunction isWebGPUAvailable(): boolean {\n return typeof navigator !== \"undefined\" && \"gpu\" in navigator;\n}\n\ninterface SamplingParams {\n max_tokens?: number;\n temperature?: number;\n top_p?: number;\n}\n\nfunction buildSamplingParams(options: GenerationOptions): SamplingParams {\n const params: SamplingParams = {};\n if (options.maxTokens !== undefined) params.max_tokens = options.maxTokens;\n if (options.temperature !== undefined) params.temperature = options.temperature;\n if (options.topP !== undefined) params.top_p = options.topP;\n return params;\n}\n\nfunction toChatMessages(messages: Message[]): ChatCompletionMessageParam[] {\n return messages.map((m): ChatCompletionMessageParam => {\n switch (m.role) {\n case \"system\":\n return { role: \"system\", content: m.content };\n case \"user\":\n return { role: \"user\", content: m.content };\n case \"assistant\":\n return { role: \"assistant\", content: m.content };\n case \"tool\":\n return { role: \"tool\", content: m.content, tool_call_id: m.name ?? \"\" };\n }\n });\n}\n\n/**\n * Inference engine backed by [WebLLM (MLC)](https://github.com/mlc-ai/web-llm).\n *\n * Requires WebGPU. The fallback path planned for v0.5 will route to ORT-Web\n * when WebGPU is missing.\n */\nexport class WebLLMEngine implements Engine {\n private engine: MLCEngine | null = null;\n\n isLoaded(): boolean {\n return this.engine !== null;\n }\n\n async load(modelId: string, onProgress?: ProgressCallback): Promise<void> {\n if (!isWebGPUAvailable()) {\n throw new WebGPUUnavailableError(\n \"WebGPU is not available in this browser. The ORT-Web fallback is planned for v0.5.\"\n );\n }\n const webllm = await loadWebLLM();\n try {\n this.engine = await webllm.CreateMLCEngine(modelId, {\n initProgressCallback: (report): void => {\n onProgress?.({\n progress: report.progress,\n text: report.text,\n loaded: 0,\n total: 0,\n phase: classifyLoadPhase(report.text),\n });\n },\n });\n onProgress?.({\n progress: 1,\n text: \"Model ready.\",\n loaded: 0,\n total: 0,\n phase: \"ready\",\n });\n } catch (err) {\n throw new ModelLoadError(`Failed to load model \"${modelId}\".`, err);\n }\n }\n\n async generate(messages: Message[], options: GenerationOptions = {}): Promise<string> {\n const engine = this.requireEngine();\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted before start.\");\n }\n const completion = await engine.chat.completions.create({\n ...buildSamplingParams(options),\n messages: toChatMessages(messages),\n stream: false,\n });\n return completion.choices[0]?.message?.content ?? \"\";\n }\n\n async *stream(messages: Message[], options: GenerationOptions = {}): AsyncIterable<TokenChunk> {\n const engine = this.requireEngine();\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted before start.\");\n }\n const completion = await engine.chat.completions.create({\n ...buildSamplingParams(options),\n messages: toChatMessages(messages),\n stream: true,\n });\n let index: number = 0;\n let finished: boolean = false;\n try {\n for await (const chunk of completion) {\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted by signal.\");\n }\n const choice = chunk.choices[0];\n const delta = choice?.delta?.content ?? \"\";\n if (delta) {\n yield { text: delta, index, done: false };\n index += 1;\n }\n if (choice?.finish_reason) {\n finished = true;\n yield { text: \"\", index, done: true };\n index += 1;\n }\n }\n if (!finished) {\n yield { text: \"\", index, done: true };\n }\n } catch (err) {\n if (err instanceof GenerationAbortedError) throw err;\n throw new ModelLoadError(\"Streaming generation failed.\", err);\n }\n }\n\n async complete(prompt: string, options: GenerationOptions = {}): Promise<string> {\n const engine = this.requireEngine();\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted before start.\");\n }\n const completion = await engine.completions.create({\n ...buildSamplingParams(options),\n prompt,\n stream: false,\n });\n return completion.choices[0]?.text ?? \"\";\n }\n\n async *streamCompletion(\n prompt: string,\n options: GenerationOptions = {}\n ): AsyncIterable<TokenChunk> {\n const engine = this.requireEngine();\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted before start.\");\n }\n const completion = await engine.completions.create({\n ...buildSamplingParams(options),\n prompt,\n stream: true,\n });\n let index: number = 0;\n let finished: boolean = false;\n try {\n for await (const chunk of completion) {\n if (options.signal?.aborted) {\n throw new GenerationAbortedError(\"Generation aborted by signal.\");\n }\n const choice = chunk.choices[0];\n const delta = choice?.text ?? \"\";\n if (delta) {\n yield { text: delta, index, done: false };\n index += 1;\n }\n if (choice?.finish_reason) {\n finished = true;\n yield { text: \"\", index, done: true };\n index += 1;\n }\n }\n if (!finished) {\n yield { text: \"\", index, done: true };\n }\n } catch (err) {\n if (err instanceof GenerationAbortedError) throw err;\n throw new ModelLoadError(\"Streaming completion failed.\", err);\n }\n }\n\n async unload(): Promise<void> {\n if (this.engine) {\n await this.engine.unload();\n this.engine = null;\n }\n }\n\n private requireEngine(): MLCEngine {\n if (!this.engine) {\n throw new ModelNotLoadedError(\"Engine not loaded. Call load() before generation.\");\n }\n return this.engine;\n }\n}\n","/// <reference lib=\"webworker\" />\n\nimport { WebLLMEngine } from \"../core/webllm-engine\";\nimport type { WorkerRequest, WorkerResponse } from \"./protocol\";\n\ndeclare const self: DedicatedWorkerGlobalScope;\n\nconst engine: WebLLMEngine = new WebLLMEngine();\nconst aborts: Map<number, AbortController> = new Map();\n\nfunction reply(message: WorkerResponse): void {\n self.postMessage(message);\n}\n\nfunction fail(id: number, err: unknown): void {\n const error = err instanceof Error ? err : new Error(String(err));\n reply({ op: \"error\", id, name: error.name, message: error.message });\n}\n\nasync function handleLoad(req: Extract<WorkerRequest, { op: \"load\" }>): Promise<void> {\n try {\n await engine.load(req.modelId, (payload) => {\n reply({ op: \"progress\", id: req.id, payload });\n });\n reply({ op: \"loaded\", id: req.id });\n } catch (err) {\n fail(req.id, err);\n }\n}\n\nasync function handleGenerate(req: Extract<WorkerRequest, { op: \"generate\" }>): Promise<void> {\n const controller: AbortController = new AbortController();\n aborts.set(req.id, controller);\n try {\n const text: string = await engine.generate(req.messages, {\n ...req.options,\n signal: controller.signal,\n });\n reply({ op: \"generated\", id: req.id, text });\n } catch (err) {\n fail(req.id, err);\n } finally {\n aborts.delete(req.id);\n }\n}\n\nasync function handleComplete(req: Extract<WorkerRequest, { op: \"complete\" }>): Promise<void> {\n const controller: AbortController = new AbortController();\n aborts.set(req.id, controller);\n try {\n const text: string = await engine.complete(req.prompt, {\n ...req.options,\n signal: controller.signal,\n });\n reply({ op: \"generated\", id: req.id, text });\n } catch (err) {\n fail(req.id, err);\n } finally {\n aborts.delete(req.id);\n }\n}\n\nasync function handleStreamCompletion(\n req: Extract<WorkerRequest, { op: \"stream-completion\" }>\n): Promise<void> {\n const controller: AbortController = new AbortController();\n aborts.set(req.id, controller);\n try {\n for await (const chunk of engine.streamCompletion(req.prompt, {\n ...req.options,\n signal: controller.signal,\n })) {\n reply({ op: \"token\", id: req.id, chunk });\n }\n reply({ op: \"stream-end\", id: req.id });\n } catch (err) {\n fail(req.id, err);\n } finally {\n aborts.delete(req.id);\n }\n}\n\nasync function handleStream(req: Extract<WorkerRequest, { op: \"stream\" }>): Promise<void> {\n const controller: AbortController = new AbortController();\n aborts.set(req.id, controller);\n try {\n for await (const chunk of engine.stream(req.messages, {\n ...req.options,\n signal: controller.signal,\n })) {\n reply({ op: \"token\", id: req.id, chunk });\n }\n reply({ op: \"stream-end\", id: req.id });\n } catch (err) {\n fail(req.id, err);\n } finally {\n aborts.delete(req.id);\n }\n}\n\nasync function handleUnload(req: Extract<WorkerRequest, { op: \"unload\" }>): Promise<void> {\n try {\n await engine.unload();\n reply({ op: \"unloaded\", id: req.id });\n } catch (err) {\n fail(req.id, err);\n }\n}\n\nfunction handleIsLoaded(req: Extract<WorkerRequest, { op: \"isLoaded\" }>): void {\n reply({ op: \"is-loaded\", id: req.id, value: engine.isLoaded() });\n}\n\nfunction handleAbort(req: Extract<WorkerRequest, { op: \"abort\" }>): void {\n aborts.get(req.id)?.abort();\n}\n\nself.addEventListener(\"message\", (event: MessageEvent<WorkerRequest>): void => {\n const req = event.data;\n switch (req.op) {\n case \"load\":\n void handleLoad(req);\n return;\n case \"generate\":\n void handleGenerate(req);\n return;\n case \"stream\":\n void handleStream(req);\n return;\n case \"complete\":\n void handleComplete(req);\n return;\n case \"stream-completion\":\n void handleStreamCompletion(req);\n return;\n case \"unload\":\n void handleUnload(req);\n return;\n case \"isLoaded\":\n handleIsLoaded(req);\n return;\n case \"abort\":\n handleAbort(req);\n return;\n }\n});\n"],"names":["engine"],"mappings":"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"}