{"version":3,"sources":["../../src/adapters/transformers.ts"],"names":["transformersAdapter","pipeline","TextStreamer","env","_task","config","task","device","onProgress","model","dtype","fileTotals","pipe","info","file","total","totalBytes","size","input","options","result","serializeOutput","onChunk","streamer","text","value","obj","k","v"],"mappings":"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","file":"transformers.cjs","sourcesContent":["import type {\n  Device,\n  LoadedModel,\n  LoadProgressEvent,\n  ModelAdapter,\n  ModelAdapterFactory,\n} from '../core/types.js';\n\n// eslint-disable-next-line ts/no-explicit-any\ntype AnyPipeline = any;\n\n/**\n * Adapter for @huggingface/transformers v3+.\n *\n * @remarks\n * The adapter is instantiated INSIDE the worker via `create()`.\n * The heavy `@huggingface/transformers` library is dynamically imported\n * inside the worker, keeping the main thread bundle lightweight.\n *\n * @example\n * ```ts\n * import { createPool } from 'inferis-ml';\n * import { transformersAdapter } from 'inferis-ml/adapters/transformers';\n *\n * const pool = await createPool({ adapter: transformersAdapter() });\n * const model = await pool.load<number[][]>('feature-extraction', {\n *   model: 'mixedbread-ai/mxbai-embed-xsmall-v1',\n * });\n * ```\n */\nexport function transformersAdapter(): ModelAdapterFactory {\n  return {\n    name: 'transformers',\n\n    async create(): Promise<ModelAdapter> {\n      // Dynamic import — runs inside the worker only\n      // @ts-expect-error - optional peer dependency, resolved at runtime inside worker\n      const { pipeline, TextStreamer, env } = await import('@huggingface/transformers');\n\n      // Use ONNX WASM backend with optimizations\n      env.backends.onnx.wasm.proxy = false;\n\n      return {\n        name: 'transformers',\n\n        estimateMemoryMB(_task: string, config: Record<string, unknown>): number {\n          return (config.estimatedMemoryMB as number | undefined) ?? 100;\n        },\n\n        async load(\n          task: string,\n          config: Record<string, unknown>,\n          device: Device,\n          onProgress: (event: LoadProgressEvent) => void,\n        ): Promise<LoadedModel> {\n          const model = config.model as string;\n          const dtype = (config.dtype as string | undefined) ?? 'fp32';\n\n          const fileTotals = new Map<string, number>();\n\n          const pipe = await pipeline(task as Parameters<typeof pipeline>[0], model, {\n            device: device === 'webgpu' ? 'webgpu' : 'wasm',\n            dtype,\n            progress_callback: (info: Record<string, unknown>) => {\n              if (info.status === 'progress') {\n                const file = (info.file as string) ?? 'unknown';\n                const total = (info.total as number) ?? 0;\n                fileTotals.set(file, total);\n                onProgress({\n                  loaded: (info.loaded as number) ?? 0,\n                  phase: file,\n                  total,\n                });\n              }\n              else if (info.status === 'initiate') {\n                onProgress({ loaded: 0, phase: 'initiate', total: 0 });\n              }\n              else if (info.status === 'done') {\n                onProgress({ loaded: 1, phase: 'done', total: 1 });\n              }\n            },\n          });\n\n          let totalBytes = 0;\n          for (const size of fileTotals.values()) totalBytes += size;\n\n          return {\n            instance: pipe,\n            memoryMB: Math.ceil(totalBytes / (1024 * 1024)) || 100,\n          };\n        },\n\n        async run(model: LoadedModel, input: unknown, options?: unknown): Promise<unknown> {\n          const pipe = model.instance as AnyPipeline;\n          const result = Array.isArray(input)\n            ? await pipe(...(input as [unknown, ...unknown[]]), options ?? {})\n            : await pipe(input, options ?? {});\n          return serializeOutput(result);\n        },\n\n        async stream(\n          model: LoadedModel,\n          input: unknown,\n          onChunk: (chunk: unknown) => void,\n          options?: unknown,\n        ): Promise<void> {\n          const pipe = model.instance as AnyPipeline;\n\n          const streamer = new TextStreamer(pipe.tokenizer, {\n            callback_function: (text: string) => onChunk(text),\n            skip_prompt: true,\n            skip_special_tokens: true,\n          });\n\n          await pipe(input, {\n            ...(options as object ?? {}),\n            streamer,\n          });\n        },\n\n        async unload(model: LoadedModel): Promise<void> {\n          const pipe = model.instance as AnyPipeline;\n          await pipe.dispose?.();\n        },\n      };\n    },\n  };\n}\n\n/**\n * Recursively converts Tensor class instances and typed arrays to plain\n * structured-clone-compatible objects so they can cross the worker boundary.\n */\nexport function serializeOutput(value: unknown): unknown {\n  if (value === null || typeof value !== 'object')\n    return value;\n\n  if (Array.isArray(value))\n    return value.map(serializeOutput);\n\n  const obj = value as Record<string, unknown>;\n\n  if (typeof obj.data !== 'undefined' && Array.isArray(obj.dims)) {\n    return {\n      data: Array.from(obj.data as ArrayLike<number>),\n      dims: obj.dims as number[],\n      size: obj.size,\n      type: obj.type,\n    };\n  }\n\n  return Object.fromEntries(\n    Object.entries(obj).map(([k, v]) => [k, serializeOutput(v)]),\n  );\n}\n"]}