@eclipse-docks/extension-in-browser-ml 0.7.71 → 0.7.72

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.
@@ -1,4 +1,4 @@
1
- import { n as MLModel, r as MLTask, t as inBrowserMLService } from "./in-browser-ml-service-BL4aSLZ-.js";
1
+ import { n as MLModel, r as MLTask, t as inBrowserMLService } from "./in-browser-ml-service-18Xw5br1.js";
2
2
  import { contributionRegistry, createLogger, registerAll, rootContext, taskService, toastError } from "@eclipse-docks/core";
3
3
  import { signal } from "@eclipse-docks/core/externals/lit";
4
4
  //#region src/media-viewer-toolbar-contribution.ts
@@ -124,4 +124,4 @@ var in_browser_ml_extension_default = ({}) => {
124
124
  //#endregion
125
125
  export { in_browser_ml_extension_default as default };
126
126
 
127
- //# sourceMappingURL=in-browser-ml-extension-C4QPEYEY.js.map
127
+ //# sourceMappingURL=in-browser-ml-extension-B_JuNITB.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"in-browser-ml-extension-C4QPEYEY.js","names":[],"sources":["../src/media-viewer-toolbar-contribution.ts","../src/in-browser-ml-extension.ts"],"sourcesContent":["import { contributionRegistry, registerAll, type ExecutionContext, taskService, toastError, createLogger } from \"@eclipse-docks/core\";\nimport { signal } from \"@eclipse-docks/core/externals/lit\";\nimport { inBrowserMLService } from \"./in-browser-ml-service\";\nimport { MLTask, MLModel } from \"./ml-models\";\n\nconst logger = createLogger(\"InBrowserML\");\n\nconst MEDIA_VIEWER_TOOLBAR_TARGET = \"toolbar:media-viewer\";\n\nconst detectionRunningSignal = signal(false);\nconst segmentationRunningSignal = signal(false);\n\nfunction isMlRunning(): boolean {\n return detectionRunningSignal.get() || segmentationRunningSignal.get();\n}\n\ntype BboxOverlay = { type: 'bbox'; left: number; top: number; width: number; height: number; label?: string; color?: string };\ntype MaskOverlay = { type: 'mask'; dataUrl: string; label?: string; color?: string };\ntype MediaViewerOverlay = BboxOverlay | MaskOverlay;\n\nfunction isMediaViewerWithImage(part: unknown): part is {\n getMediaUrl(): string | undefined;\n getIsImage(): boolean;\n getImageDimensions(): { width: number; height: number };\n setOverlays(overlays: MediaViewerOverlay[]): void;\n} {\n if (!part || typeof (part as any).getMediaUrl !== \"function\") return false;\n return (part as any).getIsImage?.() === true;\n}\n\nconst CATEGORY_PALETTE = [\n '#0d6efd', '#dc3545', '#198754', '#fd7e14', '#6f42c1',\n '#20c997', '#e83e8c', '#ffc107', '#0dcaf0', '#6c757d'\n];\n\nfunction categoryToColor(category: string, palette: string[]): string {\n let n = 0;\n for (let i = 0; i < category.length; i++) n = (n * 31 + category.charCodeAt(i)) >>> 0;\n return palette[n % palette.length];\n}\n\nfunction detectionResultsToOverlays(\n results: Array<{ label: string; score: number; box: { xmin: number; ymin: number; xmax: number; ymax: number } }>,\n imageWidth: number,\n imageHeight: number\n): BboxOverlay[] {\n const w = imageWidth || 1;\n const h = imageHeight || 1;\n return results.map((r) => ({\n type: 'bbox' as const,\n left: r.box.xmin / w,\n top: r.box.ymin / h,\n width: (r.box.xmax - r.box.xmin) / w,\n height: (r.box.ymax - r.box.ymin) / h,\n label: `${r.label} ${(r.score * 100).toFixed(0)}%`,\n color: categoryToColor(r.label, CATEGORY_PALETTE)\n }));\n}\n\nregisterAll({\n command: {\n id: \"detect_objects_in_current_image\",\n name: \"Detect objects\",\n description: \"Runs object detection on the image currently open in the media viewer.\",\n parameters: [],\n output: []\n },\n handler: {\n execute: async (context: ExecutionContext) => {\n const part = context.activeEditor;\n if (!isMediaViewerWithImage(part)) {\n return { error: \"No image open in the media viewer.\" };\n }\n const url = part.getMediaUrl();\n if (!url) {\n return { error: \"No image URL available.\" };\n }\n try {\n detectionRunningSignal.set(true);\n await taskService.runAsync(\"Detecting objects\", async () => {\n const detector = await inBrowserMLService.getPipeline(\n MLTask.OBJECT_DETECTION,\n MLModel.OBJECT_DETECTION_YOLOV9\n );\n const results = (await detector(url)) as Array<{\n label: string;\n score: number;\n box: { xmin: number; ymin: number; xmax: number; ymax: number };\n }>;\n const { width, height } = part.getImageDimensions();\n part.setOverlays(detectionResultsToOverlays(results, width, height));\n });\n return { ok: true };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(`Object detection failed: ${msg}`);\n toastError(msg);\n return { error: msg };\n } finally {\n detectionRunningSignal.set(false);\n }\n }\n }\n});\n\nregisterAll({\n command: {\n id: \"segment_image_in_current_image\",\n name: \"Segment\",\n description: \"Runs image segmentation on the image currently open in the media viewer.\",\n parameters: [],\n output: []\n },\n handler: {\n execute: async (context: ExecutionContext) => {\n const part = context.activeEditor;\n if (!isMediaViewerWithImage(part)) {\n return { error: \"No image open in the media viewer.\" };\n }\n const url = part.getMediaUrl();\n if (!url) {\n return { error: \"No image URL available.\" };\n }\n try {\n segmentationRunningSignal.set(true);\n await taskService.runAsync(\"Segmenting image\", async () => {\n const segmenter = await inBrowserMLService.getPipeline(\n MLTask.IMAGE_SEGMENTATION,\n MLModel.IMAGE_SEGMENTATION\n );\n const results = (await segmenter(url, { taskType: \"image-segmentation\" })) as MaskOverlay[];\n part.setOverlays(results);\n });\n return { ok: true };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(`Segmentation failed: ${msg}`);\n toastError(msg);\n return { error: msg };\n } finally {\n segmentationRunningSignal.set(false);\n }\n }\n }\n});\n\ncontributionRegistry.registerContribution(MEDIA_VIEWER_TOOLBAR_TARGET, {\n label: \"Detect objects\",\n icon: \"magnifying-glass\",\n command: \"detect_objects_in_current_image\",\n disabled: () => isMlRunning()\n});\n\ncontributionRegistry.registerContribution(MEDIA_VIEWER_TOOLBAR_TARGET, {\n label: \"Segment\",\n icon: \"scissors\",\n command: \"segment_image_in_current_image\",\n disabled: () => isMlRunning()\n});\n","import { rootContext } from \"@eclipse-docks/core\";\nimport { inBrowserMLService } from \"./in-browser-ml-service\";\nimport \"./media-viewer-toolbar-contribution\";\n//import \"./ml-commands\";\n\nexport default ({ }: any) => {\n // Register the in-browser ML service in the dependency injection context\n rootContext.put(\"inBrowserMLService\", inBrowserMLService);\n // ML commands are registered via side-effect import of ml-commands.ts\n}\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"in-browser-ml-extension-B_JuNITB.js","names":[],"sources":["../src/media-viewer-toolbar-contribution.ts","../src/in-browser-ml-extension.ts"],"sourcesContent":["import { contributionRegistry, registerAll, type ExecutionContext, taskService, toastError, createLogger } from \"@eclipse-docks/core\";\nimport { signal } from \"@eclipse-docks/core/externals/lit\";\nimport { inBrowserMLService } from \"./in-browser-ml-service\";\nimport { MLTask, MLModel } from \"./ml-models\";\n\nconst logger = createLogger(\"InBrowserML\");\n\nconst MEDIA_VIEWER_TOOLBAR_TARGET = \"toolbar:media-viewer\";\n\nconst detectionRunningSignal = signal(false);\nconst segmentationRunningSignal = signal(false);\n\nfunction isMlRunning(): boolean {\n return detectionRunningSignal.get() || segmentationRunningSignal.get();\n}\n\ntype BboxOverlay = { type: 'bbox'; left: number; top: number; width: number; height: number; label?: string; color?: string };\ntype MaskOverlay = { type: 'mask'; dataUrl: string; label?: string; color?: string };\ntype MediaViewerOverlay = BboxOverlay | MaskOverlay;\n\nfunction isMediaViewerWithImage(part: unknown): part is {\n getMediaUrl(): string | undefined;\n getIsImage(): boolean;\n getImageDimensions(): { width: number; height: number };\n setOverlays(overlays: MediaViewerOverlay[]): void;\n} {\n if (!part || typeof (part as any).getMediaUrl !== \"function\") return false;\n return (part as any).getIsImage?.() === true;\n}\n\nconst CATEGORY_PALETTE = [\n '#0d6efd', '#dc3545', '#198754', '#fd7e14', '#6f42c1',\n '#20c997', '#e83e8c', '#ffc107', '#0dcaf0', '#6c757d'\n];\n\nfunction categoryToColor(category: string, palette: string[]): string {\n let n = 0;\n for (let i = 0; i < category.length; i++) n = (n * 31 + category.charCodeAt(i)) >>> 0;\n return palette[n % palette.length];\n}\n\nfunction detectionResultsToOverlays(\n results: Array<{ label: string; score: number; box: { xmin: number; ymin: number; xmax: number; ymax: number } }>,\n imageWidth: number,\n imageHeight: number\n): BboxOverlay[] {\n const w = imageWidth || 1;\n const h = imageHeight || 1;\n return results.map((r) => ({\n type: 'bbox' as const,\n left: r.box.xmin / w,\n top: r.box.ymin / h,\n width: (r.box.xmax - r.box.xmin) / w,\n height: (r.box.ymax - r.box.ymin) / h,\n label: `${r.label} ${(r.score * 100).toFixed(0)}%`,\n color: categoryToColor(r.label, CATEGORY_PALETTE)\n }));\n}\n\nregisterAll({\n command: {\n id: \"detect_objects_in_current_image\",\n name: \"Detect objects\",\n description: \"Runs object detection on the image currently open in the media viewer.\",\n parameters: [],\n output: []\n },\n handler: {\n execute: async (context: ExecutionContext) => {\n const part = context.activeEditor;\n if (!isMediaViewerWithImage(part)) {\n return { error: \"No image open in the media viewer.\" };\n }\n const url = part.getMediaUrl();\n if (!url) {\n return { error: \"No image URL available.\" };\n }\n try {\n detectionRunningSignal.set(true);\n await taskService.runAsync(\"Detecting objects\", async () => {\n const detector = await inBrowserMLService.getPipeline(\n MLTask.OBJECT_DETECTION,\n MLModel.OBJECT_DETECTION_YOLOV9\n );\n const results = (await detector(url)) as Array<{\n label: string;\n score: number;\n box: { xmin: number; ymin: number; xmax: number; ymax: number };\n }>;\n const { width, height } = part.getImageDimensions();\n part.setOverlays(detectionResultsToOverlays(results, width, height));\n });\n return { ok: true };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(`Object detection failed: ${msg}`);\n toastError(msg);\n return { error: msg };\n } finally {\n detectionRunningSignal.set(false);\n }\n }\n }\n});\n\nregisterAll({\n command: {\n id: \"segment_image_in_current_image\",\n name: \"Segment\",\n description: \"Runs image segmentation on the image currently open in the media viewer.\",\n parameters: [],\n output: []\n },\n handler: {\n execute: async (context: ExecutionContext) => {\n const part = context.activeEditor;\n if (!isMediaViewerWithImage(part)) {\n return { error: \"No image open in the media viewer.\" };\n }\n const url = part.getMediaUrl();\n if (!url) {\n return { error: \"No image URL available.\" };\n }\n try {\n segmentationRunningSignal.set(true);\n await taskService.runAsync(\"Segmenting image\", async () => {\n const segmenter = await inBrowserMLService.getPipeline(\n MLTask.IMAGE_SEGMENTATION,\n MLModel.IMAGE_SEGMENTATION\n );\n const results = (await segmenter(url, { taskType: \"image-segmentation\" })) as MaskOverlay[];\n part.setOverlays(results);\n });\n return { ok: true };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(`Segmentation failed: ${msg}`);\n toastError(msg);\n return { error: msg };\n } finally {\n segmentationRunningSignal.set(false);\n }\n }\n }\n});\n\ncontributionRegistry.registerContribution(MEDIA_VIEWER_TOOLBAR_TARGET, {\n label: \"Detect objects\",\n icon: \"magnifying-glass\",\n command: \"detect_objects_in_current_image\",\n disabled: () => isMlRunning()\n});\n\ncontributionRegistry.registerContribution(MEDIA_VIEWER_TOOLBAR_TARGET, {\n label: \"Segment\",\n icon: \"scissors\",\n command: \"segment_image_in_current_image\",\n disabled: () => isMlRunning()\n});\n","import { rootContext } from \"@eclipse-docks/core\";\nimport { inBrowserMLService } from \"./in-browser-ml-service\";\nimport \"./media-viewer-toolbar-contribution\";\n//import \"./ml-commands\";\n\nexport default ({ }: any) => {\n // Register the in-browser ML service in the dependency injection context\n rootContext.put(\"inBrowserMLService\", inBrowserMLService);\n // ML commands are registered via side-effect import of ml-commands.ts\n}\n\n"],"mappings":"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"}
@@ -189,7 +189,7 @@ function getModelForTask(task) {
189
189
  //#endregion
190
190
  //#region src/ml-worker.ts?worker
191
191
  function WorkerWrapper(options) {
192
- return new Worker("/assets/ml-worker-CpR18FZQ.js", { name: options?.name });
192
+ return new Worker("/assets/ml-worker-Cxga53IO.js", { name: options?.name });
193
193
  }
194
194
  //#endregion
195
195
  //#region src/in-browser-ml-service.ts
@@ -308,4 +308,4 @@ var inBrowserMLService = class InBrowserMLService {
308
308
  //#endregion
309
309
  export { getModelForTask as i, MLModel as n, MLTask as r, inBrowserMLService as t };
310
310
 
311
- //# sourceMappingURL=in-browser-ml-service-BL4aSLZ-.js.map
311
+ //# sourceMappingURL=in-browser-ml-service-18Xw5br1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"in-browser-ml-service-BL4aSLZ-.js","names":[],"sources":["../src/ml-models.ts","../src/in-browser-ml-service.ts"],"sourcesContent":["/**\n * Supported in-browser ML models for specific tasks\n * These models are optimized for browser use and are well-tested with transformers.js\n * All models use the Xenova quantized versions for optimal browser performance\n */\nexport enum MLModel {\n /**\n * Zero-shot classification model for text classification tasks\n * Model: distilbert-base-uncased-mnli\n * Size: ~60-80MB quantized\n * Use case: Tool detection, text classification\n */\n ZERO_SHOT_CLASSIFICATION = 'Xenova/distilbert-base-uncased-mnli',\n \n /**\n * Feature extraction model for embeddings\n * Model: all-MiniLM-L6-v2\n * Size: ~23MB quantized\n * Use case: Text embeddings, semantic search\n */\n FEATURE_EXTRACTION = 'Xenova/all-MiniLM-L6-v2',\n \n /**\n * Text classification model\n * Model: distilbert-base-uncased-finetuned-sst-2-english\n * Size: ~67MB quantized\n * Use case: Sentiment analysis, text classification\n */\n TEXT_CLASSIFICATION = 'Xenova/distilbert-base-uncased-finetuned-sst-2-english',\n \n /**\n * Question answering model\n * Model: distilbert-base-cased-distilled-squad\n * Size: ~125MB quantized\n * Use case: Question answering, reading comprehension\n */\n QUESTION_ANSWERING = 'Xenova/distilbert-base-cased-distilled-squad',\n \n /**\n * Summarization model\n * Model: distilbart-cnn-6-6\n * Size: ~300MB quantized\n * Use case: Text summarization\n */\n SUMMARIZATION = 'Xenova/distilbart-cnn-6-6',\n \n /**\n * Translation model (English to French)\n * Model: opus-mt-en-fr\n * Size: ~200MB quantized\n * Use case: Machine translation\n */\n TRANSLATION_EN_FR = 'Xenova/opus-mt-en-fr',\n \n /**\n * Fill-mask model\n * Model: distilbert-base-uncased\n * Size: ~67MB quantized\n * Use case: Masked language modeling, text completion\n */\n FILL_MASK = 'Xenova/distilbert-base-uncased',\n \n /**\n * Sentence similarity model\n * Model: all-MiniLM-L6-v2 (same as feature extraction)\n * Size: ~23MB quantized\n * Use case: Sentence similarity, semantic search\n */\n SENTENCE_SIMILARITY = 'Xenova/all-MiniLM-L6-v2',\n \n /**\n * Named entity recognition (token classification)\n * Model: distilbert-base-uncased-finetuned-conll03-english\n * Size: ~67MB quantized\n * Use case: Named entity recognition, token classification\n */\n TOKEN_CLASSIFICATION = 'Xenova/distilbert-base-uncased-finetuned-conll03-english',\n \n /**\n * Image classification model\n * Model: vit-base-patch16-224\n * Size: ~330MB quantized\n * Use case: Image classification\n */\n IMAGE_CLASSIFICATION = 'Xenova/vit-base-patch16-224',\n \n /**\n * Object detection model\n * Model: detr-resnet-50\n * Size: ~160MB quantized\n * Use case: Object detection in images\n */\n OBJECT_DETECTION = 'Xenova/detr-resnet-50',\n\n /**\n * Object detection model (YOLO-style, default for YOLO flows)\n * Uses YOLOS-tiny (public, no auth). For YOLOv9-web see OBJECT_DETECTION_YOLOV9_WEB (may require HF token).\n */\n OBJECT_DETECTION_YOLOV9 = 'Xenova/yolos-tiny',\n\n /**\n * Object detection model (YOLOv9 web). May require Hugging Face token if repo is gated.\n */\n OBJECT_DETECTION_YOLOV9_WEB = 'Xenova/yolov9-web',\n\n /**\n * Object detection model (YOLOS tiny)\n * Model: yolos-tiny\n * Use case: Lightweight object detection, ViT-based\n */\n OBJECT_DETECTION_YOLOS_TINY = 'Xenova/yolos-tiny',\n\n /**\n * Object detection model (YOLOS small)\n * Model: yolos-small\n * Use case: Object detection, higher accuracy than tiny\n */\n OBJECT_DETECTION_YOLOS_SMALL = 'Xenova/yolos-small',\n\n /**\n * Object detection model (YOLOS base)\n * Model: yolos-base\n * Use case: Object detection, higher accuracy\n */\n OBJECT_DETECTION_YOLOS_BASE = 'Xenova/yolos-base',\n\n /**\n * Object detection model (GELAN / YOLOv9-based). Not supported by pipeline() API.\n * Use OBJECT_DETECTION_YOLOS_* or OBJECT_DETECTION (DETR) instead.\n */\n OBJECT_DETECTION_GELAN = 'Xenova/gelan-c_all',\n\n /**\n * Image segmentation model (panoptic)\n * Model: detr-resnet-50-panoptic\n * Use case: Segment objects in images, each with label and mask\n */\n IMAGE_SEGMENTATION = 'Xenova/detr-resnet-50-panoptic',\n\n /**\n * Automatic speech recognition model\n * Model: whisper-tiny\n * Size: ~75MB quantized\n * Use case: Speech-to-text transcription\n */\n AUTOMATIC_SPEECH_RECOGNITION = 'Xenova/whisper-tiny',\n \n /**\n * Audio classification model\n * Model: wav2vec2-base\n * Size: ~95MB quantized\n * Use case: Audio classification, sound recognition\n */\n AUDIO_CLASSIFICATION = 'Xenova/wav2vec2-base',\n}\n\n/**\n * ML task types supported by transformers.js\n * These correspond to pipeline types available in transformers.js\n */\nexport enum MLTask {\n ZERO_SHOT_CLASSIFICATION = 'zero-shot-classification',\n FEATURE_EXTRACTION = 'feature-extraction',\n TEXT_CLASSIFICATION = 'text-classification',\n SENTIMENT_ANALYSIS = 'sentiment-analysis',\n QUESTION_ANSWERING = 'question-answering',\n SUMMARIZATION = 'summarization',\n TRANSLATION = 'translation',\n FILL_MASK = 'fill-mask',\n SENTENCE_SIMILARITY = 'sentence-similarity',\n TOKEN_CLASSIFICATION = 'token-classification',\n IMAGE_CLASSIFICATION = 'image-classification',\n OBJECT_DETECTION = 'object-detection',\n AUTOMATIC_SPEECH_RECOGNITION = 'automatic-speech-recognition',\n AUDIO_CLASSIFICATION = 'audio-classification',\n IMAGE_TO_TEXT = 'image-to-text',\n TEXT_TO_IMAGE = 'text-to-image',\n IMAGE_SEGMENTATION = 'image-segmentation',\n DEPTH_ESTIMATION = 'depth-estimation',\n}\n\n/**\n * Get the recommended model for a specific task\n * Returns the default model for the task, or null if no default is specified\n */\nexport function getModelForTask(task: MLTask): MLModel | null {\n switch (task) {\n case MLTask.ZERO_SHOT_CLASSIFICATION:\n return MLModel.ZERO_SHOT_CLASSIFICATION;\n case MLTask.FEATURE_EXTRACTION:\n return MLModel.FEATURE_EXTRACTION;\n case MLTask.TEXT_CLASSIFICATION:\n case MLTask.SENTIMENT_ANALYSIS:\n return MLModel.TEXT_CLASSIFICATION;\n case MLTask.QUESTION_ANSWERING:\n return MLModel.QUESTION_ANSWERING;\n case MLTask.SUMMARIZATION:\n return MLModel.SUMMARIZATION;\n case MLTask.TRANSLATION:\n return MLModel.TRANSLATION_EN_FR;\n case MLTask.FILL_MASK:\n return MLModel.FILL_MASK;\n case MLTask.SENTENCE_SIMILARITY:\n return MLModel.SENTENCE_SIMILARITY;\n case MLTask.TOKEN_CLASSIFICATION:\n return MLModel.TOKEN_CLASSIFICATION;\n case MLTask.IMAGE_CLASSIFICATION:\n return MLModel.IMAGE_CLASSIFICATION;\n case MLTask.OBJECT_DETECTION:\n return MLModel.OBJECT_DETECTION;\n case MLTask.IMAGE_SEGMENTATION:\n return MLModel.IMAGE_SEGMENTATION;\n case MLTask.AUTOMATIC_SPEECH_RECOGNITION:\n return MLModel.AUTOMATIC_SPEECH_RECOGNITION;\n case MLTask.AUDIO_CLASSIFICATION:\n return MLModel.AUDIO_CLASSIFICATION;\n default:\n return null;\n }\n}\n\n","import { createLogger } from '@eclipse-docks/core';\nimport { MLTask, MLModel, getModelForTask } from './ml-models';\nimport MLWorker from './ml-worker?worker';\n\nconst logger = createLogger('InBrowserMLService');\n\ntype RunResolver = { resolve: (value: unknown) => void; reject: (reason: unknown) => void };\n\n/**\n * Service for in-browser machine learning tasks using transformers.js in a Web Worker.\n * Keeps pipeline loading and inference off the main thread so the UI does not freeze.\n */\nexport class InBrowserMLService {\n private static instance: InBrowserMLService;\n private worker: Worker | null = null;\n private pendingLoad: Map<string, Promise<void>> = new Map();\n private runRequestId = 0;\n private runPending: Map<number, RunResolver> = new Map();\n\n private constructor() {}\n\n static getInstance(): InBrowserMLService {\n if (!InBrowserMLService.instance) {\n InBrowserMLService.instance = new InBrowserMLService();\n }\n return InBrowserMLService.instance;\n }\n\n private getWorker(): Worker {\n if (this.worker) return this.worker;\n this.worker = new MLWorker();\n this.worker.onmessage = (e: MessageEvent) => {\n const { type, requestId, result, error } = e.data ?? {};\n if (type === 'runResult') {\n const resolver = requestId != null ? this.runPending.get(requestId) : undefined;\n if (resolver) {\n this.runPending.delete(requestId);\n if (error != null) resolver.reject(new Error(error));\n else resolver.resolve(result);\n }\n }\n };\n this.worker.onerror = (err) => logger.error(`ML worker error: ${err.message ?? String(err)}`);\n return this.worker;\n }\n\n /**\n * Set Hugging Face token for authenticated model access (forwarded to worker).\n */\n setAuthToken(token: string | null): void {\n try {\n this.getWorker().postMessage({ type: 'setAuthToken', token });\n if (token?.trim()) logger.info('Hugging Face token set for authenticated model access');\n } catch (e) {\n logger.warn(`Failed to set auth token: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n\n private ensurePipelineLoaded(pipelineKey: string, task: string, model: string, options: Record<string, unknown>): Promise<void> {\n let p = this.pendingLoad.get(pipelineKey);\n if (p) return p;\n p = new Promise((resolve, reject) => {\n const handler = (e: MessageEvent) => {\n const data = e.data ?? {};\n if (data.type !== 'loadResult' || data.pipelineKey !== pipelineKey) return;\n this.getWorker().removeEventListener('message', handler);\n this.pendingLoad.delete(pipelineKey);\n if (data.error) reject(new Error(data.error));\n else resolve();\n };\n this.getWorker().addEventListener('message', handler);\n this.getWorker().postMessage({ type: 'load', pipelineKey, task, model, options });\n });\n this.pendingLoad.set(pipelineKey, p);\n return p;\n }\n\n /**\n * Get a callable pipeline for a specific task and model. Pipeline runs in a Web Worker.\n */\n async getPipeline(\n task: MLTask | string,\n modelName: MLModel | string,\n options: Record<string, unknown> = {}\n ): Promise<(input: unknown, runOptions?: Record<string, unknown>) => Promise<unknown>> {\n const model = modelName || (typeof task !== 'string' ? getModelForTask(task as MLTask) : undefined);\n if (!model) throw new Error('Model is required');\n const taskStr = typeof task === 'string' ? task : task;\n const modelStr = typeof model === 'string' ? model : model;\n const pipelineKey = `${taskStr}:${modelStr}`;\n\n const loadOptions: Record<string, unknown> = { quantized: true, ...options };\n if (options.device === \"webgpu\" && !('gpu' in navigator)) {\n loadOptions.device = undefined;\n }\n await this.ensurePipelineLoaded(pipelineKey, taskStr, modelStr, loadOptions);\n\n return (input: unknown, runOptions?: Record<string, unknown>) => {\n const requestId = ++this.runRequestId;\n return new Promise<unknown>((resolve, reject) => {\n this.runPending.set(requestId, { resolve, reject });\n this.getWorker().postMessage({ type: 'run', requestId, pipelineKey, input, options: runOptions });\n });\n };\n }\n\n clearPipeline(task: MLTask | string, modelName: MLModel | string): void {\n const taskStr = typeof task === 'string' ? task : task;\n const modelStr = typeof modelName === 'string' ? modelName : modelName;\n const pipelineKey = `${taskStr}:${modelStr}`;\n this.pendingLoad.delete(pipelineKey);\n this.getWorker().postMessage({ type: 'clear', pipelineKey });\n }\n\n clearAllPipelines(): void {\n this.pendingLoad.clear();\n if (this.worker) this.worker.postMessage({ type: 'clearAll' });\n }\n}\n\nexport const inBrowserMLService = InBrowserMLService.getInstance();\n"],"mappings":"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"}
1
+ {"version":3,"file":"in-browser-ml-service-18Xw5br1.js","names":[],"sources":["../src/ml-models.ts","../src/in-browser-ml-service.ts"],"sourcesContent":["/**\n * Supported in-browser ML models for specific tasks\n * These models are optimized for browser use and are well-tested with transformers.js\n * All models use the Xenova quantized versions for optimal browser performance\n */\nexport enum MLModel {\n /**\n * Zero-shot classification model for text classification tasks\n * Model: distilbert-base-uncased-mnli\n * Size: ~60-80MB quantized\n * Use case: Tool detection, text classification\n */\n ZERO_SHOT_CLASSIFICATION = 'Xenova/distilbert-base-uncased-mnli',\n \n /**\n * Feature extraction model for embeddings\n * Model: all-MiniLM-L6-v2\n * Size: ~23MB quantized\n * Use case: Text embeddings, semantic search\n */\n FEATURE_EXTRACTION = 'Xenova/all-MiniLM-L6-v2',\n \n /**\n * Text classification model\n * Model: distilbert-base-uncased-finetuned-sst-2-english\n * Size: ~67MB quantized\n * Use case: Sentiment analysis, text classification\n */\n TEXT_CLASSIFICATION = 'Xenova/distilbert-base-uncased-finetuned-sst-2-english',\n \n /**\n * Question answering model\n * Model: distilbert-base-cased-distilled-squad\n * Size: ~125MB quantized\n * Use case: Question answering, reading comprehension\n */\n QUESTION_ANSWERING = 'Xenova/distilbert-base-cased-distilled-squad',\n \n /**\n * Summarization model\n * Model: distilbart-cnn-6-6\n * Size: ~300MB quantized\n * Use case: Text summarization\n */\n SUMMARIZATION = 'Xenova/distilbart-cnn-6-6',\n \n /**\n * Translation model (English to French)\n * Model: opus-mt-en-fr\n * Size: ~200MB quantized\n * Use case: Machine translation\n */\n TRANSLATION_EN_FR = 'Xenova/opus-mt-en-fr',\n \n /**\n * Fill-mask model\n * Model: distilbert-base-uncased\n * Size: ~67MB quantized\n * Use case: Masked language modeling, text completion\n */\n FILL_MASK = 'Xenova/distilbert-base-uncased',\n \n /**\n * Sentence similarity model\n * Model: all-MiniLM-L6-v2 (same as feature extraction)\n * Size: ~23MB quantized\n * Use case: Sentence similarity, semantic search\n */\n SENTENCE_SIMILARITY = 'Xenova/all-MiniLM-L6-v2',\n \n /**\n * Named entity recognition (token classification)\n * Model: distilbert-base-uncased-finetuned-conll03-english\n * Size: ~67MB quantized\n * Use case: Named entity recognition, token classification\n */\n TOKEN_CLASSIFICATION = 'Xenova/distilbert-base-uncased-finetuned-conll03-english',\n \n /**\n * Image classification model\n * Model: vit-base-patch16-224\n * Size: ~330MB quantized\n * Use case: Image classification\n */\n IMAGE_CLASSIFICATION = 'Xenova/vit-base-patch16-224',\n \n /**\n * Object detection model\n * Model: detr-resnet-50\n * Size: ~160MB quantized\n * Use case: Object detection in images\n */\n OBJECT_DETECTION = 'Xenova/detr-resnet-50',\n\n /**\n * Object detection model (YOLO-style, default for YOLO flows)\n * Uses YOLOS-tiny (public, no auth). For YOLOv9-web see OBJECT_DETECTION_YOLOV9_WEB (may require HF token).\n */\n OBJECT_DETECTION_YOLOV9 = 'Xenova/yolos-tiny',\n\n /**\n * Object detection model (YOLOv9 web). May require Hugging Face token if repo is gated.\n */\n OBJECT_DETECTION_YOLOV9_WEB = 'Xenova/yolov9-web',\n\n /**\n * Object detection model (YOLOS tiny)\n * Model: yolos-tiny\n * Use case: Lightweight object detection, ViT-based\n */\n OBJECT_DETECTION_YOLOS_TINY = 'Xenova/yolos-tiny',\n\n /**\n * Object detection model (YOLOS small)\n * Model: yolos-small\n * Use case: Object detection, higher accuracy than tiny\n */\n OBJECT_DETECTION_YOLOS_SMALL = 'Xenova/yolos-small',\n\n /**\n * Object detection model (YOLOS base)\n * Model: yolos-base\n * Use case: Object detection, higher accuracy\n */\n OBJECT_DETECTION_YOLOS_BASE = 'Xenova/yolos-base',\n\n /**\n * Object detection model (GELAN / YOLOv9-based). Not supported by pipeline() API.\n * Use OBJECT_DETECTION_YOLOS_* or OBJECT_DETECTION (DETR) instead.\n */\n OBJECT_DETECTION_GELAN = 'Xenova/gelan-c_all',\n\n /**\n * Image segmentation model (panoptic)\n * Model: detr-resnet-50-panoptic\n * Use case: Segment objects in images, each with label and mask\n */\n IMAGE_SEGMENTATION = 'Xenova/detr-resnet-50-panoptic',\n\n /**\n * Automatic speech recognition model\n * Model: whisper-tiny\n * Size: ~75MB quantized\n * Use case: Speech-to-text transcription\n */\n AUTOMATIC_SPEECH_RECOGNITION = 'Xenova/whisper-tiny',\n \n /**\n * Audio classification model\n * Model: wav2vec2-base\n * Size: ~95MB quantized\n * Use case: Audio classification, sound recognition\n */\n AUDIO_CLASSIFICATION = 'Xenova/wav2vec2-base',\n}\n\n/**\n * ML task types supported by transformers.js\n * These correspond to pipeline types available in transformers.js\n */\nexport enum MLTask {\n ZERO_SHOT_CLASSIFICATION = 'zero-shot-classification',\n FEATURE_EXTRACTION = 'feature-extraction',\n TEXT_CLASSIFICATION = 'text-classification',\n SENTIMENT_ANALYSIS = 'sentiment-analysis',\n QUESTION_ANSWERING = 'question-answering',\n SUMMARIZATION = 'summarization',\n TRANSLATION = 'translation',\n FILL_MASK = 'fill-mask',\n SENTENCE_SIMILARITY = 'sentence-similarity',\n TOKEN_CLASSIFICATION = 'token-classification',\n IMAGE_CLASSIFICATION = 'image-classification',\n OBJECT_DETECTION = 'object-detection',\n AUTOMATIC_SPEECH_RECOGNITION = 'automatic-speech-recognition',\n AUDIO_CLASSIFICATION = 'audio-classification',\n IMAGE_TO_TEXT = 'image-to-text',\n TEXT_TO_IMAGE = 'text-to-image',\n IMAGE_SEGMENTATION = 'image-segmentation',\n DEPTH_ESTIMATION = 'depth-estimation',\n}\n\n/**\n * Get the recommended model for a specific task\n * Returns the default model for the task, or null if no default is specified\n */\nexport function getModelForTask(task: MLTask): MLModel | null {\n switch (task) {\n case MLTask.ZERO_SHOT_CLASSIFICATION:\n return MLModel.ZERO_SHOT_CLASSIFICATION;\n case MLTask.FEATURE_EXTRACTION:\n return MLModel.FEATURE_EXTRACTION;\n case MLTask.TEXT_CLASSIFICATION:\n case MLTask.SENTIMENT_ANALYSIS:\n return MLModel.TEXT_CLASSIFICATION;\n case MLTask.QUESTION_ANSWERING:\n return MLModel.QUESTION_ANSWERING;\n case MLTask.SUMMARIZATION:\n return MLModel.SUMMARIZATION;\n case MLTask.TRANSLATION:\n return MLModel.TRANSLATION_EN_FR;\n case MLTask.FILL_MASK:\n return MLModel.FILL_MASK;\n case MLTask.SENTENCE_SIMILARITY:\n return MLModel.SENTENCE_SIMILARITY;\n case MLTask.TOKEN_CLASSIFICATION:\n return MLModel.TOKEN_CLASSIFICATION;\n case MLTask.IMAGE_CLASSIFICATION:\n return MLModel.IMAGE_CLASSIFICATION;\n case MLTask.OBJECT_DETECTION:\n return MLModel.OBJECT_DETECTION;\n case MLTask.IMAGE_SEGMENTATION:\n return MLModel.IMAGE_SEGMENTATION;\n case MLTask.AUTOMATIC_SPEECH_RECOGNITION:\n return MLModel.AUTOMATIC_SPEECH_RECOGNITION;\n case MLTask.AUDIO_CLASSIFICATION:\n return MLModel.AUDIO_CLASSIFICATION;\n default:\n return null;\n }\n}\n\n","import { createLogger } from '@eclipse-docks/core';\nimport { MLTask, MLModel, getModelForTask } from './ml-models';\nimport MLWorker from './ml-worker?worker';\n\nconst logger = createLogger('InBrowserMLService');\n\ntype RunResolver = { resolve: (value: unknown) => void; reject: (reason: unknown) => void };\n\n/**\n * Service for in-browser machine learning tasks using transformers.js in a Web Worker.\n * Keeps pipeline loading and inference off the main thread so the UI does not freeze.\n */\nexport class InBrowserMLService {\n private static instance: InBrowserMLService;\n private worker: Worker | null = null;\n private pendingLoad: Map<string, Promise<void>> = new Map();\n private runRequestId = 0;\n private runPending: Map<number, RunResolver> = new Map();\n\n private constructor() {}\n\n static getInstance(): InBrowserMLService {\n if (!InBrowserMLService.instance) {\n InBrowserMLService.instance = new InBrowserMLService();\n }\n return InBrowserMLService.instance;\n }\n\n private getWorker(): Worker {\n if (this.worker) return this.worker;\n this.worker = new MLWorker();\n this.worker.onmessage = (e: MessageEvent) => {\n const { type, requestId, result, error } = e.data ?? {};\n if (type === 'runResult') {\n const resolver = requestId != null ? this.runPending.get(requestId) : undefined;\n if (resolver) {\n this.runPending.delete(requestId);\n if (error != null) resolver.reject(new Error(error));\n else resolver.resolve(result);\n }\n }\n };\n this.worker.onerror = (err) => logger.error(`ML worker error: ${err.message ?? String(err)}`);\n return this.worker;\n }\n\n /**\n * Set Hugging Face token for authenticated model access (forwarded to worker).\n */\n setAuthToken(token: string | null): void {\n try {\n this.getWorker().postMessage({ type: 'setAuthToken', token });\n if (token?.trim()) logger.info('Hugging Face token set for authenticated model access');\n } catch (e) {\n logger.warn(`Failed to set auth token: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n\n private ensurePipelineLoaded(pipelineKey: string, task: string, model: string, options: Record<string, unknown>): Promise<void> {\n let p = this.pendingLoad.get(pipelineKey);\n if (p) return p;\n p = new Promise((resolve, reject) => {\n const handler = (e: MessageEvent) => {\n const data = e.data ?? {};\n if (data.type !== 'loadResult' || data.pipelineKey !== pipelineKey) return;\n this.getWorker().removeEventListener('message', handler);\n this.pendingLoad.delete(pipelineKey);\n if (data.error) reject(new Error(data.error));\n else resolve();\n };\n this.getWorker().addEventListener('message', handler);\n this.getWorker().postMessage({ type: 'load', pipelineKey, task, model, options });\n });\n this.pendingLoad.set(pipelineKey, p);\n return p;\n }\n\n /**\n * Get a callable pipeline for a specific task and model. Pipeline runs in a Web Worker.\n */\n async getPipeline(\n task: MLTask | string,\n modelName: MLModel | string,\n options: Record<string, unknown> = {}\n ): Promise<(input: unknown, runOptions?: Record<string, unknown>) => Promise<unknown>> {\n const model = modelName || (typeof task !== 'string' ? getModelForTask(task as MLTask) : undefined);\n if (!model) throw new Error('Model is required');\n const taskStr = typeof task === 'string' ? task : task;\n const modelStr = typeof model === 'string' ? model : model;\n const pipelineKey = `${taskStr}:${modelStr}`;\n\n const loadOptions: Record<string, unknown> = { quantized: true, ...options };\n if (options.device === \"webgpu\" && !('gpu' in navigator)) {\n loadOptions.device = undefined;\n }\n await this.ensurePipelineLoaded(pipelineKey, taskStr, modelStr, loadOptions);\n\n return (input: unknown, runOptions?: Record<string, unknown>) => {\n const requestId = ++this.runRequestId;\n return new Promise<unknown>((resolve, reject) => {\n this.runPending.set(requestId, { resolve, reject });\n this.getWorker().postMessage({ type: 'run', requestId, pipelineKey, input, options: runOptions });\n });\n };\n }\n\n clearPipeline(task: MLTask | string, modelName: MLModel | string): void {\n const taskStr = typeof task === 'string' ? task : task;\n const modelStr = typeof modelName === 'string' ? modelName : modelName;\n const pipelineKey = `${taskStr}:${modelStr}`;\n this.pendingLoad.delete(pipelineKey);\n this.getWorker().postMessage({ type: 'clear', pipelineKey });\n }\n\n clearAllPipelines(): void {\n this.pendingLoad.clear();\n if (this.worker) this.worker.postMessage({ type: 'clearAll' });\n }\n}\n\nexport const inBrowserMLService = InBrowserMLService.getInstance();\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ extensionRegistry.registerExtension({
9
9
  id: pkg.name,
10
10
  name: t.EXT_IN_BROWSER_ML_NAME,
11
11
  description: t.EXT_IN_BROWSER_ML_DESC,
12
- loader: () => import("./in-browser-ml-extension-C4QPEYEY.js"),
12
+ loader: () => import("./in-browser-ml-extension-B_JuNITB.js"),
13
13
  icon: "brain",
14
14
  experimental: true
15
15
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eclipse-docks/extension-in-browser-ml",
3
- "version": "0.7.71",
3
+ "version": "0.7.72",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",