@octomil/browser 1.0.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/LICENSE +21 -0
- package/README.md +75 -0
- package/dist/cache.d.ts +25 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +202 -0
- package/dist/cache.js.map +1 -0
- package/dist/device-auth.d.ts +41 -0
- package/dist/device-auth.d.ts.map +1 -0
- package/dist/device-auth.js +203 -0
- package/dist/device-auth.js.map +1 -0
- package/dist/experiments.d.ts +44 -0
- package/dist/experiments.d.ts.map +1 -0
- package/dist/experiments.js +135 -0
- package/dist/experiments.js.map +1 -0
- package/dist/federated.d.ts +53 -0
- package/dist/federated.d.ts.map +1 -0
- package/dist/federated.js +180 -0
- package/dist/federated.js.map +1 -0
- package/dist/index.cjs +2148 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/inference.d.ts +43 -0
- package/dist/inference.d.ts.map +1 -0
- package/dist/inference.js +213 -0
- package/dist/inference.js.map +1 -0
- package/dist/integrity.d.ts +19 -0
- package/dist/integrity.d.ts.map +1 -0
- package/dist/integrity.js +35 -0
- package/dist/integrity.js.map +1 -0
- package/dist/model-loader.d.ts +40 -0
- package/dist/model-loader.d.ts.map +1 -0
- package/dist/model-loader.js +232 -0
- package/dist/model-loader.js.map +1 -0
- package/dist/octomil.d.ts +92 -0
- package/dist/octomil.d.ts.map +1 -0
- package/dist/octomil.js +368 -0
- package/dist/octomil.js.map +1 -0
- package/dist/octomil.min.js +2849 -0
- package/dist/octomil.min.js.map +7 -0
- package/dist/privacy.d.ts +40 -0
- package/dist/privacy.d.ts.map +1 -0
- package/dist/privacy.js +118 -0
- package/dist/privacy.js.map +1 -0
- package/dist/rollouts.d.ts +43 -0
- package/dist/rollouts.d.ts.map +1 -0
- package/dist/rollouts.js +114 -0
- package/dist/rollouts.js.map +1 -0
- package/dist/secure-aggregation.d.ts +50 -0
- package/dist/secure-aggregation.d.ts.map +1 -0
- package/dist/secure-aggregation.js +174 -0
- package/dist/secure-aggregation.js.map +1 -0
- package/dist/streaming.d.ts +25 -0
- package/dist/streaming.d.ts.map +1 -0
- package/dist/streaming.js +148 -0
- package/dist/streaming.js.map +1 -0
- package/dist/telemetry.d.ts +41 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +130 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types.d.ts +239 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"octomil.d.ts","sourceRoot":"","sources":["../src/octomil.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAOH,OAAO,KAAK,EACV,OAAO,EACP,SAAS,EACT,SAAS,EACT,WAAW,EACX,WAAW,EACX,YAAY,EACZ,cAAc,EAEd,YAAY,EACZ,aAAa,EAEd,MAAM,YAAY,CAAC;AAOpB,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAGP;IAEjB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,SAAS,CAAkC;IAEnD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAS;gBAEb,OAAO,EAAE,cAAc;IAuBnC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA2C3B;;;;;OAKG;IACG,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAiB1D;;;;OAIG;IACG,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IA4BpE;;;;OAIG;IACG,IAAI,CACR,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,YAAY,CAAC;IAsCxB;;OAEG;IACI,UAAU,CACf,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,GAAE,WAAgB,GACxB,cAAc,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC;IAqC7C,kEAAkE;IAC5D,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAKlC,sCAAsC;IAChC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAKjC,wCAAwC;IAClC,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC;IASrC,+DAA+D;IAC/D,IAAI,aAAa,IAAI,OAAO,GAAG,IAAI,CAElC;IAED,sDAAsD;IACtD,IAAI,UAAU,IAAI,SAAS,MAAM,EAAE,CAGlC;IAED,uDAAuD;IACvD,IAAI,WAAW,IAAI,SAAS,MAAM,EAAE,CAGnC;IAED,qDAAqD;IACrD,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAMD,qEAAqE;IACrE,OAAO,IAAI,IAAI;IAcf,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,WAAW;IAUnB;;;OAGG;IACH,OAAO,CAAC,cAAc;IA8CtB,mCAAmC;IACnC,OAAO,CAAC,cAAc;IAYtB;;;OAGG;IACH,OAAO,CAAC,cAAc;IA0DtB,OAAO,CAAC,UAAU;CAGnB"}
|
package/dist/octomil.js
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @octomil/browser — Main SDK entry point
|
|
3
|
+
*
|
|
4
|
+
* The `Octomil` class is the primary public interface. It orchestrates
|
|
5
|
+
* model loading, caching, inference, and optional telemetry.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { Octomil } from '@octomil/browser';
|
|
10
|
+
*
|
|
11
|
+
* const ml = new Octomil({
|
|
12
|
+
* model: 'https://models.octomil.io/sentiment-v1.onnx',
|
|
13
|
+
* backend: 'webgpu',
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* await ml.load();
|
|
17
|
+
* const result = await ml.predict({ raw: inputData, dims: [1, 3, 224, 224] });
|
|
18
|
+
* console.log(result.label, result.score);
|
|
19
|
+
* ml.dispose();
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import { createModelCache } from "./cache.js";
|
|
23
|
+
import { InferenceEngine } from "./inference.js";
|
|
24
|
+
import { ModelLoader } from "./model-loader.js";
|
|
25
|
+
import { TelemetryReporter } from "./telemetry.js";
|
|
26
|
+
import { StreamingInferenceEngine } from "./streaming.js";
|
|
27
|
+
import { OctomilError } from "./types.js";
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Octomil
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
export class Octomil {
|
|
32
|
+
options;
|
|
33
|
+
cache;
|
|
34
|
+
loader;
|
|
35
|
+
engine;
|
|
36
|
+
telemetry = null;
|
|
37
|
+
loaded = false;
|
|
38
|
+
disposed = false;
|
|
39
|
+
constructor(options) {
|
|
40
|
+
this.options = {
|
|
41
|
+
telemetry: false,
|
|
42
|
+
cacheStrategy: "cache-api",
|
|
43
|
+
...options,
|
|
44
|
+
};
|
|
45
|
+
this.cache = createModelCache(this.options.cacheStrategy);
|
|
46
|
+
this.loader = new ModelLoader(this.options, this.cache);
|
|
47
|
+
this.engine = new InferenceEngine();
|
|
48
|
+
if (this.options.telemetry) {
|
|
49
|
+
this.telemetry = new TelemetryReporter({
|
|
50
|
+
url: this.options.telemetryUrl,
|
|
51
|
+
apiKey: this.options.apiKey,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// -----------------------------------------------------------------------
|
|
56
|
+
// Lifecycle
|
|
57
|
+
// -----------------------------------------------------------------------
|
|
58
|
+
/**
|
|
59
|
+
* Download (or load from cache) the ONNX model and create the
|
|
60
|
+
* inference session. Must be called before `predict()` or `chat()`.
|
|
61
|
+
*/
|
|
62
|
+
async load() {
|
|
63
|
+
this.ensureNotDisposed();
|
|
64
|
+
const start = performance.now();
|
|
65
|
+
const wasCached = await this.loader.isCached();
|
|
66
|
+
const modelData = await this.loader.load();
|
|
67
|
+
await this.engine.createSession(modelData, this.options.backend);
|
|
68
|
+
this.loaded = true;
|
|
69
|
+
const durationMs = performance.now() - start;
|
|
70
|
+
this.trackEvent({
|
|
71
|
+
type: "model_load",
|
|
72
|
+
model: this.options.model,
|
|
73
|
+
durationMs,
|
|
74
|
+
metadata: {
|
|
75
|
+
backend: this.engine.activeBackend,
|
|
76
|
+
cached: wasCached,
|
|
77
|
+
sizeBytes: modelData.byteLength,
|
|
78
|
+
},
|
|
79
|
+
timestamp: Date.now(),
|
|
80
|
+
});
|
|
81
|
+
if (wasCached) {
|
|
82
|
+
this.trackEvent({
|
|
83
|
+
type: "cache_hit",
|
|
84
|
+
model: this.options.model,
|
|
85
|
+
timestamp: Date.now(),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
this.trackEvent({
|
|
90
|
+
type: "cache_miss",
|
|
91
|
+
model: this.options.model,
|
|
92
|
+
timestamp: Date.now(),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// -----------------------------------------------------------------------
|
|
97
|
+
// Inference
|
|
98
|
+
// -----------------------------------------------------------------------
|
|
99
|
+
/**
|
|
100
|
+
* Run a single inference pass.
|
|
101
|
+
*
|
|
102
|
+
* Accepts either raw named tensors or convenience payloads
|
|
103
|
+
* (`{ text }`, `{ image }`, `{ raw, dims }`).
|
|
104
|
+
*/
|
|
105
|
+
async predict(input) {
|
|
106
|
+
this.ensureReady();
|
|
107
|
+
const tensors = this.prepareTensors(input);
|
|
108
|
+
const result = await this.engine.run(tensors);
|
|
109
|
+
this.trackEvent({
|
|
110
|
+
type: "inference",
|
|
111
|
+
model: this.options.model,
|
|
112
|
+
durationMs: result.latencyMs,
|
|
113
|
+
metadata: { backend: this.engine.activeBackend },
|
|
114
|
+
timestamp: Date.now(),
|
|
115
|
+
});
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Run inference on multiple inputs sequentially.
|
|
120
|
+
* ONNX Runtime Web doesn't handle concurrent sessions well,
|
|
121
|
+
* so we process one at a time.
|
|
122
|
+
*/
|
|
123
|
+
async predictBatch(inputs) {
|
|
124
|
+
this.ensureReady();
|
|
125
|
+
const start = performance.now();
|
|
126
|
+
const results = [];
|
|
127
|
+
for (const input of inputs) {
|
|
128
|
+
const tensors = this.prepareTensors(input);
|
|
129
|
+
const result = await this.engine.run(tensors);
|
|
130
|
+
results.push(result);
|
|
131
|
+
}
|
|
132
|
+
const totalMs = performance.now() - start;
|
|
133
|
+
this.trackEvent({
|
|
134
|
+
type: "inference",
|
|
135
|
+
model: this.options.model,
|
|
136
|
+
durationMs: totalMs,
|
|
137
|
+
metadata: {
|
|
138
|
+
backend: this.engine.activeBackend,
|
|
139
|
+
batchSize: inputs.length,
|
|
140
|
+
},
|
|
141
|
+
timestamp: Date.now(),
|
|
142
|
+
});
|
|
143
|
+
return results;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* OpenAI-compatible chat completion.
|
|
147
|
+
* Requires a server with streaming endpoint. Uses StreamingInferenceEngine
|
|
148
|
+
* under the hood to collect the full response.
|
|
149
|
+
*/
|
|
150
|
+
async chat(messages, options = {}) {
|
|
151
|
+
this.ensureReady();
|
|
152
|
+
if (!this.options.serverUrl) {
|
|
153
|
+
throw new OctomilError("INFERENCE_FAILED", "chat() requires serverUrl to be configured.");
|
|
154
|
+
}
|
|
155
|
+
const streaming = new StreamingInferenceEngine({
|
|
156
|
+
serverUrl: this.options.serverUrl,
|
|
157
|
+
apiKey: this.options.apiKey,
|
|
158
|
+
onTelemetry: (e) => this.trackEvent(e),
|
|
159
|
+
});
|
|
160
|
+
const start = performance.now();
|
|
161
|
+
let content = "";
|
|
162
|
+
const generator = streaming.stream(this.options.model, {
|
|
163
|
+
messages,
|
|
164
|
+
temperature: options.temperature,
|
|
165
|
+
max_tokens: options.maxTokens,
|
|
166
|
+
top_p: options.topP,
|
|
167
|
+
}, { modality: "text", signal: options.signal });
|
|
168
|
+
for await (const chunk of generator) {
|
|
169
|
+
if (typeof chunk.data === "string") {
|
|
170
|
+
content += chunk.data;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
message: { role: "assistant", content },
|
|
175
|
+
latencyMs: performance.now() - start,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Streaming chat — yields chunks as they arrive.
|
|
180
|
+
*/
|
|
181
|
+
async *chatStream(messages, options = {}) {
|
|
182
|
+
this.ensureReady();
|
|
183
|
+
if (!this.options.serverUrl) {
|
|
184
|
+
throw new OctomilError("INFERENCE_FAILED", "chatStream() requires serverUrl to be configured.");
|
|
185
|
+
}
|
|
186
|
+
const streaming = new StreamingInferenceEngine({
|
|
187
|
+
serverUrl: this.options.serverUrl,
|
|
188
|
+
apiKey: this.options.apiKey,
|
|
189
|
+
onTelemetry: (e) => this.trackEvent(e),
|
|
190
|
+
});
|
|
191
|
+
const generator = streaming.stream(this.options.model, {
|
|
192
|
+
messages,
|
|
193
|
+
temperature: options.temperature,
|
|
194
|
+
max_tokens: options.maxTokens,
|
|
195
|
+
top_p: options.topP,
|
|
196
|
+
}, { modality: "text", signal: options.signal });
|
|
197
|
+
for await (const chunk of generator) {
|
|
198
|
+
yield {
|
|
199
|
+
index: chunk.index,
|
|
200
|
+
content: typeof chunk.data === "string" ? chunk.data : JSON.stringify(chunk.data),
|
|
201
|
+
done: chunk.done,
|
|
202
|
+
role: "assistant",
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// -----------------------------------------------------------------------
|
|
207
|
+
// Cache
|
|
208
|
+
// -----------------------------------------------------------------------
|
|
209
|
+
/** Check whether the model binary is currently cached locally. */
|
|
210
|
+
async isCached() {
|
|
211
|
+
this.ensureNotDisposed();
|
|
212
|
+
return this.loader.isCached();
|
|
213
|
+
}
|
|
214
|
+
/** Remove the cached model binary. */
|
|
215
|
+
async clearCache() {
|
|
216
|
+
this.ensureNotDisposed();
|
|
217
|
+
return this.loader.clearCache();
|
|
218
|
+
}
|
|
219
|
+
/** Get cache metadata for the model. */
|
|
220
|
+
async cacheInfo() {
|
|
221
|
+
this.ensureNotDisposed();
|
|
222
|
+
return this.loader.getCacheInfo();
|
|
223
|
+
}
|
|
224
|
+
// -----------------------------------------------------------------------
|
|
225
|
+
// Introspection
|
|
226
|
+
// -----------------------------------------------------------------------
|
|
227
|
+
/** The inference backend currently in use (after `load()`). */
|
|
228
|
+
get activeBackend() {
|
|
229
|
+
return this.engine.activeBackend;
|
|
230
|
+
}
|
|
231
|
+
/** Input tensor names defined by the loaded model. */
|
|
232
|
+
get inputNames() {
|
|
233
|
+
this.ensureReady();
|
|
234
|
+
return this.engine.inputNames;
|
|
235
|
+
}
|
|
236
|
+
/** Output tensor names defined by the loaded model. */
|
|
237
|
+
get outputNames() {
|
|
238
|
+
this.ensureReady();
|
|
239
|
+
return this.engine.outputNames;
|
|
240
|
+
}
|
|
241
|
+
/** Whether `load()` has been called successfully. */
|
|
242
|
+
get isLoaded() {
|
|
243
|
+
return this.loaded;
|
|
244
|
+
}
|
|
245
|
+
// -----------------------------------------------------------------------
|
|
246
|
+
// Cleanup
|
|
247
|
+
// -----------------------------------------------------------------------
|
|
248
|
+
/** Release all resources (WASM memory, WebGPU device, telemetry). */
|
|
249
|
+
dispose() {
|
|
250
|
+
if (this.disposed)
|
|
251
|
+
return;
|
|
252
|
+
this.disposed = true;
|
|
253
|
+
this.loaded = false;
|
|
254
|
+
this.engine.dispose();
|
|
255
|
+
this.telemetry?.dispose();
|
|
256
|
+
this.telemetry = null;
|
|
257
|
+
}
|
|
258
|
+
// -----------------------------------------------------------------------
|
|
259
|
+
// Private helpers
|
|
260
|
+
// -----------------------------------------------------------------------
|
|
261
|
+
ensureNotDisposed() {
|
|
262
|
+
if (this.disposed) {
|
|
263
|
+
throw new OctomilError("SESSION_DISPOSED", "This Octomil instance has been disposed. Create a new one.");
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
ensureReady() {
|
|
267
|
+
this.ensureNotDisposed();
|
|
268
|
+
if (!this.loaded) {
|
|
269
|
+
throw new OctomilError("NOT_LOADED", "Model not loaded. Call load() before predict() or chat().");
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Normalise the various `PredictInput` shapes into a flat
|
|
274
|
+
* `NamedTensors` map suitable for the inference engine.
|
|
275
|
+
*/
|
|
276
|
+
prepareTensors(input) {
|
|
277
|
+
// Already a NamedTensors map — pass through.
|
|
278
|
+
if (this.isNamedTensors(input)) {
|
|
279
|
+
return input;
|
|
280
|
+
}
|
|
281
|
+
// { raw, dims } — wrap in the first input name.
|
|
282
|
+
if ("raw" in input && "dims" in input) {
|
|
283
|
+
const name = this.engine.inputNames[0];
|
|
284
|
+
if (!name) {
|
|
285
|
+
throw new OctomilError("INVALID_INPUT", "Model has no input tensors defined.");
|
|
286
|
+
}
|
|
287
|
+
return { [name]: { data: input.raw, dims: input.dims } };
|
|
288
|
+
}
|
|
289
|
+
// { text } — encode as a simple int32 character-code sequence.
|
|
290
|
+
// Real tokenization would require a tokenizer; this is a minimal
|
|
291
|
+
// placeholder that works for models expecting raw code-point inputs.
|
|
292
|
+
if ("text" in input) {
|
|
293
|
+
const name = this.engine.inputNames[0];
|
|
294
|
+
if (!name) {
|
|
295
|
+
throw new OctomilError("INVALID_INPUT", "Model has no input tensors defined.");
|
|
296
|
+
}
|
|
297
|
+
const codes = new Int32Array(Array.from(input.text).map((ch) => ch.codePointAt(0) ?? 0));
|
|
298
|
+
return { [name]: { data: codes, dims: [1, codes.length] } };
|
|
299
|
+
}
|
|
300
|
+
// { image } — extract pixel data from ImageData / Canvas / Image.
|
|
301
|
+
if ("image" in input) {
|
|
302
|
+
return this.imageToTensors(input.image);
|
|
303
|
+
}
|
|
304
|
+
throw new OctomilError("INVALID_INPUT", "Unrecognised PredictInput format. Provide named tensors, { text }, { image }, or { raw, dims }.");
|
|
305
|
+
}
|
|
306
|
+
/** Type guard for NamedTensors. */
|
|
307
|
+
isNamedTensors(input) {
|
|
308
|
+
if ("text" in input || "image" in input || "raw" in input)
|
|
309
|
+
return false;
|
|
310
|
+
// If none of the convenience keys exist, treat as NamedTensors.
|
|
311
|
+
const firstValue = Object.values(input)[0];
|
|
312
|
+
return (firstValue !== undefined &&
|
|
313
|
+
typeof firstValue === "object" &&
|
|
314
|
+
"data" in firstValue &&
|
|
315
|
+
"dims" in firstValue);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Convert an image source to a Float32Array in NCHW format
|
|
319
|
+
* (batch=1, channels=3, H, W) normalised to [0, 1].
|
|
320
|
+
*/
|
|
321
|
+
imageToTensors(source) {
|
|
322
|
+
let imageData;
|
|
323
|
+
if (source instanceof ImageData) {
|
|
324
|
+
imageData = source;
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
// Draw onto an offscreen canvas to get pixel data.
|
|
328
|
+
const canvas = source instanceof HTMLCanvasElement
|
|
329
|
+
? source
|
|
330
|
+
: (() => {
|
|
331
|
+
const c = document.createElement("canvas");
|
|
332
|
+
c.width = source.naturalWidth || source.width;
|
|
333
|
+
c.height = source.naturalHeight || source.height;
|
|
334
|
+
const ctx = c.getContext("2d");
|
|
335
|
+
ctx.drawImage(source, 0, 0);
|
|
336
|
+
return c;
|
|
337
|
+
})();
|
|
338
|
+
const ctx = canvas.getContext("2d");
|
|
339
|
+
if (!ctx) {
|
|
340
|
+
throw new OctomilError("INVALID_INPUT", "Could not get 2D context from canvas.");
|
|
341
|
+
}
|
|
342
|
+
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
343
|
+
}
|
|
344
|
+
const { width, height, data: rgba } = imageData;
|
|
345
|
+
const pixels = width * height;
|
|
346
|
+
const float = new Float32Array(3 * pixels);
|
|
347
|
+
// RGBA → CHW (R plane, G plane, B plane), normalised 0–1.
|
|
348
|
+
for (let i = 0; i < pixels; i++) {
|
|
349
|
+
float[i] = rgba[i * 4] / 255; // R
|
|
350
|
+
float[pixels + i] = rgba[i * 4 + 1] / 255; // G
|
|
351
|
+
float[2 * pixels + i] = rgba[i * 4 + 2] / 255; // B
|
|
352
|
+
}
|
|
353
|
+
const name = this.engine.inputNames[0];
|
|
354
|
+
if (!name) {
|
|
355
|
+
throw new OctomilError("INVALID_INPUT", "Model has no input tensors defined.");
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
[name]: {
|
|
359
|
+
data: float,
|
|
360
|
+
dims: [1, 3, height, width],
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
trackEvent(event) {
|
|
365
|
+
this.telemetry?.track(event);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
//# sourceMappingURL=octomil.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"octomil.js","sourceRoot":"","sources":["../src/octomil.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,gBAAgB,EAAmB,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAc1D,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,MAAM,OAAO,OAAO;IACD,OAAO,CAGP;IAEA,KAAK,CAAa;IAClB,MAAM,CAAc;IACpB,MAAM,CAAkB;IACjC,SAAS,GAA6B,IAAI,CAAC;IAE3C,MAAM,GAAG,KAAK,CAAC;IACf,QAAQ,GAAG,KAAK,CAAC;IAEzB,YAAY,OAAuB;QACjC,IAAI,CAAC,OAAO,GAAG;YACb,SAAS,EAAE,KAAK;YAChB,aAAa,EAAE,WAAW;YAC1B,GAAG,OAAO;SACX,CAAC;QAEF,IAAI,CAAC,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAEpC,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,iBAAiB,CAAC;gBACrC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY;gBAC9B,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;aAC5B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,YAAY;IACZ,0EAA0E;IAE1E;;;OAGG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEzB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QAE/C,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC3C,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACjE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAE7C,IAAI,CAAC,UAAU,CAAC;YACd,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;YACzB,UAAU;YACV,QAAQ,EAAE;gBACR,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa;gBAClC,MAAM,EAAE,SAAS;gBACjB,SAAS,EAAE,SAAS,CAAC,UAAU;aAChC;YACD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;QAEH,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,UAAU,CAAC;gBACd,IAAI,EAAE,WAAW;gBACjB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;gBACzB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,CAAC;gBACd,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;gBACzB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,YAAY;IACZ,0EAA0E;IAE1E;;;;;OAKG;IACH,KAAK,CAAC,OAAO,CAAC,KAAmB;QAC/B,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE9C,IAAI,CAAC,UAAU,CAAC;YACd,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;YACzB,UAAU,EAAE,MAAM,CAAC,SAAS;YAC5B,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE;YAChD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY,CAAC,MAAsB;QACvC,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,OAAO,GAAoB,EAAE,CAAC;QAEpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC9C,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;QAED,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAE1C,IAAI,CAAC,UAAU,CAAC;YACd,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;YACzB,UAAU,EAAE,OAAO;YACnB,QAAQ,EAAE;gBACR,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa;gBAClC,SAAS,EAAE,MAAM,CAAC,MAAM;aACzB;YACD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,IAAI,CACR,QAAuB,EACvB,UAAuB,EAAE;QAEzB,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YAC5B,MAAM,IAAI,YAAY,CACpB,kBAAkB,EAClB,6CAA6C,CAC9C,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,wBAAwB,CAAC;YAC7C,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;YACjC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC3B,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;SACvC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,IAAI,OAAO,GAAG,EAAE,CAAC;QAEjB,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;YACrD,QAAQ;YACR,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,UAAU,EAAE,OAAO,CAAC,SAAS;YAC7B,KAAK,EAAE,OAAO,CAAC,IAAI;SACpB,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAEjD,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;YACpC,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACnC,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC;YACxB,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE;YACvC,SAAS,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK;SACrC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,CAAC,UAAU,CACf,QAAuB,EACvB,UAAuB,EAAE;QAEzB,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YAC5B,MAAM,IAAI,YAAY,CACpB,kBAAkB,EAClB,mDAAmD,CACpD,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,wBAAwB,CAAC;YAC7C,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;YACjC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC3B,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;SACvC,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;YACrD,QAAQ;YACR,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,UAAU,EAAE,OAAO,CAAC,SAAS;YAC7B,KAAK,EAAE,OAAO,CAAC,IAAI;SACpB,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAEjD,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;YACpC,MAAM;gBACJ,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,OAAO,EAAE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;gBACjF,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,IAAI,EAAE,WAAW;aAClB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,QAAQ;IACR,0EAA0E;IAE1E,kEAAkE;IAClE,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;IAChC,CAAC;IAED,sCAAsC;IACtC,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;IAClC,CAAC;IAED,wCAAwC;IACxC,KAAK,CAAC,SAAS;QACb,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;IACpC,CAAC;IAED,0EAA0E;IAC1E,gBAAgB;IAChB,0EAA0E;IAE1E,+DAA+D;IAC/D,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;IACnC,CAAC;IAED,sDAAsD;IACtD,IAAI,UAAU;QACZ,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;IAChC,CAAC;IAED,uDAAuD;IACvD,IAAI,WAAW;QACb,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;IACjC,CAAC;IAED,qDAAqD;IACrD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,0EAA0E;IAC1E,UAAU;IACV,0EAA0E;IAE1E,qEAAqE;IACrE,OAAO;QACL,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QAEpB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACtB,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,0EAA0E;IAC1E,kBAAkB;IAClB,0EAA0E;IAElE,iBAAiB;QACvB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,IAAI,YAAY,CACpB,kBAAkB,EAClB,4DAA4D,CAC7D,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,YAAY,CACpB,YAAY,EACZ,2DAA2D,CAC5D,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,cAAc,CAAC,KAAmB;QACxC,6CAA6C;QAC7C,IAAI,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,gDAAgD;QAChD,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YACvC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,YAAY,CACpB,eAAe,EACf,qCAAqC,CACtC,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC3D,CAAC;QAED,+DAA+D;QAC/D,iEAAiE;QACjE,qEAAqE;QACrE,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YACvC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,YAAY,CACpB,eAAe,EACf,qCAAqC,CACtC,CAAC;YACJ,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,UAAU,CAC1B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAC3D,CAAC;YACF,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QAC9D,CAAC;QAED,kEAAkE;QAClE,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;QAED,MAAM,IAAI,YAAY,CACpB,eAAe,EACf,iGAAiG,CAClG,CAAC;IACJ,CAAC;IAED,mCAAmC;IAC3B,cAAc,CAAC,KAAmB;QACxC,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxE,gEAAgE;QAChE,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,OAAO,CACL,UAAU,KAAK,SAAS;YACxB,OAAO,UAAU,KAAK,QAAQ;YAC9B,MAAM,IAAI,UAAU;YACpB,MAAM,IAAI,UAAU,CACrB,CAAC;IACJ,CAAC;IAED;;;OAGG;IACK,cAAc,CACpB,MAAwD;QAExD,IAAI,SAAoB,CAAC;QAEzB,IAAI,MAAM,YAAY,SAAS,EAAE,CAAC;YAChC,SAAS,GAAG,MAAM,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,mDAAmD;YACnD,MAAM,MAAM,GACV,MAAM,YAAY,iBAAiB;gBACjC,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,CAAC,GAAG,EAAE;oBACJ,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;oBAC3C,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,KAAK,CAAC;oBAC9C,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,MAAM,CAAC;oBACjD,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,CAAC,IAAI,CAAE,CAAC;oBAChC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC5B,OAAO,CAAC,CAAC;gBACX,CAAC,CAAC,EAAE,CAAC;YAEX,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,IAAI,YAAY,CACpB,eAAe,EACf,uCAAuC,CACxC,CAAC;YACJ,CAAC;YACD,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC;QAChD,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;QAE3C,0DAA0D;QAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAChC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAE,GAAG,GAAG,CAAC,CAAe,IAAI;YACjD,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAE,GAAG,GAAG,CAAC,CAAE,IAAI;YACjD,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAE,GAAG,GAAG,CAAC,CAAC,IAAI;QACtD,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,YAAY,CACpB,eAAe,EACf,qCAAqC,CACtC,CAAC;QACJ,CAAC;QAED,OAAO;YACL,CAAC,IAAI,CAAC,EAAE;gBACN,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC;aAC5B;SACF,CAAC;IACJ,CAAC;IAEO,UAAU,CAAC,KAAqB;QACtC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;CACF"}
|