@framers/agentos-ext-ml-classifiers 0.1.0 → 0.3.1

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.
Files changed (83) hide show
  1. package/.github/workflows/ci.yml +20 -0
  2. package/.github/workflows/release.yml +37 -0
  3. package/.releaserc.json +9 -0
  4. package/LICENSE +96 -21
  5. package/README.md +72 -0
  6. package/dist/MLClassifierGuardrail.d.ts +88 -117
  7. package/dist/MLClassifierGuardrail.d.ts.map +1 -1
  8. package/dist/MLClassifierGuardrail.js +263 -264
  9. package/dist/MLClassifierGuardrail.js.map +1 -1
  10. package/dist/index.d.ts +16 -90
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +36 -309
  13. package/dist/index.js.map +1 -1
  14. package/dist/keyword-classifier.d.ts +26 -0
  15. package/dist/keyword-classifier.d.ts.map +1 -0
  16. package/dist/keyword-classifier.js +113 -0
  17. package/dist/keyword-classifier.js.map +1 -0
  18. package/dist/llm-classifier.d.ts +27 -0
  19. package/dist/llm-classifier.d.ts.map +1 -0
  20. package/dist/llm-classifier.js +129 -0
  21. package/dist/llm-classifier.js.map +1 -0
  22. package/dist/tools/ClassifyContentTool.d.ts +53 -80
  23. package/dist/tools/ClassifyContentTool.d.ts.map +1 -1
  24. package/dist/tools/ClassifyContentTool.js +52 -103
  25. package/dist/tools/ClassifyContentTool.js.map +1 -1
  26. package/dist/types.d.ts +77 -277
  27. package/dist/types.d.ts.map +1 -1
  28. package/dist/types.js +9 -55
  29. package/dist/types.js.map +1 -1
  30. package/package.json +10 -24
  31. package/scripts/fix-esm-imports.mjs +181 -0
  32. package/src/MLClassifierGuardrail.ts +306 -310
  33. package/src/index.ts +35 -339
  34. package/src/keyword-classifier.ts +130 -0
  35. package/src/llm-classifier.ts +163 -0
  36. package/src/tools/ClassifyContentTool.ts +75 -132
  37. package/src/types.ts +78 -325
  38. package/test/llm-tier.spec.ts +267 -0
  39. package/test/ml-classifiers.spec.ts +57 -0
  40. package/test/onnx-tier.spec.ts +255 -0
  41. package/test/tier-fallthrough.spec.ts +185 -0
  42. package/tsconfig.json +20 -0
  43. package/vitest.config.ts +35 -0
  44. package/dist/ClassifierOrchestrator.d.ts +0 -126
  45. package/dist/ClassifierOrchestrator.d.ts.map +0 -1
  46. package/dist/ClassifierOrchestrator.js +0 -239
  47. package/dist/ClassifierOrchestrator.js.map +0 -1
  48. package/dist/IContentClassifier.d.ts +0 -117
  49. package/dist/IContentClassifier.d.ts.map +0 -1
  50. package/dist/IContentClassifier.js +0 -22
  51. package/dist/IContentClassifier.js.map +0 -1
  52. package/dist/SlidingWindowBuffer.d.ts +0 -213
  53. package/dist/SlidingWindowBuffer.d.ts.map +0 -1
  54. package/dist/SlidingWindowBuffer.js +0 -246
  55. package/dist/SlidingWindowBuffer.js.map +0 -1
  56. package/dist/classifiers/InjectionClassifier.d.ts +0 -126
  57. package/dist/classifiers/InjectionClassifier.d.ts.map +0 -1
  58. package/dist/classifiers/InjectionClassifier.js +0 -210
  59. package/dist/classifiers/InjectionClassifier.js.map +0 -1
  60. package/dist/classifiers/JailbreakClassifier.d.ts +0 -124
  61. package/dist/classifiers/JailbreakClassifier.d.ts.map +0 -1
  62. package/dist/classifiers/JailbreakClassifier.js +0 -208
  63. package/dist/classifiers/JailbreakClassifier.js.map +0 -1
  64. package/dist/classifiers/ToxicityClassifier.d.ts +0 -125
  65. package/dist/classifiers/ToxicityClassifier.d.ts.map +0 -1
  66. package/dist/classifiers/ToxicityClassifier.js +0 -212
  67. package/dist/classifiers/ToxicityClassifier.js.map +0 -1
  68. package/dist/classifiers/WorkerClassifierProxy.d.ts +0 -158
  69. package/dist/classifiers/WorkerClassifierProxy.d.ts.map +0 -1
  70. package/dist/classifiers/WorkerClassifierProxy.js +0 -268
  71. package/dist/classifiers/WorkerClassifierProxy.js.map +0 -1
  72. package/dist/worker/classifier-worker.d.ts +0 -49
  73. package/dist/worker/classifier-worker.d.ts.map +0 -1
  74. package/dist/worker/classifier-worker.js +0 -180
  75. package/dist/worker/classifier-worker.js.map +0 -1
  76. package/src/ClassifierOrchestrator.ts +0 -290
  77. package/src/IContentClassifier.ts +0 -124
  78. package/src/SlidingWindowBuffer.ts +0 -384
  79. package/src/classifiers/InjectionClassifier.ts +0 -261
  80. package/src/classifiers/JailbreakClassifier.ts +0 -259
  81. package/src/classifiers/ToxicityClassifier.ts +0 -263
  82. package/src/classifiers/WorkerClassifierProxy.ts +0 -366
  83. package/src/worker/classifier-worker.ts +0 -267
@@ -1,158 +0,0 @@
1
- /**
2
- * @fileoverview WorkerClassifierProxy — wraps an IContentClassifier to run
3
- * inference inside a Web Worker, with automatic main-thread fallback.
4
- *
5
- * ## Why a proxy?
6
- * ML inference (even quantized ONNX / WASM pipelines) can block the main
7
- * thread for 50–500 ms per classification. Moving classification into a
8
- * Web Worker keeps the UI responsive. This proxy makes the switch
9
- * transparent to callers: they still call `classify(text)` and receive a
10
- * `ClassificationResult`; the underlying transport (Worker vs. direct call)
11
- * is an implementation detail.
12
- *
13
- * ## Fallback policy
14
- * The proxy falls back to direct (main-thread) delegation whenever:
15
- * - The global `Worker` constructor is undefined (Node.js, older browsers).
16
- * - `browserConfig.useWebWorker` is explicitly `false`.
17
- * - Worker creation throws (e.g. strict CSP that blocks `blob:` URLs).
18
- *
19
- * Once a fallback has been triggered by a Worker creation error the proxy
20
- * sets `workerFailed = true` and remains in fallback mode for all subsequent
21
- * calls.
22
- *
23
- * ## IContentClassifier contract
24
- * The proxy forwards all identity fields (`id`, `displayName`, `description`,
25
- * `modelId`) and the `isLoaded` state directly from the wrapped classifier so
26
- * it is completely transparent to the orchestrator.
27
- *
28
- * @module agentos/extensions/packs/ml-classifiers/classifiers/WorkerClassifierProxy
29
- */
30
- import type { ClassificationResult } from '@framers/agentos';
31
- import type { IContentClassifier } from '../IContentClassifier';
32
- import type { BrowserConfig } from '../types';
33
- /**
34
- * Transparent proxy around an {@link IContentClassifier} that offloads
35
- * `classify()` calls to a Web Worker when the browser environment supports it.
36
- *
37
- * In all other environments (Node.js, strict CSP, explicit opt-out) the proxy
38
- * delegates calls directly to the wrapped classifier on the main thread.
39
- *
40
- * @implements {IContentClassifier}
41
- *
42
- * @example Browser context — Web Worker path
43
- * ```typescript
44
- * const toxicity = new ToxicityClassifier(serviceRegistry);
45
- * const proxy = new WorkerClassifierProxy(toxicity, { useWebWorker: true });
46
- * const result = await proxy.classify('some text');
47
- * ```
48
- *
49
- * @example Node.js / forced fallback path
50
- * ```typescript
51
- * const proxy = new WorkerClassifierProxy(toxicity, { useWebWorker: false });
52
- * // Delegates directly to toxicity.classify() on the same thread.
53
- * ```
54
- */
55
- export declare class WorkerClassifierProxy implements IContentClassifier {
56
- private readonly wrapped;
57
- private readonly browserConfig?;
58
- /**
59
- * {@inheritDoc IContentClassifier.id}
60
- * Delegated from the wrapped classifier so this proxy is transparent in
61
- * the orchestrator's service-ID lookups.
62
- */
63
- get id(): string;
64
- /**
65
- * {@inheritDoc IContentClassifier.displayName}
66
- * Returns the wrapped classifier's display name with a `(Worker)` suffix
67
- * when the Web Worker path is active, so logs clearly indicate the mode.
68
- */
69
- get displayName(): string;
70
- /**
71
- * {@inheritDoc IContentClassifier.description}
72
- * Delegated directly from the wrapped classifier.
73
- */
74
- get description(): string;
75
- /**
76
- * {@inheritDoc IContentClassifier.modelId}
77
- * Delegated directly from the wrapped classifier.
78
- */
79
- get modelId(): string;
80
- /**
81
- * {@inheritDoc IContentClassifier.isLoaded}
82
- *
83
- * Reflects the wrapped classifier's `isLoaded` state. The wrapped
84
- * instance is the authoritative source because it owns the model weights
85
- * (whether they live in the Worker or on the main thread).
86
- */
87
- get isLoaded(): boolean;
88
- /**
89
- * IContentClassifier requires `isLoaded` to be settable via the interface
90
- * contract (`isLoaded: boolean`). We store the value through the wrapped
91
- * classifier so the authoritative state lives in one place.
92
- */
93
- set isLoaded(value: boolean);
94
- /**
95
- * Set to `true` after a Worker creation failure. Once set, all subsequent
96
- * `classify()` calls are routed directly to the wrapped classifier without
97
- * attempting to re-create the Worker.
98
- */
99
- private workerFailed;
100
- /**
101
- * Create a WorkerClassifierProxy.
102
- *
103
- * @param wrapped - The real classifier to delegate to. In Worker
104
- * mode this classifier is still responsible for
105
- * model loading and inference; the proxy just
106
- * changes the thread on which it executes.
107
- * @param browserConfig - Optional browser-side configuration. Controls
108
- * whether Worker mode is attempted
109
- * (`useWebWorker`, default `true`).
110
- */
111
- constructor(wrapped: IContentClassifier, browserConfig?: BrowserConfig | undefined);
112
- /**
113
- * Classify the provided text, routing to a Web Worker when available.
114
- *
115
- * ### Routing decision (evaluated once per call)
116
- * 1. `typeof Worker === 'undefined'` → fallback (Node.js / no Worker API).
117
- * 2. `browserConfig.useWebWorker === false` → fallback (explicit opt-out).
118
- * 3. `workerFailed === true` → fallback (previous Worker creation error).
119
- * 4. Otherwise → attempt to run in a Web Worker.
120
- *
121
- * If the Worker is created but fails to post a result within the
122
- * classification request, the error is propagated as a rejected promise
123
- * (not silently swallowed) so the orchestrator can log and fall back at
124
- * a higher level.
125
- *
126
- * @param text - The text to classify. Must not be empty.
127
- * @returns A promise that resolves with the classification result.
128
- */
129
- classify(text: string): Promise<ClassificationResult>;
130
- /**
131
- * Release resources held by the wrapped classifier.
132
- *
133
- * Delegates to `wrapped.dispose()` if it exists. Idempotent.
134
- */
135
- dispose(): Promise<void>;
136
- /**
137
- * Determine whether the current environment and configuration support
138
- * running inference in a Web Worker.
139
- *
140
- * @returns `true` when Web Worker mode should be attempted.
141
- */
142
- private shouldUseWebWorker;
143
- /**
144
- * Run `classify(text)` inside a transient Web Worker.
145
- *
146
- * Each call creates a new Worker, sends a single `classify` message,
147
- * awaits the `result` or `error` response, then terminates the Worker.
148
- *
149
- * If Worker creation itself throws (e.g. CSP violation), `workerFailed`
150
- * is set to `true` and the call falls back to the wrapped classifier on
151
- * the main thread.
152
- *
153
- * @param text - The text to classify inside the Worker.
154
- * @returns A promise resolving with the {@link ClassificationResult}.
155
- */
156
- private classifyInWorker;
157
- }
158
- //# sourceMappingURL=WorkerClassifierProxy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"WorkerClassifierProxy.d.ts","sourceRoot":"","sources":["../../src/classifiers/WorkerClassifierProxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAoE9C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,qBAAsB,YAAW,kBAAkB;IAsF5D,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;IAlFjC;;;;OAIG;IACH,IAAI,EAAE,IAAI,MAAM,CAEf;IAED;;;;OAIG;IACH,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;;OAGG;IACH,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;;OAGG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;;;;OAMG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;;;;OAIG;IACH,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;IAMD;;;;OAIG;IACH,OAAO,CAAC,YAAY,CAAS;IAM7B;;;;;;;;;;OAUG;gBAEgB,OAAO,EAAE,kBAAkB,EAC3B,aAAa,CAAC,EAAE,aAAa,YAAA;IAOhD;;;;;;;;;;;;;;;;OAgBG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAiB3D;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAU9B;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAmB1B;;;;;;;;;;;;OAYG;YACW,gBAAgB;CA8D/B"}
@@ -1,268 +0,0 @@
1
- /**
2
- * @fileoverview WorkerClassifierProxy — wraps an IContentClassifier to run
3
- * inference inside a Web Worker, with automatic main-thread fallback.
4
- *
5
- * ## Why a proxy?
6
- * ML inference (even quantized ONNX / WASM pipelines) can block the main
7
- * thread for 50–500 ms per classification. Moving classification into a
8
- * Web Worker keeps the UI responsive. This proxy makes the switch
9
- * transparent to callers: they still call `classify(text)` and receive a
10
- * `ClassificationResult`; the underlying transport (Worker vs. direct call)
11
- * is an implementation detail.
12
- *
13
- * ## Fallback policy
14
- * The proxy falls back to direct (main-thread) delegation whenever:
15
- * - The global `Worker` constructor is undefined (Node.js, older browsers).
16
- * - `browserConfig.useWebWorker` is explicitly `false`.
17
- * - Worker creation throws (e.g. strict CSP that blocks `blob:` URLs).
18
- *
19
- * Once a fallback has been triggered by a Worker creation error the proxy
20
- * sets `workerFailed = true` and remains in fallback mode for all subsequent
21
- * calls.
22
- *
23
- * ## IContentClassifier contract
24
- * The proxy forwards all identity fields (`id`, `displayName`, `description`,
25
- * `modelId`) and the `isLoaded` state directly from the wrapped classifier so
26
- * it is completely transparent to the orchestrator.
27
- *
28
- * @module agentos/extensions/packs/ml-classifiers/classifiers/WorkerClassifierProxy
29
- */
30
- // ---------------------------------------------------------------------------
31
- // WorkerClassifierProxy
32
- // ---------------------------------------------------------------------------
33
- /**
34
- * Transparent proxy around an {@link IContentClassifier} that offloads
35
- * `classify()` calls to a Web Worker when the browser environment supports it.
36
- *
37
- * In all other environments (Node.js, strict CSP, explicit opt-out) the proxy
38
- * delegates calls directly to the wrapped classifier on the main thread.
39
- *
40
- * @implements {IContentClassifier}
41
- *
42
- * @example Browser context — Web Worker path
43
- * ```typescript
44
- * const toxicity = new ToxicityClassifier(serviceRegistry);
45
- * const proxy = new WorkerClassifierProxy(toxicity, { useWebWorker: true });
46
- * const result = await proxy.classify('some text');
47
- * ```
48
- *
49
- * @example Node.js / forced fallback path
50
- * ```typescript
51
- * const proxy = new WorkerClassifierProxy(toxicity, { useWebWorker: false });
52
- * // Delegates directly to toxicity.classify() on the same thread.
53
- * ```
54
- */
55
- export class WorkerClassifierProxy {
56
- wrapped;
57
- browserConfig;
58
- // -------------------------------------------------------------------------
59
- // IContentClassifier identity — delegated from wrapped classifier
60
- // -------------------------------------------------------------------------
61
- /**
62
- * {@inheritDoc IContentClassifier.id}
63
- * Delegated from the wrapped classifier so this proxy is transparent in
64
- * the orchestrator's service-ID lookups.
65
- */
66
- get id() {
67
- return this.wrapped.id;
68
- }
69
- /**
70
- * {@inheritDoc IContentClassifier.displayName}
71
- * Returns the wrapped classifier's display name with a `(Worker)` suffix
72
- * when the Web Worker path is active, so logs clearly indicate the mode.
73
- */
74
- get displayName() {
75
- return this.wrapped.displayName;
76
- }
77
- /**
78
- * {@inheritDoc IContentClassifier.description}
79
- * Delegated directly from the wrapped classifier.
80
- */
81
- get description() {
82
- return this.wrapped.description;
83
- }
84
- /**
85
- * {@inheritDoc IContentClassifier.modelId}
86
- * Delegated directly from the wrapped classifier.
87
- */
88
- get modelId() {
89
- return this.wrapped.modelId;
90
- }
91
- /**
92
- * {@inheritDoc IContentClassifier.isLoaded}
93
- *
94
- * Reflects the wrapped classifier's `isLoaded` state. The wrapped
95
- * instance is the authoritative source because it owns the model weights
96
- * (whether they live in the Worker or on the main thread).
97
- */
98
- get isLoaded() {
99
- return this.wrapped.isLoaded;
100
- }
101
- /**
102
- * IContentClassifier requires `isLoaded` to be settable via the interface
103
- * contract (`isLoaded: boolean`). We store the value through the wrapped
104
- * classifier so the authoritative state lives in one place.
105
- */
106
- set isLoaded(value) {
107
- this.wrapped.isLoaded = value;
108
- }
109
- // -------------------------------------------------------------------------
110
- // Internal state
111
- // -------------------------------------------------------------------------
112
- /**
113
- * Set to `true` after a Worker creation failure. Once set, all subsequent
114
- * `classify()` calls are routed directly to the wrapped classifier without
115
- * attempting to re-create the Worker.
116
- */
117
- workerFailed = false;
118
- // -------------------------------------------------------------------------
119
- // Constructor
120
- // -------------------------------------------------------------------------
121
- /**
122
- * Create a WorkerClassifierProxy.
123
- *
124
- * @param wrapped - The real classifier to delegate to. In Worker
125
- * mode this classifier is still responsible for
126
- * model loading and inference; the proxy just
127
- * changes the thread on which it executes.
128
- * @param browserConfig - Optional browser-side configuration. Controls
129
- * whether Worker mode is attempted
130
- * (`useWebWorker`, default `true`).
131
- */
132
- constructor(wrapped, browserConfig) {
133
- this.wrapped = wrapped;
134
- this.browserConfig = browserConfig;
135
- }
136
- // -------------------------------------------------------------------------
137
- // classify
138
- // -------------------------------------------------------------------------
139
- /**
140
- * Classify the provided text, routing to a Web Worker when available.
141
- *
142
- * ### Routing decision (evaluated once per call)
143
- * 1. `typeof Worker === 'undefined'` → fallback (Node.js / no Worker API).
144
- * 2. `browserConfig.useWebWorker === false` → fallback (explicit opt-out).
145
- * 3. `workerFailed === true` → fallback (previous Worker creation error).
146
- * 4. Otherwise → attempt to run in a Web Worker.
147
- *
148
- * If the Worker is created but fails to post a result within the
149
- * classification request, the error is propagated as a rejected promise
150
- * (not silently swallowed) so the orchestrator can log and fall back at
151
- * a higher level.
152
- *
153
- * @param text - The text to classify. Must not be empty.
154
- * @returns A promise that resolves with the classification result.
155
- */
156
- async classify(text) {
157
- // Determine whether to use a Web Worker.
158
- const shouldUseWorker = this.shouldUseWebWorker();
159
- if (!shouldUseWorker) {
160
- // Fallback: delegate directly to the wrapped classifier on this thread.
161
- return this.wrapped.classify(text);
162
- }
163
- // Attempt to classify in a Worker.
164
- return this.classifyInWorker(text);
165
- }
166
- // -------------------------------------------------------------------------
167
- // dispose (optional IContentClassifier lifecycle hook)
168
- // -------------------------------------------------------------------------
169
- /**
170
- * Release resources held by the wrapped classifier.
171
- *
172
- * Delegates to `wrapped.dispose()` if it exists. Idempotent.
173
- */
174
- async dispose() {
175
- if (this.wrapped.dispose) {
176
- await this.wrapped.dispose();
177
- }
178
- }
179
- // -------------------------------------------------------------------------
180
- // Private helpers
181
- // -------------------------------------------------------------------------
182
- /**
183
- * Determine whether the current environment and configuration support
184
- * running inference in a Web Worker.
185
- *
186
- * @returns `true` when Web Worker mode should be attempted.
187
- */
188
- shouldUseWebWorker() {
189
- // Worker API is not available (Node.js, JSDOM without worker support, etc.)
190
- if (typeof Worker === 'undefined') {
191
- return false;
192
- }
193
- // Caller explicitly opted out of Web Worker mode.
194
- if (this.browserConfig?.useWebWorker === false) {
195
- return false;
196
- }
197
- // A previous Worker creation attempt failed — stay on main thread.
198
- if (this.workerFailed) {
199
- return false;
200
- }
201
- return true;
202
- }
203
- /**
204
- * Run `classify(text)` inside a transient Web Worker.
205
- *
206
- * Each call creates a new Worker, sends a single `classify` message,
207
- * awaits the `result` or `error` response, then terminates the Worker.
208
- *
209
- * If Worker creation itself throws (e.g. CSP violation), `workerFailed`
210
- * is set to `true` and the call falls back to the wrapped classifier on
211
- * the main thread.
212
- *
213
- * @param text - The text to classify inside the Worker.
214
- * @returns A promise resolving with the {@link ClassificationResult}.
215
- */
216
- async classifyInWorker(text) {
217
- let worker;
218
- try {
219
- // Resolve the Worker script URL. We use the sibling classifier-worker
220
- // module. In a bundled environment this will be a blob URL or a
221
- // `new URL(...)` import; here we use a relative path that bundlers
222
- // understand via the standard Worker constructor pattern.
223
- worker = new Worker(new URL('../worker/classifier-worker.ts', import.meta.url), {
224
- type: 'module',
225
- });
226
- }
227
- catch (err) {
228
- // Worker could not be created (CSP, missing support, etc.).
229
- // Mark as failed and fall back to the main thread.
230
- this.workerFailed = true;
231
- console.warn(`[WorkerClassifierProxy] Worker creation failed for "${this.wrapped.id}"; ` +
232
- `falling back to main-thread classification. Reason: ${err}`);
233
- return this.wrapped.classify(text);
234
- }
235
- // Build the request message.
236
- const request = {
237
- type: 'classify',
238
- text,
239
- modelId: this.wrapped.modelId,
240
- // Default to non-quantized; the wrapped classifier's config owns this,
241
- // but the Worker needs it to load the right model variant.
242
- quantized: false,
243
- taskType: 'text-classification',
244
- };
245
- return new Promise((resolve, reject) => {
246
- // Handle the single response message from the Worker.
247
- worker.onmessage = (event) => {
248
- const message = event.data;
249
- if (message.type === 'result') {
250
- resolve(message.result);
251
- }
252
- else {
253
- reject(new Error(`Worker classification error: ${message.error}`));
254
- }
255
- // Terminate the Worker after receiving its response to free resources.
256
- worker.terminate();
257
- };
258
- // Handle any uncaught errors thrown inside the Worker.
259
- worker.onerror = (errorEvent) => {
260
- reject(new Error(`Worker runtime error in "${this.wrapped.id}": ${errorEvent.message}`));
261
- worker.terminate();
262
- };
263
- // Send the classify request to the Worker.
264
- worker.postMessage(request);
265
- });
266
- }
267
- }
268
- //# sourceMappingURL=WorkerClassifierProxy.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"WorkerClassifierProxy.js","sourceRoot":"","sources":["../../src/classifiers/WorkerClassifierProxy.ts"],"names":[],"mappings":"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"}
@@ -1,49 +0,0 @@
1
- /**
2
- * @fileoverview Web Worker entry point for ML content classification.
3
- *
4
- * This script is loaded by {@link WorkerClassifierProxy} as a dedicated Web
5
- * Worker. It listens for `classify` messages from the main thread, lazily
6
- * loads the requested model pipeline via `@huggingface/transformers`, runs
7
- * inference, then posts the result (or an error) back.
8
- *
9
- * ## Message protocol
10
- *
11
- * **Incoming** (main thread → worker):
12
- * ```json
13
- * {
14
- * "type": "classify",
15
- * "text": "<string>",
16
- * "modelId": "<HuggingFace model ID or local path>",
17
- * "quantized": true | false,
18
- * "taskType": "<transformers.js task string>"
19
- * }
20
- * ```
21
- *
22
- * **Outgoing** (worker → main thread) on success:
23
- * ```json
24
- * { "type": "result", "result": { "bestClass": "...", "confidence": 0.92, "allScores": [...] } }
25
- * ```
26
- *
27
- * **Outgoing** (worker → main thread) on error:
28
- * ```json
29
- * { "type": "error", "error": "<error message>" }
30
- * ```
31
- *
32
- * ## Pipeline caching
33
- * The pipeline is loaded once per `(modelId, taskType)` key and cached in
34
- * a module-level `Map`. Subsequent `classify` messages for the same model
35
- * reuse the cached instance, avoiding repeated expensive model downloads and
36
- * WASM initialisation.
37
- *
38
- * ## Raw label normalisation
39
- * The worker normalises the raw `@huggingface/transformers` output (an array
40
- * of `{ label, score }` objects when called with `topk: null`) into the
41
- * AgentOS {@link ClassificationResult} shape:
42
- * - `bestClass` — label with the highest score
43
- * - `confidence` — score of the winning label
44
- * - `allScores` — all labels mapped to `{ classLabel, score }` pairs
45
- *
46
- * @module agentos/extensions/packs/ml-classifiers/worker/classifier-worker
47
- */
48
- export {};
49
- //# sourceMappingURL=classifier-worker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"classifier-worker.d.ts","sourceRoot":"","sources":["../../src/worker/classifier-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG"}
@@ -1,180 +0,0 @@
1
- /**
2
- * @fileoverview Web Worker entry point for ML content classification.
3
- *
4
- * This script is loaded by {@link WorkerClassifierProxy} as a dedicated Web
5
- * Worker. It listens for `classify` messages from the main thread, lazily
6
- * loads the requested model pipeline via `@huggingface/transformers`, runs
7
- * inference, then posts the result (or an error) back.
8
- *
9
- * ## Message protocol
10
- *
11
- * **Incoming** (main thread → worker):
12
- * ```json
13
- * {
14
- * "type": "classify",
15
- * "text": "<string>",
16
- * "modelId": "<HuggingFace model ID or local path>",
17
- * "quantized": true | false,
18
- * "taskType": "<transformers.js task string>"
19
- * }
20
- * ```
21
- *
22
- * **Outgoing** (worker → main thread) on success:
23
- * ```json
24
- * { "type": "result", "result": { "bestClass": "...", "confidence": 0.92, "allScores": [...] } }
25
- * ```
26
- *
27
- * **Outgoing** (worker → main thread) on error:
28
- * ```json
29
- * { "type": "error", "error": "<error message>" }
30
- * ```
31
- *
32
- * ## Pipeline caching
33
- * The pipeline is loaded once per `(modelId, taskType)` key and cached in
34
- * a module-level `Map`. Subsequent `classify` messages for the same model
35
- * reuse the cached instance, avoiding repeated expensive model downloads and
36
- * WASM initialisation.
37
- *
38
- * ## Raw label normalisation
39
- * The worker normalises the raw `@huggingface/transformers` output (an array
40
- * of `{ label, score }` objects when called with `topk: null`) into the
41
- * AgentOS {@link ClassificationResult} shape:
42
- * - `bestClass` — label with the highest score
43
- * - `confidence` — score of the winning label
44
- * - `allScores` — all labels mapped to `{ classLabel, score }` pairs
45
- *
46
- * @module agentos/extensions/packs/ml-classifiers/worker/classifier-worker
47
- */
48
- // ---------------------------------------------------------------------------
49
- // Pipeline cache
50
- // ---------------------------------------------------------------------------
51
- /**
52
- * Cache key composed of `modelId` and `taskType` so different task types
53
- * for the same model ID are kept separate.
54
- *
55
- * @param modelId - Hugging Face model ID or local path.
56
- * @param taskType - transformers.js task string.
57
- * @returns Cache key string.
58
- */
59
- function cacheKey(modelId, taskType) {
60
- return `${taskType}::${modelId}`;
61
- }
62
- /**
63
- * Module-level pipeline cache.
64
- *
65
- * Maps cache keys (see {@link cacheKey}) to loaded pipeline functions.
66
- * Populated lazily on the first `classify` message for each unique
67
- * `(modelId, taskType)` combination.
68
- */
69
- const pipelineCache = new Map();
70
- // ---------------------------------------------------------------------------
71
- // Classification logic
72
- // ---------------------------------------------------------------------------
73
- /**
74
- * Load (or retrieve from cache) the text-classification pipeline for the
75
- * given model and run inference on `text`.
76
- *
77
- * @param request - The incoming classify request.
78
- * @returns A promise resolving with the raw label array from the pipeline.
79
- * @throws If the pipeline fails to load or inference throws.
80
- */
81
- async function runPipeline(request) {
82
- const key = cacheKey(request.modelId, request.taskType);
83
- // Check the cache first to avoid re-loading on every message.
84
- let pipe = pipelineCache.get(key);
85
- if (!pipe) {
86
- // Lazy-load the @huggingface/transformers package.
87
- // Dynamic import is used so this module can be evaluated in environments
88
- // where the package is optional (the Worker is only instantiated when
89
- // browser runtime is active and the package is present).
90
- const { pipeline: createPipeline } = await import('@huggingface/transformers');
91
- // Create the pipeline with quantisation option from the request.
92
- const newPipe = await createPipeline(request.taskType, request.modelId, {
93
- quantized: request.quantized,
94
- });
95
- // Store in cache and narrow the type.
96
- pipe = newPipe;
97
- pipelineCache.set(key, pipe);
98
- }
99
- // Run inference — request all label scores (topk: null).
100
- return pipe(request.text, { topk: null });
101
- }
102
- /**
103
- * Normalise raw pipeline output into an AgentOS {@link ClassificationResult}.
104
- *
105
- * @param raw - Array of `{ label, score }` objects from the pipeline.
106
- * @returns A fully-populated `ClassificationResult`.
107
- */
108
- function normaliseResult(raw) {
109
- if (!raw || raw.length === 0) {
110
- // No output — return a benign pass result so the orchestrator treats this
111
- // as ALLOW rather than an error.
112
- return { bestClass: 'benign', confidence: 0, allScores: [] };
113
- }
114
- // Find the label with the highest confidence score.
115
- let best = raw[0];
116
- for (const item of raw) {
117
- if (item.score > best.score) {
118
- best = item;
119
- }
120
- }
121
- // Map every label to the AgentOS ClassificationScore shape.
122
- const allScores = raw.map((item) => ({
123
- classLabel: item.label,
124
- score: item.score,
125
- }));
126
- return {
127
- bestClass: best.label,
128
- confidence: best.score,
129
- allScores,
130
- };
131
- }
132
- // ---------------------------------------------------------------------------
133
- // Message handler
134
- // ---------------------------------------------------------------------------
135
- /**
136
- * Handle a `classify` message from the main thread.
137
- *
138
- * Runs the pipeline and posts either a {@link ResultMessage} or an
139
- * {@link ErrorMessage} back to the main thread.
140
- *
141
- * @param request - The incoming classify request.
142
- */
143
- async function handleClassify(request) {
144
- try {
145
- const raw = await runPipeline(request);
146
- const result = normaliseResult(raw);
147
- const response = { type: 'result', result };
148
- self.postMessage(response);
149
- }
150
- catch (err) {
151
- const message = err instanceof Error ? err.message : String(err);
152
- const response = { type: 'error', error: message };
153
- self.postMessage(response);
154
- }
155
- }
156
- // ---------------------------------------------------------------------------
157
- // Worker bootstrap — listen for messages from the main thread
158
- // ---------------------------------------------------------------------------
159
- /**
160
- * The primary message listener for this Worker.
161
- *
162
- * Dispatches incoming messages to {@link handleClassify} when the message
163
- * type is `'classify'`. All other message types are ignored with a warning
164
- * logged to the Worker console (useful for debugging unexpected messages
165
- * during development).
166
- */
167
- self.onmessage = (event) => {
168
- const data = event.data;
169
- if (data?.type === 'classify') {
170
- // Kick off async classification. Errors are caught inside handleClassify
171
- // and posted back as ErrorMessage, so we do not need a top-level catch here.
172
- void handleClassify(data);
173
- }
174
- else {
175
- // Unknown message type — log and ignore.
176
- console.warn('[classifier-worker] Received unexpected message type:', data?.type ?? data);
177
- }
178
- };
179
- export {};
180
- //# sourceMappingURL=classifier-worker.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"classifier-worker.js","sourceRoot":"","sources":["../../src/worker/classifier-worker.ts"],"names":[],"mappings":"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"}